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