1ad01827f1519aef033590f68254323484dc1fab
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16IncomingRequestService.ts
1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
2
3 import fs from 'fs';
4 import path from 'path';
5 import { URL, fileURLToPath } from 'url';
6
7 import type { JSONSchemaType } from 'ajv';
8 import { Client, FTPResponse } from 'basic-ftp';
9 import tar from 'tar';
10
11 import OCPPError from '../../../exception/OCPPError';
12 import type { JsonObject, JsonType } from '../../../types/JsonType';
13 import { OCPP16ChargePointErrorCode } from '../../../types/ocpp/1.6/ChargePointErrorCode';
14 import { OCPP16ChargePointStatus } from '../../../types/ocpp/1.6/ChargePointStatus';
15 import {
16 ChargingProfilePurposeType,
17 OCPP16ChargingProfile,
18 } from '../../../types/ocpp/1.6/ChargingProfile';
19 import {
20 OCPP16StandardParametersKey,
21 OCPP16SupportedFeatureProfiles,
22 } from '../../../types/ocpp/1.6/Configuration';
23 import { OCPP16DiagnosticsStatus } from '../../../types/ocpp/1.6/DiagnosticsStatus';
24 import {
25 ChangeAvailabilityRequest,
26 ChangeConfigurationRequest,
27 ClearChargingProfileRequest,
28 DiagnosticsStatusNotificationRequest,
29 GetConfigurationRequest,
30 GetDiagnosticsRequest,
31 MessageTrigger,
32 OCPP16AvailabilityType,
33 OCPP16BootNotificationRequest,
34 OCPP16ClearCacheRequest,
35 OCPP16HeartbeatRequest,
36 OCPP16IncomingRequestCommand,
37 OCPP16RequestCommand,
38 OCPP16StatusNotificationRequest,
39 OCPP16TriggerMessageRequest,
40 RemoteStartTransactionRequest,
41 RemoteStopTransactionRequest,
42 ResetRequest,
43 SetChargingProfileRequest,
44 UnlockConnectorRequest,
45 } from '../../../types/ocpp/1.6/Requests';
46 import type {
47 ChangeAvailabilityResponse,
48 ChangeConfigurationResponse,
49 ClearChargingProfileResponse,
50 DiagnosticsStatusNotificationResponse,
51 GetConfigurationResponse,
52 GetDiagnosticsResponse,
53 OCPP16BootNotificationResponse,
54 OCPP16HeartbeatResponse,
55 OCPP16StatusNotificationResponse,
56 OCPP16TriggerMessageResponse,
57 SetChargingProfileResponse,
58 UnlockConnectorResponse,
59 } from '../../../types/ocpp/1.6/Responses';
60 import {
61 OCPP16AuthorizationStatus,
62 OCPP16AuthorizeRequest,
63 OCPP16AuthorizeResponse,
64 OCPP16StartTransactionRequest,
65 OCPP16StartTransactionResponse,
66 OCPP16StopTransactionReason,
67 } from '../../../types/ocpp/1.6/Transaction';
68 import type { OCPPConfigurationKey } from '../../../types/ocpp/Configuration';
69 import { ErrorType } from '../../../types/ocpp/ErrorType';
70 import type { IncomingRequestHandler } from '../../../types/ocpp/Requests';
71 import type { DefaultResponse } from '../../../types/ocpp/Responses';
72 import Constants from '../../../utils/Constants';
73 import logger from '../../../utils/Logger';
74 import Utils from '../../../utils/Utils';
75 import type ChargingStation from '../../ChargingStation';
76 import { ChargingStationConfigurationUtils } from '../../ChargingStationConfigurationUtils';
77 import { ChargingStationUtils } from '../../ChargingStationUtils';
78 import OCPPIncomingRequestService from '../OCPPIncomingRequestService';
79 import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
80
81 const moduleName = 'OCPP16IncomingRequestService';
82
83 export default class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
84 private incomingRequestHandlers: Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>;
85 private jsonSchemas: Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonObject>>;
86
87 public constructor() {
88 if (new.target?.name === moduleName) {
89 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
90 }
91 super();
92 this.incomingRequestHandlers = new Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>([
93 [OCPP16IncomingRequestCommand.RESET, this.handleRequestReset.bind(this)],
94 [OCPP16IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)],
95 [OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR, this.handleRequestUnlockConnector.bind(this)],
96 [
97 OCPP16IncomingRequestCommand.GET_CONFIGURATION,
98 this.handleRequestGetConfiguration.bind(this),
99 ],
100 [
101 OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
102 this.handleRequestChangeConfiguration.bind(this),
103 ],
104 [
105 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
106 this.handleRequestSetChargingProfile.bind(this),
107 ],
108 [
109 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
110 this.handleRequestClearChargingProfile.bind(this),
111 ],
112 [
113 OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
114 this.handleRequestChangeAvailability.bind(this),
115 ],
116 [
117 OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
118 this.handleRequestRemoteStartTransaction.bind(this),
119 ],
120 [
121 OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
122 this.handleRequestRemoteStopTransaction.bind(this),
123 ],
124 [OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, this.handleRequestGetDiagnostics.bind(this)],
125 [OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, this.handleRequestTriggerMessage.bind(this)],
126 ]);
127 this.jsonSchemas = new Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonObject>>([
128 [
129 OCPP16IncomingRequestCommand.RESET,
130 JSON.parse(
131 fs.readFileSync(
132 path.resolve(
133 path.dirname(fileURLToPath(import.meta.url)),
134 '../../../assets/json-schemas/ocpp/1.6/Reset.json'
135 ),
136 'utf8'
137 )
138 ) as JSONSchemaType<ResetRequest>,
139 ],
140 [
141 OCPP16IncomingRequestCommand.CLEAR_CACHE,
142 JSON.parse(
143 fs.readFileSync(
144 path.resolve(
145 path.dirname(fileURLToPath(import.meta.url)),
146 '../../../assets/json-schemas/ocpp/1.6/ClearCache.json'
147 ),
148 'utf8'
149 )
150 ) as JSONSchemaType<OCPP16ClearCacheRequest>,
151 ],
152 [
153 OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
154 JSON.parse(
155 fs.readFileSync(
156 path.resolve(
157 path.dirname(fileURLToPath(import.meta.url)),
158 '../../../assets/json-schemas/ocpp/1.6/UnlockConnector.json'
159 ),
160 'utf8'
161 )
162 ) as JSONSchemaType<UnlockConnectorRequest>,
163 ],
164 [
165 OCPP16IncomingRequestCommand.GET_CONFIGURATION,
166 JSON.parse(
167 fs.readFileSync(
168 path.resolve(
169 path.dirname(fileURLToPath(import.meta.url)),
170 '../../../assets/json-schemas/ocpp/1.6/GetConfiguration.json'
171 ),
172 'utf8'
173 )
174 ) as JSONSchemaType<GetConfigurationRequest>,
175 ],
176 [
177 OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
178 JSON.parse(
179 fs.readFileSync(
180 path.resolve(
181 path.dirname(fileURLToPath(import.meta.url)),
182 '../../../assets/json-schemas/ocpp/1.6/ChangeConfiguration.json'
183 ),
184 'utf8'
185 )
186 ) as JSONSchemaType<ChangeConfigurationRequest>,
187 ],
188 [
189 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
190 JSON.parse(
191 fs.readFileSync(
192 path.resolve(
193 path.dirname(fileURLToPath(import.meta.url)),
194 '../../../assets/json-schemas/ocpp/1.6/GetDiagnostics.json'
195 ),
196 'utf8'
197 )
198 ) as JSONSchemaType<GetDiagnosticsRequest>,
199 ],
200 [
201 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
202 JSON.parse(
203 fs.readFileSync(
204 path.resolve(
205 path.dirname(fileURLToPath(import.meta.url)),
206 '../../../assets/json-schemas/ocpp/1.6/SetChargingProfile.json'
207 ),
208 'utf8'
209 )
210 ) as JSONSchemaType<SetChargingProfileRequest>,
211 ],
212 [
213 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
214 JSON.parse(
215 fs.readFileSync(
216 path.resolve(
217 path.dirname(fileURLToPath(import.meta.url)),
218 '../../../assets/json-schemas/ocpp/1.6/ClearChargingProfile.json'
219 ),
220 'utf8'
221 )
222 ) as JSONSchemaType<ClearChargingProfileRequest>,
223 ],
224 [
225 OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
226 JSON.parse(
227 fs.readFileSync(
228 path.resolve(
229 path.dirname(fileURLToPath(import.meta.url)),
230 '../../../assets/json-schemas/ocpp/1.6/ChangeAvailability.json'
231 ),
232 'utf8'
233 )
234 ) as JSONSchemaType<ChangeAvailabilityRequest>,
235 ],
236 [
237 OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
238 JSON.parse(
239 fs.readFileSync(
240 path.resolve(
241 path.dirname(fileURLToPath(import.meta.url)),
242 '../../../assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json'
243 ),
244 'utf8'
245 )
246 ) as JSONSchemaType<RemoteStartTransactionRequest>,
247 ],
248 [
249 OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
250 JSON.parse(
251 fs.readFileSync(
252 path.resolve(
253 path.dirname(fileURLToPath(import.meta.url)),
254 '../../../assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json'
255 ),
256 'utf8'
257 )
258 ) as JSONSchemaType<RemoteStopTransactionRequest>,
259 ],
260 [
261 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
262 JSON.parse(
263 fs.readFileSync(
264 path.resolve(
265 path.dirname(fileURLToPath(import.meta.url)),
266 '../../../assets/json-schemas/ocpp/1.6/TriggerMessage.json'
267 ),
268 'utf8'
269 )
270 ) as JSONSchemaType<OCPP16TriggerMessageRequest>,
271 ],
272 ]);
273 this.validatePayload.bind(this);
274 }
275
276 public async incomingRequestHandler(
277 chargingStation: ChargingStation,
278 messageId: string,
279 commandName: OCPP16IncomingRequestCommand,
280 commandPayload: JsonType
281 ): Promise<void> {
282 let response: JsonType;
283 if (
284 chargingStation.getOcppStrictCompliance() &&
285 chargingStation.isInPendingState() &&
286 (commandName === OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION ||
287 commandName === OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION)
288 ) {
289 throw new OCPPError(
290 ErrorType.SECURITY_ERROR,
291 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
292 commandPayload,
293 null,
294 2
295 )} while the charging station is in pending state on the central server`,
296 commandName,
297 commandPayload
298 );
299 }
300 if (
301 chargingStation.isRegistered() === true ||
302 (chargingStation.getOcppStrictCompliance() === false &&
303 chargingStation.isInUnknownState() === true)
304 ) {
305 if (
306 this.incomingRequestHandlers.has(commandName) === true &&
307 OCPP16ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName) === true
308 ) {
309 try {
310 this.validatePayload(chargingStation, commandName, commandPayload);
311 // Call the method to build the response
312 response = await this.incomingRequestHandlers.get(commandName)(
313 chargingStation,
314 commandPayload
315 );
316 } catch (error) {
317 // Log
318 logger.error(
319 `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
320 error
321 );
322 throw error;
323 }
324 } else {
325 // Throw exception
326 throw new OCPPError(
327 ErrorType.NOT_IMPLEMENTED,
328 `${commandName} is not implemented to handle request PDU ${JSON.stringify(
329 commandPayload,
330 null,
331 2
332 )}`,
333 commandName,
334 commandPayload
335 );
336 }
337 } else {
338 throw new OCPPError(
339 ErrorType.SECURITY_ERROR,
340 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
341 commandPayload,
342 null,
343 2
344 )} while the charging station is not registered on the central server.`,
345 commandName,
346 commandPayload
347 );
348 }
349 // Send the built response
350 await chargingStation.ocppRequestService.sendResponse(
351 chargingStation,
352 messageId,
353 response,
354 commandName
355 );
356 }
357
358 private validatePayload(
359 chargingStation: ChargingStation,
360 commandName: OCPP16IncomingRequestCommand,
361 commandPayload: JsonType
362 ): boolean {
363 if (this.jsonSchemas.has(commandName)) {
364 return this.validateIncomingRequestPayload(
365 chargingStation,
366 commandName,
367 this.jsonSchemas.get(commandName),
368 commandPayload
369 );
370 }
371 logger.warn(
372 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command ${commandName} PDU validation`
373 );
374 return false;
375 }
376
377 // Simulate charging station restart
378 private handleRequestReset(
379 chargingStation: ChargingStation,
380 commandPayload: ResetRequest
381 ): DefaultResponse {
382 this.asyncResource
383 .runInAsyncScope(
384 chargingStation.reset.bind(chargingStation) as (
385 this: ChargingStation,
386 ...args: any[]
387 ) => Promise<void>,
388 chargingStation,
389 (commandPayload.type + 'Reset') as OCPP16StopTransactionReason
390 )
391 .catch(() => {
392 /* This is intentional */
393 });
394 logger.info(
395 `${chargingStation.logPrefix()} ${
396 commandPayload.type
397 } reset command received, simulating it. The station will be back online in ${Utils.formatDurationMilliSeconds(
398 chargingStation.stationInfo.resetTime
399 )}`
400 );
401 return Constants.OCPP_RESPONSE_ACCEPTED;
402 }
403
404 private handleRequestClearCache(chargingStation: ChargingStation): DefaultResponse {
405 chargingStation.authorizedTagsCache.deleteAuthorizedTags(
406 ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo)
407 );
408 return Constants.OCPP_RESPONSE_ACCEPTED;
409 }
410
411 private async handleRequestUnlockConnector(
412 chargingStation: ChargingStation,
413 commandPayload: UnlockConnectorRequest
414 ): Promise<UnlockConnectorResponse> {
415 const connectorId = commandPayload.connectorId;
416 if (connectorId === 0) {
417 logger.error(
418 chargingStation.logPrefix() + ' Trying to unlock connector ' + connectorId.toString()
419 );
420 return Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
421 }
422 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
423 const stopResponse = await chargingStation.stopTransactionOnConnector(
424 connectorId,
425 OCPP16StopTransactionReason.UNLOCK_COMMAND
426 );
427 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
428 return Constants.OCPP_RESPONSE_UNLOCKED;
429 }
430 return Constants.OCPP_RESPONSE_UNLOCK_FAILED;
431 }
432 await chargingStation.ocppRequestService.requestHandler<
433 OCPP16StatusNotificationRequest,
434 OCPP16StatusNotificationResponse
435 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
436 connectorId,
437 status: OCPP16ChargePointStatus.AVAILABLE,
438 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
439 });
440 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE;
441 return Constants.OCPP_RESPONSE_UNLOCKED;
442 }
443
444 private handleRequestGetConfiguration(
445 chargingStation: ChargingStation,
446 commandPayload: GetConfigurationRequest
447 ): GetConfigurationResponse {
448 const configurationKey: OCPPConfigurationKey[] = [];
449 const unknownKey: string[] = [];
450 if (Utils.isEmptyArray(commandPayload.key) === true) {
451 for (const configuration of chargingStation.ocppConfiguration.configurationKey) {
452 if (Utils.isUndefined(configuration.visible) === true) {
453 configuration.visible = true;
454 }
455 if (configuration.visible === false) {
456 continue;
457 }
458 configurationKey.push({
459 key: configuration.key,
460 readonly: configuration.readonly,
461 value: configuration.value,
462 });
463 }
464 } else {
465 for (const key of commandPayload.key) {
466 const keyFound = ChargingStationConfigurationUtils.getConfigurationKey(
467 chargingStation,
468 key
469 );
470 if (keyFound) {
471 if (Utils.isUndefined(keyFound.visible) === true) {
472 keyFound.visible = true;
473 }
474 if (keyFound.visible === false) {
475 continue;
476 }
477 configurationKey.push({
478 key: keyFound.key,
479 readonly: keyFound.readonly,
480 value: keyFound.value,
481 });
482 } else {
483 unknownKey.push(key);
484 }
485 }
486 }
487 return {
488 configurationKey,
489 unknownKey,
490 };
491 }
492
493 private handleRequestChangeConfiguration(
494 chargingStation: ChargingStation,
495 commandPayload: ChangeConfigurationRequest
496 ): ChangeConfigurationResponse {
497 const keyToChange = ChargingStationConfigurationUtils.getConfigurationKey(
498 chargingStation,
499 commandPayload.key,
500 true
501 );
502 if (!keyToChange) {
503 return Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED;
504 } else if (keyToChange && keyToChange.readonly) {
505 return Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED;
506 } else if (keyToChange && !keyToChange.readonly) {
507 let valueChanged = false;
508 if (keyToChange.value !== commandPayload.value) {
509 ChargingStationConfigurationUtils.setConfigurationKeyValue(
510 chargingStation,
511 commandPayload.key,
512 commandPayload.value,
513 true
514 );
515 valueChanged = true;
516 }
517 let triggerHeartbeatRestart = false;
518 if (keyToChange.key === OCPP16StandardParametersKey.HeartBeatInterval && valueChanged) {
519 ChargingStationConfigurationUtils.setConfigurationKeyValue(
520 chargingStation,
521 OCPP16StandardParametersKey.HeartbeatInterval,
522 commandPayload.value
523 );
524 triggerHeartbeatRestart = true;
525 }
526 if (keyToChange.key === OCPP16StandardParametersKey.HeartbeatInterval && valueChanged) {
527 ChargingStationConfigurationUtils.setConfigurationKeyValue(
528 chargingStation,
529 OCPP16StandardParametersKey.HeartBeatInterval,
530 commandPayload.value
531 );
532 triggerHeartbeatRestart = true;
533 }
534 if (triggerHeartbeatRestart) {
535 chargingStation.restartHeartbeat();
536 }
537 if (keyToChange.key === OCPP16StandardParametersKey.WebSocketPingInterval && valueChanged) {
538 chargingStation.restartWebSocketPing();
539 }
540 if (keyToChange.reboot) {
541 return Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED;
542 }
543 return Constants.OCPP_CONFIGURATION_RESPONSE_ACCEPTED;
544 }
545 }
546
547 private handleRequestSetChargingProfile(
548 chargingStation: ChargingStation,
549 commandPayload: SetChargingProfileRequest
550 ): SetChargingProfileResponse {
551 if (
552 OCPP16ServiceUtils.checkFeatureProfile(
553 chargingStation,
554 OCPP16SupportedFeatureProfiles.SmartCharging,
555 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
556 ) === false
557 ) {
558 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED;
559 }
560 if (chargingStation.connectors.has(commandPayload.connectorId) === false) {
561 logger.error(
562 `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector Id ${
563 commandPayload.connectorId
564 }`
565 );
566 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
567 }
568 if (
569 commandPayload.csChargingProfiles.chargingProfilePurpose ===
570 ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
571 commandPayload.connectorId !== 0
572 ) {
573 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
574 }
575 if (
576 commandPayload.csChargingProfiles.chargingProfilePurpose ===
577 ChargingProfilePurposeType.TX_PROFILE &&
578 (commandPayload.connectorId === 0 ||
579 chargingStation.getConnectorStatus(commandPayload.connectorId)?.transactionStarted ===
580 false)
581 ) {
582 logger.error(
583 `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${
584 commandPayload.connectorId
585 } without a started transaction`
586 );
587 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
588 }
589 OCPP16ServiceUtils.setChargingProfile(
590 chargingStation,
591 commandPayload.connectorId,
592 commandPayload.csChargingProfiles
593 );
594 logger.debug(
595 `${chargingStation.logPrefix()} Charging profile(s) set on connector id ${
596 commandPayload.connectorId
597 }, dump their stack: %j`,
598 chargingStation.getConnectorStatus(commandPayload.connectorId).chargingProfiles
599 );
600 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED;
601 }
602
603 private handleRequestClearChargingProfile(
604 chargingStation: ChargingStation,
605 commandPayload: ClearChargingProfileRequest
606 ): ClearChargingProfileResponse {
607 if (
608 OCPP16ServiceUtils.checkFeatureProfile(
609 chargingStation,
610 OCPP16SupportedFeatureProfiles.SmartCharging,
611 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
612 ) === false
613 ) {
614 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
615 }
616 if (chargingStation.connectors.has(commandPayload.connectorId) === false) {
617 logger.error(
618 `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector Id ${
619 commandPayload.connectorId
620 }`
621 );
622 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
623 }
624 const connectorStatus = chargingStation.getConnectorStatus(commandPayload.connectorId);
625 if (commandPayload.connectorId && !Utils.isEmptyArray(connectorStatus.chargingProfiles)) {
626 connectorStatus.chargingProfiles = [];
627 logger.debug(
628 `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${
629 commandPayload.connectorId
630 }, dump their stack: %j`,
631 connectorStatus.chargingProfiles
632 );
633 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
634 }
635 if (!commandPayload.connectorId) {
636 let clearedCP = false;
637 for (const connectorId of chargingStation.connectors.keys()) {
638 if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
639 chargingStation
640 .getConnectorStatus(connectorId)
641 .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
642 let clearCurrentCP = false;
643 if (chargingProfile.chargingProfileId === commandPayload.id) {
644 clearCurrentCP = true;
645 }
646 if (
647 !commandPayload.chargingProfilePurpose &&
648 chargingProfile.stackLevel === commandPayload.stackLevel
649 ) {
650 clearCurrentCP = true;
651 }
652 if (
653 !chargingProfile.stackLevel &&
654 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
655 ) {
656 clearCurrentCP = true;
657 }
658 if (
659 chargingProfile.stackLevel === commandPayload.stackLevel &&
660 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
661 ) {
662 clearCurrentCP = true;
663 }
664 if (clearCurrentCP) {
665 connectorStatus.chargingProfiles.splice(index, 1);
666 logger.debug(
667 `${chargingStation.logPrefix()} Matching charging profile(s) cleared on connector id ${
668 commandPayload.connectorId
669 }, dump their stack: %j`,
670 connectorStatus.chargingProfiles
671 );
672 clearedCP = true;
673 }
674 });
675 }
676 }
677 if (clearedCP) {
678 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
679 }
680 }
681 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
682 }
683
684 private async handleRequestChangeAvailability(
685 chargingStation: ChargingStation,
686 commandPayload: ChangeAvailabilityRequest
687 ): Promise<ChangeAvailabilityResponse> {
688 const connectorId: number = commandPayload.connectorId;
689 if (!chargingStation.getConnectorStatus(connectorId)) {
690 logger.error(
691 `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector Id ${connectorId.toString()}`
692 );
693 return Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
694 }
695 const chargePointStatus: OCPP16ChargePointStatus =
696 commandPayload.type === OCPP16AvailabilityType.OPERATIVE
697 ? OCPP16ChargePointStatus.AVAILABLE
698 : OCPP16ChargePointStatus.UNAVAILABLE;
699 if (connectorId === 0) {
700 let response: ChangeAvailabilityResponse = Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
701 for (const id of chargingStation.connectors.keys()) {
702 if (chargingStation.getConnectorStatus(id)?.transactionStarted === true) {
703 response = Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
704 }
705 chargingStation.getConnectorStatus(id).availability = commandPayload.type;
706 if (response === Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) {
707 await chargingStation.ocppRequestService.requestHandler<
708 OCPP16StatusNotificationRequest,
709 OCPP16StatusNotificationResponse
710 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
711 connectorId: id,
712 status: chargePointStatus,
713 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
714 });
715 chargingStation.getConnectorStatus(id).status = chargePointStatus;
716 }
717 }
718 return response;
719 } else if (
720 connectorId > 0 &&
721 (chargingStation.isChargingStationAvailable() === true ||
722 (chargingStation.isChargingStationAvailable() === false &&
723 commandPayload.type === OCPP16AvailabilityType.INOPERATIVE))
724 ) {
725 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
726 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
727 return Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
728 }
729 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
730 await chargingStation.ocppRequestService.requestHandler<
731 OCPP16StatusNotificationRequest,
732 OCPP16StatusNotificationResponse
733 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
734 connectorId,
735 status: chargePointStatus,
736 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
737 });
738 chargingStation.getConnectorStatus(connectorId).status = chargePointStatus;
739 return Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
740 }
741 return Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
742 }
743
744 private async handleRequestRemoteStartTransaction(
745 chargingStation: ChargingStation,
746 commandPayload: RemoteStartTransactionRequest
747 ): Promise<DefaultResponse> {
748 const transactionConnectorId = commandPayload.connectorId;
749 if (chargingStation.connectors.has(transactionConnectorId) === true) {
750 const remoteStartTransactionLogMsg =
751 chargingStation.logPrefix() +
752 ' Transaction remotely STARTED on ' +
753 chargingStation.stationInfo.chargingStationId +
754 '#' +
755 transactionConnectorId.toString() +
756 " for idTag '" +
757 commandPayload.idTag +
758 "'";
759 await chargingStation.ocppRequestService.requestHandler<
760 OCPP16StatusNotificationRequest,
761 OCPP16StatusNotificationResponse
762 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
763 connectorId: transactionConnectorId,
764 status: OCPP16ChargePointStatus.PREPARING,
765 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
766 });
767 const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId);
768 connectorStatus.status = OCPP16ChargePointStatus.PREPARING;
769 if (chargingStation.isChargingStationAvailable() === true) {
770 // Check if authorized
771 if (chargingStation.getAuthorizeRemoteTxRequests() === true) {
772 let authorized = false;
773 if (
774 chargingStation.getLocalAuthListEnabled() === true &&
775 chargingStation.hasAuthorizedTags() === true &&
776 chargingStation.authorizedTagsCache
777 .getAuthorizedTags(
778 ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo)
779 )
780 .find((idTag) => idTag === commandPayload.idTag)
781 ) {
782 connectorStatus.localAuthorizeIdTag = commandPayload.idTag;
783 connectorStatus.idTagLocalAuthorized = true;
784 authorized = true;
785 } else if (chargingStation.getMustAuthorizeAtRemoteStart() === true) {
786 connectorStatus.authorizeIdTag = commandPayload.idTag;
787 const authorizeResponse: OCPP16AuthorizeResponse =
788 await chargingStation.ocppRequestService.requestHandler<
789 OCPP16AuthorizeRequest,
790 OCPP16AuthorizeResponse
791 >(chargingStation, OCPP16RequestCommand.AUTHORIZE, {
792 idTag: commandPayload.idTag,
793 });
794 if (authorizeResponse?.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
795 authorized = true;
796 }
797 } else {
798 logger.warn(
799 `${chargingStation.logPrefix()} The charging station configuration expects authorize at remote start transaction but local authorization or authorize isn't enabled`
800 );
801 }
802 if (authorized === true) {
803 // Authorization successful, start transaction
804 if (
805 this.setRemoteStartTransactionChargingProfile(
806 chargingStation,
807 transactionConnectorId,
808 commandPayload.chargingProfile
809 ) === true
810 ) {
811 connectorStatus.transactionRemoteStarted = true;
812 if (
813 (
814 await chargingStation.ocppRequestService.requestHandler<
815 OCPP16StartTransactionRequest,
816 OCPP16StartTransactionResponse
817 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
818 connectorId: transactionConnectorId,
819 idTag: commandPayload.idTag,
820 })
821 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
822 ) {
823 logger.debug(remoteStartTransactionLogMsg);
824 return Constants.OCPP_RESPONSE_ACCEPTED;
825 }
826 return this.notifyRemoteStartTransactionRejected(
827 chargingStation,
828 transactionConnectorId,
829 commandPayload.idTag
830 );
831 }
832 return this.notifyRemoteStartTransactionRejected(
833 chargingStation,
834 transactionConnectorId,
835 commandPayload.idTag
836 );
837 }
838 return this.notifyRemoteStartTransactionRejected(
839 chargingStation,
840 transactionConnectorId,
841 commandPayload.idTag
842 );
843 }
844 // No authorization check required, start transaction
845 if (
846 this.setRemoteStartTransactionChargingProfile(
847 chargingStation,
848 transactionConnectorId,
849 commandPayload.chargingProfile
850 ) === true
851 ) {
852 connectorStatus.transactionRemoteStarted = true;
853 if (
854 (
855 await chargingStation.ocppRequestService.requestHandler<
856 OCPP16StartTransactionRequest,
857 OCPP16StartTransactionResponse
858 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
859 connectorId: transactionConnectorId,
860 idTag: commandPayload.idTag,
861 })
862 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
863 ) {
864 logger.debug(remoteStartTransactionLogMsg);
865 return Constants.OCPP_RESPONSE_ACCEPTED;
866 }
867 return this.notifyRemoteStartTransactionRejected(
868 chargingStation,
869 transactionConnectorId,
870 commandPayload.idTag
871 );
872 }
873 return this.notifyRemoteStartTransactionRejected(
874 chargingStation,
875 transactionConnectorId,
876 commandPayload.idTag
877 );
878 }
879 return this.notifyRemoteStartTransactionRejected(
880 chargingStation,
881 transactionConnectorId,
882 commandPayload.idTag
883 );
884 }
885 return this.notifyRemoteStartTransactionRejected(
886 chargingStation,
887 transactionConnectorId,
888 commandPayload.idTag
889 );
890 }
891
892 private async notifyRemoteStartTransactionRejected(
893 chargingStation: ChargingStation,
894 connectorId: number,
895 idTag: string
896 ): Promise<DefaultResponse> {
897 if (
898 chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE
899 ) {
900 await chargingStation.ocppRequestService.requestHandler<
901 OCPP16StatusNotificationRequest,
902 OCPP16StatusNotificationResponse
903 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
904 connectorId,
905 status: OCPP16ChargePointStatus.AVAILABLE,
906 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
907 });
908 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE;
909 }
910 logger.warn(
911 chargingStation.logPrefix() +
912 ' Remote starting transaction REJECTED on connector Id ' +
913 connectorId.toString() +
914 ", idTag '" +
915 idTag +
916 "', availability '" +
917 chargingStation.getConnectorStatus(connectorId).availability +
918 "', status '" +
919 chargingStation.getConnectorStatus(connectorId).status +
920 "'"
921 );
922 return Constants.OCPP_RESPONSE_REJECTED;
923 }
924
925 private setRemoteStartTransactionChargingProfile(
926 chargingStation: ChargingStation,
927 connectorId: number,
928 cp: OCPP16ChargingProfile
929 ): boolean {
930 if (cp && cp.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE) {
931 OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, cp);
932 logger.debug(
933 `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}, dump their stack: %j`,
934 chargingStation.getConnectorStatus(connectorId).chargingProfiles
935 );
936 return true;
937 } else if (cp && cp.chargingProfilePurpose !== ChargingProfilePurposeType.TX_PROFILE) {
938 logger.warn(
939 `${chargingStation.logPrefix()} Not allowed to set ${
940 cp.chargingProfilePurpose
941 } charging profile(s) at remote start transaction`
942 );
943 return false;
944 } else if (!cp) {
945 return true;
946 }
947 }
948
949 private async handleRequestRemoteStopTransaction(
950 chargingStation: ChargingStation,
951 commandPayload: RemoteStopTransactionRequest
952 ): Promise<DefaultResponse> {
953 const transactionId = commandPayload.transactionId;
954 for (const connectorId of chargingStation.connectors.keys()) {
955 if (
956 connectorId > 0 &&
957 chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId
958 ) {
959 await chargingStation.ocppRequestService.requestHandler<
960 OCPP16StatusNotificationRequest,
961 OCPP16StatusNotificationResponse
962 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
963 connectorId,
964 status: OCPP16ChargePointStatus.FINISHING,
965 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
966 });
967 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.FINISHING;
968 const stopResponse = await chargingStation.stopTransactionOnConnector(
969 connectorId,
970 OCPP16StopTransactionReason.REMOTE
971 );
972 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
973 return Constants.OCPP_RESPONSE_ACCEPTED;
974 }
975 return Constants.OCPP_RESPONSE_REJECTED;
976 }
977 }
978 logger.warn(
979 chargingStation.logPrefix() +
980 ' Trying to remote stop a non existing transaction ' +
981 transactionId.toString()
982 );
983 return Constants.OCPP_RESPONSE_REJECTED;
984 }
985
986 private async handleRequestGetDiagnostics(
987 chargingStation: ChargingStation,
988 commandPayload: GetDiagnosticsRequest
989 ): Promise<GetDiagnosticsResponse> {
990 if (
991 OCPP16ServiceUtils.checkFeatureProfile(
992 chargingStation,
993 OCPP16SupportedFeatureProfiles.FirmwareManagement,
994 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
995 ) === false
996 ) {
997 return Constants.OCPP_RESPONSE_EMPTY;
998 }
999 logger.debug(
1000 chargingStation.logPrefix() +
1001 ' ' +
1002 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS +
1003 ' request received: %j',
1004 commandPayload
1005 );
1006 const uri = new URL(commandPayload.location);
1007 if (uri.protocol.startsWith('ftp:')) {
1008 let ftpClient: Client;
1009 try {
1010 const logFiles = fs
1011 .readdirSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'))
1012 .filter((file) => file.endsWith('.log'))
1013 .map((file) => path.join('./', file));
1014 const diagnosticsArchive = chargingStation.stationInfo.chargingStationId + '_logs.tar.gz';
1015 tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive));
1016 ftpClient = new Client();
1017 const accessResponse = await ftpClient.access({
1018 host: uri.host,
1019 ...(!Utils.isEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }),
1020 ...(!Utils.isEmptyString(uri.username) && { user: uri.username }),
1021 ...(!Utils.isEmptyString(uri.password) && { password: uri.password }),
1022 });
1023 let uploadResponse: FTPResponse;
1024 if (accessResponse.code === 220) {
1025 // eslint-disable-next-line @typescript-eslint/no-misused-promises
1026 ftpClient.trackProgress(async (info) => {
1027 logger.info(
1028 `${chargingStation.logPrefix()} ${
1029 info.bytes / 1024
1030 } bytes transferred from diagnostics archive ${info.name}`
1031 );
1032 await chargingStation.ocppRequestService.requestHandler<
1033 DiagnosticsStatusNotificationRequest,
1034 DiagnosticsStatusNotificationResponse
1035 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1036 status: OCPP16DiagnosticsStatus.Uploading,
1037 });
1038 });
1039 uploadResponse = await ftpClient.uploadFrom(
1040 path.join(
1041 path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'),
1042 diagnosticsArchive
1043 ),
1044 uri.pathname + diagnosticsArchive
1045 );
1046 if (uploadResponse.code === 226) {
1047 await chargingStation.ocppRequestService.requestHandler<
1048 DiagnosticsStatusNotificationRequest,
1049 DiagnosticsStatusNotificationResponse
1050 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1051 status: OCPP16DiagnosticsStatus.Uploaded,
1052 });
1053 if (ftpClient) {
1054 ftpClient.close();
1055 }
1056 return { fileName: diagnosticsArchive };
1057 }
1058 throw new OCPPError(
1059 ErrorType.GENERIC_ERROR,
1060 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
1061 uploadResponse?.code && '|' + uploadResponse?.code.toString()
1062 }`,
1063 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1064 );
1065 }
1066 throw new OCPPError(
1067 ErrorType.GENERIC_ERROR,
1068 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
1069 uploadResponse?.code && '|' + uploadResponse?.code.toString()
1070 }`,
1071 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1072 );
1073 } catch (error) {
1074 await chargingStation.ocppRequestService.requestHandler<
1075 DiagnosticsStatusNotificationRequest,
1076 DiagnosticsStatusNotificationResponse
1077 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1078 status: OCPP16DiagnosticsStatus.UploadFailed,
1079 });
1080 if (ftpClient) {
1081 ftpClient.close();
1082 }
1083 return this.handleIncomingRequestError(
1084 chargingStation,
1085 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
1086 error as Error,
1087 { errorResponse: Constants.OCPP_RESPONSE_EMPTY }
1088 );
1089 }
1090 } else {
1091 logger.error(
1092 `${chargingStation.logPrefix()} Unsupported protocol ${
1093 uri.protocol
1094 } to transfer the diagnostic logs archive`
1095 );
1096 await chargingStation.ocppRequestService.requestHandler<
1097 DiagnosticsStatusNotificationRequest,
1098 DiagnosticsStatusNotificationResponse
1099 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1100 status: OCPP16DiagnosticsStatus.UploadFailed,
1101 });
1102 return Constants.OCPP_RESPONSE_EMPTY;
1103 }
1104 }
1105
1106 private handleRequestTriggerMessage(
1107 chargingStation: ChargingStation,
1108 commandPayload: OCPP16TriggerMessageRequest
1109 ): OCPP16TriggerMessageResponse {
1110 if (
1111 !OCPP16ServiceUtils.checkFeatureProfile(
1112 chargingStation,
1113 OCPP16SupportedFeatureProfiles.RemoteTrigger,
1114 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
1115 )
1116 ) {
1117 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
1118 }
1119 // TODO: factor out the check on connector id
1120 if (commandPayload?.connectorId < 0) {
1121 logger.warn(
1122 `${chargingStation.logPrefix()} ${
1123 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
1124 } incoming request received with invalid connectorId ${commandPayload.connectorId}`
1125 );
1126 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED;
1127 }
1128 try {
1129 switch (commandPayload.requestedMessage) {
1130 case MessageTrigger.BootNotification:
1131 setTimeout(() => {
1132 chargingStation.ocppRequestService
1133 .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
1134 chargingStation,
1135 OCPP16RequestCommand.BOOT_NOTIFICATION,
1136 chargingStation.bootNotificationRequest,
1137 { skipBufferingOnError: true, triggerMessage: true }
1138 )
1139 .then((response) => {
1140 chargingStation.bootNotificationResponse = response;
1141 })
1142 .catch(() => {
1143 /* This is intentional */
1144 });
1145 }, Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1146 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
1147 case MessageTrigger.Heartbeat:
1148 setTimeout(() => {
1149 chargingStation.ocppRequestService
1150 .requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
1151 chargingStation,
1152 OCPP16RequestCommand.HEARTBEAT,
1153 null,
1154 {
1155 triggerMessage: true,
1156 }
1157 )
1158 .catch(() => {
1159 /* This is intentional */
1160 });
1161 }, Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1162 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
1163 case MessageTrigger.StatusNotification:
1164 setTimeout(() => {
1165 if (commandPayload?.connectorId) {
1166 chargingStation.ocppRequestService
1167 .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
1168 chargingStation,
1169 OCPP16RequestCommand.STATUS_NOTIFICATION,
1170 {
1171 connectorId: commandPayload.connectorId,
1172 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
1173 status: chargingStation.getConnectorStatus(commandPayload.connectorId).status,
1174 },
1175 {
1176 triggerMessage: true,
1177 }
1178 )
1179 .catch(() => {
1180 /* This is intentional */
1181 });
1182 } else {
1183 for (const connectorId of chargingStation.connectors.keys()) {
1184 chargingStation.ocppRequestService
1185 .requestHandler<
1186 OCPP16StatusNotificationRequest,
1187 OCPP16StatusNotificationResponse
1188 >(
1189 chargingStation,
1190 OCPP16RequestCommand.STATUS_NOTIFICATION,
1191 {
1192 connectorId,
1193 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
1194 status: chargingStation.getConnectorStatus(connectorId).status,
1195 },
1196 {
1197 triggerMessage: true,
1198 }
1199 )
1200 .catch(() => {
1201 /* This is intentional */
1202 });
1203 }
1204 }
1205 }, Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1206 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
1207 default:
1208 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
1209 }
1210 } catch (error) {
1211 return this.handleIncomingRequestError(
1212 chargingStation,
1213 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
1214 error as Error,
1215 { errorResponse: Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED }
1216 );
1217 }
1218 }
1219 }