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