build(simulator): don't preserve modules
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16IncomingRequestService.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
c8eeb62b 2
130783a7
JB
3import fs from 'node:fs';
4import path from 'node:path';
5import { URL, fileURLToPath } from 'node:url';
8114d10e 6
6c1761d4 7import type { JSONSchemaType } from 'ajv';
27782dbc 8import { Client, type FTPResponse } from 'basic-ftp';
8114d10e
JB
9import tar from 'tar';
10
4c3c0d59
JB
11import { OCPP16Constants } from './OCPP16Constants';
12import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
2896e06d
JB
13import {
14 type ChargingStation,
15 ChargingStationConfigurationUtils,
16 ChargingStationUtils,
17} from '../../../charging-station';
268a74bb 18import { OCPPError } from '../../../exception';
e7aeea18 19import {
27782dbc 20 type ChangeAvailabilityRequest,
268a74bb 21 type ChangeAvailabilityResponse,
27782dbc 22 type ChangeConfigurationRequest,
268a74bb 23 type ChangeConfigurationResponse,
27782dbc 24 type ClearChargingProfileRequest,
268a74bb 25 type ClearChargingProfileResponse,
4334db72 26 type ConnectorStatus,
268a74bb
JB
27 ErrorType,
28 type GenericResponse,
41189456 29 GenericStatus,
27782dbc 30 type GetConfigurationRequest,
268a74bb 31 type GetConfigurationResponse,
27782dbc 32 type GetDiagnosticsRequest,
268a74bb
JB
33 type GetDiagnosticsResponse,
34 type IncomingRequestHandler,
35 type JsonObject,
36 type JsonType,
37 OCPP16AuthorizationStatus,
38 type OCPP16AuthorizeRequest,
39 type OCPP16AuthorizeResponse,
e7aeea18 40 OCPP16AvailabilityType,
27782dbc 41 type OCPP16BootNotificationRequest,
268a74bb
JB
42 type OCPP16BootNotificationResponse,
43 OCPP16ChargePointErrorCode,
44 OCPP16ChargePointStatus,
45 type OCPP16ChargingProfile,
0ac97927 46 OCPP16ChargingProfilePurposeType,
41189456 47 type OCPP16ChargingSchedule,
27782dbc
JB
48 type OCPP16ClearCacheRequest,
49 type OCPP16DataTransferRequest,
268a74bb
JB
50 type OCPP16DataTransferResponse,
51 OCPP16DataTransferStatus,
77b95a89 52 OCPP16DataTransferVendorId,
268a74bb 53 OCPP16DiagnosticsStatus,
c9a4f9ea 54 type OCPP16DiagnosticsStatusNotificationRequest,
268a74bb 55 type OCPP16DiagnosticsStatusNotificationResponse,
c9a4f9ea
JB
56 OCPP16FirmwareStatus,
57 type OCPP16FirmwareStatusNotificationRequest,
268a74bb 58 type OCPP16FirmwareStatusNotificationResponse,
41189456
JB
59 type OCPP16GetCompositeScheduleRequest,
60 type OCPP16GetCompositeScheduleResponse,
27782dbc 61 type OCPP16HeartbeatRequest,
268a74bb 62 type OCPP16HeartbeatResponse,
e7aeea18 63 OCPP16IncomingRequestCommand,
c60ed4b8 64 OCPP16MessageTrigger,
94a464f9 65 OCPP16RequestCommand,
268a74bb
JB
66 OCPP16StandardParametersKey,
67 type OCPP16StartTransactionRequest,
68 type OCPP16StartTransactionResponse,
27782dbc 69 type OCPP16StatusNotificationRequest,
268a74bb
JB
70 type OCPP16StatusNotificationResponse,
71 OCPP16StopTransactionReason,
72 OCPP16SupportedFeatureProfiles,
27782dbc 73 type OCPP16TriggerMessageRequest,
268a74bb 74 type OCPP16TriggerMessageResponse,
27782dbc 75 type OCPP16UpdateFirmwareRequest,
268a74bb
JB
76 type OCPP16UpdateFirmwareResponse,
77 type OCPPConfigurationKey,
78 OCPPVersion,
27782dbc
JB
79 type RemoteStartTransactionRequest,
80 type RemoteStopTransactionRequest,
81 type ResetRequest,
82 type SetChargingProfileRequest,
27782dbc 83 type SetChargingProfileResponse,
268a74bb 84 type UnlockConnectorRequest,
27782dbc 85 type UnlockConnectorResponse,
268a74bb 86} from '../../../types';
60a74391 87import { Constants, Utils, logger } from '../../../utils';
4c3c0d59 88import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService';
c0560973 89
2a115f87 90const moduleName = 'OCPP16IncomingRequestService';
909dcf2d 91
268a74bb 92export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
b3fc3ff5 93 protected jsonSchemas: Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonObject>>;
58144adb
JB
94 private incomingRequestHandlers: Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>;
95
08f130a0 96 public constructor() {
b768993d
JB
97 // if (new.target?.name === moduleName) {
98 // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
99 // }
d270cc87 100 super(OCPPVersion.VERSION_16);
58144adb
JB
101 this.incomingRequestHandlers = new Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>([
102 [OCPP16IncomingRequestCommand.RESET, this.handleRequestReset.bind(this)],
103 [OCPP16IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)],
104 [OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR, this.handleRequestUnlockConnector.bind(this)],
e7aeea18
JB
105 [
106 OCPP16IncomingRequestCommand.GET_CONFIGURATION,
107 this.handleRequestGetConfiguration.bind(this),
108 ],
109 [
110 OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
111 this.handleRequestChangeConfiguration.bind(this),
112 ],
41189456
JB
113 [
114 OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
115 this.handleRequestGetCompositeSchedule.bind(this),
116 ],
e7aeea18
JB
117 [
118 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
119 this.handleRequestSetChargingProfile.bind(this),
120 ],
121 [
122 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
123 this.handleRequestClearChargingProfile.bind(this),
124 ],
125 [
126 OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
127 this.handleRequestChangeAvailability.bind(this),
128 ],
129 [
130 OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
131 this.handleRequestRemoteStartTransaction.bind(this),
132 ],
133 [
134 OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
135 this.handleRequestRemoteStopTransaction.bind(this),
136 ],
734d790d 137 [OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, this.handleRequestGetDiagnostics.bind(this)],
e7aeea18 138 [OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, this.handleRequestTriggerMessage.bind(this)],
77b95a89 139 [OCPP16IncomingRequestCommand.DATA_TRANSFER, this.handleRequestDataTransfer.bind(this)],
c9a4f9ea 140 [OCPP16IncomingRequestCommand.UPDATE_FIRMWARE, this.handleRequestUpdateFirmware.bind(this)],
58144adb 141 ]);
b52c969d
JB
142 this.jsonSchemas = new Map<OCPP16IncomingRequestCommand, JSONSchemaType<JsonObject>>([
143 [
144 OCPP16IncomingRequestCommand.RESET,
130783a7 145 OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
51022aa0 146 'assets/json-schemas/ocpp/1.6/Reset.json',
1b271a54
JB
147 moduleName,
148 'constructor'
130783a7 149 ),
b52c969d
JB
150 ],
151 [
152 OCPP16IncomingRequestCommand.CLEAR_CACHE,
130783a7 153 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
51022aa0 154 'assets/json-schemas/ocpp/1.6/ClearCache.json',
1b271a54
JB
155 moduleName,
156 'constructor'
e9a4164c 157 ),
b52c969d
JB
158 ],
159 [
160 OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
130783a7 161 OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
51022aa0 162 'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
1b271a54
JB
163 moduleName,
164 'constructor'
e9a4164c 165 ),
b52c969d
JB
166 ],
167 [
168 OCPP16IncomingRequestCommand.GET_CONFIGURATION,
130783a7 169 OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
51022aa0 170 'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
1b271a54
JB
171 moduleName,
172 'constructor'
e9a4164c 173 ),
b52c969d
JB
174 ],
175 [
176 OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
130783a7 177 OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
51022aa0 178 'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
1b271a54
JB
179 moduleName,
180 'constructor'
e9a4164c 181 ),
b52c969d
JB
182 ],
183 [
184 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
130783a7 185 OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
51022aa0 186 'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
1b271a54
JB
187 moduleName,
188 'constructor'
e9a4164c 189 ),
b52c969d 190 ],
41189456
JB
191 [
192 OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
193 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
51022aa0 194 'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
41189456
JB
195 moduleName,
196 'constructor'
197 ),
198 ],
b52c969d
JB
199 [
200 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
130783a7 201 OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
51022aa0 202 'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
1b271a54
JB
203 moduleName,
204 'constructor'
e9a4164c 205 ),
b52c969d
JB
206 ],
207 [
208 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
130783a7 209 OCPP16ServiceUtils.parseJsonSchemaFile<ClearChargingProfileRequest>(
51022aa0 210 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
1b271a54
JB
211 moduleName,
212 'constructor'
e9a4164c 213 ),
b52c969d
JB
214 ],
215 [
216 OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
130783a7 217 OCPP16ServiceUtils.parseJsonSchemaFile<ChangeAvailabilityRequest>(
51022aa0 218 'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
1b271a54
JB
219 moduleName,
220 'constructor'
e9a4164c 221 ),
b52c969d
JB
222 ],
223 [
224 OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
130783a7 225 OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
51022aa0 226 'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
1b271a54
JB
227 moduleName,
228 'constructor'
e9a4164c 229 ),
b52c969d
JB
230 ],
231 [
232 OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
130783a7 233 OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
51022aa0 234 'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
1b271a54
JB
235 moduleName,
236 'constructor'
e9a4164c 237 ),
b52c969d
JB
238 ],
239 [
240 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
130783a7 241 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
51022aa0 242 'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
1b271a54
JB
243 moduleName,
244 'constructor'
e9a4164c 245 ),
b52c969d 246 ],
77b95a89
JB
247 [
248 OCPP16IncomingRequestCommand.DATA_TRANSFER,
130783a7 249 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
51022aa0 250 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
1b271a54
JB
251 moduleName,
252 'constructor'
e9a4164c 253 ),
77b95a89 254 ],
bfbda738
JB
255 [
256 OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
130783a7 257 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
51022aa0 258 'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
1b271a54
JB
259 moduleName,
260 'constructor'
e9a4164c 261 ),
bfbda738 262 ],
b52c969d 263 ]);
31f59c6d
JB
264 this.validatePayload = this.validatePayload.bind(this) as (
265 chargingStation: ChargingStation,
266 commandName: OCPP16IncomingRequestCommand,
267 commandPayload: JsonType
268 ) => boolean;
58144adb
JB
269 }
270
f7f98c68 271 public async incomingRequestHandler(
08f130a0 272 chargingStation: ChargingStation,
e7aeea18
JB
273 messageId: string,
274 commandName: OCPP16IncomingRequestCommand,
5cc4b63b 275 commandPayload: JsonType
e7aeea18 276 ): Promise<void> {
5cc4b63b 277 let response: JsonType;
e7aeea18 278 if (
3a13fc92 279 chargingStation.getOcppStrictCompliance() === true &&
f7c2994d 280 chargingStation.inPendingState() === true &&
e7aeea18
JB
281 (commandName === OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION ||
282 commandName === OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION)
283 ) {
284 throw new OCPPError(
285 ErrorType.SECURITY_ERROR,
e3018bc4 286 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
e7aeea18
JB
287 commandPayload,
288 null,
289 2
290 )} while the charging station is in pending state on the central server`,
7369e417
JB
291 commandName,
292 commandPayload
e7aeea18 293 );
caad9d6b 294 }
e7aeea18 295 if (
ed6cfcff
JB
296 chargingStation.isRegistered() === true ||
297 (chargingStation.getOcppStrictCompliance() === false &&
f7c2994d 298 chargingStation.inUnknownState() === true)
e7aeea18 299 ) {
65554cc3 300 if (
ed6cfcff
JB
301 this.incomingRequestHandlers.has(commandName) === true &&
302 OCPP16ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName) === true
65554cc3 303 ) {
124f3553 304 try {
9c5c4195 305 this.validatePayload(chargingStation, commandName, commandPayload);
c75a6675 306 // Call the method to build the response
08f130a0
JB
307 response = await this.incomingRequestHandlers.get(commandName)(
308 chargingStation,
309 commandPayload
310 );
124f3553
JB
311 } catch (error) {
312 // Log
6c8f5d90
JB
313 logger.error(
314 `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
315 error
316 );
124f3553
JB
317 throw error;
318 }
319 } else {
320 // Throw exception
e7aeea18
JB
321 throw new OCPPError(
322 ErrorType.NOT_IMPLEMENTED,
e3018bc4 323 `${commandName} is not implemented to handle request PDU ${JSON.stringify(
e7aeea18
JB
324 commandPayload,
325 null,
326 2
327 )}`,
7369e417
JB
328 commandName,
329 commandPayload
e7aeea18 330 );
c0560973
JB
331 }
332 } else {
e7aeea18
JB
333 throw new OCPPError(
334 ErrorType.SECURITY_ERROR,
e3018bc4 335 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
e7aeea18
JB
336 commandPayload,
337 null,
338 2
339 )} while the charging station is not registered on the central server.`,
7369e417
JB
340 commandName,
341 commandPayload
e7aeea18 342 );
c0560973 343 }
c75a6675 344 // Send the built response
08f130a0
JB
345 await chargingStation.ocppRequestService.sendResponse(
346 chargingStation,
347 messageId,
348 response,
349 commandName
350 );
c0560973
JB
351 }
352
9c5c4195
JB
353 private validatePayload(
354 chargingStation: ChargingStation,
355 commandName: OCPP16IncomingRequestCommand,
356 commandPayload: JsonType
357 ): boolean {
45988780 358 if (this.jsonSchemas.has(commandName) === true) {
9c5c4195
JB
359 return this.validateIncomingRequestPayload(
360 chargingStation,
361 commandName,
362 this.jsonSchemas.get(commandName),
363 commandPayload
364 );
365 }
366 logger.warn(
b3fc3ff5 367 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
9c5c4195
JB
368 );
369 return false;
370 }
371
c0560973 372 // Simulate charging station restart
08f130a0
JB
373 private handleRequestReset(
374 chargingStation: ChargingStation,
375 commandPayload: ResetRequest
f03e1042 376 ): GenericResponse {
27f08ad3
JB
377 this.runInAsyncScope(
378 chargingStation.reset.bind(chargingStation) as (
379 this: ChargingStation,
380 ...args: any[]
381 ) => Promise<void>,
382 chargingStation,
383 `${commandPayload.type}Reset` as OCPP16StopTransactionReason
59b6ed8d 384 ).catch(Constants.EMPTY_FUNCTION);
e7aeea18 385 logger.info(
08f130a0 386 `${chargingStation.logPrefix()} ${
e7aeea18
JB
387 commandPayload.type
388 } reset command received, simulating it. The station will be back online in ${Utils.formatDurationMilliSeconds(
08f130a0 389 chargingStation.stationInfo.resetTime
e7aeea18
JB
390 )}`
391 );
d8b1fab1 392 return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
c0560973
JB
393 }
394
e7aeea18 395 private async handleRequestUnlockConnector(
08f130a0 396 chargingStation: ChargingStation,
e7aeea18
JB
397 commandPayload: UnlockConnectorRequest
398 ): Promise<UnlockConnectorResponse> {
c0560973 399 const connectorId = commandPayload.connectorId;
a14022a2 400 if (chargingStation.hasConnector(connectorId) === false) {
c60ed4b8 401 logger.error(
2585c6e9 402 `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId.toString()}`
c60ed4b8 403 );
d8b1fab1 404 return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
c60ed4b8 405 }
c0560973 406 if (connectorId === 0) {
e7aeea18 407 logger.error(
2585c6e9 408 `${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId.toString()}`
e7aeea18 409 );
d8b1fab1 410 return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
c0560973 411 }
5e3cb728
JB
412 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
413 const stopResponse = await chargingStation.stopTransactionOnConnector(
414 connectorId,
415 OCPP16StopTransactionReason.UNLOCK_COMMAND
416 );
c0560973 417 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
d8b1fab1 418 return OCPP16Constants.OCPP_RESPONSE_UNLOCKED;
c0560973 419 }
d8b1fab1 420 return OCPP16Constants.OCPP_RESPONSE_UNLOCK_FAILED;
c0560973 421 }
4ecff7ce
JB
422 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
423 chargingStation,
ef6fa3fb 424 connectorId,
4ecff7ce
JB
425 OCPP16ChargePointStatus.Available
426 );
d8b1fab1 427 return OCPP16Constants.OCPP_RESPONSE_UNLOCKED;
c0560973
JB
428 }
429
e7aeea18 430 private handleRequestGetConfiguration(
08f130a0 431 chargingStation: ChargingStation,
e7aeea18
JB
432 commandPayload: GetConfigurationRequest
433 ): GetConfigurationResponse {
c0560973
JB
434 const configurationKey: OCPPConfigurationKey[] = [];
435 const unknownKey: string[] = [];
9a15316c 436 if (Utils.isUndefined(commandPayload.key) === true) {
08f130a0 437 for (const configuration of chargingStation.ocppConfiguration.configurationKey) {
a723e7e9 438 if (Utils.isUndefined(configuration.visible) === true) {
7f7b65ca 439 configuration.visible = true;
c0560973 440 }
da8629bb 441 if (configuration.visible === false) {
c0560973
JB
442 continue;
443 }
444 configurationKey.push({
7f7b65ca
JB
445 key: configuration.key,
446 readonly: configuration.readonly,
447 value: configuration.value,
c0560973
JB
448 });
449 }
9a15316c 450 } else if (Utils.isNotEmptyArray(commandPayload.key) === true) {
c0560973 451 for (const key of commandPayload.key) {
17ac262c
JB
452 const keyFound = ChargingStationConfigurationUtils.getConfigurationKey(
453 chargingStation,
acda9cab
JB
454 key,
455 true
17ac262c 456 );
c0560973 457 if (keyFound) {
a723e7e9 458 if (Utils.isUndefined(keyFound.visible) === true) {
c0560973
JB
459 keyFound.visible = true;
460 }
a723e7e9 461 if (keyFound.visible === false) {
c0560973
JB
462 continue;
463 }
464 configurationKey.push({
465 key: keyFound.key,
466 readonly: keyFound.readonly,
467 value: keyFound.value,
468 });
469 } else {
470 unknownKey.push(key);
471 }
472 }
473 }
474 return {
475 configurationKey,
476 unknownKey,
477 };
478 }
479
e7aeea18 480 private handleRequestChangeConfiguration(
08f130a0 481 chargingStation: ChargingStation,
e7aeea18
JB
482 commandPayload: ChangeConfigurationRequest
483 ): ChangeConfigurationResponse {
17ac262c
JB
484 const keyToChange = ChargingStationConfigurationUtils.getConfigurationKey(
485 chargingStation,
486 commandPayload.key,
487 true
488 );
c0560973 489 if (!keyToChange) {
d8b1fab1 490 return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED;
bd5d98e0 491 } else if (keyToChange?.readonly === true) {
d8b1fab1 492 return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED;
bd5d98e0 493 } else if (keyToChange?.readonly === false) {
c0560973 494 let valueChanged = false;
a95873d8 495 if (keyToChange.value !== commandPayload.value) {
17ac262c
JB
496 ChargingStationConfigurationUtils.setConfigurationKeyValue(
497 chargingStation,
498 commandPayload.key,
499 commandPayload.value,
500 true
501 );
c0560973
JB
502 valueChanged = true;
503 }
504 let triggerHeartbeatRestart = false;
505 if (keyToChange.key === OCPP16StandardParametersKey.HeartBeatInterval && valueChanged) {
17ac262c
JB
506 ChargingStationConfigurationUtils.setConfigurationKeyValue(
507 chargingStation,
e7aeea18
JB
508 OCPP16StandardParametersKey.HeartbeatInterval,
509 commandPayload.value
510 );
c0560973
JB
511 triggerHeartbeatRestart = true;
512 }
513 if (keyToChange.key === OCPP16StandardParametersKey.HeartbeatInterval && valueChanged) {
17ac262c
JB
514 ChargingStationConfigurationUtils.setConfigurationKeyValue(
515 chargingStation,
e7aeea18
JB
516 OCPP16StandardParametersKey.HeartBeatInterval,
517 commandPayload.value
518 );
c0560973
JB
519 triggerHeartbeatRestart = true;
520 }
521 if (triggerHeartbeatRestart) {
08f130a0 522 chargingStation.restartHeartbeat();
c0560973
JB
523 }
524 if (keyToChange.key === OCPP16StandardParametersKey.WebSocketPingInterval && valueChanged) {
08f130a0 525 chargingStation.restartWebSocketPing();
c0560973
JB
526 }
527 if (keyToChange.reboot) {
d8b1fab1 528 return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED;
c0560973 529 }
d8b1fab1 530 return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_ACCEPTED;
c0560973
JB
531 }
532 }
533
e7aeea18 534 private handleRequestSetChargingProfile(
08f130a0 535 chargingStation: ChargingStation,
e7aeea18
JB
536 commandPayload: SetChargingProfileRequest
537 ): SetChargingProfileResponse {
370ae4ee 538 if (
1789ba2c 539 OCPP16ServiceUtils.checkFeatureProfile(
08f130a0 540 chargingStation,
370ae4ee
JB
541 OCPP16SupportedFeatureProfiles.SmartCharging,
542 OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
1789ba2c 543 ) === false
370ae4ee 544 ) {
d8b1fab1 545 return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED;
68cb8b91 546 }
a14022a2 547 if (chargingStation.hasConnector(commandPayload.connectorId) === false) {
e7aeea18 548 logger.error(
2585c6e9 549 `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${
e7aeea18
JB
550 commandPayload.connectorId
551 }`
552 );
d8b1fab1 553 return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
c0560973 554 }
e7aeea18
JB
555 if (
556 commandPayload.csChargingProfiles.chargingProfilePurpose ===
0ac97927 557 OCPP16ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
e7aeea18
JB
558 commandPayload.connectorId !== 0
559 ) {
d8b1fab1 560 return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
c0560973 561 }
e7aeea18
JB
562 if (
563 commandPayload.csChargingProfiles.chargingProfilePurpose ===
0ac97927 564 OCPP16ChargingProfilePurposeType.TX_PROFILE &&
e7aeea18 565 (commandPayload.connectorId === 0 ||
5e3cb728
JB
566 chargingStation.getConnectorStatus(commandPayload.connectorId)?.transactionStarted ===
567 false)
e7aeea18 568 ) {
db0af086
JB
569 logger.error(
570 `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${
571 commandPayload.connectorId
572 } without a started transaction`
573 );
d8b1fab1 574 return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
c0560973 575 }
ed3d2808 576 OCPP16ServiceUtils.setChargingProfile(
7cb5b17f 577 chargingStation,
e7aeea18
JB
578 commandPayload.connectorId,
579 commandPayload.csChargingProfiles
580 );
581 logger.debug(
08f130a0 582 `${chargingStation.logPrefix()} Charging profile(s) set on connector id ${
ad8537a7 583 commandPayload.connectorId
ad67a158
JB
584 }: %j`,
585 commandPayload.csChargingProfiles
e7aeea18 586 );
d8b1fab1 587 return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED;
c0560973
JB
588 }
589
41189456
JB
590 private handleRequestGetCompositeSchedule(
591 chargingStation: ChargingStation,
592 commandPayload: OCPP16GetCompositeScheduleRequest
593 ): OCPP16GetCompositeScheduleResponse {
594 if (
595 OCPP16ServiceUtils.checkFeatureProfile(
596 chargingStation,
597 OCPP16SupportedFeatureProfiles.SmartCharging,
598 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
599 ) === false
600 ) {
d8b1fab1 601 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
41189456 602 }
a14022a2 603 if (chargingStation.hasConnector(commandPayload.connectorId) === false) {
41189456 604 logger.error(
2585c6e9 605 `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${
41189456
JB
606 commandPayload.connectorId
607 }`
608 );
d8b1fab1 609 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
41189456
JB
610 }
611 if (
612 Utils.isEmptyArray(
613 chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles
614 )
615 ) {
d8b1fab1 616 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
41189456
JB
617 }
618 const startDate = new Date();
619 const endDate = new Date(startDate.getTime() + commandPayload.duration * 1000);
620 let compositeSchedule: OCPP16ChargingSchedule;
621 for (const chargingProfile of chargingStation.getConnectorStatus(commandPayload.connectorId)
622 .chargingProfiles) {
623 // FIXME: build the composite schedule including the local power limit, the stack level, the charging rate unit, etc.
624 if (
625 chargingProfile.chargingSchedule?.startSchedule >= startDate &&
626 chargingProfile.chargingSchedule?.startSchedule <= endDate
627 ) {
628 compositeSchedule = chargingProfile.chargingSchedule;
629 break;
630 }
631 }
632 return {
633 status: GenericStatus.Accepted,
634 scheduleStart: compositeSchedule?.startSchedule,
635 connectorId: commandPayload.connectorId,
636 chargingSchedule: compositeSchedule,
637 };
638 }
639
e7aeea18 640 private handleRequestClearChargingProfile(
08f130a0 641 chargingStation: ChargingStation,
e7aeea18
JB
642 commandPayload: ClearChargingProfileRequest
643 ): ClearChargingProfileResponse {
370ae4ee 644 if (
a36bad10 645 OCPP16ServiceUtils.checkFeatureProfile(
08f130a0 646 chargingStation,
370ae4ee
JB
647 OCPP16SupportedFeatureProfiles.SmartCharging,
648 OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
a36bad10 649 ) === false
370ae4ee 650 ) {
d8b1fab1 651 return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
68cb8b91 652 }
a14022a2 653 if (chargingStation.hasConnector(commandPayload.connectorId) === false) {
e7aeea18 654 logger.error(
2585c6e9 655 `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${
e7aeea18
JB
656 commandPayload.connectorId
657 }`
658 );
d8b1fab1 659 return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
c0560973 660 }
d812bdcb
JB
661 if (
662 !Utils.isNullOrUndefined(commandPayload.connectorId) &&
4334db72
JB
663 Utils.isNotEmptyArray(
664 chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles
665 )
d812bdcb 666 ) {
4334db72 667 chargingStation.getConnectorStatus(commandPayload.connectorId).chargingProfiles = [];
e7aeea18 668 logger.debug(
08f130a0 669 `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${
ad8537a7 670 commandPayload.connectorId
ad67a158 671 }`
e7aeea18 672 );
d8b1fab1 673 return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
c0560973 674 }
d812bdcb 675 if (Utils.isNullOrUndefined(commandPayload.connectorId)) {
c0560973 676 let clearedCP = false;
4334db72
JB
677 const clearChargingProfiles = (connectorStatus: ConnectorStatus) => {
678 if (Utils.isNotEmptyArray(connectorStatus?.chargingProfiles)) {
679 connectorStatus?.chargingProfiles?.forEach(
680 (chargingProfile: OCPP16ChargingProfile, index: number) => {
e7aeea18
JB
681 let clearCurrentCP = false;
682 if (chargingProfile.chargingProfileId === commandPayload.id) {
683 clearCurrentCP = true;
684 }
685 if (
686 !commandPayload.chargingProfilePurpose &&
687 chargingProfile.stackLevel === commandPayload.stackLevel
688 ) {
689 clearCurrentCP = true;
690 }
691 if (
692 !chargingProfile.stackLevel &&
693 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
694 ) {
695 clearCurrentCP = true;
696 }
697 if (
698 chargingProfile.stackLevel === commandPayload.stackLevel &&
699 chargingProfile.chargingProfilePurpose === commandPayload.chargingProfilePurpose
700 ) {
701 clearCurrentCP = true;
702 }
703 if (clearCurrentCP) {
72092cfc 704 connectorStatus?.chargingProfiles?.splice(index, 1);
e7aeea18 705 logger.debug(
ad67a158
JB
706 `${chargingStation.logPrefix()} Matching charging profile(s) cleared: %j`,
707 chargingProfile
e7aeea18
JB
708 );
709 clearedCP = true;
710 }
4334db72
JB
711 }
712 );
713 }
714 };
715 if (chargingStation.hasEvses) {
716 for (const evseStatus of chargingStation.evses.values()) {
717 for (const connectorStatus of evseStatus.connectors.values()) {
718 clearChargingProfiles(connectorStatus);
719 }
720 }
721 } else {
722 for (const connectorId of chargingStation.connectors.keys()) {
723 clearChargingProfiles(chargingStation.getConnectorStatus(connectorId));
c0560973
JB
724 }
725 }
726 if (clearedCP) {
d8b1fab1 727 return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
c0560973
JB
728 }
729 }
d8b1fab1 730 return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
c0560973
JB
731 }
732
e7aeea18 733 private async handleRequestChangeAvailability(
08f130a0 734 chargingStation: ChargingStation,
e7aeea18
JB
735 commandPayload: ChangeAvailabilityRequest
736 ): Promise<ChangeAvailabilityResponse> {
c0560973 737 const connectorId: number = commandPayload.connectorId;
a14022a2 738 if (chargingStation.hasConnector(connectorId) === false) {
e7aeea18 739 logger.error(
2585c6e9 740 `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId.toString()}`
e7aeea18 741 );
d8b1fab1 742 return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
c0560973 743 }
e7aeea18 744 const chargePointStatus: OCPP16ChargePointStatus =
0d6f335f 745 commandPayload.type === OCPP16AvailabilityType.Operative
721646e9
JB
746 ? OCPP16ChargePointStatus.Available
747 : OCPP16ChargePointStatus.Unavailable;
c0560973 748 if (connectorId === 0) {
d8b1fab1
JB
749 let response: ChangeAvailabilityResponse =
750 OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
ded57f02
JB
751 const changeAvailability = async (id: number, connectorStatus: ConnectorStatus) => {
752 if (connectorStatus?.transactionStarted === true) {
d8b1fab1 753 response = OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
c0560973 754 }
ded57f02 755 connectorStatus.availability = commandPayload.type;
d8b1fab1 756 if (response === OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) {
4ecff7ce
JB
757 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
758 chargingStation,
759 id,
760 chargePointStatus
761 );
c0560973 762 }
ded57f02
JB
763 };
764 if (chargingStation.hasEvses) {
765 for (const evseStatus of chargingStation.evses.values()) {
766 for (const [id, connectorStatus] of evseStatus.connectors) {
767 await changeAvailability(id, connectorStatus);
768 }
769 }
770 } else {
771 for (const id of chargingStation.connectors.keys()) {
772 await changeAvailability(id, chargingStation.getConnectorStatus(id));
773 }
c0560973
JB
774 }
775 return response;
e7aeea18
JB
776 } else if (
777 connectorId > 0 &&
56eb297e
JB
778 (chargingStation.isChargingStationAvailable() === true ||
779 (chargingStation.isChargingStationAvailable() === false &&
0d6f335f 780 commandPayload.type === OCPP16AvailabilityType.Inoperative))
e7aeea18 781 ) {
5e3cb728 782 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
08f130a0 783 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
d8b1fab1 784 return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
c0560973 785 }
08f130a0 786 chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type;
4ecff7ce
JB
787 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
788 chargingStation,
ef6fa3fb 789 connectorId,
4ecff7ce
JB
790 chargePointStatus
791 );
d8b1fab1 792 return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
c0560973 793 }
d8b1fab1 794 return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED;
c0560973
JB
795 }
796
e7aeea18 797 private async handleRequestRemoteStartTransaction(
08f130a0 798 chargingStation: ChargingStation,
e7aeea18 799 commandPayload: RemoteStartTransactionRequest
f03e1042 800 ): Promise<GenericResponse> {
658e2d16 801 const transactionConnectorId = commandPayload.connectorId;
649287f8
JB
802 if (chargingStation.hasConnector(transactionConnectorId) === false) {
803 return this.notifyRemoteStartTransactionRejected(
4ecff7ce
JB
804 chargingStation,
805 transactionConnectorId,
649287f8 806 commandPayload.idTag
4ecff7ce 807 );
649287f8
JB
808 }
809 if (
810 chargingStation.isChargingStationAvailable() === false ||
811 chargingStation.isConnectorAvailable(transactionConnectorId) === false
812 ) {
813 return this.notifyRemoteStartTransactionRejected(
814 chargingStation,
815 transactionConnectorId,
816 commandPayload.idTag
817 );
818 }
819 const remoteStartTransactionLogMsg = `${chargingStation.logPrefix()} Transaction remotely STARTED on ${
820 chargingStation.stationInfo.chargingStationId
821 }#${transactionConnectorId.toString()} for idTag '${commandPayload.idTag}'`;
822 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
823 chargingStation,
824 transactionConnectorId,
825 OCPP16ChargePointStatus.Preparing
826 );
827 const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId);
828 // Check if authorized
829 if (chargingStation.getAuthorizeRemoteTxRequests() === true) {
830 let authorized = false;
62340a29 831 if (
649287f8
JB
832 chargingStation.getLocalAuthListEnabled() === true &&
833 chargingStation.hasIdTags() === true &&
834 Utils.isNotEmptyString(
835 chargingStation.idTagsCache
836 .getIdTags(ChargingStationUtils.getIdTagsFile(chargingStation.stationInfo))
837 ?.find((idTag) => idTag === commandPayload.idTag)
838 )
62340a29 839 ) {
649287f8
JB
840 connectorStatus.localAuthorizeIdTag = commandPayload.idTag;
841 connectorStatus.idTagLocalAuthorized = true;
842 authorized = true;
843 } else if (chargingStation.getMustAuthorizeAtRemoteStart() === true) {
844 connectorStatus.authorizeIdTag = commandPayload.idTag;
845 const authorizeResponse: OCPP16AuthorizeResponse =
846 await chargingStation.ocppRequestService.requestHandler<
847 OCPP16AuthorizeRequest,
848 OCPP16AuthorizeResponse
849 >(chargingStation, OCPP16RequestCommand.AUTHORIZE, {
850 idTag: commandPayload.idTag,
851 });
852 if (authorizeResponse?.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
853 authorized = true;
36f6a92e 854 }
649287f8
JB
855 } else {
856 logger.warn(
857 `${chargingStation.logPrefix()} The charging station configuration expects authorize at remote start transaction but local authorization or authorize isn't enabled`
858 );
859 }
860 if (authorized === true) {
861 // Authorization successful, start transaction
e7aeea18
JB
862 if (
863 this.setRemoteStartTransactionChargingProfile(
08f130a0 864 chargingStation,
e7aeea18
JB
865 transactionConnectorId,
866 commandPayload.chargingProfile
1789ba2c 867 ) === true
e7aeea18 868 ) {
658e2d16 869 connectorStatus.transactionRemoteStarted = true;
e7aeea18
JB
870 if (
871 (
08f130a0 872 await chargingStation.ocppRequestService.requestHandler<
ef6fa3fb
JB
873 OCPP16StartTransactionRequest,
874 OCPP16StartTransactionResponse
08f130a0 875 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
ef6fa3fb
JB
876 connectorId: transactionConnectorId,
877 idTag: commandPayload.idTag,
878 })
e7aeea18
JB
879 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
880 ) {
91a4f151 881 logger.debug(remoteStartTransactionLogMsg);
d8b1fab1 882 return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
e060fe58 883 }
e7aeea18 884 return this.notifyRemoteStartTransactionRejected(
08f130a0 885 chargingStation,
e7aeea18
JB
886 transactionConnectorId,
887 commandPayload.idTag
888 );
e060fe58 889 }
e7aeea18 890 return this.notifyRemoteStartTransactionRejected(
08f130a0 891 chargingStation,
e7aeea18
JB
892 transactionConnectorId,
893 commandPayload.idTag
894 );
c0560973 895 }
e7aeea18 896 return this.notifyRemoteStartTransactionRejected(
08f130a0 897 chargingStation,
e7aeea18
JB
898 transactionConnectorId,
899 commandPayload.idTag
900 );
c0560973 901 }
649287f8
JB
902 // No authorization check required, start transaction
903 if (
904 this.setRemoteStartTransactionChargingProfile(
905 chargingStation,
906 transactionConnectorId,
907 commandPayload.chargingProfile
908 ) === true
909 ) {
910 connectorStatus.transactionRemoteStarted = true;
911 if (
912 (
913 await chargingStation.ocppRequestService.requestHandler<
914 OCPP16StartTransactionRequest,
915 OCPP16StartTransactionResponse
916 >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
917 connectorId: transactionConnectorId,
918 idTag: commandPayload.idTag,
919 })
920 ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
921 ) {
922 logger.debug(remoteStartTransactionLogMsg);
923 return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
924 }
925 return this.notifyRemoteStartTransactionRejected(
926 chargingStation,
927 transactionConnectorId,
928 commandPayload.idTag
929 );
930 }
08f130a0
JB
931 return this.notifyRemoteStartTransactionRejected(
932 chargingStation,
933 transactionConnectorId,
934 commandPayload.idTag
935 );
a7fc8211
JB
936 }
937
e7aeea18 938 private async notifyRemoteStartTransactionRejected(
08f130a0 939 chargingStation: ChargingStation,
e7aeea18
JB
940 connectorId: number,
941 idTag: string
f03e1042 942 ): Promise<GenericResponse> {
e7aeea18 943 if (
721646e9 944 chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available
e7aeea18 945 ) {
4ecff7ce
JB
946 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
947 chargingStation,
ef6fa3fb 948 connectorId,
4ecff7ce
JB
949 OCPP16ChargePointStatus.Available
950 );
e060fe58 951 }
e7aeea18 952 logger.warn(
2585c6e9 953 `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId.toString()}, idTag '${idTag}', availability '${
72092cfc
JB
954 chargingStation.getConnectorStatus(connectorId)?.availability
955 }', status '${chargingStation.getConnectorStatus(connectorId)?.status}'`
e7aeea18 956 );
d8b1fab1 957 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
c0560973
JB
958 }
959
e7aeea18 960 private setRemoteStartTransactionChargingProfile(
08f130a0 961 chargingStation: ChargingStation,
e7aeea18
JB
962 connectorId: number,
963 cp: OCPP16ChargingProfile
964 ): boolean {
0ac97927 965 if (cp && cp.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) {
ed3d2808 966 OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, cp);
e7aeea18 967 logger.debug(
ad67a158
JB
968 `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}: %j`,
969 cp
e7aeea18 970 );
a7fc8211 971 return true;
0ac97927 972 } else if (cp && cp.chargingProfilePurpose !== OCPP16ChargingProfilePurposeType.TX_PROFILE) {
e7aeea18 973 logger.warn(
08f130a0 974 `${chargingStation.logPrefix()} Not allowed to set ${
e7aeea18
JB
975 cp.chargingProfilePurpose
976 } charging profile(s) at remote start transaction`
977 );
a7fc8211 978 return false;
e060fe58
JB
979 } else if (!cp) {
980 return true;
a7fc8211
JB
981 }
982 }
983
e7aeea18 984 private async handleRequestRemoteStopTransaction(
08f130a0 985 chargingStation: ChargingStation,
e7aeea18 986 commandPayload: RemoteStopTransactionRequest
f03e1042 987 ): Promise<GenericResponse> {
c0560973 988 const transactionId = commandPayload.transactionId;
ded57f02
JB
989 const remoteStopTransaction = async (connectorId: number): Promise<GenericResponse> => {
990 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
991 chargingStation,
992 connectorId,
993 OCPP16ChargePointStatus.Finishing
994 );
995 const stopResponse = await chargingStation.stopTransactionOnConnector(
996 connectorId,
997 OCPP16StopTransactionReason.REMOTE
998 );
999 if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
1000 return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
1001 }
1002 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
1003 };
1004 if (chargingStation.hasEvses) {
1005 for (const [evseId, evseStatus] of chargingStation.evses) {
1006 if (evseId > 0) {
1007 for (const [connectorId, connectorStatus] of evseStatus.connectors) {
1008 if (connectorStatus.transactionId === transactionId) {
1009 return remoteStopTransaction(connectorId);
1010 }
1011 }
1012 }
1013 }
1014 } else {
1015 for (const connectorId of chargingStation.connectors.keys()) {
1016 if (
1017 connectorId > 0 &&
1018 chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId
1019 ) {
1020 return remoteStopTransaction(connectorId);
ef6fa3fb 1021 }
c0560973
JB
1022 }
1023 }
44b9b577 1024 logger.warn(
54ebb82c 1025 `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id: ${transactionId.toString()}`
e7aeea18 1026 );
d8b1fab1 1027 return OCPP16Constants.OCPP_RESPONSE_REJECTED;
c0560973 1028 }
47e22477 1029
b03df580
JB
1030 private handleRequestUpdateFirmware(
1031 chargingStation: ChargingStation,
1032 commandPayload: OCPP16UpdateFirmwareRequest
1033 ): OCPP16UpdateFirmwareResponse {
1034 if (
1035 OCPP16ServiceUtils.checkFeatureProfile(
1036 chargingStation,
1037 OCPP16SupportedFeatureProfiles.FirmwareManagement,
1038 OCPP16IncomingRequestCommand.UPDATE_FIRMWARE
1039 ) === false
1040 ) {
5d280aae 1041 logger.warn(
90293abb 1042 `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`
5d280aae 1043 );
d8b1fab1 1044 return OCPP16Constants.OCPP_RESPONSE_EMPTY;
5d280aae
JB
1045 }
1046 if (
1047 !Utils.isNullOrUndefined(chargingStation.stationInfo.firmwareStatus) &&
1048 chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed
1049 ) {
1050 logger.warn(
90293abb 1051 `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`
5d280aae 1052 );
d8b1fab1 1053 return OCPP16Constants.OCPP_RESPONSE_EMPTY;
b03df580 1054 }
c9a4f9ea 1055 const retrieveDate = Utils.convertToDate(commandPayload.retrieveDate);
2c7bdc61 1056 const now = Date.now();
72092cfc 1057 if (retrieveDate?.getTime() <= now) {
27f08ad3 1058 this.runInAsyncScope(
62340a29 1059 this.updateFirmwareSimulation.bind(this) as (
27f08ad3
JB
1060 this: OCPP16IncomingRequestService,
1061 ...args: any[]
1062 ) => Promise<void>,
1063 this,
1064 chargingStation
59b6ed8d 1065 ).catch(Constants.EMPTY_FUNCTION);
c9a4f9ea
JB
1066 } else {
1067 setTimeout(() => {
62340a29 1068 this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION);
72092cfc 1069 }, retrieveDate?.getTime() - now);
c9a4f9ea 1070 }
d8b1fab1 1071 return OCPP16Constants.OCPP_RESPONSE_EMPTY;
c9a4f9ea
JB
1072 }
1073
62340a29 1074 private async updateFirmwareSimulation(
c9a4f9ea 1075 chargingStation: ChargingStation,
90293abb
JB
1076 maxDelay = 30,
1077 minDelay = 15
c9a4f9ea 1078 ): Promise<void> {
1bf29f5b
JB
1079 if (
1080 ChargingStationUtils.checkChargingStation(chargingStation, chargingStation.logPrefix()) ===
1081 false
1082 ) {
1083 return;
1084 }
ded57f02
JB
1085 if (chargingStation.hasEvses) {
1086 for (const [evseId, evseStatus] of chargingStation.evses) {
1087 if (evseId > 0) {
1088 for (const [connectorId, connectorStatus] of evseStatus.connectors) {
1089 if (connectorStatus?.transactionStarted === false) {
1090 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
1091 chargingStation,
1092 connectorId,
1093 OCPP16ChargePointStatus.Unavailable
1094 );
1095 }
1096 }
1097 }
1098 }
1099 } else {
1100 for (const connectorId of chargingStation.connectors.keys()) {
1101 if (
1102 connectorId > 0 &&
1103 chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false
1104 ) {
1105 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
1106 chargingStation,
1107 connectorId,
1108 OCPP16ChargePointStatus.Unavailable
1109 );
1110 }
c9a4f9ea
JB
1111 }
1112 }
93f0c2c8
JB
1113 await chargingStation.ocppRequestService.requestHandler<
1114 OCPP16FirmwareStatusNotificationRequest,
1115 OCPP16FirmwareStatusNotificationResponse
1116 >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
1117 status: OCPP16FirmwareStatus.Downloading,
1118 });
1119 chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloading;
5d280aae 1120 if (
93f0c2c8
JB
1121 chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
1122 OCPP16FirmwareStatus.DownloadFailed
5d280aae 1123 ) {
93f0c2c8 1124 await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
5d280aae
JB
1125 await chargingStation.ocppRequestService.requestHandler<
1126 OCPP16FirmwareStatusNotificationRequest,
1127 OCPP16FirmwareStatusNotificationResponse
1128 >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
15748260 1129 status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus,
5d280aae 1130 });
93f0c2c8
JB
1131 chargingStation.stationInfo.firmwareStatus =
1132 chargingStation.stationInfo?.firmwareUpgrade?.failureStatus;
5d280aae
JB
1133 return;
1134 }
90293abb 1135 await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
c9a4f9ea
JB
1136 await chargingStation.ocppRequestService.requestHandler<
1137 OCPP16FirmwareStatusNotificationRequest,
1138 OCPP16FirmwareStatusNotificationResponse
1139 >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
1140 status: OCPP16FirmwareStatus.Downloaded,
1141 });
1142 chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloaded;
380ccc42 1143 let wasTransactionsStarted = false;
62340a29
JB
1144 let transactionsStarted: boolean;
1145 do {
ded57f02
JB
1146 const runningTransactions = chargingStation.getNumberOfRunningTransactions();
1147 if (runningTransactions > 0) {
62340a29
JB
1148 const waitTime = 15 * 1000;
1149 logger.debug(
ded57f02 1150 `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${runningTransactions} transaction(s) in progress, waiting ${
62340a29
JB
1151 waitTime / 1000
1152 } seconds before continuing firmware update simulation`
1153 );
1154 await Utils.sleep(waitTime);
1155 transactionsStarted = true;
380ccc42 1156 wasTransactionsStarted = true;
62340a29 1157 } else {
ded57f02
JB
1158 if (chargingStation.hasEvses) {
1159 for (const [evseId, evseStatus] of chargingStation.evses) {
1160 if (evseId > 0) {
1161 for (const [connectorId, connectorStatus] of evseStatus.connectors) {
1162 if (connectorStatus?.status !== OCPP16ChargePointStatus.Unavailable) {
1163 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
1164 chargingStation,
1165 connectorId,
1166 OCPP16ChargePointStatus.Unavailable
1167 );
1168 }
1169 }
1170 }
1171 }
1172 } else {
1173 for (const connectorId of chargingStation.connectors.keys()) {
1174 if (
1175 connectorId > 0 &&
1176 chargingStation.getConnectorStatus(connectorId)?.status !==
1177 OCPP16ChargePointStatus.Unavailable
1178 ) {
1179 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
1180 chargingStation,
1181 connectorId,
1182 OCPP16ChargePointStatus.Unavailable
1183 );
1184 }
62340a29
JB
1185 }
1186 }
1187 transactionsStarted = false;
1188 }
1189 } while (transactionsStarted);
380ccc42
JB
1190 !wasTransactionsStarted &&
1191 (await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000));
1bf29f5b
JB
1192 if (
1193 ChargingStationUtils.checkChargingStation(chargingStation, chargingStation.logPrefix()) ===
1194 false
1195 ) {
1196 return;
1197 }
c9a4f9ea
JB
1198 await chargingStation.ocppRequestService.requestHandler<
1199 OCPP16FirmwareStatusNotificationRequest,
1200 OCPP16FirmwareStatusNotificationResponse
1201 >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
1202 status: OCPP16FirmwareStatus.Installing,
1203 });
1204 chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Installing;
93f0c2c8
JB
1205 if (
1206 chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
1207 OCPP16FirmwareStatus.InstallationFailed
1208 ) {
1209 await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
1210 await chargingStation.ocppRequestService.requestHandler<
1211 OCPP16FirmwareStatusNotificationRequest,
1212 OCPP16FirmwareStatusNotificationResponse
1213 >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
1214 status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus,
1215 });
1216 chargingStation.stationInfo.firmwareStatus =
1217 chargingStation.stationInfo?.firmwareUpgrade?.failureStatus;
1218 return;
1219 }
15748260 1220 if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) {
90293abb 1221 await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
5d280aae
JB
1222 await chargingStation.reset(OCPP16StopTransactionReason.REBOOT);
1223 }
b03df580
JB
1224 }
1225
e7aeea18 1226 private async handleRequestGetDiagnostics(
08f130a0 1227 chargingStation: ChargingStation,
e7aeea18
JB
1228 commandPayload: GetDiagnosticsRequest
1229 ): Promise<GetDiagnosticsResponse> {
68cb8b91 1230 if (
1789ba2c 1231 OCPP16ServiceUtils.checkFeatureProfile(
08f130a0 1232 chargingStation,
370ae4ee
JB
1233 OCPP16SupportedFeatureProfiles.FirmwareManagement,
1234 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1789ba2c 1235 ) === false
68cb8b91 1236 ) {
90293abb
JB
1237 logger.warn(
1238 `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`
1239 );
d8b1fab1 1240 return OCPP16Constants.OCPP_RESPONSE_EMPTY;
68cb8b91 1241 }
a3868ec4 1242 const uri = new URL(commandPayload.location);
47e22477
JB
1243 if (uri.protocol.startsWith('ftp:')) {
1244 let ftpClient: Client;
1245 try {
e7aeea18 1246 const logFiles = fs
51022aa0 1247 .readdirSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../'))
72092cfc
JB
1248 .filter((file) => file.endsWith('.log'))
1249 .map((file) => path.join('./', file));
44eb6026 1250 const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz`;
47e22477
JB
1251 tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive));
1252 ftpClient = new Client();
1253 const accessResponse = await ftpClient.access({
1254 host: uri.host,
5a2a53cf
JB
1255 ...(Utils.isNotEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }),
1256 ...(Utils.isNotEmptyString(uri.username) && { user: uri.username }),
1257 ...(Utils.isNotEmptyString(uri.password) && { password: uri.password }),
47e22477
JB
1258 });
1259 let uploadResponse: FTPResponse;
1260 if (accessResponse.code === 220) {
72092cfc 1261 ftpClient.trackProgress((info) => {
e7aeea18 1262 logger.info(
08f130a0 1263 `${chargingStation.logPrefix()} ${
e7aeea18
JB
1264 info.bytes / 1024
1265 } bytes transferred from diagnostics archive ${info.name}`
1266 );
6a8329b4
JB
1267 chargingStation.ocppRequestService
1268 .requestHandler<
1269 OCPP16DiagnosticsStatusNotificationRequest,
1270 OCPP16DiagnosticsStatusNotificationResponse
1271 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
1272 status: OCPP16DiagnosticsStatus.Uploading,
1273 })
72092cfc 1274 .catch((error) => {
6a8329b4
JB
1275 logger.error(
1276 `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${
1277 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
1278 }'`,
1279 error
1280 );
1281 });
47e22477 1282 });
e7aeea18 1283 uploadResponse = await ftpClient.uploadFrom(
0d8140bd 1284 path.join(
51022aa0 1285 path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../'),
0d8140bd
JB
1286 diagnosticsArchive
1287 ),
14ecae6a 1288 `${uri.pathname}${diagnosticsArchive}`
e7aeea18 1289 );
47e22477 1290 if (uploadResponse.code === 226) {
08f130a0 1291 await chargingStation.ocppRequestService.requestHandler<
c9a4f9ea
JB
1292 OCPP16DiagnosticsStatusNotificationRequest,
1293 OCPP16DiagnosticsStatusNotificationResponse
08f130a0 1294 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
ef6fa3fb
JB
1295 status: OCPP16DiagnosticsStatus.Uploaded,
1296 });
47e22477
JB
1297 if (ftpClient) {
1298 ftpClient.close();
1299 }
1300 return { fileName: diagnosticsArchive };
1301 }
e7aeea18
JB
1302 throw new OCPPError(
1303 ErrorType.GENERIC_ERROR,
1304 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
44eb6026 1305 uploadResponse?.code && `|${uploadResponse?.code.toString()}`
e7aeea18
JB
1306 }`,
1307 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1308 );
47e22477 1309 }
e7aeea18
JB
1310 throw new OCPPError(
1311 ErrorType.GENERIC_ERROR,
1312 `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${
44eb6026 1313 uploadResponse?.code && `|${uploadResponse?.code.toString()}`
e7aeea18
JB
1314 }`,
1315 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
1316 );
47e22477 1317 } catch (error) {
08f130a0 1318 await chargingStation.ocppRequestService.requestHandler<
c9a4f9ea
JB
1319 OCPP16DiagnosticsStatusNotificationRequest,
1320 OCPP16DiagnosticsStatusNotificationResponse
08f130a0 1321 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
ef6fa3fb
JB
1322 status: OCPP16DiagnosticsStatus.UploadFailed,
1323 });
47e22477
JB
1324 if (ftpClient) {
1325 ftpClient.close();
1326 }
e7aeea18 1327 return this.handleIncomingRequestError(
08f130a0 1328 chargingStation,
e7aeea18
JB
1329 OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
1330 error as Error,
d8b1fab1 1331 { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY }
e7aeea18 1332 );
47e22477
JB
1333 }
1334 } else {
e7aeea18 1335 logger.error(
08f130a0 1336 `${chargingStation.logPrefix()} Unsupported protocol ${
e7aeea18
JB
1337 uri.protocol
1338 } to transfer the diagnostic logs archive`
1339 );
08f130a0 1340 await chargingStation.ocppRequestService.requestHandler<
c9a4f9ea
JB
1341 OCPP16DiagnosticsStatusNotificationRequest,
1342 OCPP16DiagnosticsStatusNotificationResponse
08f130a0 1343 >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
ef6fa3fb
JB
1344 status: OCPP16DiagnosticsStatus.UploadFailed,
1345 });
d8b1fab1 1346 return OCPP16Constants.OCPP_RESPONSE_EMPTY;
47e22477
JB
1347 }
1348 }
802cfa13 1349
e7aeea18 1350 private handleRequestTriggerMessage(
08f130a0 1351 chargingStation: ChargingStation,
e7aeea18
JB
1352 commandPayload: OCPP16TriggerMessageRequest
1353 ): OCPP16TriggerMessageResponse {
370ae4ee
JB
1354 if (
1355 !OCPP16ServiceUtils.checkFeatureProfile(
08f130a0 1356 chargingStation,
370ae4ee
JB
1357 OCPP16SupportedFeatureProfiles.RemoteTrigger,
1358 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
c60ed4b8
JB
1359 ) ||
1360 !OCPP16ServiceUtils.isMessageTriggerSupported(
1361 chargingStation,
1362 commandPayload.requestedMessage
370ae4ee
JB
1363 )
1364 ) {
d8b1fab1 1365 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
68cb8b91 1366 }
c60ed4b8 1367 if (
4caa7e67 1368 !OCPP16ServiceUtils.isConnectorIdValid(
c60ed4b8
JB
1369 chargingStation,
1370 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
1371 commandPayload.connectorId
1372 )
1373 ) {
d8b1fab1 1374 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED;
dc661702 1375 }
802cfa13
JB
1376 try {
1377 switch (commandPayload.requestedMessage) {
c60ed4b8 1378 case OCPP16MessageTrigger.BootNotification:
802cfa13 1379 setTimeout(() => {
08f130a0 1380 chargingStation.ocppRequestService
f7f98c68 1381 .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
08f130a0 1382 chargingStation,
6a8b180d 1383 OCPP16RequestCommand.BOOT_NOTIFICATION,
8bfbc743 1384 chargingStation.bootNotificationRequest,
6a8b180d 1385 { skipBufferingOnError: true, triggerMessage: true }
e7aeea18 1386 )
72092cfc 1387 .then((response) => {
8bfbc743 1388 chargingStation.bootNotificationResponse = response;
ae711c83 1389 })
59b6ed8d 1390 .catch(Constants.EMPTY_FUNCTION);
d8b1fab1
JB
1391 }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1392 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
c60ed4b8 1393 case OCPP16MessageTrigger.Heartbeat:
802cfa13 1394 setTimeout(() => {
08f130a0 1395 chargingStation.ocppRequestService
f7f98c68 1396 .requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
08f130a0 1397 chargingStation,
ef6fa3fb
JB
1398 OCPP16RequestCommand.HEARTBEAT,
1399 null,
1400 {
1401 triggerMessage: true,
1402 }
1403 )
59b6ed8d 1404 .catch(Constants.EMPTY_FUNCTION);
d8b1fab1
JB
1405 }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1406 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
c60ed4b8 1407 case OCPP16MessageTrigger.StatusNotification:
dc661702 1408 setTimeout(() => {
d812bdcb 1409 if (!Utils.isNullOrUndefined(commandPayload?.connectorId)) {
08f130a0 1410 chargingStation.ocppRequestService
dc661702 1411 .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
08f130a0 1412 chargingStation,
dc661702
JB
1413 OCPP16RequestCommand.STATUS_NOTIFICATION,
1414 {
1415 connectorId: commandPayload.connectorId,
1416 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
72092cfc 1417 status: chargingStation.getConnectorStatus(commandPayload.connectorId)?.status,
dc661702
JB
1418 },
1419 {
1420 triggerMessage: true,
1421 }
1422 )
59b6ed8d 1423 .catch(Constants.EMPTY_FUNCTION);
dc661702 1424 } else {
ded57f02
JB
1425 // eslint-disable-next-line no-lonely-if
1426 if (chargingStation.hasEvses) {
1427 for (const evseStatus of chargingStation.evses.values()) {
1428 for (const [connectorId, connectorStatus] of evseStatus.connectors) {
1429 chargingStation.ocppRequestService
1430 .requestHandler<
1431 OCPP16StatusNotificationRequest,
1432 OCPP16StatusNotificationResponse
1433 >(
1434 chargingStation,
1435 OCPP16RequestCommand.STATUS_NOTIFICATION,
1436 {
1437 connectorId,
1438 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
1439 status: connectorStatus.status,
1440 },
1441 {
1442 triggerMessage: true,
1443 }
1444 )
1445 .catch(Constants.EMPTY_FUNCTION);
1446 }
1447 }
1448 } else {
1449 for (const connectorId of chargingStation.connectors.keys()) {
1450 chargingStation.ocppRequestService
1451 .requestHandler<
1452 OCPP16StatusNotificationRequest,
1453 OCPP16StatusNotificationResponse
1454 >(
1455 chargingStation,
1456 OCPP16RequestCommand.STATUS_NOTIFICATION,
1457 {
1458 connectorId,
1459 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
1460 status: chargingStation.getConnectorStatus(connectorId)?.status,
1461 },
1462 {
1463 triggerMessage: true,
1464 }
1465 )
1466 .catch(Constants.EMPTY_FUNCTION);
1467 }
dc661702
JB
1468 }
1469 }
d8b1fab1
JB
1470 }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY);
1471 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
802cfa13 1472 default:
d8b1fab1 1473 return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
802cfa13
JB
1474 }
1475 } catch (error) {
e7aeea18 1476 return this.handleIncomingRequestError(
08f130a0 1477 chargingStation,
e7aeea18
JB
1478 OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
1479 error as Error,
d8b1fab1 1480 { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED }
e7aeea18 1481 );
802cfa13
JB
1482 }
1483 }
77b95a89
JB
1484
1485 private handleRequestDataTransfer(
1486 chargingStation: ChargingStation,
1487 commandPayload: OCPP16DataTransferRequest
1488 ): OCPP16DataTransferResponse {
1489 try {
1490 if (Object.values(OCPP16DataTransferVendorId).includes(commandPayload.vendorId)) {
1491 return {
1492 status: OCPP16DataTransferStatus.ACCEPTED,
1493 };
1494 }
1495 return {
1496 status: OCPP16DataTransferStatus.UNKNOWN_VENDOR_ID,
1497 };
1498 } catch (error) {
1499 return this.handleIncomingRequestError(
1500 chargingStation,
1501 OCPP16IncomingRequestCommand.DATA_TRANSFER,
1502 error as Error,
d8b1fab1 1503 { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED }
77b95a89
JB
1504 );
1505 }
1506 }
c0560973 1507}