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