X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStationUtils.ts;h=28f38b4619738e81ba07708dc5c5676bf93017e7;hb=2a61222f10b8abdb97d022790e4ad543c4bd1d6c;hp=ffe90a776167d0e5535cce7b2057e5c5fe935528;hpb=0d8140bd623b67d6d7fddeda288fd945af0cb168;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStationUtils.ts b/src/charging-station/ChargingStationUtils.ts index ffe90a77..28f38b46 100644 --- a/src/charging-station/ChargingStationUtils.ts +++ b/src/charging-station/ChargingStationUtils.ts @@ -1,34 +1,41 @@ -import { ChargingProfile, ChargingSchedulePeriod } from '../types/ocpp/ChargingProfile'; -import { ChargingProfileKindType, RecurrencyKindType } from '../types/ocpp/1.6/ChargingProfile'; +import crypto from 'crypto'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +import moment from 'moment'; + +import BaseError from '../exception/BaseError'; +import type ChargingStationInfo from '../types/ChargingStationInfo'; import ChargingStationTemplate, { AmpereUnits, CurrentType, Voltage, } from '../types/ChargingStationTemplate'; +import type { SampledValueTemplate } from '../types/MeasurandPerPhaseSampledValueTemplates'; +import { ChargingProfileKindType, RecurrencyKindType } from '../types/ocpp/1.6/ChargingProfile'; +import type { ChargingProfile, ChargingSchedulePeriod } from '../types/ocpp/ChargingProfile'; +import { StandardParametersKey } from '../types/ocpp/Configuration'; import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues'; - -import BaseError from '../exception/BaseError'; -import { BootNotificationRequest } from '../types/ocpp/Requests'; -import ChargingStation from './ChargingStation'; -import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils'; -import ChargingStationInfo from '../types/ChargingStationInfo'; +import { + BootNotificationRequest, + IncomingRequestCommand, + RequestCommand, +} from '../types/ocpp/Requests'; +import { WorkerProcessType } from '../types/Worker'; import Configuration from '../utils/Configuration'; import Constants from '../utils/Constants'; -import { FileType } from '../types/FileType'; -import FileUtils from '../utils/FileUtils'; -import { SampledValueTemplate } from '../types/MeasurandPerPhaseSampledValueTemplates'; -import { StandardParametersKey } from '../types/ocpp/Configuration'; -import Utils from '../utils/Utils'; -import { WebSocketCloseEventStatusString } from '../types/WebSocket'; -import { WorkerProcessType } from '../types/Worker'; -import crypto from 'crypto'; -import { fileURLToPath } from 'url'; -import fs from 'fs'; import logger from '../utils/Logger'; -import moment from 'moment'; -import path from 'path'; +import Utils from '../utils/Utils'; +import type ChargingStation from './ChargingStation'; +import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils'; + +const moduleName = 'ChargingStationUtils'; export class ChargingStationUtils { + private constructor() { + // This is intentional + } + public static getChargingStationId( index: number, stationTemplate: ChargingStationTemplate @@ -160,38 +167,12 @@ export class ChargingStationUtils { public static workerPoolInUse(): boolean { return [WorkerProcessType.DYNAMIC_POOL, WorkerProcessType.STATIC_POOL].includes( - Configuration.getWorkerProcess() + Configuration.getWorker().processType ); } public static workerDynamicPoolInUse(): boolean { - return Configuration.getWorkerProcess() === WorkerProcessType.DYNAMIC_POOL; - } - - /** - * Convert websocket error code to human readable string message - * - * @param code websocket error code - * @returns human readable string message - */ - public static getWebSocketCloseEventStatusString(code: number): string { - if (code >= 0 && code <= 999) { - return '(Unused)'; - } else if (code >= 1016) { - if (code <= 1999) { - return '(For WebSocket standard)'; - } else if (code <= 2999) { - return '(For WebSocket extensions)'; - } else if (code <= 3999) { - return '(For libraries and frameworks)'; - } else if (code <= 4999) { - return '(For applications)'; - } - } - if (!Utils.isUndefined(WebSocketCloseEventStatusString[code])) { - return WebSocketCloseEventStatusString[code] as string; - } - return '(Unknown)'; + return Configuration.getWorker().processType === WorkerProcessType.DYNAMIC_POOL; } public static warnDeprecatedTemplateKey( @@ -232,7 +213,7 @@ export class ChargingStationUtils { delete stationTemplate.chargeBoxSerialNumberPrefix; delete stationTemplate.chargePointSerialNumberPrefix; delete stationTemplate.meterSerialNumberPrefix; - return stationTemplate; + return stationTemplate as unknown as ChargingStationInfo; } public static createStationInfoHash(stationInfo: ChargingStationInfo): void { @@ -324,6 +305,7 @@ export class ChargingStationUtils { limit: number; matchingChargingProfile: ChargingProfile; } | null { + const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`; for (const chargingProfile of chargingProfiles) { // Set helpers const currentMoment = moment(); @@ -367,10 +349,7 @@ export class ChargingStationUtils { limit: schedulePeriod.limit, matchingChargingProfile: chargingProfile, }; - logger.debug( - `${logPrefix} Matching charging profile found for power limitation: %j`, - result - ); + logger.debug(debugLogMsg, result); return result; } // Find the right schedule period @@ -384,10 +363,7 @@ export class ChargingStationUtils { limit: lastButOneSchedule.limit, matchingChargingProfile: chargingProfile, }; - logger.debug( - `${logPrefix} Matching charging profile found for power limitation: %j`, - result - ); + logger.debug(debugLogMsg, result); return result; } // Keep it @@ -403,10 +379,7 @@ export class ChargingStationUtils { limit: lastButOneSchedule.limit, matchingChargingProfile: chargingProfile, }; - logger.debug( - `${logPrefix} Matching charging profile found for power limitation: %j`, - result - ); + logger.debug(debugLogMsg, result); return result; } } @@ -420,7 +393,7 @@ export class ChargingStationUtils { templateFile: string, logPrefix: string ): Voltage { - const errMsg = `${logPrefix} Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`; + const errMsg = `Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`; let defaultVoltageOut: number; switch (currentType) { case CurrentType.AC: @@ -430,8 +403,8 @@ export class ChargingStationUtils { defaultVoltageOut = Voltage.VOLTAGE_400; break; default: - logger.error(errMsg); - throw new Error(errMsg); + logger.error(`${logPrefix} ${errMsg}`); + throw new BaseError(errMsg); } return defaultVoltageOut; } @@ -508,40 +481,15 @@ export class ChargingStationUtils { } } if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) { - const errorMsg = `${chargingStation.logPrefix()} Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`; - logger.error(errorMsg); - throw new Error(errorMsg); + const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`; + logger.error(`${chargingStation.logPrefix()} ${errorMsg}`); + throw new BaseError(errorMsg); } logger.debug( `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}` ); } - public static getAuthorizedTags( - stationInfo: ChargingStationInfo, - templateFile: string, - logPrefix: string - ): string[] { - let authorizedTags: string[] = []; - const authorizationFile = ChargingStationUtils.getAuthorizationFile(stationInfo); - if (authorizationFile) { - try { - // Load authorization file - authorizedTags = JSON.parse(fs.readFileSync(authorizationFile, 'utf8')) as string[]; - } catch (error) { - FileUtils.handleFileException( - logPrefix, - FileType.Authorization, - authorizationFile, - error as NodeJS.ErrnoException - ); - } - } else { - logger.info(logPrefix + ' No authorization file given in template file ' + templateFile); - } - return authorizedTags; - } - public static getAuthorizationFile(stationInfo: ChargingStationInfo): string | undefined { return ( stationInfo.authorizationFile && @@ -553,6 +501,40 @@ export class ChargingStationUtils { ); } + public static isRequestCommandSupported( + command: RequestCommand, + chargingStation: ChargingStation + ): boolean { + const isRequestCommand = Object.values(RequestCommand).includes(command); + if (isRequestCommand && !chargingStation.stationInfo?.commandsSupport?.outgoingCommands) { + return true; + } else if (isRequestCommand && chargingStation.stationInfo?.commandsSupport?.outgoingCommands) { + return chargingStation.stationInfo?.commandsSupport?.outgoingCommands[command] ?? false; + } + logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`); + return false; + } + + public static isIncomingRequestCommandSupported( + command: IncomingRequestCommand, + chargingStation: ChargingStation + ): boolean { + const isIncomingRequestCommand = Object.values(IncomingRequestCommand).includes(command); + if ( + isIncomingRequestCommand && + !chargingStation.stationInfo?.commandsSupport?.incomingCommands + ) { + return true; + } else if ( + isIncomingRequestCommand && + chargingStation.stationInfo?.commandsSupport?.incomingCommands + ) { + return chargingStation.stationInfo?.commandsSupport?.incomingCommands[command] ?? false; + } + logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`); + return false; + } + private static getRandomSerialNumberSuffix(params?: { randomBytesLength?: number; upperCase?: boolean;