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