Remove now useless Date conversions to string
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 2.0 / OCPP20ResponseService.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
953d6b02 2
d270cc87
JB
3import fs from 'fs';
4import path from 'path';
5import { fileURLToPath } from 'url';
6
953d6b02
JB
7import type { JSONSchemaType } from 'ajv';
8
9import OCPPError from '../../../exception/OCPPError';
10import type { JsonObject, JsonType } from '../../../types/JsonType';
d270cc87
JB
11import { OCPP20RequestCommand } from '../../../types/ocpp/2.0/Requests';
12import type { OCPP20BootNotificationResponse } from '../../../types/ocpp/2.0/Responses';
953d6b02 13import { ErrorType } from '../../../types/ocpp/ErrorType';
d270cc87
JB
14import { OCPPVersion } from '../../../types/ocpp/OCPPVersion';
15import { RegistrationStatusEnumType, ResponseHandler } from '../../../types/ocpp/Responses';
953d6b02
JB
16import logger from '../../../utils/Logger';
17import type ChargingStation from '../../ChargingStation';
18import OCPPResponseService from '../OCPPResponseService';
19import { OCPP20ServiceUtils } from './OCPP20ServiceUtils';
20
21const moduleName = 'OCPP20ResponseService';
22
23export default class OCPP20ResponseService extends OCPPResponseService {
24 private responseHandlers: Map<OCPP20RequestCommand, ResponseHandler>;
25 private jsonSchemas: Map<OCPP20RequestCommand, JSONSchemaType<JsonObject>>;
26
27 public constructor() {
28 if (new.target?.name === moduleName) {
29 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
30 }
d270cc87
JB
31 super(OCPPVersion.VERSION_20);
32 this.responseHandlers = new Map<OCPP20RequestCommand, ResponseHandler>([
33 [OCPP20RequestCommand.BOOT_NOTIFICATION, this.handleResponseBootNotification.bind(this)],
34 ]);
35 this.jsonSchemas = new Map<OCPP20RequestCommand, JSONSchemaType<JsonObject>>([
36 [
37 OCPP20RequestCommand.BOOT_NOTIFICATION,
38 JSON.parse(
39 fs.readFileSync(
40 path.resolve(
41 path.dirname(fileURLToPath(import.meta.url)),
42 '../../../assets/json-schemas/ocpp/2.0/BootNotificationResponse.json'
43 ),
44 'utf8'
45 )
46 ) as JSONSchemaType<OCPP20BootNotificationResponse>,
47 ],
48 ]);
953d6b02
JB
49 this.validatePayload.bind(this);
50 }
51
52 public async responseHandler(
53 chargingStation: ChargingStation,
54 commandName: OCPP20RequestCommand,
55 payload: JsonType,
56 requestPayload: JsonType
57 ): Promise<void> {
58 if (
d270cc87
JB
59 chargingStation.isRegistered() === true ||
60 commandName === OCPP20RequestCommand.BOOT_NOTIFICATION
953d6b02
JB
61 ) {
62 if (
63 this.responseHandlers.has(commandName) === true &&
64 OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true
65 ) {
66 try {
67 this.validatePayload(chargingStation, commandName, payload);
68 await this.responseHandlers.get(commandName)(chargingStation, payload, requestPayload);
69 } catch (error) {
70 logger.error(
71 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
72 error
73 );
74 throw error;
75 }
76 } else {
77 // Throw exception
78 throw new OCPPError(
79 ErrorType.NOT_IMPLEMENTED,
80 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
81 payload,
82 null,
83 2
84 )}`,
85 commandName,
86 payload
87 );
88 }
89 } else {
90 throw new OCPPError(
91 ErrorType.SECURITY_ERROR,
92 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
93 payload,
94 null,
95 2
439fc71b 96 )} while the charging station is not registered on the central server.`,
953d6b02
JB
97 commandName,
98 payload
99 );
100 }
101 }
102
103 private validatePayload(
104 chargingStation: ChargingStation,
105 commandName: OCPP20RequestCommand,
106 payload: JsonType
107 ): boolean {
108 if (this.jsonSchemas.has(commandName)) {
109 return this.validateResponsePayload(
110 chargingStation,
111 commandName,
112 this.jsonSchemas.get(commandName),
113 payload
114 );
115 }
116 logger.warn(
117 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command ${commandName} PDU validation`
118 );
119 return false;
120 }
d270cc87
JB
121
122 private handleResponseBootNotification(
123 chargingStation: ChargingStation,
124 payload: OCPP20BootNotificationResponse
125 ): void {
126 if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
127 // ChargingStationConfigurationUtils.addConfigurationKey(
128 // chargingStation,
129 // OCPP16StandardParametersKey.HeartbeatInterval,
130 // payload.interval.toString(),
131 // {},
132 // { overwrite: true, save: true }
133 // );
134 // ChargingStationConfigurationUtils.addConfigurationKey(
135 // chargingStation,
136 // OCPP16StandardParametersKey.HeartBeatInterval,
137 // payload.interval.toString(),
138 // { visible: false },
139 // { overwrite: true, save: true }
140 // );
141 chargingStation.heartbeatSetInterval
142 ? chargingStation.restartHeartbeat()
143 : chargingStation.startHeartbeat();
144 }
145 if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
146 const logMsg = `${chargingStation.logPrefix()} Charging station in '${
147 payload.status
148 }' state on the central server`;
149 payload.status === RegistrationStatusEnumType.REJECTED
150 ? logger.warn(logMsg)
151 : logger.info(logMsg);
152 } else {
153 logger.error(
154 chargingStation.logPrefix() +
155 ' Charging station boot notification response received: %j with undefined registration status',
156 payload
157 );
158 }
159 }
953d6b02 160}