X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=e41ea5ec79980db46558684cca08f2ff9cab6d38;hb=5dcb9d4945027c6be39e4342f1627ea2da3813b7;hp=f79a59cea3943c2c9a79ca7c6cde8b37582b3d85;hpb=a33026fe3cd6ce141efa55d27d35b4eb5c1a54b9;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index f79a59ce..e41ea5ec 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -1,67 +1,16 @@ // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. -import { createHash } from 'node:crypto' +import { createHash, randomInt } from 'node:crypto' import { EventEmitter } from 'node:events' -import { type FSWatcher, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs' +import { existsSync, type FSWatcher, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { URL } from 'node:url' import { parentPort } from 'node:worker_threads' import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns' -import { mergeDeepRight } from 'rambda' +import { mergeDeepRight, once } from 'rambda' import { type RawData, WebSocket } from 'ws' -import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js' -import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel.js' -import { - addConfigurationKey, - deleteConfigurationKey, - getConfigurationKey, - setConfigurationKeyValue -} from './ConfigurationKeyUtils.js' -import { - buildConnectorsMap, - checkChargingStation, - checkConfiguration, - checkConnectorsConfiguration, - checkStationInfoConnectorStatus, - checkTemplate, - createBootNotificationRequest, - createSerialNumber, - getAmperageLimitationUnitDivider, - getBootConnectorStatus, - getChargingStationConnectorChargingProfilesPowerLimit, - getChargingStationId, - getDefaultVoltageOut, - getHashId, - getIdTagsFile, - getMaxNumberOfEvses, - getNumberOfReservableConnectors, - getPhaseRotationValue, - hasFeatureProfile, - hasReservationExpired, - initializeConnectorsMapStatus, - propagateSerialNumber, - setChargingStationOptions, - stationTemplateToStationInfo, - warnTemplateKeysDeprecation -} from './Helpers.js' -import { IdTagsCache } from './IdTagsCache.js' -import { - OCPP16IncomingRequestService, - OCPP16RequestService, - OCPP16ResponseService, - OCPP20IncomingRequestService, - OCPP20RequestService, - OCPP20ResponseService, - type OCPPIncomingRequestService, - type OCPPRequestService, - buildMeterValue, - buildTransactionEndMeterValue, - getMessageTypeString, - sendAndSetConnectorStatus -} from './ocpp/index.js' -import { SharedLRUCache } from './SharedLRUCache.js' import { BaseError, OCPPError } from '../exception/index.js' import { PerformanceStatistics } from '../performance/index.js' import { @@ -113,17 +62,14 @@ import { SupervisionUrlDistribution, SupportedFeatureProfiles, type Voltage, - type WSError, WebSocketCloseEventStatusCode, + type WSError, type WsOptions } from '../types/index.js' import { ACElectricUtils, AsyncLock, AsyncLockType, - Configuration, - Constants, - DCElectricUtils, buildAddedMessage, buildChargingStationAutomaticTransactionGeneratorConfiguration, buildConnectorsStatus, @@ -131,29 +77,81 @@ import { buildEvsesStatus, buildStartedMessage, buildStoppedMessage, - buildTemplateName, buildUpdatedMessage, clone, + Configuration, + Constants, convertToBoolean, convertToDate, convertToInt, + DCElectricUtils, exponentialDelay, formatDurationMilliSeconds, formatDurationSeconds, - getRandomInteger, getWebSocketCloseEventStatusString, handleFileException, isNotEmptyArray, isNotEmptyString, - logPrefix, logger, + logPrefix, min, - once, roundTo, secureRandom, sleep, watchJsonFile } from '../utils/index.js' +import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js' +import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel.js' +import { + addConfigurationKey, + deleteConfigurationKey, + getConfigurationKey, + setConfigurationKeyValue +} from './ConfigurationKeyUtils.js' +import { + buildConnectorsMap, + buildTemplateName, + checkChargingStation, + checkConfiguration, + checkConnectorsConfiguration, + checkStationInfoConnectorStatus, + checkTemplate, + createBootNotificationRequest, + createSerialNumber, + getAmperageLimitationUnitDivider, + getBootConnectorStatus, + getChargingStationConnectorChargingProfilesPowerLimit, + getChargingStationId, + getDefaultVoltageOut, + getHashId, + getIdTagsFile, + getMaxNumberOfEvses, + getNumberOfReservableConnectors, + getPhaseRotationValue, + hasFeatureProfile, + hasReservationExpired, + initializeConnectorsMapStatus, + propagateSerialNumber, + setChargingStationOptions, + stationTemplateToStationInfo, + warnTemplateKeysDeprecation +} from './Helpers.js' +import { IdTagsCache } from './IdTagsCache.js' +import { + buildMeterValue, + buildTransactionEndMeterValue, + getMessageTypeString, + OCPP16IncomingRequestService, + OCPP16RequestService, + OCPP16ResponseService, + OCPP20IncomingRequestService, + OCPP20RequestService, + OCPP20ResponseService, + type OCPPIncomingRequestService, + type OCPPRequestService, + sendAndSetConnectorStatus +} from './ocpp/index.js' +import { SharedLRUCache } from './SharedLRUCache.js' export class ChargingStation extends EventEmitter { public readonly index: number @@ -230,7 +228,7 @@ export class ChargingStation extends EventEmitter { this.wsConnectionRetried ? true : this.getAutomaticTransactionGeneratorConfiguration()?.stopAbsoluteDuration - ).catch(error => { + ).catch((error: unknown) => { logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error) }) this.wsConnectionRetried = false @@ -554,7 +552,7 @@ export class ChargingStation extends EventEmitter { this.heartbeatSetInterval = setInterval(() => { this.ocppRequestService .requestHandler(this, RequestCommand.HEARTBEAT) - .catch(error => { + .catch((error: unknown) => { logger.error( `${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`, error @@ -639,7 +637,7 @@ export class ChargingStation extends EventEmitter { meterValue: [meterValue] } ) - .catch(error => { + .catch((error: unknown) => { logger.error( `${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`, error @@ -843,7 +841,7 @@ export class ChargingStation extends EventEmitter { this.wsConnection.on('close', this.onClose.bind(this)) // Handle WebSocket open this.wsConnection.on('open', () => { - this.onOpen().catch(error => + this.onOpen().catch((error: unknown) => logger.error(`${this.logPrefix()} Error while opening WebSocket connection:`, error) ) }) @@ -1156,7 +1154,7 @@ export class ChargingStation extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const stationTemplate = this.getTemplateFromFile()! checkTemplate(stationTemplate, this.logPrefix(), this.templateFile) - const warnTemplateKeysDeprecationOnce = once(warnTemplateKeysDeprecation, this) + const warnTemplateKeysDeprecationOnce = once(warnTemplateKeysDeprecation) warnTemplateKeysDeprecationOnce(stationTemplate, this.logPrefix(), this.templateFile) if (stationTemplate.Connectors != null) { checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile) @@ -1193,15 +1191,6 @@ export class ChargingStation extends EventEmitter { } does not match firmware version pattern '${stationInfo.firmwareVersionPattern}'` ) } - stationInfo.firmwareUpgrade = mergeDeepRight( - { - versionUpgrade: { - step: 1 - }, - reset: true - }, - stationTemplate.firmwareUpgrade ?? {} - ) if (stationTemplate.resetTime != null) { stationInfo.resetTime = secondsToMilliseconds(stationTemplate.resetTime) } @@ -1246,7 +1235,7 @@ export class ChargingStation extends EventEmitter { stationInfoFromFile.templateHash === stationInfoFromTemplate.templateHash ) { return setChargingStationOptions( - { ...Constants.DEFAULT_STATION_INFO, ...stationInfoFromFile }, + mergeDeepRight(Constants.DEFAULT_STATION_INFO, stationInfoFromFile), options ) } @@ -1257,7 +1246,7 @@ export class ChargingStation extends EventEmitter { stationInfoFromTemplate ) return setChargingStationOptions( - { ...Constants.DEFAULT_STATION_INFO, ...stationInfoFromTemplate }, + mergeDeepRight(Constants.DEFAULT_STATION_INFO, stationInfoFromTemplate), options ) } @@ -1555,7 +1544,7 @@ export class ChargingStation extends EventEmitter { } const templateConnectorId = connectorId > 0 && stationTemplate.randomConnectors === true - ? getRandomInteger(templateMaxAvailableConnectors, 1) + ? randomInt(1, templateMaxAvailableConnectors) : connectorId const connectorStatus = stationTemplate.Connectors[templateConnectorId] checkStationInfoConnectorStatus( @@ -1768,7 +1757,7 @@ export class ChargingStation extends EventEmitter { this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash) this.sharedLRUCache.setChargingStationConfiguration(configurationData) this.configurationFileHash = configurationHash - }).catch(error => { + }).catch((error: unknown) => { handleFileException( this.configurationFile, FileType.ChargingStationConfiguration, @@ -1912,7 +1901,9 @@ export class ChargingStation extends EventEmitter { .then(() => { this.emit(ChargingStationEvents.updated) }) - .catch(error => logger.error(`${this.logPrefix()} Error while reconnecting:`, error)) + .catch((error: unknown) => + logger.error(`${this.logPrefix()} Error while reconnecting:`, error) + ) break } } @@ -2365,11 +2356,11 @@ export class ChargingStation extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion Configuration.getSupervisionUrlDistribution()! ) && - logger.error( + logger.warn( // eslint-disable-next-line @typescript-eslint/no-base-to-string - `${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' from values '${SupervisionUrlDistribution.toString()}', defaulting to ${ + `${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' in configuration from values '${SupervisionUrlDistribution.toString()}', defaulting to '${ SupervisionUrlDistribution.CHARGING_STATION_AFFINITY - }` + }'` ) configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length break