X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=7c64c2ad20789cfbc0520956b7dfb1addb8cd0ef;hb=cd01b1d8f00898e27f78f4795650a78a179f0d14;hp=83230fb83c888dc5e1a64fe57e3285face6b8874;hpb=2c975e3a297739c2e71d5a2c1383452373b41bb3;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 83230fb8..7c64c2ad 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -1,26 +1,26 @@ // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. +import { randomInt } from 'node:crypto' import { createWriteStream, readdirSync } from 'node:fs' -import { dirname, join, resolve } from 'node:path' -import { URL, fileURLToPath } from 'node:url' +import { dirname, extname, join, resolve } from 'node:path' +import { fileURLToPath, URL } from 'node:url' import type { ValidateFunction } from 'ajv' import { Client, type FTPResponse } from 'basic-ftp' import { - type Interval, addSeconds, differenceInSeconds, + type Interval, isDate, secondsToMilliseconds } from 'date-fns' import { maxTime } from 'date-fns/constants' +import { isEmpty } from 'rambda' import { create } from 'tar' -import { OCPP16Constants } from './OCPP16Constants.js' -import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js' import { - type ChargingStation, canProceedChargingProfile, + type ChargingStation, checkChargingStation, getConfigurationKey, getConnectorChargingProfiles, @@ -32,6 +32,7 @@ import { OCPPError } from '../../../exception/index.js' import { type ChangeConfigurationRequest, type ChangeConfigurationResponse, + ConfigurationSection, ErrorType, type GenericResponse, GenericStatus, @@ -41,6 +42,7 @@ import { type GetDiagnosticsResponse, type IncomingRequestHandler, type JsonType, + type LogConfiguration, OCPP16AuthorizationStatus, OCPP16AvailabilityType, type OCPP16BootNotificationRequest, @@ -98,19 +100,20 @@ import { type UnlockConnectorResponse } from '../../../types/index.js' import { + Configuration, Constants, convertToDate, convertToInt, formatDurationMilliSeconds, - getRandomInteger, isAsyncFunction, - isEmptyArray, isNotEmptyArray, isNotEmptyString, logger, sleep } from '../../../utils/index.js' import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js' +import { OCPP16Constants } from './OCPP16Constants.js' +import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js' const moduleName = 'OCPP16IncomingRequestService' @@ -419,7 +422,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion chargingStation.getConnectorStatus(connectorId)!.transactionRemoteStarted = true chargingStation.ocppRequestService - .requestHandler( + .requestHandler, OCPP16StartTransactionResponse>( chargingStation, OCPP16RequestCommand.START_TRANSACTION, { @@ -430,15 +433,19 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .then(response => { if (response.status === OCPP16AuthorizationStatus.ACCEPTED) { logger.debug( - `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'` + `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId} for idTag '${idTag}'` ) } else { logger.debug( - `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'` + `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId} for idTag '${idTag}'` ) } }) - .catch(error => { + .catch((error: unknown) => { logger.error( `${chargingStation.logPrefix()} ${moduleName}.constructor: Remote start transaction error:`, error @@ -462,15 +469,19 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .then(response => { if (response.status === GenericStatus.Accepted) { logger.debug( - `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'` + `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId} for transaction '${transactionId}'` ) } else { logger.debug( - `${chargingStation.logPrefix()} Remote stop transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'` + `${chargingStation.logPrefix()} Remote stop transaction REJECTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId} for transaction '${transactionId}'` ) } }) - .catch(error => { + .catch((error: unknown) => { logger.error( `${chargingStation.logPrefix()} ${moduleName}.constructor: Remote stop transaction error:`, error @@ -490,7 +501,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return } const { requestedMessage, connectorId } = request - const errorHandler = (error: Error): void => { + const errorHandler = (error: unknown): void => { logger.error( `${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger ${requestedMessage} error:`, error @@ -502,7 +513,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .requestHandler( chargingStation, OCPP16RequestCommand.BOOT_NOTIFICATION, - chargingStation.bootNotificationRequest, + chargingStation.bootNotificationRequest as OCPP16BootNotificationRequest, { skipBufferingOnError: true, triggerMessage: true } ) .then(response => { @@ -531,7 +542,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { { connectorId, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(connectorId)?.status + status: chargingStation.getConnectorStatus(connectorId) + ?.status as OCPP16ChargePointStatus }, { triggerMessage: true @@ -551,7 +563,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { { connectorId: id, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status + status: connectorStatus.status as OCPP16ChargePointStatus }, { triggerMessage: true @@ -572,7 +584,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { { connectorId: id, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status + status: connectorStatus.status as OCPP16ChargePointStatus }, { triggerMessage: true @@ -940,8 +952,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } const connectorStatus = chargingStation.getConnectorStatus(connectorId) if ( - isEmptyArray(connectorStatus?.chargingProfiles) && - isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles) + isEmpty(connectorStatus?.chargingProfiles) && + isEmpty(chargingStation.getConnectorStatus(0)?.chargingProfiles) ) { return OCPP16Constants.OCPP_RESPONSE_REJECTED } @@ -1150,7 +1162,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ): Promise { const { connectorId: transactionConnectorId, idTag, chargingProfile } = commandPayload if (!chargingStation.hasConnector(transactionConnectorId)) { - return await this.notifyRemoteStartTransactionRejected( + return this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag @@ -1160,7 +1172,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { !chargingStation.isChargingStationAvailable() || !chargingStation.isConnectorAvailable(transactionConnectorId) ) { - return await this.notifyRemoteStartTransactionRejected( + return this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag @@ -1171,17 +1183,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.getAuthorizeRemoteTxRequests() && !(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag)) ) { - return await this.notifyRemoteStartTransactionRejected( + return this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag ) } - await OCPP16ServiceUtils.sendAndSetConnectorStatus( - chargingStation, - transactionConnectorId, - OCPP16ChargePointStatus.Preparing - ) if ( chargingProfile != null && !this.setRemoteStartTransactionChargingProfile( @@ -1190,33 +1197,32 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingProfile ) ) { - return await this.notifyRemoteStartTransactionRejected( + return this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag ) } logger.debug( - `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on connector id ${transactionConnectorId}, idTag '${idTag}'` + `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${transactionConnectorId}}, idTag '${idTag}'` ) return OCPP16Constants.OCPP_RESPONSE_ACCEPTED } - private async notifyRemoteStartTransactionRejected ( + private notifyRemoteStartTransactionRejected ( chargingStation: ChargingStation, connectorId: number, idTag: string - ): Promise { + ): GenericResponse { const connectorStatus = chargingStation.getConnectorStatus(connectorId) - if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) { - await OCPP16ServiceUtils.sendAndSetConnectorStatus( - chargingStation, - connectorId, - OCPP16ChargePointStatus.Available - ) - } logger.debug( - `${chargingStation.logPrefix()} Remote start transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'` + `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId}, idTag '${idTag}', availability '${ + connectorStatus?.availability + }', status '${connectorStatus?.status}'` ) return OCPP16Constants.OCPP_RESPONSE_REJECTED } @@ -1229,7 +1235,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { 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`, + `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on ${ + chargingStation.stationInfo?.chargingStationId + }#${connectorId}`, chargingProfile ) return true @@ -1343,7 +1351,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.DownloadFailed ) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1354,7 +1362,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo.firmwareUpgrade.failureStatus return } - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1410,8 +1418,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { transactionsStarted = false } } while (transactionsStarted) - !wasTransactionsStarted && - (await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))) + !wasTransactionsStarted && (await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))) if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) { return } @@ -1427,7 +1434,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.InstallationFailed ) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1439,7 +1446,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return } if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.reset(OCPP16StopTransactionReason.REBOOT) } } @@ -1465,9 +1472,17 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { if (uri.protocol.startsWith('ftp:')) { let ftpClient: Client | undefined try { - const logFiles = readdirSync(resolve(dirname(fileURLToPath(import.meta.url)), '../')) - .filter(file => file.endsWith('.log')) - .map(file => join('./', file)) + const logConfiguration = Configuration.getConfigurationSection( + ConfigurationSection.log + ) + const logFiles = readdirSync( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + resolve((fileURLToPath(import.meta.url), '../', dirname(logConfiguration.file!))) + ) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .filter(file => file.endsWith(extname(logConfiguration.file!))) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .map(file => join(dirname(logConfiguration.file!), file)) const diagnosticsArchive = `${chargingStation.stationInfo?.chargingStationId}_logs.tar.gz` create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive)) ftpClient = new Client() @@ -1492,7 +1507,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, { status: OCPP16DiagnosticsStatus.Uploading }) - .catch(error => { + .catch((error: unknown) => { logger.error( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION @@ -1721,7 +1736,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation, OCPP16IncomingRequestCommand.CANCEL_RESERVATION, error as Error, - { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED } + { + errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED + } )! } }