X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=a61dedd8edcfebfd6e0b26a17672ae7695f6d7d5;hb=a095d7d7fc3f3e99d472b4c57f355414c5bcb852;hp=2f2ef4c10cbaa63dda8bc74c0577efd6c4c086c5;hpb=300418e9ba42d252a1a7079dab7904f40561a7ef;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 2f2ef4c1..a61dedd8 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -1,4 +1,4 @@ -// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved. +// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. import { createWriteStream, readdirSync } from 'node:fs' import { dirname, join, resolve } from 'node:path' @@ -120,8 +120,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { > public constructor () { - // if (new.target?.name === moduleName) { - // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`) + // if (new.target.name === moduleName) { + // throw new TypeError(`Cannot construct ${new.target.name} instances directly`) // } super(OCPPVersion.VERSION_16) this.incomingRequestHandlers = new Map([ @@ -454,7 +454,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { logger.info( `${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be back online in ${formatDurationMilliSeconds( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - chargingStation.stationInfo.resetTime! + chargingStation.stationInfo!.resetTime! )}` ) return OCPP16Constants.OCPP_RESPONSE_ACCEPTED @@ -502,27 +502,21 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const unknownKey: string[] = [] if (key == null) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - for (const configuration of chargingStation.ocppConfiguration!.configurationKey!) { - if (configuration.visible == null) { - configuration.visible = true - } - if (!configuration.visible) { + for (const configKey of chargingStation.ocppConfiguration!.configurationKey!) { + if (!OCPP16ServiceUtils.isConfigurationKeyVisible(configKey)) { continue } configurationKey.push({ - key: configuration.key, - readonly: configuration.readonly, - value: configuration.value + key: configKey.key, + readonly: configKey.readonly, + value: configKey.value }) } } else if (isNotEmptyArray(key)) { for (const k of key) { const keyFound = getConfigurationKey(chargingStation, k, true) if (keyFound != null) { - if (keyFound.visible == null) { - keyFound.visible = true - } - if (!keyFound.visible) { + if (!OCPP16ServiceUtils.isConfigurationKeyVisible(keyFound)) { continue } configurationKey.push({ @@ -649,12 +643,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE && connectorId > 0 && connectorStatus?.transactionStarted === true && - csChargingProfiles.transactionId !== connectorStatus?.transactionId + csChargingProfiles.transactionId !== connectorStatus.transactionId ) { logger.error( `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} with a different transaction id ${ csChargingProfiles.transactionId - } than the started transaction id ${connectorStatus?.transactionId}` + } than the started transaction id ${connectorStatus.transactionId}` ) return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED } @@ -697,13 +691,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { `${chargingStation.logPrefix()} Get composite schedule with a specified rate unit is not yet supported, no conversion will be done` ) } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const connectorStatus = chargingStation.getConnectorStatus(connectorId)! + const connectorStatus = chargingStation.getConnectorStatus(connectorId) if ( - isEmptyArray( - connectorStatus?.chargingProfiles != null && - isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles) - ) + isEmptyArray(connectorStatus?.chargingProfiles) && + isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles) ) { return OCPP16Constants.OCPP_RESPONSE_REJECTED } @@ -720,10 +711,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { let previousCompositeSchedule: OCPP16ChargingSchedule | undefined let compositeSchedule: OCPP16ChargingSchedule | undefined for (const chargingProfile of chargingProfiles) { - if ( - chargingProfile.chargingSchedule?.startSchedule == null && - connectorStatus?.transactionStarted === true - ) { + if (chargingProfile.chargingSchedule.startSchedule == null) { logger.debug( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ chargingProfile.chargingProfileId @@ -732,24 +720,17 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart } - if ( - chargingProfile.chargingSchedule?.startSchedule != null && - !isDate(chargingProfile.chargingSchedule?.startSchedule) - ) { + if (!isDate(chargingProfile.chargingSchedule.startSchedule)) { logger.warn( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ chargingProfile.chargingProfileId } startSchedule property is not a Date instance. Trying to convert it to a Date instance` ) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion chargingProfile.chargingSchedule.startSchedule = convertToDate( - chargingProfile.chargingSchedule?.startSchedule - )! + chargingProfile.chargingSchedule.startSchedule + ) } - if ( - chargingProfile.chargingSchedule?.startSchedule != null && - chargingProfile.chargingSchedule?.duration == null - ) { + if (chargingProfile.chargingSchedule.duration == null) { logger.debug( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ chargingProfile.chargingProfileId @@ -758,14 +739,15 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // OCPP specifies that if duration is not defined, it should be infinite chargingProfile.chargingSchedule.duration = differenceInSeconds( maxTime, - chargingProfile.chargingSchedule.startSchedule + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingProfile.chargingSchedule.startSchedule! ) } if ( !prepareChargingProfileKind( connectorStatus, chargingProfile, - compositeScheduleInterval.start as Date, + compositeScheduleInterval.start, chargingStation.logPrefix() ) ) { @@ -774,7 +756,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { if ( !canProceedChargingProfile( chargingProfile, - compositeScheduleInterval.start as Date, + compositeScheduleInterval.start, chargingStation.logPrefix() ) ) { @@ -790,8 +772,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { if (compositeSchedule != null) { return { status: GenericStatus.Accepted, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - scheduleStart: compositeSchedule.startSchedule!, + scheduleStart: compositeSchedule.startSchedule, connectorId, chargingSchedule: compositeSchedule } @@ -823,8 +804,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const connectorStatus = chargingStation.getConnectorStatus(connectorId!) if (connectorId != null && isNotEmptyArray(connectorStatus?.chargingProfiles)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - connectorStatus!.chargingProfiles = [] + connectorStatus.chargingProfiles = [] logger.debug( `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}` ) @@ -874,7 +854,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ? OCPP16ChargePointStatus.Available : OCPP16ChargePointStatus.Unavailable if (connectorId === 0) { - let response: OCPP16ChangeAvailabilityResponse + let response: OCPP16ChangeAvailabilityResponse | undefined if (chargingStation.hasEvses) { for (const evseStatus of chargingStation.evses.values()) { response = await OCPP16ServiceUtils.changeAvailability( @@ -941,7 +921,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } const remoteStartTransactionLogMsg = ` ${chargingStation.logPrefix()} Transaction remotely STARTED on ${ - chargingStation.stationInfo.chargingStationId + chargingStation.stationInfo?.chargingStationId }#${transactionConnectorId} for idTag '${idTag}'` await OCPP16ServiceUtils.sendAndSetConnectorStatus( chargingStation, @@ -1054,7 +1034,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId: number, chargingProfile: OCPP16ChargingProfile ): boolean { - if (chargingProfile?.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) { + if (chargingProfile.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) { OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile) logger.debug( `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}: %j`, @@ -1117,28 +1097,22 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) return OCPP16Constants.OCPP_RESPONSE_EMPTY } - let { retrieveDate } = commandPayload - if ( - chargingStation.stationInfo.firmwareStatus != null && - chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed - ) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + commandPayload.retrieveDate = convertToDate(commandPayload.retrieveDate)! + const { retrieveDate } = commandPayload + if (chargingStation.stationInfo?.firmwareStatus !== OCPP16FirmwareStatus.Installed) { logger.warn( `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress` ) return OCPP16Constants.OCPP_RESPONSE_EMPTY } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - retrieveDate = convertToDate(retrieveDate)! const now = Date.now() - if (retrieveDate?.getTime() <= now) { + if (retrieveDate.getTime() <= now) { this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION) } else { - setTimeout( - () => { - this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION) - }, - retrieveDate?.getTime() - now - ) + setTimeout(() => { + this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION) + }, retrieveDate.getTime() - now) } return OCPP16Constants.OCPP_RESPONSE_EMPTY } @@ -1155,7 +1129,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { for (const [evseId, evseStatus] of chargingStation.evses) { if (evseId > 0) { for (const [connectorId, connectorStatus] of evseStatus.connectors) { - if (connectorStatus?.transactionStarted === false) { + if (connectorStatus.transactionStarted === false) { await OCPP16ServiceUtils.sendAndSetConnectorStatus( chargingStation, connectorId, @@ -1185,7 +1159,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, { status: OCPP16FirmwareStatus.Downloading }) - chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloading + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloading if ( chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.DownloadFailed @@ -1195,10 +1170,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, { - status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus + status: chargingStation.stationInfo.firmwareUpgrade.failureStatus }) chargingStation.stationInfo.firmwareStatus = - chargingStation.stationInfo?.firmwareUpgrade?.failureStatus + chargingStation.stationInfo.firmwareUpgrade.failureStatus return } await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) @@ -1208,7 +1183,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, { status: OCPP16FirmwareStatus.Downloaded }) - chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloaded + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloaded let wasTransactionsStarted = false let transactionsStarted: boolean do { @@ -1228,7 +1204,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { for (const [evseId, evseStatus] of chargingStation.evses) { if (evseId > 0) { for (const [connectorId, connectorStatus] of evseStatus.connectors) { - if (connectorStatus?.status !== OCPP16ChargePointStatus.Unavailable) { + if (connectorStatus.status !== OCPP16ChargePointStatus.Unavailable) { await OCPP16ServiceUtils.sendAndSetConnectorStatus( chargingStation, connectorId, @@ -1267,7 +1243,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, { status: OCPP16FirmwareStatus.Installing }) - chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Installing + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Installing if ( chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.InstallationFailed @@ -1277,10 +1254,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, { - status: chargingStation.stationInfo?.firmwareUpgrade?.failureStatus + status: chargingStation.stationInfo.firmwareUpgrade.failureStatus }) chargingStation.stationInfo.firmwareStatus = - chargingStation.stationInfo?.firmwareUpgrade?.failureStatus + chargingStation.stationInfo.firmwareUpgrade.failureStatus return } if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) { @@ -1311,9 +1288,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { let ftpClient: Client | undefined try { const logFiles = readdirSync(resolve(dirname(fileURLToPath(import.meta.url)), '../')) - .filter((file) => file.endsWith('.log')) - .map((file) => join('./', file)) - const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz` + .filter(file => file.endsWith('.log')) + .map(file => join('./', file)) + const diagnosticsArchive = `${chargingStation.stationInfo?.chargingStationId}_logs.tar.gz` create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive)) ftpClient = new Client() const accessResponse = await ftpClient.access({ @@ -1324,7 +1301,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { }) let uploadResponse: FTPResponse | undefined if (accessResponse.code === 220) { - ftpClient.trackProgress((info) => { + ftpClient.trackProgress(info => { logger.info( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: ${ info.bytes / 1024 @@ -1337,7 +1314,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, { status: OCPP16DiagnosticsStatus.Uploading }) - .catch((error) => { + .catch(error => { logger.error( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION @@ -1357,24 +1334,18 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, { status: OCPP16DiagnosticsStatus.Uploaded }) - if (ftpClient != null) { - ftpClient.close() - } + ftpClient.close() return { fileName: diagnosticsArchive } } throw new OCPPError( ErrorType.GENERIC_ERROR, - `Diagnostics transfer failed with error code ${accessResponse.code}${ - uploadResponse?.code != null && `|${uploadResponse?.code}` - }`, + `Diagnostics transfer failed with error code ${accessResponse.code}|${uploadResponse.code}`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS ) } throw new OCPPError( ErrorType.GENERIC_ERROR, - `Diagnostics transfer failed with error code ${accessResponse.code}${ - uploadResponse?.code != null && `|${uploadResponse?.code}` - }`, + `Diagnostics transfer failed with error code ${accessResponse.code}|${uploadResponse?.code}`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS ) } catch (error) { @@ -1384,9 +1355,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, { status: OCPP16DiagnosticsStatus.UploadFailed }) - if (ftpClient != null) { - ftpClient.close() - } + ftpClient?.close() // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.handleIncomingRequestError( chargingStation, @@ -1447,7 +1416,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.bootNotificationRequest, { skipBufferingOnError: true, triggerMessage: true } ) - .then((response) => { + .then(response => { chargingStation.bootNotificationResponse = response }) .catch(Constants.EMPTY_FUNCTION) @@ -1484,31 +1453,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } ) .catch(Constants.EMPTY_FUNCTION) - } else { - if (chargingStation.hasEvses) { - for (const evseStatus of chargingStation.evses.values()) { - for (const [id, connectorStatus] of evseStatus.connectors) { - chargingStation.ocppRequestService - .requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >( - chargingStation, - OCPP16RequestCommand.STATUS_NOTIFICATION, - { - connectorId: id, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status - }, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - } - } - } else { - for (const id of chargingStation.connectors.keys()) { + } else if (chargingStation.hasEvses) { + for (const evseStatus of chargingStation.evses.values()) { + for (const [id, connectorStatus] of evseStatus.connectors) { chargingStation.ocppRequestService .requestHandler< OCPP16StatusNotificationRequest, @@ -1519,7 +1466,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { { connectorId: id, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(id)?.status + status: connectorStatus.status }, { triggerMessage: true @@ -1528,6 +1475,26 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .catch(Constants.EMPTY_FUNCTION) } } + } else { + for (const [id, connectorStatus] of chargingStation.connectors) { + chargingStation.ocppRequestService + .requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >( + chargingStation, + OCPP16RequestCommand.STATUS_NOTIFICATION, + { + connectorId: id, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + status: connectorStatus.status + }, + { + triggerMessage: true + } + ) + .catch(Constants.EMPTY_FUNCTION) + } } }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY) return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED @@ -1579,6 +1546,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) { return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + commandPayload.expiryDate = convertToDate(commandPayload.expiryDate)! const { reservationId, idTag, connectorId } = commandPayload let response: OCPP16ReserveNowResponse try { @@ -1592,8 +1561,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED } await removeExpiredReservations(chargingStation) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - switch (chargingStation.getConnectorStatus(connectorId)!.status) { + switch (chargingStation.getConnectorStatus(connectorId)?.status) { case OCPP16ChargePointStatus.Faulted: response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED break