1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
3 import type { JSONSchemaType
} from
'ajv';
5 import { OCPP16Constants
} from
'./OCPP16Constants';
6 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
7 import type { ChargingStation
} from
'../../../charging-station';
8 import { OCPPError
} from
'../../../exception';
13 type OCPP16AuthorizeRequest
,
14 type OCPP16BootNotificationRequest
,
15 type OCPP16DataTransferRequest
,
16 type OCPP16DiagnosticsStatusNotificationRequest
,
17 type OCPP16FirmwareStatusNotificationRequest
,
18 type OCPP16HeartbeatRequest
,
19 type OCPP16MeterValuesRequest
,
21 type OCPP16StartTransactionRequest
,
22 type OCPP16StatusNotificationRequest
,
23 type OCPP16StopTransactionRequest
,
26 } from
'../../../types';
28 OCPP16CancelReservationRequest
,
29 OCPP16ReserveNowRequest
,
30 } from
'../../../types/ocpp/1.6/Requests';
31 import { Constants
, Utils
} from
'../../../utils';
32 import { OCPPRequestService
} from
'../OCPPRequestService';
33 import type { OCPPResponseService
} from
'../OCPPResponseService';
35 const moduleName
= 'OCPP16RequestService';
37 export class OCPP16RequestService
extends OCPPRequestService
{
38 protected jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>;
40 public constructor(ocppResponseService
: OCPPResponseService
) {
41 // if (new.target?.name === moduleName) {
42 // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
44 super(OCPPVersion
.VERSION_16
, ocppResponseService
);
45 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>([
47 OCPP16RequestCommand
.AUTHORIZE
,
48 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeRequest
>(
49 'assets/json-schemas/ocpp/1.6/Authorize.json',
55 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
56 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationRequest
>(
57 'assets/json-schemas/ocpp/1.6/BootNotification.json',
63 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
64 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationRequest
>(
65 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
71 OCPP16RequestCommand
.HEARTBEAT
,
72 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatRequest
>(
73 'assets/json-schemas/ocpp/1.6/Heartbeat.json',
79 OCPP16RequestCommand
.METER_VALUES
,
80 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesRequest
>(
81 'assets/json-schemas/ocpp/1.6/MeterValues.json',
87 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
88 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationRequest
>(
89 'assets/json-schemas/ocpp/1.6/StatusNotification.json',
95 OCPP16RequestCommand
.START_TRANSACTION
,
96 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionRequest
>(
97 'assets/json-schemas/ocpp/1.6/StartTransaction.json',
103 OCPP16RequestCommand
.STOP_TRANSACTION
,
104 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionRequest
>(
105 'assets/json-schemas/ocpp/1.6/StopTransaction.json',
111 OCPP16RequestCommand
.DATA_TRANSFER
,
112 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferRequest
>(
113 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
119 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
120 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationRequest
>(
121 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
127 OCPP16RequestCommand
.RESERVE_NOW
,
128 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ReserveNowRequest
>(
129 'assets/json-schemas/ocpp/1.6/ReserveNow.json',
135 OCPP16RequestCommand
.CANCEL_RESERVATION
,
136 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16CancelReservationRequest
>(
137 'assets/json-schemas/ocpp/1.6/CancelReservation.json',
143 this.buildRequestPayload
= this.buildRequestPayload
.bind(this) as <Request
extends JsonType
>(
144 chargingStation
: ChargingStation
,
145 commandName
: OCPP16RequestCommand
,
146 commandParams
?: JsonType
150 public async requestHandler
<RequestType
extends JsonType
, ResponseType
extends JsonType
>(
151 chargingStation
: ChargingStation
,
152 commandName
: OCPP16RequestCommand
,
153 commandParams
?: JsonType
,
154 params
?: RequestParams
155 ): Promise
<ResponseType
> {
156 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
157 if (OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true) {
158 return (await this.sendMessage(
160 Utils
.generateUUID(),
161 this.buildRequestPayload
<RequestType
>(chargingStation
, commandName
, commandParams
),
166 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
168 ErrorType
.NOT_SUPPORTED
,
169 `Unsupported OCPP command '${commandName}'`,
175 private buildRequestPayload
<Request
extends JsonType
>(
176 chargingStation
: ChargingStation
,
177 commandName
: OCPP16RequestCommand
,
178 commandParams
?: JsonType
180 let connectorId
: number;
181 let energyActiveImportRegister
: number;
182 commandParams
= commandParams
as JsonObject
;
183 switch (commandName
) {
184 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
185 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
186 case OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
:
187 case OCPP16RequestCommand
.METER_VALUES
:
188 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
189 case OCPP16RequestCommand
.DATA_TRANSFER
:
190 return commandParams
as unknown
as Request
;
191 case OCPP16RequestCommand
.AUTHORIZE
:
193 idTag
: Constants
.DEFAULT_IDTAG
,
195 } as unknown
as Request
;
196 case OCPP16RequestCommand
.HEARTBEAT
:
197 return OCPP16Constants
.OCPP_REQUEST_EMPTY
as unknown
as Request
;
198 case OCPP16RequestCommand
.START_TRANSACTION
:
200 idTag
: Constants
.DEFAULT_IDTAG
,
201 meterStart
: chargingStation
.getEnergyActiveImportRegisterByConnectorId(
202 commandParams
?.connectorId
as number,
205 timestamp
: new Date(),
207 } as unknown
as Request
;
208 case OCPP16RequestCommand
.STOP_TRANSACTION
:
209 chargingStation
.getTransactionDataMeterValues() &&
210 (connectorId
= chargingStation
.getConnectorIdByTransactionId(
211 commandParams
?.transactionId
as number
213 energyActiveImportRegister
= chargingStation
.getEnergyActiveImportRegisterByTransactionId(
214 commandParams
?.transactionId
as number,
218 idTag
: chargingStation
.getTransactionIdTag(commandParams
?.transactionId
as number),
219 meterStop
: energyActiveImportRegister
,
220 timestamp
: new Date(),
221 ...(chargingStation
.getTransactionDataMeterValues() && {
222 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
223 chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
224 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
227 energyActiveImportRegister
232 } as unknown
as Request
;
234 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
236 ErrorType
.NOT_SUPPORTED
,
237 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
238 `Unsupported OCPP command '${commandName}'`,