X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2FChargingStation.ts;h=bd25116b990170ab1a4c776a693306a359d23021;hb=f3a6f63b4e690cecc8fdf84847a994970e12b94a;hp=0f2034fa30f5c2ff5d774a8f289a80edbdccfbc8;hpb=6b10669bf67da4baa14bc5b28161710e4025c913;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 0f2034fa..bd25116b 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -1,6 +1,6 @@ import { BootNotificationResponse, RegistrationStatus } from '../types/ocpp/Responses'; import ChargingStationConfiguration, { ConfigurationKey } from '../types/ChargingStationConfiguration'; -import ChargingStationTemplate, { CurrentOutType, PowerUnits, VoltageOut } from '../types/ChargingStationTemplate'; +import ChargingStationTemplate, { CurrentType, PowerUnits, Voltage } from '../types/ChargingStationTemplate'; import { ConnectorPhaseRotation, StandardParametersKey, SupportedFeatureProfiles } from '../types/ocpp/Configuration'; import Connectors, { Connector, SampledValueTemplate } from '../types/Connectors'; import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues'; @@ -19,7 +19,7 @@ import { MessageType } from '../types/ocpp/MessageType'; import OCPP16IncomingRequestService from './ocpp/1.6/OCCP16IncomingRequestService'; import OCPP16RequestService from './ocpp/1.6/OCPP16RequestService'; import OCPP16ResponseService from './ocpp/1.6/OCPP16ResponseService'; -import OCPPError from './OcppError'; +import OCPPError from './OCPPError'; import OCPPIncomingRequestService from './ocpp/OCPPIncomingRequestService'; import OCPPRequestService from './ocpp/OCPPRequestService'; import { OCPPVersion } from '../types/ocpp/OCPPVersion'; @@ -91,11 +91,15 @@ export default class ChargingStation { return !Utils.isUndefined(this.stationInfo.enableStatistics) ? this.stationInfo.enableStatistics : true; } + public getMayAuthorizeAtRemoteStart(): boolean | undefined { + return this.stationInfo.mayAuthorizeAtRemoteStart ?? true; + } + public getNumberOfPhases(): number | undefined { switch (this.getCurrentOutType()) { - case CurrentOutType.AC: + case CurrentType.AC: return !Utils.isUndefined(this.stationInfo.numberOfPhases) ? this.stationInfo.numberOfPhases : 3; - case CurrentOutType.DC: + case CurrentType.DC: return 0; } } @@ -120,23 +124,23 @@ export default class ChargingStation { return this.connectors[id]; } - public getCurrentOutType(): CurrentOutType | undefined { - return this.stationInfo.currentOutType ?? CurrentOutType.AC; + public getCurrentOutType(): CurrentType | undefined { + return this.stationInfo.currentOutType ?? CurrentType.AC; } public getVoltageOut(): number | undefined { const errMsg = `${this.logPrefix()} Unknown ${this.getCurrentOutType()} currentOutType in template file ${this.stationTemplateFile}, cannot define default voltage out`; let defaultVoltageOut: number; switch (this.getCurrentOutType()) { - case CurrentOutType.AC: - defaultVoltageOut = VoltageOut.VOLTAGE_230; + case CurrentType.AC: + defaultVoltageOut = Voltage.VOLTAGE_230; break; - case CurrentOutType.DC: - defaultVoltageOut = VoltageOut.VOLTAGE_400; + case CurrentType.DC: + defaultVoltageOut = Voltage.VOLTAGE_400; break; default: logger.error(errMsg); - throw Error(errMsg); + throw new Error(errMsg); } return !Utils.isUndefined(this.stationInfo.voltageOut) ? this.stationInfo.voltageOut : defaultVoltageOut; } @@ -144,7 +148,7 @@ export default class ChargingStation { public getTransactionIdTag(transactionId: number): string | undefined { for (const connector in this.connectors) { if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector)).transactionId === transactionId) { - return this.getConnector(Utils.convertToInt(connector)).idTag; + return this.getConnector(Utils.convertToInt(connector)).transactionIdTag; } } } @@ -219,12 +223,15 @@ export default class ChargingStation { return; } if (measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER && !this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { - logger.warn(`${this.logPrefix()} Trying to get MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId} not found in '${StandardParametersKey.MeterValuesSampledData}' OCPP parameter`); + logger.debug(`${this.logPrefix()} Trying to get MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId} not found in '${StandardParametersKey.MeterValuesSampledData}' OCPP parameter`); return; } const sampledValueTemplates: SampledValueTemplate[] = this.getConnector(connectorId).MeterValues; for (let index = 0; !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length; index++) { - if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand + if (!Constants.SUPPORTED_MEASURANDS.includes(sampledValueTemplates[index]?.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER)) { + logger.warn(`${this.logPrefix()} Unsupported MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`); + continue; + } else if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand && this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { return sampledValueTemplates[index]; } else if (!phase && !sampledValueTemplates[index].phase && sampledValueTemplates[index]?.measurand === measurand @@ -371,24 +378,26 @@ export default class ChargingStation { } } - public setChargingProfile(connectorId: number, cp: ChargingProfile): boolean { + public setChargingProfile(connectorId: number, cp: ChargingProfile): void { + let cpReplaced = false; if (!Utils.isEmptyArray(this.getConnector(connectorId).chargingProfiles)) { this.getConnector(connectorId).chargingProfiles?.forEach((chargingProfile: ChargingProfile, index: number) => { if (chargingProfile.chargingProfileId === cp.chargingProfileId - || (chargingProfile.stackLevel === cp.stackLevel && chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)) { + || (chargingProfile.stackLevel === cp.stackLevel && chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)) { this.getConnector(connectorId).chargingProfiles[index] = cp; - return true; + cpReplaced = true; } }); } - this.getConnector(connectorId).chargingProfiles?.push(cp); - return true; + !cpReplaced && this.getConnector(connectorId).chargingProfiles?.push(cp); } public resetTransactionOnConnector(connectorId: number): void { + this.getConnector(connectorId).authorized = false; this.getConnector(connectorId).transactionStarted = false; + delete this.getConnector(connectorId).authorizeIdTag; delete this.getConnector(connectorId).transactionId; - delete this.getConnector(connectorId).idTag; + delete this.getConnector(connectorId).transactionIdTag; this.getConnector(connectorId).transactionEnergyActiveImportRegisterValue = 0; delete this.getConnector(connectorId).transactionBeginMeterValue; this.stopMeterValues(connectorId); @@ -513,8 +522,8 @@ export default class ChargingStation { // Generate all connectors if ((this.stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) > 0) { for (let index = 1; index <= maxConnectors; index++) { - const randConnectorID = this.stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index; - this.connectors[index] = Utils.cloneObject(this.stationInfo.Connectors[randConnectorID]); + const randConnectorId = this.stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index; + this.connectors[index] = Utils.cloneObject(this.stationInfo.Connectors[randConnectorId]); this.connectors[index].availability = AvailabilityType.OPERATIVE; if (Utils.isUndefined(this.connectors[lastConnector]?.chargingProfiles)) { this.connectors[index].chargingProfiles = []; @@ -541,6 +550,13 @@ export default class ChargingStation { } // OCPP parameters this.initOCPPParameters(); + if (this.stationInfo.autoRegister) { + this.bootNotificationResponse = { + currentTime: new Date().toISOString(), + interval: this.getHeartbeatInterval() / 1000, + status: RegistrationStatus.ACCEPTED + }; + } this.stationInfo.powerDivider = this.getPowerDivider(); if (this.getEnableStatistics()) { this.performanceStatistics = new PerformanceStatistics(this.stationInfo.chargingStationId); @@ -637,8 +653,13 @@ export default class ChargingStation { let requestPayload: Record; let errMsg: string; try { - // Parse the message - [messageType, messageId, commandName, commandPayload, errorDetails] = JSON.parse(messageEvent.toString()) as IncomingRequest; + const request = JSON.parse(messageEvent.toString()) as IncomingRequest; + if (Utils.isIterable(request)) { + // Parse the message + [messageType, messageId, commandName, commandPayload, errorDetails] = request; + } else { + throw new Error('Incoming request is not iterable'); + } // Check the Type of message switch (messageType) { // Incoming Message @@ -686,7 +707,7 @@ export default class ChargingStation { } } catch (error) { // Log - logger.error('%s Incoming message %j processing error %j on request content type %j', this.logPrefix(), messageEvent, error, this.requests[messageId]); + logger.error('%s Incoming request message %j processing error %j on content type %j', this.logPrefix(), messageEvent, error, this.requests[messageId]); // Send error messageType !== MessageType.CALL_ERROR_MESSAGE && await this.ocppRequestService.sendError(messageId, error, commandName); } @@ -920,6 +941,8 @@ export default class ChargingStation { if (HeartBeatInterval) { return Utils.convertToInt(HeartBeatInterval.value) * 1000; } + !this.stationInfo.autoRegister && logger.warn(`${this.logPrefix()} Heartbeat interval configuration key not set, using default value: ${Constants.DEFAULT_HEARTBEAT_INTERVAL}`); + return Constants.DEFAULT_HEARTBEAT_INTERVAL; } private stopHeartbeat(): void { @@ -1027,6 +1050,7 @@ export default class ChargingStation { } private initTransactionAttributesOnConnector(connectorId: number): void { + this.getConnector(connectorId).authorized = false; this.getConnector(connectorId).transactionStarted = false; this.getConnector(connectorId).energyActiveImportRegisterValue = 0; this.getConnector(connectorId).transactionEnergyActiveImportRegisterValue = 0;