build(deps-dev): apply updates
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16RequestService.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. 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 ])
31f59c6d
JB
124 this.buildRequestPayload = this.buildRequestPayload.bind(this) as <Request extends JsonType>(
125 chargingStation: ChargingStation,
126 commandName: OCPP16RequestCommand,
66a7748d
JB
127 commandParams?: JsonType
128 ) => Request
9f2e3130
JB
129 }
130
6c1761d4 131 public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
08f130a0 132 chargingStation: ChargingStation,
94a464f9 133 commandName: OCPP16RequestCommand,
5cc4b63b 134 commandParams?: JsonType,
66a7748d 135 params?: RequestParams
6c1761d4 136 ): Promise<ResponseType> {
62340a29 137 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
66a7748d 138 if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
f22266fd 139 return (await this.sendMessage(
08f130a0 140 chargingStation,
9bf0ef23 141 generateUUID(),
18bf8274 142 this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
94a464f9 143 commandName,
66a7748d
JB
144 params
145 )) as ResponseType
94a464f9 146 }
e909d2a7 147 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
94a464f9
JB
148 throw new OCPPError(
149 ErrorType.NOT_SUPPORTED,
6c8f5d90 150 `Unsupported OCPP command '${commandName}'`,
94a464f9 151 commandName,
66a7748d
JB
152 commandParams
153 )
c0560973
JB
154 }
155
5cc4b63b 156 private buildRequestPayload<Request extends JsonType>(
08f130a0 157 chargingStation: ChargingStation,
78085c42 158 commandName: OCPP16RequestCommand,
66a7748d 159 commandParams?: JsonType
f22266fd 160 ): Request {
66a7748d
JB
161 let connectorId: number | undefined
162 let energyActiveImportRegister: number
163 commandParams = commandParams as JsonObject
78085c42 164 switch (commandName) {
78085c42 165 case OCPP16RequestCommand.BOOT_NOTIFICATION:
78085c42 166 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
22e0d48e 167 case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
78085c42 168 case OCPP16RequestCommand.METER_VALUES:
78085c42 169 case OCPP16RequestCommand.STATUS_NOTIFICATION:
36c462a4 170 case OCPP16RequestCommand.DATA_TRANSFER:
66a7748d 171 return commandParams as unknown as Request
36c462a4 172 case OCPP16RequestCommand.AUTHORIZE:
78085c42 173 return {
36c462a4 174 idTag: Constants.DEFAULT_IDTAG,
66a7748d
JB
175 ...commandParams
176 } as unknown as Request
36c462a4 177 case OCPP16RequestCommand.HEARTBEAT:
66a7748d 178 return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request
78085c42
JB
179 case OCPP16RequestCommand.START_TRANSACTION:
180 return {
36c462a4
JB
181 idTag: Constants.DEFAULT_IDTAG,
182 meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
5199f9fd 183 commandParams.connectorId as number,
66a7748d 184 true
36c462a4
JB
185 ),
186 timestamp: new Date(),
90aceaf6
JB
187 ...(OCPP16ServiceUtils.hasReservation(
188 chargingStation,
5199f9fd
JB
189 commandParams.connectorId as number,
190 commandParams.idTag as string
90aceaf6 191 ) && {
66a7748d 192 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
90aceaf6
JB
193 reservationId: chargingStation.getReservationBy(
194 'connectorId',
195 chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved
196 ? 0
5199f9fd 197 : (commandParams.connectorId as number)
66a7748d 198 )!.reservationId
90aceaf6 199 }),
66a7748d
JB
200 ...commandParams
201 } as unknown as Request
78085c42 202 case OCPP16RequestCommand.STOP_TRANSACTION:
66a7748d 203 chargingStation.stationInfo?.transactionDataMeterValues === true &&
f1e731bd 204 (connectorId = chargingStation.getConnectorIdByTransactionId(
5199f9fd 205 commandParams.transactionId as number
f938317f 206 ))
36c462a4 207 energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId(
5199f9fd 208 commandParams.transactionId as number,
66a7748d
JB
209 true
210 )
78085c42 211 return {
5199f9fd 212 idTag: chargingStation.getTransactionIdTag(commandParams.transactionId as number),
36c462a4
JB
213 meterStop: energyActiveImportRegister,
214 timestamp: new Date(),
66a7748d 215 ...(chargingStation.stationInfo?.transactionDataMeterValues === true && {
36c462a4 216 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
66a7748d 217 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 218 chargingStation.getConnectorStatus(connectorId!)!.transactionBeginMeterValue!,
36c462a4
JB
219 OCPP16ServiceUtils.buildTransactionEndMeterValue(
220 chargingStation,
66a7748d 221 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e1d9a0f4 222 connectorId!,
66a7748d
JB
223 energyActiveImportRegister
224 )
225 )
78085c42 226 }),
66a7748d
JB
227 ...commandParams
228 } as unknown as Request
78085c42 229 default:
e909d2a7 230 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
78085c42
JB
231 throw new OCPPError(
232 ErrorType.NOT_SUPPORTED,
233 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
6c8f5d90 234 `Unsupported OCPP command '${commandName}'`,
78085c42 235 commandName,
66a7748d
JB
236 commandParams
237 )
78085c42
JB
238 }
239 }
c0560973 240}