]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/blame - 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
a19b897d 1// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
c8eeb62b 2
24d15716 3import type { ValidateFunction } from 'ajv'
b52c969d 4
66a7748d 5import type { ChargingStation } from '../../../charging-station/index.js'
0749233f
JB
6import type { OCPPResponseService } from '../OCPPResponseService.js'
7
66a7748d 8import { OCPPError } from '../../../exception/index.js'
b52c969d 9import {
268a74bb
JB
10 ErrorType,
11 type JsonObject,
12 type JsonType,
13 type OCPP16AuthorizeRequest,
27782dbc 14 type OCPP16BootNotificationRequest,
90aceaf6 15 OCPP16ChargePointStatus,
27782dbc 16 type OCPP16DataTransferRequest,
c9a4f9ea 17 type OCPP16DiagnosticsStatusNotificationRequest,
e9a4164c 18 type OCPP16FirmwareStatusNotificationRequest,
27782dbc 19 type OCPP16HeartbeatRequest,
268a74bb 20 type OCPP16MeterValuesRequest,
b52c969d 21 OCPP16RequestCommand,
268a74bb 22 type OCPP16StartTransactionRequest,
27782dbc 23 type OCPP16StatusNotificationRequest,
268a74bb
JB
24 type OCPP16StopTransactionRequest,
25 OCPPVersion,
d1f5bfd8 26 type RequestParams,
66a7748d
JB
27} from '../../../types/index.js'
28import { Constants, generateUUID } from '../../../utils/index.js'
29import { OCPPRequestService } from '../OCPPRequestService.js'
4c3f6c20
JB
30import { OCPP16Constants } from './OCPP16Constants.js'
31import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
c0560973 32
66a7748d 33const moduleName = 'OCPP16RequestService'
909dcf2d 34
268a74bb 35export class OCPP16RequestService extends OCPPRequestService {
d5490a13 36 protected payloadValidateFunctions: Map<OCPP16RequestCommand, ValidateFunction<JsonType>>
b52c969d 37
66a7748d 38 public constructor (ocppResponseService: OCPPResponseService) {
5199f9fd
JB
39 // if (new.target.name === moduleName) {
40 // throw new TypeError(`Cannot construct ${new.target.name} instances directly`)
b768993d 41 // }
66a7748d 42 super(OCPPVersion.VERSION_16, ocppResponseService)
d5490a13 43 this.payloadValidateFunctions = new Map<OCPP16RequestCommand, ValidateFunction<JsonType>>([
b52c969d
JB
44 [
45 OCPP16RequestCommand.AUTHORIZE,
d712a9a3
JB
46 this.ajv.compile(
47 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
48 'assets/json-schemas/ocpp/1.6/Authorize.json',
49 moduleName,
50 'constructor'
51 )
52 ),
b52c969d
JB
53 ],
54 [
55 OCPP16RequestCommand.BOOT_NOTIFICATION,
d712a9a3
JB
56 this.ajv.compile(
57 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
58 'assets/json-schemas/ocpp/1.6/BootNotification.json',
59 moduleName,
60 'constructor'
61 )
62 ),
b52c969d
JB
63 ],
64 [
0749233f 65 OCPP16RequestCommand.DATA_TRANSFER,
d712a9a3 66 this.ajv.compile(
0749233f
JB
67 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
68 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
d712a9a3
JB
69 moduleName,
70 'constructor'
71 )
72 ),
b52c969d
JB
73 ],
74 [
0749233f 75 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
d712a9a3 76 this.ajv.compile(
0749233f
JB
77 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
78 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
d712a9a3
JB
79 moduleName,
80 'constructor'
81 )
82 ),
b52c969d
JB
83 ],
84 [
0749233f 85 OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
d712a9a3 86 this.ajv.compile(
0749233f
JB
87 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
88 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
d712a9a3
JB
89 moduleName,
90 'constructor'
91 )
92 ),
b52c969d
JB
93 ],
94 [
0749233f 95 OCPP16RequestCommand.HEARTBEAT,
d712a9a3 96 this.ajv.compile(
0749233f
JB
97 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
98 'assets/json-schemas/ocpp/1.6/Heartbeat.json',
d712a9a3
JB
99 moduleName,
100 'constructor'
101 )
102 ),
b52c969d
JB
103 ],
104 [
0749233f 105 OCPP16RequestCommand.METER_VALUES,
d712a9a3 106 this.ajv.compile(
0749233f
JB
107 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
108 'assets/json-schemas/ocpp/1.6/MeterValues.json',
d712a9a3
JB
109 moduleName,
110 'constructor'
111 )
112 ),
b52c969d
JB
113 ],
114 [
0749233f 115 OCPP16RequestCommand.START_TRANSACTION,
d712a9a3 116 this.ajv.compile(
0749233f
JB
117 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
118 'assets/json-schemas/ocpp/1.6/StartTransaction.json',
d712a9a3
JB
119 moduleName,
120 'constructor'
121 )
122 ),
b52c969d 123 ],
91a7d3ea 124 [
0749233f 125 OCPP16RequestCommand.STATUS_NOTIFICATION,
d712a9a3 126 this.ajv.compile(
0749233f
JB
127 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
128 'assets/json-schemas/ocpp/1.6/StatusNotification.json',
d712a9a3
JB
129 moduleName,
130 'constructor'
131 )
132 ),
91a7d3ea 133 ],
c9a4f9ea 134 [
0749233f 135 OCPP16RequestCommand.STOP_TRANSACTION,
d712a9a3 136 this.ajv.compile(
0749233f
JB
137 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
138 'assets/json-schemas/ocpp/1.6/StopTransaction.json',
d712a9a3
JB
139 moduleName,
140 'constructor'
141 )
142 ),
d1f5bfd8 143 ],
66a7748d 144 ])
ba9a56a6 145 this.buildRequestPayload = this.buildRequestPayload.bind(this)
9f2e3130
JB
146 }
147
c4a89082
JB
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
01841aad 184 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
5cc4b63b 185 private buildRequestPayload<Request extends JsonType>(
08f130a0 186 chargingStation: ChargingStation,
78085c42 187 commandName: OCPP16RequestCommand,
66a7748d 188 commandParams?: JsonType
f22266fd 189 ): Request {
66a7748d
JB
190 let connectorId: number | undefined
191 let energyActiveImportRegister: number
192 commandParams = commandParams as JsonObject
78085c42 193 switch (commandName) {
0749233f
JB
194 case OCPP16RequestCommand.AUTHORIZE:
195 return {
196 idTag: Constants.DEFAULT_IDTAG,
197 ...commandParams,
198 } as unknown as Request
78085c42 199 case OCPP16RequestCommand.BOOT_NOTIFICATION:
0749233f 200 case OCPP16RequestCommand.DATA_TRANSFER:
78085c42 201 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
22e0d48e 202 case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
78085c42 203 case OCPP16RequestCommand.METER_VALUES:
78085c42 204 case OCPP16RequestCommand.STATUS_NOTIFICATION:
66a7748d 205 return commandParams as unknown as Request
36c462a4 206 case OCPP16RequestCommand.HEARTBEAT:
66a7748d 207 return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request
78085c42
JB
208 case OCPP16RequestCommand.START_TRANSACTION:
209 return {
36c462a4
JB
210 idTag: Constants.DEFAULT_IDTAG,
211 meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
5199f9fd 212 commandParams.connectorId as number,
66a7748d 213 true
36c462a4
JB
214 ),
215 timestamp: new Date(),
90aceaf6
JB
216 ...(OCPP16ServiceUtils.hasReservation(
217 chargingStation,
5199f9fd
JB
218 commandParams.connectorId as number,
219 commandParams.idTag as string
90aceaf6 220 ) && {
66a7748d 221 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
90aceaf6
JB
222 reservationId: chargingStation.getReservationBy(
223 'connectorId',
224 chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved
225 ? 0
5199f9fd 226 : (commandParams.connectorId as number)
d1f5bfd8 227 )!.reservationId,
90aceaf6 228 }),
d1f5bfd8 229 ...commandParams,
66a7748d 230 } as unknown as Request
78085c42 231 case OCPP16RequestCommand.STOP_TRANSACTION:
66a7748d 232 chargingStation.stationInfo?.transactionDataMeterValues === true &&
f1e731bd 233 (connectorId = chargingStation.getConnectorIdByTransactionId(
5199f9fd 234 commandParams.transactionId as number
f938317f 235 ))
36c462a4 236 energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId(
5199f9fd 237 commandParams.transactionId as number,
66a7748d
JB
238 true
239 )
78085c42 240 return {
5199f9fd 241 idTag: chargingStation.getTransactionIdTag(commandParams.transactionId as number),
36c462a4
JB
242 meterStop: energyActiveImportRegister,
243 timestamp: new Date(),
66a7748d 244 ...(chargingStation.stationInfo?.transactionDataMeterValues === true && {
36c462a4 245 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
66a7748d 246 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 247 chargingStation.getConnectorStatus(connectorId!)!.transactionBeginMeterValue!,
36c462a4
JB
248 OCPP16ServiceUtils.buildTransactionEndMeterValue(
249 chargingStation,
66a7748d 250 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 251 connectorId!,
66a7748d
JB
252 energyActiveImportRegister
253 )
d1f5bfd8 254 ),
78085c42 255 }),
d1f5bfd8 256 ...commandParams,
66a7748d 257 } as unknown as Request
78085c42 258 default:
e909d2a7 259 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
78085c42
JB
260 throw new OCPPError(
261 ErrorType.NOT_SUPPORTED,
262 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
3024d5b2 263 `Unsupported OCPP command ${commandName}`,
78085c42 264 commandName,
66a7748d
JB
265 commandParams
266 )
78085c42
JB
267 }
268 }
c0560973 269}