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 OCPPError from
'../../../exception/OCPPError';
10 import type { JsonObject
, JsonType
} from
'../../../types/JsonType';
11 import { OCPP20RequestCommand
} from
'../../../types/ocpp/2.0/Requests';
12 import type { OCPP20BootNotificationResponse
} from
'../../../types/ocpp/2.0/Responses';
13 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
14 import { OCPPVersion
} from
'../../../types/ocpp/OCPPVersion';
15 import { RegistrationStatusEnumType
, ResponseHandler
} from
'../../../types/ocpp/Responses';
16 import logger from
'../../../utils/Logger';
17 import type ChargingStation from
'../../ChargingStation';
18 import OCPPResponseService from
'../OCPPResponseService';
19 import { OCPP20ServiceUtils
} from
'./OCPP20ServiceUtils';
21 const moduleName
= 'OCPP20ResponseService';
23 export default class OCPP20ResponseService
extends OCPPResponseService
{
24 private responseHandlers
: Map
<OCPP20RequestCommand
, ResponseHandler
>;
25 private jsonSchemas
: Map
<OCPP20RequestCommand
, JSONSchemaType
<JsonObject
>>;
27 public constructor() {
28 if (new.target
?.name
=== moduleName
) {
29 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
31 super(OCPPVersion
.VERSION_20
);
32 this.responseHandlers
= new Map
<OCPP20RequestCommand
, ResponseHandler
>([
33 [OCPP20RequestCommand
.BOOT_NOTIFICATION
, this.handleResponseBootNotification
.bind(this)],
35 this.jsonSchemas
= new Map
<OCPP20RequestCommand
, JSONSchemaType
<JsonObject
>>([
37 OCPP20RequestCommand
.BOOT_NOTIFICATION
,
41 path
.dirname(fileURLToPath(import.meta
.url
)),
42 '../../../assets/json-schemas/ocpp/2.0/BootNotificationResponse.json'
46 ) as JSONSchemaType
<OCPP20BootNotificationResponse
>,
49 this.validatePayload
.bind(this);
52 public async responseHandler(
53 chargingStation
: ChargingStation
,
54 commandName
: OCPP20RequestCommand
,
56 requestPayload
: JsonType
59 chargingStation
.isRegistered() === true ||
60 commandName
=== OCPP20RequestCommand
.BOOT_NOTIFICATION
63 this.responseHandlers
.has(commandName
) === true &&
64 OCPP20ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true
67 this.validatePayload(chargingStation
, commandName
, payload
);
68 await this.responseHandlers
.get(commandName
)(chargingStation
, payload
, requestPayload
);
71 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
79 ErrorType
.NOT_IMPLEMENTED
,
80 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
91 ErrorType
.SECURITY_ERROR
,
92 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
96 )} while the charging station is not registered on the central server.`,
103 private validatePayload(
104 chargingStation
: ChargingStation
,
105 commandName
: OCPP20RequestCommand
,
108 if (this.jsonSchemas
.has(commandName
) === true) {
109 return this.validateResponsePayload(
112 this.jsonSchemas
.get(commandName
),
117 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command ${commandName} PDU validation`
122 private handleResponseBootNotification(
123 chargingStation
: ChargingStation
,
124 payload
: OCPP20BootNotificationResponse
126 if (payload
.status === RegistrationStatusEnumType
.ACCEPTED
) {
127 // ChargingStationConfigurationUtils.addConfigurationKey(
129 // OCPP16StandardParametersKey.HeartbeatInterval,
130 // payload.interval.toString(),
132 // { overwrite: true, save: true }
134 // ChargingStationConfigurationUtils.addConfigurationKey(
136 // OCPP16StandardParametersKey.HeartBeatInterval,
137 // payload.interval.toString(),
138 // { visible: false },
139 // { overwrite: true, save: true }
141 chargingStation
.heartbeatSetInterval
142 ? chargingStation
.restartHeartbeat()
143 : chargingStation
.startHeartbeat();
145 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
146 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
148 }' state on the central server`;
149 payload
.status === RegistrationStatusEnumType
.REJECTED
150 ? logger
.warn(logMsg
)
151 : logger
.info(logMsg
);
154 chargingStation
.logPrefix() +
155 ' Charging station boot notification response received: %j with undefined registration status',