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