X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=7fcb12fb0b79353d7b61ae02b6e6f21dcb867b60;hb=53ac516c575adaacd199a68d39b5ace22876ee83;hp=03eb83f83de114e11f2f6865e2fbba2efe3a5bed;hpb=ad67a158ed1e333a255b49e0c8b4aaa9c7b85867;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 03eb83f8..7fcb12fb 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -1,8 +1,8 @@ // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved. -import fs from 'fs'; -import path from 'path'; -import { URL, fileURLToPath } from 'url'; +import fs from 'node:fs'; +import path from 'node:path'; +import { URL, fileURLToPath } from 'node:url'; import type { JSONSchemaType } from 'ajv'; import { Client, type FTPResponse } from 'basic-ftp'; @@ -140,84 +140,114 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer this.jsonSchemas = new Map>([ [ OCPP16IncomingRequestCommand.RESET, - this.parseJsonSchemaFile('../../../assets/json-schemas/ocpp/1.6/Reset.json'), + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/Reset.json', + moduleName, + 'constructor' + ), ], [ OCPP16IncomingRequestCommand.CLEAR_CACHE, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/ClearCache.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/ClearCache.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/UnlockConnector.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/UnlockConnector.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.GET_CONFIGURATION, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/GetConfiguration.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/GetConfiguration.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/ChangeConfiguration.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/ChangeConfiguration.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/GetDiagnostics.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/GetDiagnostics.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/SetChargingProfile.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/SetChargingProfile.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/ClearChargingProfile.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/ClearChargingProfile.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/ChangeAvailability.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/ChangeAvailability.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/TriggerMessage.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/TriggerMessage.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.DATA_TRANSFER, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json', + moduleName, + 'constructor' ), ], [ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE, - this.parseJsonSchemaFile( - '../../../assets/json-schemas/ocpp/1.6/UpdateFirmware.json' + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/UpdateFirmware.json', + moduleName, + 'constructor' ), ], ]); @@ -330,18 +360,16 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer chargingStation: ChargingStation, commandPayload: ResetRequest ): GenericResponse { - this.asyncResource - .runInAsyncScope( - chargingStation.reset.bind(chargingStation) as ( - this: ChargingStation, - ...args: any[] - ) => Promise, - chargingStation, - (commandPayload.type + 'Reset') as OCPP16StopTransactionReason - ) - .catch(() => { - /* This is intentional */ - }); + this.runInAsyncScope( + chargingStation.reset.bind(chargingStation) as ( + this: ChargingStation, + ...args: any[] + ) => Promise, + chargingStation, + `${commandPayload.type}Reset` as OCPP16StopTransactionReason + ).catch(() => { + /* This is intentional */ + }); logger.info( `${chargingStation.logPrefix()} ${ commandPayload.type @@ -365,7 +393,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer } if (connectorId === 0) { logger.error( - chargingStation.logPrefix() + ' Trying to unlock connector Id ' + connectorId.toString() + `${chargingStation.logPrefix()} Trying to unlock connector Id ${connectorId.toString()}` ); return OCPPConstants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED; } @@ -572,7 +600,10 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer return OCPPConstants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN; } const connectorStatus = chargingStation.getConnectorStatus(commandPayload.connectorId); - if (commandPayload.connectorId && !Utils.isEmptyArray(connectorStatus.chargingProfiles)) { + if ( + !Utils.isNullOrUndefined(commandPayload.connectorId) && + Utils.isNotEmptyArray(connectorStatus?.chargingProfiles) + ) { connectorStatus.chargingProfiles = []; logger.debug( `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${ @@ -581,13 +612,15 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer ); return OCPPConstants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED; } - if (!commandPayload.connectorId) { + if (Utils.isNullOrUndefined(commandPayload.connectorId)) { let clearedCP = false; for (const connectorId of chargingStation.connectors.keys()) { - if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) { + if ( + Utils.isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles) + ) { chargingStation .getConnectorStatus(connectorId) - .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => { + ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => { let clearCurrentCP = false; if (chargingProfile.chargingProfileId === commandPayload.id) { clearCurrentCP = true; @@ -611,7 +644,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer clearCurrentCP = true; } if (clearCurrentCP) { - connectorStatus.chargingProfiles.splice(index, 1); + connectorStatus?.chargingProfiles?.splice(index, 1); logger.debug( `${chargingStation.logPrefix()} Matching charging profile(s) cleared: %j`, chargingProfile @@ -694,15 +727,9 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer ): Promise { const transactionConnectorId = commandPayload.connectorId; if (chargingStation.connectors.has(transactionConnectorId) === true) { - const remoteStartTransactionLogMsg = - chargingStation.logPrefix() + - ' Transaction remotely STARTED on ' + - chargingStation.stationInfo.chargingStationId + - '#' + - transactionConnectorId.toString() + - " for idTag '" + - commandPayload.idTag + - "'"; + const remoteStartTransactionLogMsg = `${chargingStation.logPrefix()} Transaction remotely STARTED on ${ + chargingStation.stationInfo.chargingStationId + }#${transactionConnectorId.toString()} for idTag '${commandPayload.idTag}'`; await chargingStation.ocppRequestService.requestHandler< OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse @@ -720,11 +747,13 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer if ( chargingStation.getLocalAuthListEnabled() === true && chargingStation.hasAuthorizedTags() === true && - chargingStation.authorizedTagsCache - .getAuthorizedTags( - ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo) - ) - .find((idTag) => idTag === commandPayload.idTag) + Utils.isNotEmptyString( + chargingStation.authorizedTagsCache + .getAuthorizedTags( + ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo) + ) + ?.find((idTag) => idTag === commandPayload.idTag) + ) ) { connectorStatus.localAuthorizeIdTag = commandPayload.idTag; connectorStatus.idTagLocalAuthorized = true; @@ -842,7 +871,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer idTag: string ): Promise { if ( - chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE + chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.AVAILABLE ) { await chargingStation.ocppRequestService.requestHandler< OCPP16StatusNotificationRequest, @@ -855,16 +884,9 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE; } logger.warn( - chargingStation.logPrefix() + - ' Remote starting transaction REJECTED on connector Id ' + - connectorId.toString() + - ", idTag '" + - idTag + - "', availability '" + - chargingStation.getConnectorStatus(connectorId).availability + - "', status '" + - chargingStation.getConnectorStatus(connectorId).status + - "'" + `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector Id ${connectorId.toString()}, idTag '${idTag}', availability '${ + chargingStation.getConnectorStatus(connectorId)?.availability + }', status '${chargingStation.getConnectorStatus(connectorId)?.status}'` ); return OCPPConstants.OCPP_RESPONSE_REJECTED; } @@ -923,9 +945,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer } } logger.warn( - chargingStation.logPrefix() + - ' Trying to remote stop a non existing transaction ' + - transactionId.toString() + `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction ${transactionId.toString()}` ); return OCPPConstants.OCPP_RESPONSE_REJECTED; } @@ -956,25 +976,24 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer return OCPPConstants.OCPP_RESPONSE_EMPTY; } const retrieveDate = Utils.convertToDate(commandPayload.retrieveDate); - if (retrieveDate.getTime() <= Date.now()) { - this.asyncResource - .runInAsyncScope( - this.updateFirmware.bind(this) as ( - this: OCPP16IncomingRequestService, - ...args: any[] - ) => Promise, - this, - chargingStation - ) - .catch(() => { - /* This is intentional */ - }); + const now = Date.now(); + if (retrieveDate?.getTime() <= now) { + this.runInAsyncScope( + this.updateFirmware.bind(this) as ( + this: OCPP16IncomingRequestService, + ...args: any[] + ) => Promise, + this, + chargingStation + ).catch(() => { + /* This is intentional */ + }); } else { setTimeout(() => { this.updateFirmware(chargingStation).catch(() => { /* Intentional */ }); - }, retrieveDate.getTime() - Date.now()); + }, retrieveDate?.getTime() - now); } return OCPPConstants.OCPP_RESPONSE_EMPTY; } @@ -988,7 +1007,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer for (const connectorId of chargingStation.connectors.keys()) { if ( connectorId > 0 && - chargingStation.getConnectorStatus(connectorId).transactionStarted === false + chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false ) { await chargingStation.ocppRequestService.requestHandler< OCPP16StatusNotificationRequest, @@ -1004,7 +1023,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer } if ( chargingStation.stationInfo?.firmwareUpgrade?.failureStatus && - !Utils.isEmptyString(chargingStation.stationInfo?.firmwareUpgrade?.failureStatus) + Utils.isNotEmptyString(chargingStation.stationInfo?.firmwareUpgrade?.failureStatus) ) { await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, @@ -1067,14 +1086,14 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer .readdirSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../')) .filter((file) => file.endsWith('.log')) .map((file) => path.join('./', file)); - const diagnosticsArchive = chargingStation.stationInfo.chargingStationId + '_logs.tar.gz'; + const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz`; tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive)); ftpClient = new Client(); const accessResponse = await ftpClient.access({ host: uri.host, - ...(!Utils.isEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }), - ...(!Utils.isEmptyString(uri.username) && { user: uri.username }), - ...(!Utils.isEmptyString(uri.password) && { password: uri.password }), + ...(Utils.isNotEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }), + ...(Utils.isNotEmptyString(uri.username) && { user: uri.username }), + ...(Utils.isNotEmptyString(uri.password) && { password: uri.password }), }); let uploadResponse: FTPResponse; if (accessResponse.code === 220) { @@ -1105,7 +1124,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'), diagnosticsArchive ), - uri.pathname + diagnosticsArchive + `${uri.pathname}${diagnosticsArchive}` ); if (uploadResponse.code === 226) { await chargingStation.ocppRequestService.requestHandler< @@ -1122,7 +1141,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer throw new OCPPError( ErrorType.GENERIC_ERROR, `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${ - uploadResponse?.code && '|' + uploadResponse?.code.toString() + uploadResponse?.code && `|${uploadResponse?.code.toString()}` }`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS ); @@ -1130,7 +1149,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer throw new OCPPError( ErrorType.GENERIC_ERROR, `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${ - uploadResponse?.code && '|' + uploadResponse?.code.toString() + uploadResponse?.code && `|${uploadResponse?.code.toString()}` }`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS ); @@ -1230,7 +1249,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer return OCPPConstants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED; case OCPP16MessageTrigger.StatusNotification: setTimeout(() => { - if (commandPayload?.connectorId) { + if (!Utils.isNullOrUndefined(commandPayload?.connectorId)) { chargingStation.ocppRequestService .requestHandler( chargingStation, @@ -1238,7 +1257,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer { connectorId: commandPayload.connectorId, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(commandPayload.connectorId).status, + status: chargingStation.getConnectorStatus(commandPayload.connectorId)?.status, }, { triggerMessage: true, @@ -1259,7 +1278,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer { connectorId, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(connectorId).status, + status: chargingStation.getConnectorStatus(connectorId)?.status, }, { triggerMessage: true, @@ -1307,13 +1326,4 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer ); } } - - private parseJsonSchemaFile(relativePath: string): JSONSchemaType { - return JSON.parse( - fs.readFileSync( - path.resolve(path.dirname(fileURLToPath(import.meta.url)), relativePath), - 'utf8' - ) - ) as JSONSchemaType; - } }