From: Jérôme Benoit Date: Sun, 13 Mar 2022 11:01:25 +0000 (+0100) Subject: Introduce a CS instance hashId dependent on its specifications and use it in X-Git-Tag: v1.1.55~14 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=3f94cab5f9ffdc613338a715cf3fad1cede5a687;hp=25b292ffc0665399325f5392cdecd2b0e354237e;p=e-mobility-charging-stations-simulator.git Introduce a CS instance hashId dependent on its specifications and use it in various places such as OCPP parameters persistence Reference #196 Signed-off-by: Jérôme Benoit --- diff --git a/README.md b/README.md index 20dedad6..7afb56f5 100644 --- a/README.md +++ b/README.md @@ -84,51 +84,51 @@ But the modifications to test have to be done to the files in the build result d ### Charging station template -| Key | Value(s) | Default Value | Value type | Description | -| --------------------------------- | ---------- | --------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| supervisionUrls | | '' | string \| string[] | string or array of connection URIs to OCPP-J servers. It has priority over the global configuration parameter | -| supervisionUser | | '' | string | basic HTTP authentication user to OCPP-J server | -| supervisionPassword | | '' | string | basic HTTP authentication password to OCPP-J server | -| supervisionUrlOcppConfiguration | true/false | false | boolean | allow supervision URL configuration via a vendor OCPP parameter key | -| supervisionUrlOcppKey | | 'ConnectionUrl' | string | the vendor string that will be used as a vendor OCPP parameter key to set the supervision URL | -| ocppVersion | 1.6 | 1.6 | string | OCPP version | -| ocppProtocol | json | json | string | OCPP protocol | -| ocppStrictCompliance | true/false | false | boolean | strict adherence to the OCPP version and protocol specifications | -| ocppPersistentConfiguration | true/false | true | boolean | enable persistent OCPP parameters by charging station autogenerated name. The persistency is ensured by JSON files in dist/assets/configurations | -| wsOptions | | {} | ClientOptions & ClientRequestArgs | [ws](https://github.com/websockets/ws) and node.js [http](https://nodejs.org/api/http.html) clients options intersection | -| authorizationFile | | '' | string | RFID tags list file relative to src/assets path | -| baseName | | '' | string | base name to build charging stations name | -| nameSuffix | | '' | string | name suffix to build charging stations name | -| fixedName | true/false | false | boolean | use the baseName as the charging stations unique name | -| chargePointModel | | '' | string | charging stations model | -| chargePointVendor | | '' | string | charging stations vendor | -| chargeBoxSerialNumberPrefix | | '' | string | charging stations serial number prefix | -| firmwareVersion | | '' | string | charging stations firmware version | -| power | | | float \| float[] | charging stations maximum power value(s) | -| powerSharedByConnectors | true/false | false | boolean | charging stations power shared by its connectors | -| powerUnit | W/kW | W | string | charging stations power unit | -| currentOutType | AC/DC | AC | string | charging stations current out type | -| voltageOut | | AC:230/DC:400 | integer | charging stations voltage out | -| numberOfPhases | 0/1/3 | AC:3/DC:0 | integer | charging stations number of phase(s) | -| numberOfConnectors | | | integer \| integer[] | charging stations number of connector(s) | -| useConnectorId0 | true/false | true | boolean | use connector id 0 definition from the template | -| randomConnectors | true/false | false | boolean | randomize runtime connector id affectation from the connector id definition in template | -| resetTime | | 60 | integer | seconds to wait before the charging stations come back at reset | -| autoRegister | true/false | false | boolean | set the charging station as registered at boot notification for testing purpose | -| autoReconnectMaxRetries | | -1 (unlimited) | integer | connection retries to the OCPP-J server | -| reconnectExponentialDelay | true/false | false | boolean | connection delay retry to the OCPP-J server | -| registrationMaxRetries | | -1 (unlimited) | integer | charging stations boot notification retries | -| enableStatistics | true/false | true | boolean | enable charging stations statistics | -| mayAuthorizeAtRemoteStart | true/false | true | boolean | always send authorize at remote start transaction when AuthorizeRemoteTxRequests is enabled | -| beginEndMeterValues | true/false | false | boolean | enable Transaction.{Begin,End} MeterValues | -| outOfOrderEndMeterValues | true/false | false | boolean | send Transaction.End MeterValues out of order. Need to relax OCPP specifications strict compliance ('ocppStrictCompliance' parameter) | -| meteringPerTransaction | true/false | true | boolean | enable metering history on a per transaction basis | -| transactionDataMeterValues | true/false | false | boolean | enable transaction data MeterValues at stop transaction | -| mainVoltageMeterValues | true/false | true | boolean | include charging station main voltage MeterValues on three phased charging stations | -| phaseLineToLineVoltageMeterValues | true/false | true | boolean | include charging station line to line voltage MeterValues on three phased charging stations | -| Configuration | | | ChargingStationConfiguration | charging stations OCPP parameters configuration section | -| AutomaticTransactionGenerator | | | AutomaticTransactionGenerator | charging stations ATG configuration section | -| Connectors | | | Connectors | charging stations connectors configuration section | +| Key | Value(s) | Default Value | Value type | Description | +| --------------------------------- | ---------- | --------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| supervisionUrls | | '' | string \| string[] | string or array of connection URIs to OCPP-J servers. It has priority over the global configuration parameter | +| supervisionUser | | '' | string | basic HTTP authentication user to OCPP-J server | +| supervisionPassword | | '' | string | basic HTTP authentication password to OCPP-J server | +| supervisionUrlOcppConfiguration | true/false | false | boolean | allow supervision URL configuration via a vendor OCPP parameter key | +| supervisionUrlOcppKey | | 'ConnectionUrl' | string | the vendor string that will be used as a vendor OCPP parameter key to set the supervision URL | +| ocppVersion | 1.6 | 1.6 | string | OCPP version | +| ocppProtocol | json | json | string | OCPP protocol | +| ocppStrictCompliance | true/false | false | boolean | strict adherence to the OCPP version and protocol specifications | +| ocppPersistentConfiguration | true/false | true | boolean | enable persistent OCPP parameters by charging station hashId. The persistency is ensured by JSON files in dist/assets/configurations | +| wsOptions | | {} | ClientOptions & ClientRequestArgs | [ws](https://github.com/websockets/ws) and node.js [http](https://nodejs.org/api/http.html) clients options intersection | +| authorizationFile | | '' | string | RFID tags list file relative to src/assets path | +| baseName | | '' | string | base name to build charging stations name | +| nameSuffix | | '' | string | name suffix to build charging stations name | +| fixedName | true/false | false | boolean | use the baseName as the charging stations unique name | +| chargePointModel | | '' | string | charging stations model | +| chargePointVendor | | '' | string | charging stations vendor | +| chargeBoxSerialNumberPrefix | | '' | string | charging stations serial number prefix | +| firmwareVersion | | '' | string | charging stations firmware version | +| power | | | float \| float[] | charging stations maximum power value(s) | +| powerSharedByConnectors | true/false | false | boolean | charging stations power shared by its connectors | +| powerUnit | W/kW | W | string | charging stations power unit | +| currentOutType | AC/DC | AC | string | charging stations current out type | +| voltageOut | | AC:230/DC:400 | integer | charging stations voltage out | +| numberOfPhases | 0/1/3 | AC:3/DC:0 | integer | charging stations number of phase(s) | +| numberOfConnectors | | | integer \| integer[] | charging stations number of connector(s) | +| useConnectorId0 | true/false | true | boolean | use connector id 0 definition from the template | +| randomConnectors | true/false | false | boolean | randomize runtime connector id affectation from the connector id definition in template | +| resetTime | | 60 | integer | seconds to wait before the charging stations come back at reset | +| autoRegister | true/false | false | boolean | set the charging station as registered at boot notification for testing purpose | +| autoReconnectMaxRetries | | -1 (unlimited) | integer | connection retries to the OCPP-J server | +| reconnectExponentialDelay | true/false | false | boolean | connection delay retry to the OCPP-J server | +| registrationMaxRetries | | -1 (unlimited) | integer | charging stations boot notification retries | +| enableStatistics | true/false | true | boolean | enable charging stations statistics | +| mayAuthorizeAtRemoteStart | true/false | true | boolean | always send authorize at remote start transaction when AuthorizeRemoteTxRequests is enabled | +| beginEndMeterValues | true/false | false | boolean | enable Transaction.{Begin,End} MeterValues | +| outOfOrderEndMeterValues | true/false | false | boolean | send Transaction.End MeterValues out of order. Need to relax OCPP specifications strict compliance ('ocppStrictCompliance' parameter) | +| meteringPerTransaction | true/false | true | boolean | enable metering history on a per transaction basis | +| transactionDataMeterValues | true/false | false | boolean | enable transaction data MeterValues at stop transaction | +| mainVoltageMeterValues | true/false | true | boolean | include charging station main voltage MeterValues on three phased charging stations | +| phaseLineToLineVoltageMeterValues | true/false | true | boolean | include charging station line to line voltage MeterValues on three phased charging stations | +| Configuration | | | ChargingStationConfiguration | charging stations OCPP parameters configuration section | +| AutomaticTransactionGenerator | | | AutomaticTransactionGenerator | charging stations ATG configuration section | +| Connectors | | | Connectors | charging stations connectors configuration section | #### Configuration section diff --git a/src/charging-station/AutomaticTransactionGenerator.ts b/src/charging-station/AutomaticTransactionGenerator.ts index 2162078b..985e8e47 100644 --- a/src/charging-station/AutomaticTransactionGenerator.ts +++ b/src/charging-station/AutomaticTransactionGenerator.ts @@ -35,13 +35,13 @@ export default class AutomaticTransactionGenerator { } public static getInstance(chargingStation: ChargingStation): AutomaticTransactionGenerator { - if (!AutomaticTransactionGenerator.instances.has(chargingStation.id)) { + if (!AutomaticTransactionGenerator.instances.has(chargingStation.hashId)) { AutomaticTransactionGenerator.instances.set( - chargingStation.id, + chargingStation.hashId, new AutomaticTransactionGenerator(chargingStation) ); } - return AutomaticTransactionGenerator.instances.get(chargingStation.id); + return AutomaticTransactionGenerator.instances.get(chargingStation.hashId); } public start(): void { diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index e8122d18..5b8247ea 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -63,7 +63,7 @@ import { parentPort } from 'worker_threads'; import path from 'path'; export default class ChargingStation { - public readonly id: string; + public hashId!: string; public readonly stationTemplateFile: string; public authorizedTags: string[]; public stationInfo!: ChargingStationInfo; @@ -89,7 +89,6 @@ export default class ChargingStation { private webSocketPingSetInterval!: NodeJS.Timeout; constructor(index: number, stationTemplateFile: string) { - this.id = Utils.generateUUID(); this.index = index; this.stationTemplateFile = stationTemplateFile; this.stopped = false; @@ -815,13 +814,6 @@ export default class ChargingStation { private initialize(): void { this.stationInfo = this.buildStationInfo(); - this.configurationFile = path.join( - path.resolve(__dirname, '../'), - 'assets/configurations', - this.stationInfo.chargingStationId + '.json' - ); - this.configuration = this.getConfiguration(); - delete this.stationInfo.Configuration; this.bootNotificationRequest = { chargePointModel: this.stationInfo.chargePointModel, chargePointVendor: this.stationInfo.chargePointVendor, @@ -831,7 +823,29 @@ export default class ChargingStation { ...(!Utils.isUndefined(this.stationInfo.firmwareVersion) && { firmwareVersion: this.stationInfo.firmwareVersion, }), + ...(Utils.isUndefined(this.stationInfo.iccid) && { iccid: this.stationInfo.iccid }), + ...(Utils.isUndefined(this.stationInfo.imsi) && { imsi: this.stationInfo.imsi }), + ...(Utils.isUndefined(this.stationInfo.meterSerialNumber) && { + meterSerialNumber: this.stationInfo.meterSerialNumber, + }), + ...(Utils.isUndefined(this.stationInfo.meterType) && { + meterType: this.stationInfo.meterType, + }), }; + + this.hashId = crypto + .createHash(Constants.DEFAULT_HASH_ALGORITHM) + .update(JSON.stringify(this.bootNotificationRequest) + this.stationInfo.chargingStationId) + .digest('hex'); + logger.info(`${this.logPrefix()} Charging station hashId '${this.hashId}'`); + this.configurationFile = path.join( + path.resolve(__dirname, '../'), + 'assets', + 'configurations', + this.hashId + '.json' + ); + this.configuration = this.getConfiguration(); + delete this.stationInfo.Configuration; // Build connectors if needed const maxConnectors = this.getMaxNumberOfConnectors(); if (maxConnectors <= 0) { @@ -870,7 +884,7 @@ export default class ChargingStation { this.stationInfo.randomConnectors = true; } const connectorsConfigHash = crypto - .createHash('sha256') + .createHash(Constants.DEFAULT_HASH_ALGORITHM) .update(JSON.stringify(this.stationInfo.Connectors) + maxConnectors.toString()) .digest('hex'); const connectorsConfigChanged = @@ -927,6 +941,8 @@ export default class ChargingStation { this.wsConfiguredConnectionUrl = new URL( this.getConfiguredSupervisionUrl().href + '/' + this.stationInfo.chargingStationId ); + // OCPP parameters + this.initOcppParameters(); switch (this.getOcppVersion()) { case OCPPVersion.VERSION_16: this.ocppIncomingRequestService = @@ -940,8 +956,6 @@ export default class ChargingStation { this.handleUnsupportedVersion(this.getOcppVersion()); break; } - // OCPP parameters - this.initOcppParameters(); if (this.stationInfo.autoRegister) { this.bootNotificationResponse = { currentTime: new Date().toISOString(), @@ -952,7 +966,7 @@ export default class ChargingStation { this.stationInfo.powerDivider = this.getPowerDivider(); if (this.getEnableStatistics()) { this.performanceStatistics = PerformanceStatistics.getInstance( - this.id, + this.hashId, this.stationInfo.chargingStationId, this.wsConnectionUrl ); diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index 93465c62..9eb82d2a 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -111,7 +111,7 @@ export default class OCPP16ResponseService extends OCPPResponseService { this.chargingStation.addConfigurationKey( OCPP16StandardParametersKey.HeartbeatInterval, payload.interval.toString(), - { visible: false }, + { visible: false, reboot: false }, { overwrite: true, save: true } ); this.chargingStation.heartbeatSetInterval diff --git a/src/charging-station/ocpp/OCPPIncomingRequestService.ts b/src/charging-station/ocpp/OCPPIncomingRequestService.ts index 431df9b9..8d34e734 100644 --- a/src/charging-station/ocpp/OCPPIncomingRequestService.ts +++ b/src/charging-station/ocpp/OCPPIncomingRequestService.ts @@ -20,10 +20,10 @@ export default abstract class OCPPIncomingRequestService { this: new (chargingStation: ChargingStation) => T, chargingStation: ChargingStation ): T { - if (!OCPPIncomingRequestService.instances.has(chargingStation.id)) { - OCPPIncomingRequestService.instances.set(chargingStation.id, new this(chargingStation)); + if (!OCPPIncomingRequestService.instances.has(chargingStation.hashId)) { + OCPPIncomingRequestService.instances.set(chargingStation.hashId, new this(chargingStation)); } - return OCPPIncomingRequestService.instances.get(chargingStation.id) as T; + return OCPPIncomingRequestService.instances.get(chargingStation.hashId) as T; } protected handleIncomingRequestError( diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index c4dc0cbf..4ab79d9d 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -41,13 +41,13 @@ export default abstract class OCPPRequestService { chargingStation: ChargingStation, ocppResponseService: OCPPResponseService ): T { - if (!OCPPRequestService.instances.has(chargingStation.id)) { + if (!OCPPRequestService.instances.has(chargingStation.hashId)) { OCPPRequestService.instances.set( - chargingStation.id, + chargingStation.hashId, new this(chargingStation, ocppResponseService) ); } - return OCPPRequestService.instances.get(chargingStation.id) as T; + return OCPPRequestService.instances.get(chargingStation.hashId) as T; } public async sendResult( diff --git a/src/charging-station/ocpp/OCPPResponseService.ts b/src/charging-station/ocpp/OCPPResponseService.ts index 311d62e3..d13a7d15 100644 --- a/src/charging-station/ocpp/OCPPResponseService.ts +++ b/src/charging-station/ocpp/OCPPResponseService.ts @@ -18,10 +18,10 @@ export default abstract class OCPPResponseService { this: new (chargingStation: ChargingStation) => T, chargingStation: ChargingStation ): T { - if (!OCPPResponseService.instances.has(chargingStation.id)) { - OCPPResponseService.instances.set(chargingStation.id, new this(chargingStation)); + if (!OCPPResponseService.instances.has(chargingStation.hashId)) { + OCPPResponseService.instances.set(chargingStation.hashId, new this(chargingStation)); } - return OCPPResponseService.instances.get(chargingStation.id) as T; + return OCPPResponseService.instances.get(chargingStation.hashId) as T; } public abstract handleResponse( diff --git a/src/types/ChargingStationTemplate.ts b/src/types/ChargingStationTemplate.ts index 914f131e..ee7df49a 100644 --- a/src/types/ChargingStationTemplate.ts +++ b/src/types/ChargingStationTemplate.ts @@ -53,6 +53,10 @@ export default interface ChargingStationTemplate { chargePointVendor: string; chargeBoxSerialNumberPrefix?: string; firmwareVersion?: string; + iccid?: string; + imsi?: string; + meterSerialNumber?: string; + meterType?: string; power: number | number[]; powerSharedByConnectors?: boolean; powerUnit: PowerUnits; diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index b115a42f..10f5ff37 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -91,6 +91,8 @@ export default class Constants { static readonly CHARGING_STATION_ATG_INITIALIZATION_TIME = 1000; // Ms static readonly CHARGING_STATION_ATG_DEFAULT_STOP_AFTER_HOURS = 0.25; // Hours + static readonly DEFAULT_HASH_ALGORITHM = 'sha384'; + static readonly DEFAULT_IDTAG = '00000000'; static readonly DEFAULT_CONNECTION_TIMEOUT = 30;