Commit | Line | Data |
---|---|---|
edd13439 | 1 | // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved. |
c8eeb62b | 2 | |
6c1761d4 | 3 | import type { JSONSchemaType } from 'ajv'; |
b52c969d | 4 | |
4c3c0d59 JB |
5 | import { OCPP16Constants } from './OCPP16Constants'; |
6 | import { OCPP16ServiceUtils } from './OCPP16ServiceUtils'; | |
2896e06d | 7 | import type { ChargingStation } from '../../../charging-station'; |
268a74bb | 8 | import { OCPPError } from '../../../exception'; |
b52c969d | 9 | import { |
268a74bb JB |
10 | ErrorType, |
11 | type JsonObject, | |
12 | type JsonType, | |
13 | type OCPP16AuthorizeRequest, | |
27782dbc JB |
14 | type OCPP16BootNotificationRequest, |
15 | type OCPP16DataTransferRequest, | |
c9a4f9ea | 16 | type OCPP16DiagnosticsStatusNotificationRequest, |
e9a4164c | 17 | type OCPP16FirmwareStatusNotificationRequest, |
27782dbc | 18 | type OCPP16HeartbeatRequest, |
268a74bb | 19 | type OCPP16MeterValuesRequest, |
b52c969d | 20 | OCPP16RequestCommand, |
268a74bb | 21 | type OCPP16StartTransactionRequest, |
27782dbc | 22 | type OCPP16StatusNotificationRequest, |
268a74bb JB |
23 | type OCPP16StopTransactionRequest, |
24 | OCPPVersion, | |
25 | type RequestParams, | |
26 | } from '../../../types'; | |
9bf0ef23 | 27 | import { Constants, generateUUID } from '../../../utils'; |
4c3c0d59 JB |
28 | import { OCPPRequestService } from '../OCPPRequestService'; |
29 | import type { OCPPResponseService } from '../OCPPResponseService'; | |
c0560973 | 30 | |
909dcf2d JB |
31 | const moduleName = 'OCPP16RequestService'; |
32 | ||
268a74bb | 33 | export class OCPP16RequestService extends OCPPRequestService { |
b3fc3ff5 | 34 | protected jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>; |
b52c969d | 35 | |
08f130a0 | 36 | public constructor(ocppResponseService: OCPPResponseService) { |
b768993d JB |
37 | // if (new.target?.name === moduleName) { |
38 | // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`); | |
39 | // } | |
d270cc87 | 40 | super(OCPPVersion.VERSION_16, ocppResponseService); |
b52c969d JB |
41 | this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>([ |
42 | [ | |
43 | OCPP16RequestCommand.AUTHORIZE, | |
130783a7 | 44 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>( |
51022aa0 | 45 | 'assets/json-schemas/ocpp/1.6/Authorize.json', |
1b271a54 JB |
46 | moduleName, |
47 | 'constructor' | |
e9a4164c | 48 | ), |
b52c969d JB |
49 | ], |
50 | [ | |
51 | OCPP16RequestCommand.BOOT_NOTIFICATION, | |
130783a7 | 52 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>( |
51022aa0 | 53 | 'assets/json-schemas/ocpp/1.6/BootNotification.json', |
1b271a54 JB |
54 | moduleName, |
55 | 'constructor' | |
e9a4164c | 56 | ), |
b52c969d JB |
57 | ], |
58 | [ | |
59 | OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, | |
130783a7 | 60 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>( |
51022aa0 | 61 | 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json', |
1b271a54 JB |
62 | moduleName, |
63 | 'constructor' | |
e9a4164c | 64 | ), |
b52c969d JB |
65 | ], |
66 | [ | |
67 | OCPP16RequestCommand.HEARTBEAT, | |
130783a7 | 68 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>( |
51022aa0 | 69 | 'assets/json-schemas/ocpp/1.6/Heartbeat.json', |
1b271a54 JB |
70 | moduleName, |
71 | 'constructor' | |
e9a4164c | 72 | ), |
b52c969d JB |
73 | ], |
74 | [ | |
75 | OCPP16RequestCommand.METER_VALUES, | |
130783a7 | 76 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>( |
51022aa0 | 77 | 'assets/json-schemas/ocpp/1.6/MeterValues.json', |
1b271a54 JB |
78 | moduleName, |
79 | 'constructor' | |
e9a4164c | 80 | ), |
b52c969d JB |
81 | ], |
82 | [ | |
83 | OCPP16RequestCommand.STATUS_NOTIFICATION, | |
130783a7 | 84 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>( |
51022aa0 | 85 | 'assets/json-schemas/ocpp/1.6/StatusNotification.json', |
1b271a54 JB |
86 | moduleName, |
87 | 'constructor' | |
e9a4164c | 88 | ), |
b52c969d JB |
89 | ], |
90 | [ | |
91 | OCPP16RequestCommand.START_TRANSACTION, | |
130783a7 | 92 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>( |
51022aa0 | 93 | 'assets/json-schemas/ocpp/1.6/StartTransaction.json', |
1b271a54 JB |
94 | moduleName, |
95 | 'constructor' | |
e9a4164c | 96 | ), |
b52c969d JB |
97 | ], |
98 | [ | |
99 | OCPP16RequestCommand.STOP_TRANSACTION, | |
130783a7 | 100 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>( |
51022aa0 | 101 | 'assets/json-schemas/ocpp/1.6/StopTransaction.json', |
1b271a54 JB |
102 | moduleName, |
103 | 'constructor' | |
e9a4164c | 104 | ), |
b52c969d | 105 | ], |
91a7d3ea JB |
106 | [ |
107 | OCPP16RequestCommand.DATA_TRANSFER, | |
130783a7 | 108 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>( |
51022aa0 | 109 | 'assets/json-schemas/ocpp/1.6/DataTransfer.json', |
1b271a54 JB |
110 | moduleName, |
111 | 'constructor' | |
e9a4164c | 112 | ), |
91a7d3ea | 113 | ], |
c9a4f9ea JB |
114 | [ |
115 | OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, | |
130783a7 | 116 | OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>( |
51022aa0 | 117 | 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json', |
1b271a54 JB |
118 | moduleName, |
119 | 'constructor' | |
e9a4164c | 120 | ), |
c9a4f9ea | 121 | ], |
b52c969d | 122 | ]); |
31f59c6d JB |
123 | this.buildRequestPayload = this.buildRequestPayload.bind(this) as <Request extends JsonType>( |
124 | chargingStation: ChargingStation, | |
125 | commandName: OCPP16RequestCommand, | |
126 | commandParams?: JsonType | |
127 | ) => Request; | |
9f2e3130 JB |
128 | } |
129 | ||
6c1761d4 | 130 | public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>( |
08f130a0 | 131 | chargingStation: ChargingStation, |
94a464f9 | 132 | commandName: OCPP16RequestCommand, |
5cc4b63b | 133 | commandParams?: JsonType, |
be9b0d50 | 134 | params?: RequestParams |
6c1761d4 | 135 | ): Promise<ResponseType> { |
62340a29 | 136 | // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc. |
ed6cfcff | 137 | if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) { |
f22266fd | 138 | return (await this.sendMessage( |
08f130a0 | 139 | chargingStation, |
9bf0ef23 | 140 | generateUUID(), |
18bf8274 | 141 | this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams), |
94a464f9 JB |
142 | commandName, |
143 | params | |
617cad0c | 144 | )) as ResponseType; |
94a464f9 | 145 | } |
e909d2a7 | 146 | // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError(). |
94a464f9 JB |
147 | throw new OCPPError( |
148 | ErrorType.NOT_SUPPORTED, | |
6c8f5d90 | 149 | `Unsupported OCPP command '${commandName}'`, |
94a464f9 | 150 | commandName, |
7369e417 | 151 | commandParams |
94a464f9 | 152 | ); |
c0560973 JB |
153 | } |
154 | ||
5cc4b63b | 155 | private buildRequestPayload<Request extends JsonType>( |
08f130a0 | 156 | chargingStation: ChargingStation, |
78085c42 | 157 | commandName: OCPP16RequestCommand, |
5cc4b63b | 158 | commandParams?: JsonType |
f22266fd | 159 | ): Request { |
68c993d5 | 160 | let connectorId: number; |
cf058664 | 161 | let energyActiveImportRegister: number; |
5cc4b63b | 162 | commandParams = commandParams as JsonObject; |
78085c42 | 163 | switch (commandName) { |
78085c42 | 164 | case OCPP16RequestCommand.BOOT_NOTIFICATION: |
78085c42 | 165 | case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION: |
22e0d48e | 166 | case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION: |
78085c42 | 167 | case OCPP16RequestCommand.METER_VALUES: |
78085c42 | 168 | case OCPP16RequestCommand.STATUS_NOTIFICATION: |
36c462a4 JB |
169 | case OCPP16RequestCommand.DATA_TRANSFER: |
170 | return commandParams as unknown as Request; | |
171 | case OCPP16RequestCommand.AUTHORIZE: | |
78085c42 | 172 | return { |
36c462a4 JB |
173 | idTag: Constants.DEFAULT_IDTAG, |
174 | ...commandParams, | |
f22266fd | 175 | } as unknown as Request; |
36c462a4 | 176 | case OCPP16RequestCommand.HEARTBEAT: |
d8b1fab1 | 177 | return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request; |
78085c42 JB |
178 | case OCPP16RequestCommand.START_TRANSACTION: |
179 | return { | |
36c462a4 JB |
180 | idTag: Constants.DEFAULT_IDTAG, |
181 | meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId( | |
18bf8274 JB |
182 | commandParams?.connectorId as number, |
183 | true | |
36c462a4 JB |
184 | ), |
185 | timestamp: new Date(), | |
186 | ...commandParams, | |
f22266fd | 187 | } as unknown as Request; |
78085c42 | 188 | case OCPP16RequestCommand.STOP_TRANSACTION: |
f1e731bd | 189 | chargingStation.getTransactionDataMeterValues() && |
f1e731bd JB |
190 | (connectorId = chargingStation.getConnectorIdByTransactionId( |
191 | commandParams?.transactionId as number | |
192 | )); | |
36c462a4 JB |
193 | energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId( |
194 | commandParams?.transactionId as number, | |
195 | true | |
196 | ); | |
78085c42 | 197 | return { |
36c462a4 JB |
198 | idTag: chargingStation.getTransactionIdTag(commandParams?.transactionId as number), |
199 | meterStop: energyActiveImportRegister, | |
200 | timestamp: new Date(), | |
201 | ...(chargingStation.getTransactionDataMeterValues() && { | |
202 | transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues( | |
203 | chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue, | |
204 | OCPP16ServiceUtils.buildTransactionEndMeterValue( | |
205 | chargingStation, | |
206 | connectorId, | |
207 | energyActiveImportRegister | |
208 | ) | |
209 | ), | |
78085c42 | 210 | }), |
36c462a4 | 211 | ...commandParams, |
f22266fd | 212 | } as unknown as Request; |
78085c42 | 213 | default: |
e909d2a7 | 214 | // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError(). |
78085c42 JB |
215 | throw new OCPPError( |
216 | ErrorType.NOT_SUPPORTED, | |
217 | // eslint-disable-next-line @typescript-eslint/restrict-template-expressions | |
6c8f5d90 | 218 | `Unsupported OCPP command '${commandName}'`, |
78085c42 | 219 | commandName, |
7369e417 | 220 | commandParams |
78085c42 JB |
221 | ); |
222 | } | |
223 | } | |
c0560973 | 224 | } |