refactor: cleanup unneeded type casting
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16RequestService.ts
1 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
2
3 import type { JSONSchemaType } from 'ajv'
4
5 import { OCPP16Constants } from './OCPP16Constants.js'
6 import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
7 import type { ChargingStation } from '../../../charging-station/index.js'
8 import { OCPPError } from '../../../exception/index.js'
9 import {
10 ErrorType,
11 type JsonObject,
12 type JsonType,
13 type OCPP16AuthorizeRequest,
14 type OCPP16BootNotificationRequest,
15 OCPP16ChargePointStatus,
16 type OCPP16DataTransferRequest,
17 type OCPP16DiagnosticsStatusNotificationRequest,
18 type OCPP16FirmwareStatusNotificationRequest,
19 type OCPP16HeartbeatRequest,
20 type OCPP16MeterValuesRequest,
21 OCPP16RequestCommand,
22 type OCPP16StartTransactionRequest,
23 type OCPP16StatusNotificationRequest,
24 type OCPP16StopTransactionRequest,
25 OCPPVersion,
26 type RequestParams
27 } from '../../../types/index.js'
28 import { Constants, generateUUID } from '../../../utils/index.js'
29 import { OCPPRequestService } from '../OCPPRequestService.js'
30 import type { OCPPResponseService } from '../OCPPResponseService.js'
31
32 const moduleName = 'OCPP16RequestService'
33
34 export class OCPP16RequestService extends OCPPRequestService {
35 protected jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>
36
37 public constructor (ocppResponseService: OCPPResponseService) {
38 // if (new.target.name === moduleName) {
39 // throw new TypeError(`Cannot construct ${new.target.name} instances directly`)
40 // }
41 super(OCPPVersion.VERSION_16, ocppResponseService)
42 this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonType>>([
43 [
44 OCPP16RequestCommand.AUTHORIZE,
45 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
46 'assets/json-schemas/ocpp/1.6/Authorize.json',
47 moduleName,
48 'constructor'
49 )
50 ],
51 [
52 OCPP16RequestCommand.BOOT_NOTIFICATION,
53 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
54 'assets/json-schemas/ocpp/1.6/BootNotification.json',
55 moduleName,
56 'constructor'
57 )
58 ],
59 [
60 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
61 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
62 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
63 moduleName,
64 'constructor'
65 )
66 ],
67 [
68 OCPP16RequestCommand.HEARTBEAT,
69 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
70 'assets/json-schemas/ocpp/1.6/Heartbeat.json',
71 moduleName,
72 'constructor'
73 )
74 ],
75 [
76 OCPP16RequestCommand.METER_VALUES,
77 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
78 'assets/json-schemas/ocpp/1.6/MeterValues.json',
79 moduleName,
80 'constructor'
81 )
82 ],
83 [
84 OCPP16RequestCommand.STATUS_NOTIFICATION,
85 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
86 'assets/json-schemas/ocpp/1.6/StatusNotification.json',
87 moduleName,
88 'constructor'
89 )
90 ],
91 [
92 OCPP16RequestCommand.START_TRANSACTION,
93 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
94 'assets/json-schemas/ocpp/1.6/StartTransaction.json',
95 moduleName,
96 'constructor'
97 )
98 ],
99 [
100 OCPP16RequestCommand.STOP_TRANSACTION,
101 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
102 'assets/json-schemas/ocpp/1.6/StopTransaction.json',
103 moduleName,
104 'constructor'
105 )
106 ],
107 [
108 OCPP16RequestCommand.DATA_TRANSFER,
109 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
110 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
111 moduleName,
112 'constructor'
113 )
114 ],
115 [
116 OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
117 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
118 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
119 moduleName,
120 'constructor'
121 )
122 ]
123 ])
124 this.buildRequestPayload = this.buildRequestPayload.bind(this)
125 }
126
127 public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
128 chargingStation: ChargingStation,
129 commandName: OCPP16RequestCommand,
130 commandParams?: JsonType,
131 params?: RequestParams
132 ): Promise<ResponseType> {
133 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
134 if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
135 return (await this.sendMessage(
136 chargingStation,
137 generateUUID(),
138 this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
139 commandName,
140 params
141 )) as ResponseType
142 }
143 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
144 throw new OCPPError(
145 ErrorType.NOT_SUPPORTED,
146 `Unsupported OCPP command '${commandName}'`,
147 commandName,
148 commandParams
149 )
150 }
151
152 private buildRequestPayload<Request extends JsonType>(
153 chargingStation: ChargingStation,
154 commandName: OCPP16RequestCommand,
155 commandParams?: JsonType
156 ): Request {
157 let connectorId: number | undefined
158 let energyActiveImportRegister: number
159 commandParams = commandParams as JsonObject
160 switch (commandName) {
161 case OCPP16RequestCommand.BOOT_NOTIFICATION:
162 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
163 case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
164 case OCPP16RequestCommand.METER_VALUES:
165 case OCPP16RequestCommand.STATUS_NOTIFICATION:
166 case OCPP16RequestCommand.DATA_TRANSFER:
167 return commandParams as unknown as Request
168 case OCPP16RequestCommand.AUTHORIZE:
169 return {
170 idTag: Constants.DEFAULT_IDTAG,
171 ...commandParams
172 } as unknown as Request
173 case OCPP16RequestCommand.HEARTBEAT:
174 return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request
175 case OCPP16RequestCommand.START_TRANSACTION:
176 return {
177 idTag: Constants.DEFAULT_IDTAG,
178 meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
179 commandParams.connectorId as number,
180 true
181 ),
182 timestamp: new Date(),
183 ...(OCPP16ServiceUtils.hasReservation(
184 chargingStation,
185 commandParams.connectorId as number,
186 commandParams.idTag as string
187 ) && {
188 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
189 reservationId: chargingStation.getReservationBy(
190 'connectorId',
191 chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved
192 ? 0
193 : (commandParams.connectorId as number)
194 )!.reservationId
195 }),
196 ...commandParams
197 } as unknown as Request
198 case OCPP16RequestCommand.STOP_TRANSACTION:
199 chargingStation.stationInfo?.transactionDataMeterValues === true &&
200 (connectorId = chargingStation.getConnectorIdByTransactionId(
201 commandParams.transactionId as number
202 ))
203 energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId(
204 commandParams.transactionId as number,
205 true
206 )
207 return {
208 idTag: chargingStation.getTransactionIdTag(commandParams.transactionId as number),
209 meterStop: energyActiveImportRegister,
210 timestamp: new Date(),
211 ...(chargingStation.stationInfo?.transactionDataMeterValues === true && {
212 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
213 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
214 chargingStation.getConnectorStatus(connectorId!)!.transactionBeginMeterValue!,
215 OCPP16ServiceUtils.buildTransactionEndMeterValue(
216 chargingStation,
217 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
218 connectorId!,
219 energyActiveImportRegister
220 )
221 )
222 }),
223 ...commandParams
224 } as unknown as Request
225 default:
226 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
227 throw new OCPPError(
228 ErrorType.NOT_SUPPORTED,
229 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
230 `Unsupported OCPP command '${commandName}'`,
231 commandName,
232 commandParams
233 )
234 }
235 }
236 }