X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2FOCPPServiceUtils.ts;h=d09d8b1a1afaffc72b9891ab52f72b48f6282c69;hb=08b58f0020986c0ad1b55e562aaf325a47b9d58c;hp=a4702dd6bcf242f3a2eeb234e5e65c985d9452f3;hpb=20f0b76c6d1eedd26a7a5d160101233f587ed6c5;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index a4702dd6..d09d8b1a 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -1,13 +1,14 @@ -import fs from 'node:fs'; -import path from 'node:path'; +import { readFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import type { DefinedError, ErrorObject, JSONSchemaType } from 'ajv'; +import { isDate } from 'date-fns'; import { OCPP16Constants } from './1.6/OCPP16Constants'; import { OCPP20Constants } from './2.0/OCPP20Constants'; import { OCPPConstants } from './OCPPConstants'; -import { type ChargingStation, ChargingStationConfigurationUtils } from '../../charging-station'; +import { type ChargingStation, getConfigurationKey } from '../../charging-station'; import { BaseError } from '../../exception'; import { ChargePointErrorCode, @@ -15,7 +16,6 @@ import { ErrorType, FileType, IncomingRequestCommand, - type JsonObject, type JsonType, MessageTrigger, MessageType, @@ -30,7 +30,13 @@ import { type StatusNotificationRequest, type StatusNotificationResponse, } from '../../types'; -import { ErrorUtils, Utils, logger } from '../../utils'; +import { + handleFileException, + isNotEmptyArray, + isNotEmptyString, + logPrefix, + logger, +} from '../../utils'; export class OCPPServiceUtils { protected constructor() { @@ -68,7 +74,7 @@ export class OCPPServiceUtils { public static isRequestCommandSupported( chargingStation: ChargingStation, - command: RequestCommand + command: RequestCommand, ): boolean { const isRequestCommand = Object.values(RequestCommand).includes(command); if ( @@ -88,7 +94,7 @@ export class OCPPServiceUtils { public static isIncomingRequestCommandSupported( chargingStation: ChargingStation, - command: IncomingRequestCommand + command: IncomingRequestCommand, ): boolean { const isIncomingRequestCommand = Object.values(IncomingRequestCommand).includes(command); @@ -109,7 +115,7 @@ export class OCPPServiceUtils { public static isMessageTriggerSupported( chargingStation: ChargingStation, - messageTrigger: MessageTrigger + messageTrigger: MessageTrigger, ): boolean { const isMessageTrigger = Object.values(MessageTrigger).includes(messageTrigger); if (isMessageTrigger === true && !chargingStation.stationInfo?.messageTriggerSupport) { @@ -118,7 +124,7 @@ export class OCPPServiceUtils { return chargingStation.stationInfo?.messageTriggerSupport[messageTrigger] ?? false; } logger.error( - `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'` + `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`, ); return false; } @@ -126,11 +132,11 @@ export class OCPPServiceUtils { public static isConnectorIdValid( chargingStation: ChargingStation, ocppCommand: IncomingRequestCommand, - connectorId: number + connectorId: number, ): boolean { if (connectorId < 0) { logger.error( - `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId}` + `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId}`, ); return false; } @@ -139,10 +145,14 @@ export class OCPPServiceUtils { public static convertDateToISOString(obj: T): void { for (const key in obj) { - if (obj[key] instanceof Date) { - (obj as JsonObject)[key] = (obj[key] as Date).toISOString(); - } else if (obj[key] !== null && typeof obj[key] === 'object') { - OCPPServiceUtils.convertDateToISOString(obj[key] as T); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + if (isDate(obj![key])) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + (obj![key] as string) = (obj![key] as Date).toISOString(); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + } else if (obj![key] !== null && typeof obj![key] === 'object') { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + OCPPServiceUtils.convertDateToISOString(obj![key] as T); } } } @@ -151,7 +161,7 @@ export class OCPPServiceUtils { chargingStation: ChargingStation, connectorId: number, status: ConnectorStatusEnum, - evseId?: number + evseId?: number, ): StatusNotificationRequest { switch (chargingStation.stationInfo.ocppVersion ?? OCPPVersion.VERSION_16) { case OCPPVersion.VERSION_16: @@ -185,37 +195,46 @@ export class OCPPServiceUtils { chargingStation: ChargingStation, connectorId: number, status: ConnectorStatusEnum, - evseId?: number + evseId?: number, + options?: { send: boolean }, ) { - OCPPServiceUtils.checkConnectorStatusTransition(chargingStation, connectorId, status); - await chargingStation.ocppRequestService.requestHandler< - StatusNotificationRequest, - StatusNotificationResponse - >( - chargingStation, - RequestCommand.STATUS_NOTIFICATION, - OCPPServiceUtils.buildStatusNotificationRequest(chargingStation, connectorId, status, evseId) - ); - chargingStation.getConnectorStatus(connectorId).status = status; + options = { send: true, ...options }; + if (options.send) { + OCPPServiceUtils.checkConnectorStatusTransition(chargingStation, connectorId, status); + await chargingStation.ocppRequestService.requestHandler< + StatusNotificationRequest, + StatusNotificationResponse + >( + chargingStation, + RequestCommand.STATUS_NOTIFICATION, + OCPPServiceUtils.buildStatusNotificationRequest( + chargingStation, + connectorId, + status, + evseId, + ), + ); + } + chargingStation.getConnectorStatus(connectorId)!.status = status; } protected static checkConnectorStatusTransition( chargingStation: ChargingStation, connectorId: number, - status: ConnectorStatusEnum + status: ConnectorStatusEnum, ): boolean { - const fromStatus = chargingStation.getConnectorStatus(connectorId).status; + const fromStatus = chargingStation.getConnectorStatus(connectorId)!.status; let transitionAllowed = false; switch (chargingStation.stationInfo.ocppVersion) { case OCPPVersion.VERSION_16: if ( (connectorId === 0 && OCPP16Constants.ChargePointStatusChargingStationTransitions.findIndex( - (transition) => transition.from === fromStatus && transition.to === status + (transition) => transition.from === fromStatus && transition.to === status, ) !== -1) || (connectorId > 0 && OCPP16Constants.ChargePointStatusConnectorTransitions.findIndex( - (transition) => transition.from === fromStatus && transition.to === status + (transition) => transition.from === fromStatus && transition.to === status, ) !== -1) ) { transitionAllowed = true; @@ -226,11 +245,11 @@ export class OCPPServiceUtils { if ( (connectorId === 0 && OCPP20Constants.ChargingStationStatusTransitions.findIndex( - (transition) => transition.from === fromStatus && transition.to === status + (transition) => transition.from === fromStatus && transition.to === status, ) !== -1) || (connectorId > 0 && OCPP20Constants.ConnectorStatusTransitions.findIndex( - (transition) => transition.from === fromStatus && transition.to === status + (transition) => transition.from === fromStatus && transition.to === status, ) !== -1) ) { transitionAllowed = true; @@ -239,7 +258,7 @@ export class OCPPServiceUtils { default: throw new BaseError( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `Cannot check connector status transition: OCPP version ${chargingStation.stationInfo.ocppVersion} not supported` + `Cannot check connector status transition: OCPP version ${chargingStation.stationInfo.ocppVersion} not supported`, ); } if (transitionAllowed === false) { @@ -247,8 +266,8 @@ export class OCPPServiceUtils { `${chargingStation.logPrefix()} OCPP ${ chargingStation.stationInfo.ocppVersion } connector id ${connectorId} status transition from '${ - chargingStation.getConnectorStatus(connectorId).status - }' to '${status}' is not allowed` + chargingStation.getConnectorStatus(connectorId)!.status + }' to '${status}' is not allowed`, ); } return transitionAllowed; @@ -258,19 +277,20 @@ export class OCPPServiceUtils { relativePath: string, ocppVersion: OCPPVersion, moduleName?: string, - methodName?: string + methodName?: string, ): JSONSchemaType { - const filePath = path.join(path.dirname(fileURLToPath(import.meta.url)), relativePath); + const filePath = join(dirname(fileURLToPath(import.meta.url)), relativePath); try { - return JSON.parse(fs.readFileSync(filePath, 'utf8')) as JSONSchemaType; + return JSON.parse(readFileSync(filePath, 'utf8')) as JSONSchemaType; } catch (error) { - ErrorUtils.handleFileException( + handleFileException( filePath, FileType.JsonSchema, error as NodeJS.ErrnoException, OCPPServiceUtils.logPrefix(ocppVersion, moduleName, methodName), - { throwError: false } + { throwError: false }, ); + return {} as JSONSchemaType; } } @@ -278,52 +298,52 @@ export class OCPPServiceUtils { chargingStation: ChargingStation, connectorId: number, measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER, - phase?: MeterValuePhase + phase?: MeterValuePhase, ): SampledValueTemplate | undefined { const onPhaseStr = phase ? `on phase ${phase} ` : ''; if (OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(measurand) === false) { logger.warn( - `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}` + `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`, ); return; } if ( measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER && - ChargingStationConfigurationUtils.getConfigurationKey( + getConfigurationKey( chargingStation, - StandardParametersKey.MeterValuesSampledData + StandardParametersKey.MeterValuesSampledData, )?.value?.includes(measurand) === false ) { logger.debug( `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId} not found in '${ StandardParametersKey.MeterValuesSampledData - }' OCPP parameter` + }' OCPP parameter`, ); return; } const sampledValueTemplates: SampledValueTemplate[] = - chargingStation.getConnectorStatus(connectorId)?.MeterValues; + chargingStation.getConnectorStatus(connectorId)!.MeterValues; for ( let index = 0; - Utils.isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length; + isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length; index++ ) { if ( OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes( sampledValueTemplates[index]?.measurand ?? - MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER + MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER, ) === false ) { logger.warn( - `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}` + `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`, ); } else if ( phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand && - ChargingStationConfigurationUtils.getConfigurationKey( + getConfigurationKey( chargingStation, - StandardParametersKey.MeterValuesSampledData + StandardParametersKey.MeterValuesSampledData, )?.value?.includes(measurand) === true ) { return sampledValueTemplates[index]; @@ -331,9 +351,9 @@ export class OCPPServiceUtils { !phase && !sampledValueTemplates[index].phase && sampledValueTemplates[index]?.measurand === measurand && - ChargingStationConfigurationUtils.getConfigurationKey( + getConfigurationKey( chargingStation, - StandardParametersKey.MeterValuesSampledData + StandardParametersKey.MeterValuesSampledData, )?.value?.includes(measurand) === true ) { return sampledValueTemplates[index]; @@ -351,7 +371,7 @@ export class OCPPServiceUtils { throw new BaseError(errorMsg); } logger.debug( - `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}` + `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`, ); } @@ -361,7 +381,7 @@ export class OCPPServiceUtils { options: { limitationEnabled?: boolean; unitMultiplier?: number } = { limitationEnabled: true, unitMultiplier: 1, - } + }, ): number { options = { ...{ @@ -373,19 +393,19 @@ export class OCPPServiceUtils { const parsedInt = parseInt(value); const numberValue = isNaN(parsedInt) ? Infinity : parsedInt; return options?.limitationEnabled - ? Math.min(numberValue * options.unitMultiplier, limit) - : numberValue * options.unitMultiplier; + ? Math.min(numberValue * options.unitMultiplier!, limit) + : numberValue * options.unitMultiplier!; } private static logPrefix = ( ocppVersion: OCPPVersion, moduleName?: string, - methodName?: string + methodName?: string, ): string => { const logMsg = - Utils.isNotEmptyString(moduleName) && Utils.isNotEmptyString(methodName) + isNotEmptyString(moduleName) && isNotEmptyString(methodName) ? ` OCPP ${ocppVersion} | ${moduleName}.${methodName}:` : ` OCPP ${ocppVersion} |`; - return Utils.logPrefix(logMsg); + return logPrefix(logMsg); }; }