1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
4 import path from
'path';
5 import { fileURLToPath
} from
'url';
7 import type { JSONSchemaType
} from
'ajv';
9 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
10 import OCPPError from
'../../../exception/OCPPError';
11 import type { JsonObject
, JsonType
} from
'../../../types/JsonType';
12 import type { OCPP16MeterValuesRequest
} from
'../../../types/ocpp/1.6/MeterValues';
14 type OCPP16BootNotificationRequest
,
15 type OCPP16DataTransferRequest
,
16 type OCPP16DiagnosticsStatusNotificationRequest
,
17 type OCPP16FirmwareStatusNotificationRequest
,
18 type OCPP16HeartbeatRequest
,
20 type OCPP16StatusNotificationRequest
,
21 } from
'../../../types/ocpp/1.6/Requests';
23 OCPP16AuthorizeRequest
,
24 OCPP16StartTransactionRequest
,
25 OCPP16StopTransactionRequest
,
26 } from
'../../../types/ocpp/1.6/Transaction';
27 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
28 import { OCPPVersion
} from
'../../../types/ocpp/OCPPVersion';
29 import type { RequestParams
} from
'../../../types/ocpp/Requests';
30 import Constants from
'../../../utils/Constants';
31 import Utils from
'../../../utils/Utils';
32 import type ChargingStation from
'../../ChargingStation';
33 import OCPPConstants from
'../OCPPConstants';
34 import OCPPRequestService from
'../OCPPRequestService';
35 import type OCPPResponseService from
'../OCPPResponseService';
37 const moduleName
= 'OCPP16RequestService';
39 export default class OCPP16RequestService
extends OCPPRequestService
{
40 protected jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>;
42 public constructor(ocppResponseService
: OCPPResponseService
) {
43 if (new.target
?.name
=== moduleName
) {
44 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
46 super(OCPPVersion
.VERSION_16
, ocppResponseService
);
47 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>([
49 OCPP16RequestCommand
.AUTHORIZE
,
50 this.parseJsonSchemaFile
<OCPP16AuthorizeRequest
>(
51 '../../../assets/json-schemas/ocpp/1.6/Authorize.json'
55 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
56 this.parseJsonSchemaFile
<OCPP16BootNotificationRequest
>(
57 '../../../assets/json-schemas/ocpp/1.6/BootNotification.json'
61 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
62 this.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationRequest
>(
63 '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json'
67 OCPP16RequestCommand
.HEARTBEAT
,
68 this.parseJsonSchemaFile
<OCPP16HeartbeatRequest
>(
69 '../../../assets/json-schemas/ocpp/1.6/Heartbeat.json'
73 OCPP16RequestCommand
.METER_VALUES
,
74 this.parseJsonSchemaFile
<OCPP16MeterValuesRequest
>(
75 '../../../assets/json-schemas/ocpp/1.6/MeterValues.json'
79 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
80 this.parseJsonSchemaFile
<OCPP16StatusNotificationRequest
>(
81 '../../../assets/json-schemas/ocpp/1.6/StatusNotification.json'
85 OCPP16RequestCommand
.START_TRANSACTION
,
86 this.parseJsonSchemaFile
<OCPP16StartTransactionRequest
>(
87 '../../../assets/json-schemas/ocpp/1.6/StartTransaction.json'
91 OCPP16RequestCommand
.STOP_TRANSACTION
,
92 this.parseJsonSchemaFile
<OCPP16StopTransactionRequest
>(
93 '../../../assets/json-schemas/ocpp/1.6/StopTransaction.json'
97 OCPP16RequestCommand
.DATA_TRANSFER
,
98 this.parseJsonSchemaFile
<OCPP16DataTransferRequest
>(
99 '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json'
103 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
104 this.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationRequest
>(
105 '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json'
109 this.buildRequestPayload
.bind(this);
112 public async requestHandler
<RequestType
extends JsonType
, ResponseType
extends JsonType
>(
113 chargingStation
: ChargingStation
,
114 commandName
: OCPP16RequestCommand
,
115 commandParams
?: JsonType
,
116 params
?: RequestParams
117 ): Promise
<ResponseType
> {
118 if (OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true) {
119 return (await this.sendMessage(
121 Utils
.generateUUID(),
122 this.buildRequestPayload
<RequestType
>(chargingStation
, commandName
, commandParams
),
125 )) as unknown
as ResponseType
;
127 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
129 ErrorType
.NOT_SUPPORTED
,
130 `Unsupported OCPP command '${commandName}'`,
136 private buildRequestPayload
<Request
extends JsonType
>(
137 chargingStation
: ChargingStation
,
138 commandName
: OCPP16RequestCommand
,
139 commandParams
?: JsonType
141 let connectorId
: number;
142 let energyActiveImportRegister
: number;
143 commandParams
= commandParams
as JsonObject
;
144 switch (commandName
) {
145 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
146 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
147 case OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
:
148 case OCPP16RequestCommand
.METER_VALUES
:
149 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
150 case OCPP16RequestCommand
.DATA_TRANSFER
:
151 return commandParams
as unknown
as Request
;
152 case OCPP16RequestCommand
.AUTHORIZE
:
154 idTag
: Constants
.DEFAULT_IDTAG
,
156 } as unknown
as Request
;
157 case OCPP16RequestCommand
.HEARTBEAT
:
158 return OCPPConstants
.OCPP_REQUEST_EMPTY
as unknown
as Request
;
159 case OCPP16RequestCommand
.START_TRANSACTION
:
161 idTag
: Constants
.DEFAULT_IDTAG
,
162 meterStart
: chargingStation
.getEnergyActiveImportRegisterByConnectorId(
163 commandParams
?.connectorId
as number,
166 timestamp
: new Date(),
168 } as unknown
as Request
;
169 case OCPP16RequestCommand
.STOP_TRANSACTION
:
170 chargingStation
.getTransactionDataMeterValues() &&
171 (connectorId
= chargingStation
.getConnectorIdByTransactionId(
172 commandParams
?.transactionId
as number
174 energyActiveImportRegister
= chargingStation
.getEnergyActiveImportRegisterByTransactionId(
175 commandParams
?.transactionId
as number,
179 idTag
: chargingStation
.getTransactionIdTag(commandParams
?.transactionId
as number),
180 meterStop
: energyActiveImportRegister
,
181 timestamp
: new Date(),
182 ...(chargingStation
.getTransactionDataMeterValues() && {
183 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
184 chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
185 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
188 energyActiveImportRegister
193 } as unknown
as Request
;
195 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
197 ErrorType
.NOT_SUPPORTED
,
198 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
199 `Unsupported OCPP command '${commandName}'`,
206 private parseJsonSchemaFile
<T
extends JsonType
>(relativePath
: string): JSONSchemaType
<T
> {
209 path
.resolve(path
.dirname(fileURLToPath(import.meta
.url
)), relativePath
),
212 ) as JSONSchemaType
<T
>;