1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
3 import type { JSONSchemaType
} from
'ajv';
5 import type { ChargingStation
} from
'../../../charging-station';
6 import { OCPPError
} from
'../../../exception';
11 type OCPP16AuthorizeRequest
,
12 type OCPP16BootNotificationRequest
,
13 type OCPP16DataTransferRequest
,
14 type OCPP16DiagnosticsStatusNotificationRequest
,
15 type OCPP16FirmwareStatusNotificationRequest
,
16 type OCPP16HeartbeatRequest
,
17 type OCPP16MeterValuesRequest
,
19 type OCPP16StartTransactionRequest
,
20 type OCPP16StatusNotificationRequest
,
21 type OCPP16StopTransactionRequest
,
24 } from
'../../../types';
25 import { Constants
, Utils
} from
'../../../utils';
30 type OCPPResponseService
,
33 const moduleName
= 'OCPP16RequestService';
35 export class OCPP16RequestService
extends OCPPRequestService
{
36 protected jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>;
38 public constructor(ocppResponseService
: OCPPResponseService
) {
39 // if (new.target?.name === moduleName) {
40 // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
42 super(OCPPVersion
.VERSION_16
, ocppResponseService
);
43 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>([
45 OCPP16RequestCommand
.AUTHORIZE
,
46 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeRequest
>(
47 '../../../assets/json-schemas/ocpp/1.6/Authorize.json',
53 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
54 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationRequest
>(
55 '../../../assets/json-schemas/ocpp/1.6/BootNotification.json',
61 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
62 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationRequest
>(
63 '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
69 OCPP16RequestCommand
.HEARTBEAT
,
70 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatRequest
>(
71 '../../../assets/json-schemas/ocpp/1.6/Heartbeat.json',
77 OCPP16RequestCommand
.METER_VALUES
,
78 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesRequest
>(
79 '../../../assets/json-schemas/ocpp/1.6/MeterValues.json',
85 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
86 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationRequest
>(
87 '../../../assets/json-schemas/ocpp/1.6/StatusNotification.json',
93 OCPP16RequestCommand
.START_TRANSACTION
,
94 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionRequest
>(
95 '../../../assets/json-schemas/ocpp/1.6/StartTransaction.json',
101 OCPP16RequestCommand
.STOP_TRANSACTION
,
102 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionRequest
>(
103 '../../../assets/json-schemas/ocpp/1.6/StopTransaction.json',
109 OCPP16RequestCommand
.DATA_TRANSFER
,
110 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferRequest
>(
111 '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json',
117 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
118 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationRequest
>(
119 '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
125 this.buildRequestPayload
= this.buildRequestPayload
.bind(this) as <Request
extends JsonType
>(
126 chargingStation
: ChargingStation
,
127 commandName
: OCPP16RequestCommand
,
128 commandParams
?: JsonType
132 public async requestHandler
<RequestType
extends JsonType
, ResponseType
extends JsonType
>(
133 chargingStation
: ChargingStation
,
134 commandName
: OCPP16RequestCommand
,
135 commandParams
?: JsonType
,
136 params
?: RequestParams
137 ): Promise
<ResponseType
> {
138 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
139 if (OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true) {
140 return (await this.sendMessage(
142 Utils
.generateUUID(),
143 this.buildRequestPayload
<RequestType
>(chargingStation
, commandName
, commandParams
),
148 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
150 ErrorType
.NOT_SUPPORTED
,
151 `Unsupported OCPP command '${commandName}'`,
157 private buildRequestPayload
<Request
extends JsonType
>(
158 chargingStation
: ChargingStation
,
159 commandName
: OCPP16RequestCommand
,
160 commandParams
?: JsonType
162 let connectorId
: number;
163 let energyActiveImportRegister
: number;
164 commandParams
= commandParams
as JsonObject
;
165 switch (commandName
) {
166 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
167 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
168 case OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
:
169 case OCPP16RequestCommand
.METER_VALUES
:
170 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
171 case OCPP16RequestCommand
.DATA_TRANSFER
:
172 return commandParams
as unknown
as Request
;
173 case OCPP16RequestCommand
.AUTHORIZE
:
175 idTag
: Constants
.DEFAULT_IDTAG
,
177 } as unknown
as Request
;
178 case OCPP16RequestCommand
.HEARTBEAT
:
179 return OCPP16Constants
.OCPP_REQUEST_EMPTY
as unknown
as Request
;
180 case OCPP16RequestCommand
.START_TRANSACTION
:
182 idTag
: Constants
.DEFAULT_IDTAG
,
183 meterStart
: chargingStation
.getEnergyActiveImportRegisterByConnectorId(
184 commandParams
?.connectorId
as number,
187 timestamp
: new Date(),
189 } as unknown
as Request
;
190 case OCPP16RequestCommand
.STOP_TRANSACTION
:
191 chargingStation
.getTransactionDataMeterValues() &&
192 (connectorId
= chargingStation
.getConnectorIdByTransactionId(
193 commandParams
?.transactionId
as number
195 energyActiveImportRegister
= chargingStation
.getEnergyActiveImportRegisterByTransactionId(
196 commandParams
?.transactionId
as number,
200 idTag
: chargingStation
.getTransactionIdTag(commandParams
?.transactionId
as number),
201 meterStop
: energyActiveImportRegister
,
202 timestamp
: new Date(),
203 ...(chargingStation
.getTransactionDataMeterValues() && {
204 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
205 chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
206 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
209 energyActiveImportRegister
214 } as unknown
as Request
;
216 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
218 ErrorType
.NOT_SUPPORTED
,
219 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
220 `Unsupported OCPP command '${commandName}'`,