Imports cleanup
[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() ||
302 (!chargingStation.getOcppStrictCompliance() && chargingStation.isInUnknownState())
303 ) {
304 if (
305 this.incomingRequestHandlers.has(commandName) &&
306 ChargingStationUtils.isIncomingRequestCommandSupported(commandName, chargingStation)
307 ) {
308 try {
309 this.validatePayload(chargingStation, commandName, commandPayload);
310 // Call the method to build the response
311 response = await this.incomingRequestHandlers.get(commandName)(
312 chargingStation,
313 commandPayload
314 );
315 } catch (error) {
316 // Log
317 logger.error(
318 `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
319 error
320 );
321 throw error;
322 }
323 } else {
324 // Throw exception
325 throw new OCPPError(
326 ErrorType.NOT_IMPLEMENTED,
327 `${commandName} is not implemented to handle request PDU ${JSON.stringify(
328 commandPayload,
329 null,
330 2
331 )}`,
332 commandName,
333 commandPayload
334 );
335 }
336 } else {
337 throw new OCPPError(
338 ErrorType.SECURITY_ERROR,
339 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
340 commandPayload,
341 null,
342 2
343 )} while the charging station is not registered on the central server.`,
344 commandName,
345 commandPayload
346 );
347 }
348 // Send the built response
349 await chargingStation.ocppRequestService.sendResponse(
350 chargingStation,
351 messageId,
352 response,
353 commandName
354 );
355 }
356
357 private validatePayload(
358 chargingStation: ChargingStation,
359 commandName: OCPP16IncomingRequestCommand,
360 commandPayload: JsonType
361 ): boolean {
362 if (this.jsonSchemas.has(commandName)) {
363 return this.validateIncomingRequestPayload(
364 chargingStation,
365 commandName,
366 this.jsonSchemas.get(commandName),
367 commandPayload
368 );
369 }
370 logger.warn(
371 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command ${commandName} PDU validation`
372 );
373 return false;
374 }
375
376 // Simulate charging station restart
377 private handleRequestReset(
378 chargingStation: ChargingStation,
379 commandPayload: ResetRequest
380 ): DefaultResponse {
381 // eslint-disable-next-line @typescript-eslint/no-misused-promises
382 setImmediate(async (): Promise<void> => {
383 if (chargingStation.getNumberOfRunningTransactions() > 0) {
384 await chargingStation.stopRunningTransactions(
385 (commandPayload.type + 'Reset') as OCPP16StopTransactionReason
386 );
387 }
388 await chargingStation.reset();
389 });
390 logger.info(
391 `${chargingStation.logPrefix()} ${
392 commandPayload.type
393 } reset command received, simulating it. The station will be back online in ${Utils.formatDurationMilliSeconds(
394 chargingStation.stationInfo.resetTime
395 )}`
396 );
397 return Constants.OCPP_RESPONSE_ACCEPTED;
398 }
399
400 private handleRequestClearCache(): DefaultResponse {
401 return Constants.OCPP_RESPONSE_ACCEPTED;
402 }
403
404 private async handleRequestUnlockConnector(
405 chargingStation: ChargingStation,
406 commandPayload: UnlockConnectorRequest
407 ): Promise<UnlockConnectorResponse> {
408 const connectorId = commandPayload.connectorId;
409 if (connectorId === 0) {
410 logger.error(
411 chargingStation.logPrefix() + ' Trying to unlock connector ' + connectorId.toString()
412 );
413 return Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
414 }
415 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
416 const stopResponse = await chargingStation.stopTransactionOnConnector(
417 connectorId,
418 OCPP16StopTransactionReason.UNLOCK_COMMAND
419 );
420 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
421 return Constants.OCPP_RESPONSE_UNLOCKED;
422 }
423 return Constants.OCPP_RESPONSE_UNLOCK_FAILED;
424 }
425 await chargingStation.ocppRequestService.requestHandler<
426 OCPP16StatusNotificationRequest,
427 OCPP16StatusNotificationResponse
428 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
429 connectorId,
430 status: OCPP16ChargePointStatus.AVAILABLE,
431 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
432 });
433 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE;
434 return Constants.OCPP_RESPONSE_UNLOCKED;
435 }
436
437 private handleRequestGetConfiguration(
438 chargingStation: ChargingStation,
439 commandPayload: GetConfigurationRequest
440 ): GetConfigurationResponse {
441 const configurationKey: OCPPConfigurationKey[] = [];
442 const unknownKey: string[] = [];
443 if (Utils.isEmptyArray(commandPayload.key)) {
444 for (const configuration of chargingStation.ocppConfiguration.configurationKey) {
445 if (Utils.isUndefined(configuration.visible)) {
446 configuration.visible = true;
447 }
448 if (!configuration.visible) {
449 continue;
450 }
451 configurationKey.push({
452 key: configuration.key,
453 readonly: configuration.readonly,
454 value: configuration.value,
455 });
456 }
457 } else {
458 for (const key of commandPayload.key) {
459 const keyFound = ChargingStationConfigurationUtils.getConfigurationKey(
460 chargingStation,
461 key
462 );
463 if (keyFound) {
464 if (Utils.isUndefined(keyFound.visible)) {
465 keyFound.visible = true;
466 }
467 if (!keyFound.visible) {
468 continue;
469 }
470 configurationKey.push({
471 key: keyFound.key,
472 readonly: keyFound.readonly,
473 value: keyFound.value,
474 });
475 } else {
476 unknownKey.push(key);
477 }
478 }
479 }
480 return {
481 configurationKey,
482 unknownKey,
483 };
484 }
485
486 private handleRequestChangeConfiguration(
487 chargingStation: ChargingStation,
488 commandPayload: ChangeConfigurationRequest
489 ): ChangeConfigurationResponse {
490 const keyToChange = ChargingStationConfigurationUtils.getConfigurationKey(
491 chargingStation,
492 commandPayload.key,
493 true
494 );
495 if (!keyToChange) {
496 return Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED;
497 } else if (keyToChange && keyToChange.readonly) {
498 return Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED;
499 } else if (keyToChange && !keyToChange.readonly) {
500 let valueChanged = false;
501 if (keyToChange.value !== commandPayload.value) {
502 ChargingStationConfigurationUtils.setConfigurationKeyValue(
503 chargingStation,
504 commandPayload.key,
505 commandPayload.value,
506 true
507 );
508 valueChanged = true;
509 }
510 let triggerHeartbeatRestart = false;
511 if (keyToChange.key === OCPP16StandardParametersKey.HeartBeatInterval && valueChanged) {
512 ChargingStationConfigurationUtils.setConfigurationKeyValue(
513 chargingStation,
514 OCPP16StandardParametersKey.HeartbeatInterval,
515 commandPayload.value
516 );
517 triggerHeartbeatRestart = true;
518 }
519 if (keyToChange.key === OCPP16StandardParametersKey.HeartbeatInterval && valueChanged) {
520 ChargingStationConfigurationUtils.setConfigurationKeyValue(
521 chargingStation,
522 OCPP16StandardParametersKey.HeartBeatInterval,
523 commandPayload.value
524 );
525 triggerHeartbeatRestart = true;
526 }
527 if (triggerHeartbeatRestart) {
528 chargingStation.restartHeartbeat();
529 }
530 if (keyToChange.key === OCPP16StandardParametersKey.WebSocketPingInterval && valueChanged) {
531 chargingStation.restartWebSocketPing();
532 }
533 if (keyToChange.reboot) {
534 return Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED;
535 }
536 return Constants.OCPP_CONFIGURATION_RESPONSE_ACCEPTED;
537 }
538 }
539
540 private handleRequestSetChargingProfile(
541 chargingStation: ChargingStation,
542 commandPayload: SetChargingProfileRequest
543 ): SetChargingProfileResponse {
544 if (
545 !OCPP16ServiceUtils.checkFeatureProfile(
546 chargingStation,
547 OCPP16SupportedFeatureProfiles.SmartCharging,
548 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
549 )
550 ) {
551 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED;
552 }
553 if (!chargingStation.getConnectorStatus(commandPayload.connectorId)) {
554 logger.error(
555 `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector Id ${
556 commandPayload.connectorId
557 }`
558 );
559 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
560 }
561 if (
562 commandPayload.csChargingProfiles.chargingProfilePurpose ===
563 ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
564 commandPayload.connectorId !== 0
565 ) {
566 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
567 }
568 if (
569 commandPayload.csChargingProfiles.chargingProfilePurpose ===
570 ChargingProfilePurposeType.TX_PROFILE &&
571 (commandPayload.connectorId === 0 ||
572 chargingStation.getConnectorStatus(commandPayload.connectorId)?.transactionStarted ===
573 false)
574 ) {
575 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
576 }
577 chargingStation.setChargingProfile(
578 commandPayload.connectorId,
579 commandPayload.csChargingProfiles
580 );
581 logger.debug(
582 `${chargingStation.logPrefix()} Charging profile(s) set on connector id ${
583 commandPayload.connectorId
584 }, dump their stack: %j`,
585 chargingStation.getConnectorStatus(commandPayload.connectorId).chargingProfiles
586 );
587 return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED;
588 }
589
590 private handleRequestClearChargingProfile(
591 chargingStation: ChargingStation,
592 commandPayload: ClearChargingProfileRequest
593 ): ClearChargingProfileResponse {
594 if (
595 !OCPP16ServiceUtils.checkFeatureProfile(
596 chargingStation,
597 OCPP16SupportedFeatureProfiles.SmartCharging,
598 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
599 )
600 ) {
601 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
602 }
603 const connectorStatus = chargingStation.getConnectorStatus(commandPayload.connectorId);
604 if (!connectorStatus) {
605 logger.error(
606 `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector Id ${
607 commandPayload.connectorId
608 }`
609 );
610 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
611 }
612 if (commandPayload.connectorId && !Utils.isEmptyArray(connectorStatus.chargingProfiles)) {
613 connectorStatus.chargingProfiles = [];
614 logger.debug(
615 `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${
616 commandPayload.connectorId
617 }, dump their stack: %j`,
618 connectorStatus.chargingProfiles
619 );
620 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
621 }
622 if (!commandPayload.connectorId) {
623 let clearedCP = false;
624 for (const connectorId of chargingStation.connectors.keys()) {
625 if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
626 chargingStation
627 .getConnectorStatus(connectorId)
628 .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
629 let clearCurrentCP = false;
630 if (chargingProfile.chargingProfileId === commandPayload.id) {
631 clearCurrentCP = true;
632 }
633 if (
634 !commandPayload.chargingProfilePurpose &&
635 chargingProfile.stackLevel === commandPayload.stackLevel
636 ) {
637 clearCurrentCP = true;
638 }
639 if (
640 !chargingProfile.stackLevel &&
641 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
642 ) {
643 clearCurrentCP = true;
644 }
645 if (
646 chargingProfile.stackLevel === commandPayload.stackLevel &&
647 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
648 ) {
649 clearCurrentCP = true;
650 }
651 if (clearCurrentCP) {
652 connectorStatus.chargingProfiles.splice(index, 1);
653 logger.debug(
654 `${chargingStation.logPrefix()} Matching charging profile(s) cleared on connector id ${
655 commandPayload.connectorId
656 }, dump their stack: %j`,
657 connectorStatus.chargingProfiles
658 );
659 clearedCP = true;
660 }
661 });
662 }
663 }
664 if (clearedCP) {
665 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
666 }
667 }
668 return Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
669 }
670
671 private async handleRequestChangeAvailability(
672 chargingStation: ChargingStation,
673 commandPayload: ChangeAvailabilityRequest
674 ): Promise<ChangeAvailabilityResponse> {
675 const connectorId: number = commandPayload.connectorId;
676 if (!chargingStation.getConnectorStatus(connectorId)) {
677 logger.error(
678 `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector Id ${connectorId.toString()}`
679 );
680 return Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
681 }
682 const chargePointStatus: OCPP16ChargePointStatus =
683 commandPayload.type === OCPP16AvailabilityType.OPERATIVE
684 ? OCPP16ChargePointStatus.AVAILABLE
685 : OCPP16ChargePointStatus.UNAVAILABLE;
686 if (connectorId === 0) {
687 let response: ChangeAvailabilityResponse = Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
688 for (const id of chargingStation.connectors.keys()) {
689 if (chargingStation.getConnectorStatus(id)?.transactionStarted === true) {
690 response = Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
691 }
692 chargingStation.getConnectorStatus(id).availability = commandPayload.type;
693 if (response === Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) {
694 await chargingStation.ocppRequestService.requestHandler<
695 OCPP16StatusNotificationRequest,
696 OCPP16StatusNotificationResponse
697 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
698 connectorId: id,
699 status: chargePointStatus,
700 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
701 });
702 chargingStation.getConnectorStatus(id).status = chargePointStatus;
703 }
704 }
705 return response;
706 } else if (
707 connectorId > 0 &&
708 (chargingStation.getConnectorStatus(0).availability === OCPP16AvailabilityType.OPERATIVE ||
709 (chargingStation.getConnectorStatus(0).availability ===
710 OCPP16AvailabilityType.INOPERATIVE &&
711 commandPayload.type === OCPP16AvailabilityType.INOPERATIVE))
712 ) {
713 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
714 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
715 return Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
716 }
717 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
718 await chargingStation.ocppRequestService.requestHandler<
719 OCPP16StatusNotificationRequest,
720 OCPP16StatusNotificationResponse
721 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
722 connectorId,
723 status: chargePointStatus,
724 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
725 });
726 chargingStation.getConnectorStatus(connectorId).status = chargePointStatus;
727 return Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
728 }
729 return Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
730 }
731
732 private async handleRequestRemoteStartTransaction(
733 chargingStation: ChargingStation,
734 commandPayload: RemoteStartTransactionRequest
735 ): Promise<DefaultResponse> {
736 const transactionConnectorId = commandPayload.connectorId;
737 const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId);
738 if (transactionConnectorId) {
739 const remoteStartTransactionLogMsg =
740 chargingStation.logPrefix() +
741 ' Transaction remotely STARTED on ' +
742 chargingStation.stationInfo.chargingStationId +
743 '#' +
744 transactionConnectorId.toString() +
745 " for idTag '" +
746 commandPayload.idTag +
747 "'";
748 await chargingStation.ocppRequestService.requestHandler<
749 OCPP16StatusNotificationRequest,
750 OCPP16StatusNotificationResponse
751 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
752 connectorId: transactionConnectorId,
753 status: OCPP16ChargePointStatus.PREPARING,
754 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
755 });
756 connectorStatus.status = OCPP16ChargePointStatus.PREPARING;
757 if (chargingStation.isChargingStationAvailable() && connectorStatus) {
758 // Check if authorized
759 if (chargingStation.getAuthorizeRemoteTxRequests()) {
760 let authorized = false;
761 if (
762 chargingStation.getLocalAuthListEnabled() &&
763 chargingStation.hasAuthorizedTags() &&
764 chargingStation.authorizedTagsCache
765 .getAuthorizedTags(
766 ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo)
767 )
768 .find((value) => value === commandPayload.idTag)
769 ) {
770 connectorStatus.localAuthorizeIdTag = commandPayload.idTag;
771 connectorStatus.idTagLocalAuthorized = true;
772 authorized = true;
773 } else if (chargingStation.getMustAuthorizeAtRemoteStart()) {
774 connectorStatus.authorizeIdTag = commandPayload.idTag;
775 const authorizeResponse: OCPP16AuthorizeResponse =
776 await chargingStation.ocppRequestService.requestHandler<
777 OCPP16AuthorizeRequest,
778 OCPP16AuthorizeResponse
779 >(chargingStation, OCPP16RequestCommand.AUTHORIZE, {
780 idTag: commandPayload.idTag,
781 });
782 if (authorizeResponse?.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
783 authorized = true;
784 }
785 } else {
786 logger.warn(
787 `${chargingStation.logPrefix()} The charging station configuration expects authorize at remote start transaction but local authorization or authorize isn't enabled`
788 );
789 }
790 if (authorized) {
791 // Authorization successful, start transaction
792 if (
793 this.setRemoteStartTransactionChargingProfile(
794 chargingStation,
795 transactionConnectorId,
796 commandPayload.chargingProfile
797 )
798 ) {
799 connectorStatus.transactionRemoteStarted = true;
800 if (
801 (
802 await chargingStation.ocppRequestService.requestHandler<
803 OCPP16StartTransactionRequest,
804 OCPP16StartTransactionResponse
805 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
806 connectorId: transactionConnectorId,
807 idTag: commandPayload.idTag,
808 })
809 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
810 ) {
811 logger.debug(remoteStartTransactionLogMsg);
812 return Constants.OCPP_RESPONSE_ACCEPTED;
813 }
814 return this.notifyRemoteStartTransactionRejected(
815 chargingStation,
816 transactionConnectorId,
817 commandPayload.idTag
818 );
819 }
820 return this.notifyRemoteStartTransactionRejected(
821 chargingStation,
822 transactionConnectorId,
823 commandPayload.idTag
824 );
825 }
826 return this.notifyRemoteStartTransactionRejected(
827 chargingStation,
828 transactionConnectorId,
829 commandPayload.idTag
830 );
831 }
832 // No authorization check required, start transaction
833 if (
834 this.setRemoteStartTransactionChargingProfile(
835 chargingStation,
836 transactionConnectorId,
837 commandPayload.chargingProfile
838 )
839 ) {
840 connectorStatus.transactionRemoteStarted = true;
841 if (
842 (
843 await chargingStation.ocppRequestService.requestHandler<
844 OCPP16StartTransactionRequest,
845 OCPP16StartTransactionResponse
846 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
847 connectorId: transactionConnectorId,
848 idTag: commandPayload.idTag,
849 })
850 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
851 ) {
852 logger.debug(remoteStartTransactionLogMsg);
853 return Constants.OCPP_RESPONSE_ACCEPTED;
854 }
855 return this.notifyRemoteStartTransactionRejected(
856 chargingStation,
857 transactionConnectorId,
858 commandPayload.idTag
859 );
860 }
861 return this.notifyRemoteStartTransactionRejected(
862 chargingStation,
863 transactionConnectorId,
864 commandPayload.idTag
865 );
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
880 private async notifyRemoteStartTransactionRejected(
881 chargingStation: ChargingStation,
882 connectorId: number,
883 idTag: string
884 ): Promise<DefaultResponse> {
885 if (
886 chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE
887 ) {
888 await chargingStation.ocppRequestService.requestHandler<
889 OCPP16StatusNotificationRequest,
890 OCPP16StatusNotificationResponse
891 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
892 connectorId,
893 status: OCPP16ChargePointStatus.AVAILABLE,
894 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
895 });
896 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE;
897 }
898 logger.warn(
899 chargingStation.logPrefix() +
900 ' Remote starting transaction REJECTED on connector Id ' +
901 connectorId.toString() +
902 ", idTag '" +
903 idTag +
904 "', availability '" +
905 chargingStation.getConnectorStatus(connectorId).availability +
906 "', status '" +
907 chargingStation.getConnectorStatus(connectorId).status +
908 "'"
909 );
910 return Constants.OCPP_RESPONSE_REJECTED;
911 }
912
913 private setRemoteStartTransactionChargingProfile(
914 chargingStation: ChargingStation,
915 connectorId: number,
916 cp: OCPP16ChargingProfile
917 ): boolean {
918 if (cp && cp.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE) {
919 chargingStation.setChargingProfile(connectorId, cp);
920 logger.debug(
921 `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}, dump their stack: %j`,
922 chargingStation.getConnectorStatus(connectorId).chargingProfiles
923 );
924 return true;
925 } else if (cp && cp.chargingProfilePurpose !== ChargingProfilePurposeType.TX_PROFILE) {
926 logger.warn(
927 `${chargingStation.logPrefix()} Not allowed to set ${
928 cp.chargingProfilePurpose
929 } charging profile(s) at remote start transaction`
930 );
931 return false;
932 } else if (!cp) {
933 return true;
934 }
935 }
936
937 private async handleRequestRemoteStopTransaction(
938 chargingStation: ChargingStation,
939 commandPayload: RemoteStopTransactionRequest
940 ): Promise<DefaultResponse> {
941 const transactionId = commandPayload.transactionId;
942 for (const connectorId of chargingStation.connectors.keys()) {
943 if (
944 connectorId > 0 &&
945 chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId
946 ) {
947 await chargingStation.ocppRequestService.requestHandler<
948 OCPP16StatusNotificationRequest,
949 OCPP16StatusNotificationResponse
950 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
951 connectorId,
952 status: OCPP16ChargePointStatus.FINISHING,
953 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
954 });
955 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.FINISHING;
956 const stopResponse = await chargingStation.stopTransactionOnConnector(
957 connectorId,
958 OCPP16StopTransactionReason.REMOTE
959 );
960 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
961 return Constants.OCPP_RESPONSE_ACCEPTED;
962 }
963 return Constants.OCPP_RESPONSE_REJECTED;
964 }
965 }
966 logger.warn(
967 chargingStation.logPrefix() +
968 ' Trying to remote stop a non existing transaction ' +
969 transactionId.toString()
970 );
971 return Constants.OCPP_RESPONSE_REJECTED;
972 }
973
974 private async handleRequestGetDiagnostics(
975 chargingStation: ChargingStation,
976 commandPayload: GetDiagnosticsRequest
977 ): Promise<GetDiagnosticsResponse> {
978 if (
979 !OCPP16ServiceUtils.checkFeatureProfile(
980 chargingStation,
981 OCPP16SupportedFeatureProfiles.FirmwareManagement,
982 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
983 )
984 ) {
985 return Constants.OCPP_RESPONSE_EMPTY;
986 }
987 logger.debug(
988 chargingStation.logPrefix() +
989 ' ' +
990 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS +
991 ' request received: %j',
992 commandPayload
993 );
994 const uri = new URL(commandPayload.location);
995 if (uri.protocol.startsWith('ftp:')) {
996 let ftpClient: Client;
997 try {
998 const logFiles = fs
999 .readdirSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'))
1000 .filter((file) => file.endsWith('.log'))
1001 .map((file) => path.join('./', file));
1002 const diagnosticsArchive = chargingStation.stationInfo.chargingStationId + '_logs.tar.gz';
1003 tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive));
1004 ftpClient = new Client();
1005 const accessResponse = await ftpClient.access({
1006 host: uri.host,
1007 ...(!Utils.isEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }),
1008 ...(!Utils.isEmptyString(uri.username) && { user: uri.username }),
1009 ...(!Utils.isEmptyString(uri.password) && { password: uri.password }),
1010 });
1011 let uploadResponse: FTPResponse;
1012 if (accessResponse.code === 220) {
1013 // eslint-disable-next-line @typescript-eslint/no-misused-promises
1014 ftpClient.trackProgress(async (info) => {
1015 logger.info(
1016 `${chargingStation.logPrefix()} ${
1017 info.bytes / 1024
1018 } bytes transferred from diagnostics archive ${info.name}`
1019 );
1020 await chargingStation.ocppRequestService.requestHandler<
1021 DiagnosticsStatusNotificationRequest,
1022 DiagnosticsStatusNotificationResponse
1023 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1024 status: OCPP16DiagnosticsStatus.Uploading,
1025 });
1026 });
1027 uploadResponse = await ftpClient.uploadFrom(
1028 path.join(
1029 path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'),
1030 diagnosticsArchive
1031 ),
1032 uri.pathname + diagnosticsArchive
1033 );
1034 if (uploadResponse.code === 226) {
1035 await chargingStation.ocppRequestService.requestHandler<
1036 DiagnosticsStatusNotificationRequest,
1037 DiagnosticsStatusNotificationResponse
1038 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1039 status: OCPP16DiagnosticsStatus.Uploaded,
1040 });
1041 if (ftpClient) {
1042 ftpClient.close();
1043 }
1044 return { fileName: diagnosticsArchive };
1045 }
1046 throw new OCPPError(
1047 ErrorType.GENERIC_ERROR,
1048 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
1049 uploadResponse?.code && '|' + uploadResponse?.code.toString()
1050 }`,
1051 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1052 );
1053 }
1054 throw new OCPPError(
1055 ErrorType.GENERIC_ERROR,
1056 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
1057 uploadResponse?.code && '|' + uploadResponse?.code.toString()
1058 }`,
1059 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1060 );
1061 } catch (error) {
1062 await chargingStation.ocppRequestService.requestHandler<
1063 DiagnosticsStatusNotificationRequest,
1064 DiagnosticsStatusNotificationResponse
1065 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1066 status: OCPP16DiagnosticsStatus.UploadFailed,
1067 });
1068 if (ftpClient) {
1069 ftpClient.close();
1070 }
1071 return this.handleIncomingRequestError(
1072 chargingStation,
1073 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
1074 error as Error,
1075 { errorResponse: Constants.OCPP_RESPONSE_EMPTY }
1076 );
1077 }
1078 } else {
1079 logger.error(
1080 `${chargingStation.logPrefix()} Unsupported protocol ${
1081 uri.protocol
1082 } to transfer the diagnostic logs archive`
1083 );
1084 await chargingStation.ocppRequestService.requestHandler<
1085 DiagnosticsStatusNotificationRequest,
1086 DiagnosticsStatusNotificationResponse
1087 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1088 status: OCPP16DiagnosticsStatus.UploadFailed,
1089 });
1090 return Constants.OCPP_RESPONSE_EMPTY;
1091 }
1092 }
1093
1094 private handleRequestTriggerMessage(
1095 chargingStation: ChargingStation,
1096 commandPayload: OCPP16TriggerMessageRequest
1097 ): OCPP16TriggerMessageResponse {
1098 if (
1099 !OCPP16ServiceUtils.checkFeatureProfile(
1100 chargingStation,
1101 OCPP16SupportedFeatureProfiles.RemoteTrigger,
1102 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
1103 )
1104 ) {
1105 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
1106 }
1107 // TODO: factor out the check on connector id
1108 if (commandPayload?.connectorId < 0) {
1109 logger.warn(
1110 `${chargingStation.logPrefix()} ${
1111 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
1112 } incoming request received with invalid connectorId ${commandPayload.connectorId}`
1113 );
1114 return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED;
1115 }
1116 try {
1117 switch (commandPayload.requestedMessage) {
1118 case MessageTrigger.BootNotification:
1119 setTimeout(() => {
1120 chargingStation.ocppRequestService
1121 .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
1122 chargingStation,
1123 OCPP16RequestCommand.BOOT_NOTIFICATION,
1124 {
1125 chargePointModel: chargingStation.bootNotificationRequest.chargePointModel,
1126 chargePointVendor: chargingStation.bootNotificationRequest.chargePointVendor,
1127 chargeBoxSerialNumber:
1128 chargingStation.bootNotificationRequest.chargeBoxSerialNumber,
1129 firmwareVersion: chargingStation.bootNotificationRequest.firmwareVersion,
1130 chargePointSerialNumber:
1131 chargingStation.bootNotificationRequest.chargePointSerialNumber,
1132 iccid: chargingStation.bootNotificationRequest.iccid,
1133 imsi: chargingStation.bootNotificationRequest.imsi,
1134 meterSerialNumber: chargingStation.bootNotificationRequest.meterSerialNumber,
1135 meterType: chargingStation.bootNotificationRequest.meterType,
1136 },
1137 { skipBufferingOnError: true, triggerMessage: true }
1138 )
1139 .then((value) => {
1140 chargingStation.bootNotificationResponse = value;
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 }