+import Connectors, { Connector } from '../types/Connectors';
+import MeterValue, { MeterValueLocation, MeterValueMeasurand, MeterValuePhase, MeterValueUnit } from '../types/MeterValue';
import { PerformanceObserver, performance } from 'perf_hooks';
import AutomaticTransactionGenerator from './AutomaticTransactionGenerator';
+import { ChargePointErrorCode } from '../types/ChargePointErrorCode';
import { ChargePointStatus } from '../types/ChargePointStatus';
import Configuration from '../utils/Configuration';
import Constants from '../utils/Constants.js';
private _stationTemplateFile: string;
private _stationInfo;
private _bootNotificationMessage;
- private _connectors;
+ private _connectors: Connectors;
private _configuration;
private _connectorsConfigurationHash: string;
- private _supervisionUrl;
- private _wsConnectionUrl;
+ private _supervisionUrl: string;
+ private _wsConnectionUrl: string;
private _wsConnection: WebSocket;
- private _isSocketRestart;
+ private _isSocketRestart: boolean;
private _autoReconnectRetryCount: number;
private _autoReconnectMaxRetries: number;
private _autoReconnectTimeout: number;
private _automaticTransactionGeneration: AutomaticTransactionGenerator;
private _authorizedTags: string[];
private _heartbeatInterval: number;
- private _heartbeatSetInterval;
+ private _heartbeatSetInterval: NodeJS.Timeout;
private _statistics: Statistics;
private _performanceObserver: PerformanceObserver;
// Initialize transaction attributes on connectors
for (const connector in this._connectors) {
if (!this.getConnector(Utils.convertToInt(connector)).transactionStarted) {
- this._initTransactionOnConnector(connector);
+ this._initTransactionOnConnector(Utils.convertToInt(connector));
}
}
// OCPP parameters
- this._addConfigurationKey('NumberOfConnectors', this._getNumberOfConnectors(), true);
+ this._addConfigurationKey('NumberOfConnectors', this._getNumberOfConnectors().toString(), true);
if (!this._getConfigurationKey('MeterValuesSampledData')) {
- this._addConfigurationKey('MeterValuesSampledData', 'Energy.Active.Import.Register');
+ this._addConfigurationKey('MeterValuesSampledData', MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER);
}
this._stationInfo.powerDivider = this._getPowerDivider();
if (this.getEnableStatistics()) {
this._statistics.objName = this._stationInfo.name;
this._performanceObserver = new PerformanceObserver((list) => {
const entry = list.getEntries()[0];
- this._statistics.logPerformance(entry, 'ChargingStation');
+ this._statistics.logPerformance(entry, Constants.ENTITY_CHARGING_STATION);
this._performanceObserver.disconnect();
});
}
}
- get connectors() {
+ get connectors(): Connectors {
return this._connectors;
}
return this._stationInfo.Configuration ? this._stationInfo.Configuration : {};
}
- _getAuthorizationFile() : string {
+ _getAuthorizationFile(): string {
return this._stationInfo.authorizationFile && this._stationInfo.authorizationFile;
}
try {
// Load authorization file
const fileDescriptor = fs.openSync(authorizationFile, 'r');
- authorizedTags = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8'));
+ authorizedTags = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as string[];
fs.closeSync(fileDescriptor);
} catch (error) {
logger.error(this._logPrefix() + ' Authorization file ' + authorizationFile + ' loading error: ' + error);
return powerDivider;
}
- getConnector(id: number) {
+ getConnector(id: number): Connector {
return this._connectors[id];
}
_getVoltageOut(): number {
const errMsg = `${this._logPrefix()} Unknown ${this._getPowerOutType()} powerOutType in template file ${this._stationTemplateFile}, cannot define default voltage out`;
- let defaultVoltageOut;
+ let defaultVoltageOut: number;
switch (this._getPowerOutType()) {
case 'AC':
defaultVoltageOut = 230;
// Initialize
this._initialize();
if (!Utils.convertToBoolean(this._stationInfo.AutomaticTransactionGenerator.enable) &&
- this._automaticTransactionGeneration) {
- this._automaticTransactionGeneration.stop().catch(() => {});
+ this._automaticTransactionGeneration) {
+ this._automaticTransactionGeneration.stop().catch(() => { });
}
} catch (error) {
logger.error(this._logPrefix() + ' Charging station template file monitoring error: ' + error);
return;
}
if (interval > 0) {
- this.getConnector(connectorId).transactionSetInterval = setInterval(async (): Promise<void> => {
+ this.getConnector(connectorId).transactionSetInterval = setInterval(async () => {
if (this.getEnableStatistics()) {
const sendMeterValues = performance.timerify(this.sendMeterValues);
this._performanceObserver.observe({
async stop(reason = ''): Promise<void> {
// Stop
- await this._stopMessageSequence();
+ await this._stopMessageSequence(reason);
// eslint-disable-next-line guard-for-in
for (const connector in this._connectors) {
await this.sendStatusNotification(Utils.convertToInt(connector), ChargePointStatus.UNAVAILABLE);
logger.debug(this._logPrefix() + ' Has received a WS ping (rfc6455) from the server');
}
- async onMessage(message) : Promise<void> {
+ async onMessage(message): Promise<void> {
let [messageType, messageId, commandName, commandPayload, errorDetails] = [0, '', Constants.ENTITY_CHARGING_STATION, '', ''];
try {
// Parse the message
}
}
- async sendStatusNotification(connectorId: number, status: ChargePointStatus, errorCode = 'NoError'): Promise<void> {
+ async sendStatusNotification(connectorId: number, status: ChargePointStatus, errorCode: ChargePointErrorCode = ChargePointErrorCode.NO_ERROR): Promise<void> {
this.getConnector(connectorId).status = status;
try {
const payload = {
// eslint-disable-next-line consistent-this
async sendMeterValues(connectorId: number, interval: number, self: ChargingStation, debug = false): Promise<void> {
try {
- const sampledValues = {
+ const sampledValues: {
+ timestamp: string;
+ sampledValue: MeterValue[];
+ } = {
timestamp: new Date().toISOString(),
sampledValue: [],
};
for (let index = 0; index < meterValuesTemplate.length; index++) {
const connector = self.getConnector(connectorId);
// SoC measurand
- if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'SoC' && self._getConfigurationKey('MeterValuesSampledData').value.includes('SoC')) {
+ if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.STATE_OF_CHARGE && self._getConfigurationKey('MeterValuesSampledData').value.includes(MeterValueMeasurand.STATE_OF_CHARGE)) {
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'Percent' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.PERCENT },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
measurand: meterValuesTemplate[index].measurand,
- ...!Utils.isUndefined(meterValuesTemplate[index].location) ? { location: meterValuesTemplate[index].location } : { location: 'EV' },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: Utils.getRandomInt(100) },
+ ...!Utils.isUndefined(meterValuesTemplate[index].location) ? { location: meterValuesTemplate[index].location } : { location: MeterValueLocation.EV },
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: Utils.getRandomInt(100).toString() },
});
const sampledValuesIndex = sampledValues.sampledValue.length - 1;
- if (sampledValues.sampledValue[sampledValuesIndex].value > 100 || debug) {
- logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : 'Energy.Active.Import.Register'}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/100`);
+ if (Utils.convertToInt(sampledValues.sampledValue[sampledValuesIndex].value) > 100 || debug) {
+ logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/100`);
}
// Voltage measurand
- } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Voltage' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Voltage')) {
+ } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.VOLTAGE && self._getConfigurationKey('MeterValuesSampledData').value.includes(MeterValueMeasurand.VOLTAGE)) {
const voltageMeasurandValue = Utils.getRandomFloatRounded(self._getVoltageOut() + self._getVoltageOut() * 0.1, self._getVoltageOut() - self._getVoltageOut() * 0.1);
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'V' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.VOLT },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
measurand: meterValuesTemplate[index].measurand,
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: voltageMeasurandValue },
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: voltageMeasurandValue.toString() },
});
for (let phase = 1; self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) {
- const voltageValue = sampledValues.sampledValue[sampledValues.sampledValue.length - 1].value;
- let phaseValue;
+ const voltageValue = Utils.convertToInt(sampledValues.sampledValue[sampledValues.sampledValue.length - 1].value);
+ let phaseValue: string;
if (voltageValue >= 0 && voltageValue <= 250) {
phaseValue = `L${phase}-N`;
} else if (voltageValue > 250) {
phaseValue = `L${phase}-L${(phase + 1) % self._getNumberOfPhases() !== 0 ? (phase + 1) % self._getNumberOfPhases() : self._getNumberOfPhases()}`;
}
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'V' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.VOLT },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
measurand: meterValuesTemplate[index].measurand,
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: voltageMeasurandValue },
- phase: phaseValue,
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: voltageMeasurandValue.toString() },
+ phase: phaseValue as MeterValuePhase,
});
}
// Power.Active.Import measurand
- } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Power.Active.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Power.Active.Import')) {
+ } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.POWER_ACTIVE_EXPORT && self._getConfigurationKey('MeterValuesSampledData').value.includes(MeterValueMeasurand.POWER_ACTIVE_EXPORT)) {
// FIXME: factor out powerDivider checks
if (Utils.isUndefined(self._stationInfo.powerDivider)) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider is undefined`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider is undefined`;
logger.error(errMsg);
throw Error(errMsg);
} else if (self._stationInfo.powerDivider && self._stationInfo.powerDivider <= 0) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
logger.error(errMsg);
throw Error(errMsg);
}
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: Unknown ${self._getPowerOutType()} powerOutType in template file ${self._stationTemplateFile}, cannot calculate ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'} measurand value`;
- const powerMeasurandValues = {} as MeasurandValues ;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${self._getPowerOutType()} powerOutType in template file ${self._stationTemplateFile}, cannot calculate ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
+ const powerMeasurandValues = {} as MeasurandValues;
const maxPower = Math.round(self._stationInfo.maxPower / self._stationInfo.powerDivider);
const maxPowerPerPhase = Math.round((self._stationInfo.maxPower / self._stationInfo.powerDivider) / self._getNumberOfPhases());
switch (self._getPowerOutType()) {
powerMeasurandValues.L2 = Utils.getRandomFloatRounded(maxPowerPerPhase);
powerMeasurandValues.L3 = Utils.getRandomFloatRounded(maxPowerPerPhase);
}
- powerMeasurandValues.all = Utils.roundTo(powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3, 2);
+ powerMeasurandValues.allPhases = Utils.roundTo(powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3, 2);
}
break;
case 'DC':
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
- powerMeasurandValues.all = Utils.getRandomFloatRounded(maxPower);
+ powerMeasurandValues.allPhases = Utils.getRandomFloatRounded(maxPower);
}
break;
default:
throw Error(errMsg);
}
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'W' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.WATT },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
measurand: meterValuesTemplate[index].measurand,
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: powerMeasurandValues.all },
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: powerMeasurandValues.allPhases.toString() },
});
const sampledValuesIndex = sampledValues.sampledValue.length - 1;
- if (sampledValues.sampledValue[sampledValuesIndex].value > maxPower || debug) {
- logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : 'Energy.Active.Import.Register'}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxPower}`);
+ if (Utils.convertToFloat(sampledValues.sampledValue[sampledValuesIndex].value) > maxPower || debug) {
+ logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxPower}`);
}
for (let phase = 1; self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) {
const phaseValue = `L${phase}-N`;
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'W' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.WATT },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: powerMeasurandValues[`L${phase}`] },
- phase: phaseValue,
+ phase: phaseValue as MeterValuePhase,
});
}
// Current.Import measurand
- } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Current.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Current.Import')) {
+ } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.CURRENT_IMPORT && self._getConfigurationKey('MeterValuesSampledData').value.includes(MeterValueMeasurand.CURRENT_IMPORT)) {
// FIXME: factor out powerDivider checks
if (Utils.isUndefined(self._stationInfo.powerDivider)) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider is undefined`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider is undefined`;
logger.error(errMsg);
throw Error(errMsg);
} else if (self._stationInfo.powerDivider && self._stationInfo.powerDivider <= 0) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
logger.error(errMsg);
throw Error(errMsg);
}
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: Unknown ${self._getPowerOutType()} powerOutType in template file ${self._stationTemplateFile}, cannot calculate ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'} measurand value`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: Unknown ${self._getPowerOutType()} powerOutType in template file ${self._stationTemplateFile}, cannot calculate ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} measurand value`;
const currentMeasurandValues = {} as MeasurandValues;
- let maxAmperage;
+ let maxAmperage: number;
switch (self._getPowerOutType()) {
case 'AC':
maxAmperage = ElectricUtils.ampPerPhaseFromPower(self._getNumberOfPhases(), self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut());
currentMeasurandValues.L2 = Utils.getRandomFloatRounded(maxAmperage);
currentMeasurandValues.L3 = Utils.getRandomFloatRounded(maxAmperage);
}
- currentMeasurandValues.all = Utils.roundTo((currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) / self._getNumberOfPhases(), 2);
+ currentMeasurandValues.allPhases = Utils.roundTo((currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) / self._getNumberOfPhases(), 2);
}
break;
case 'DC':
maxAmperage = ElectricUtils.ampTotalFromPower(self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut());
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
- currentMeasurandValues.all = Utils.getRandomFloatRounded(maxAmperage);
+ currentMeasurandValues.allPhases = Utils.getRandomFloatRounded(maxAmperage);
}
break;
default:
throw Error(errMsg);
}
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'A' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.AMP },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
measurand: meterValuesTemplate[index].measurand,
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: currentMeasurandValues.all },
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: currentMeasurandValues.allPhases.toString() },
});
const sampledValuesIndex = sampledValues.sampledValue.length - 1;
- if (sampledValues.sampledValue[sampledValuesIndex].value > maxAmperage || debug) {
- logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : 'Energy.Active.Import.Register'}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxAmperage}`);
+ if (Utils.convertToFloat(sampledValues.sampledValue[sampledValuesIndex].value) > maxAmperage || debug) {
+ logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxAmperage}`);
}
for (let phase = 1; self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) {
const phaseValue = `L${phase}`;
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'A' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.AMP },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: currentMeasurandValues[phaseValue] },
- phase: phaseValue,
+ phase: phaseValue as MeterValuePhase,
});
}
// Energy.Active.Import.Register measurand (default)
- } else if (!meterValuesTemplate[index].measurand || meterValuesTemplate[index].measurand === 'Energy.Active.Import.Register') {
+ } else if (!meterValuesTemplate[index].measurand || meterValuesTemplate[index].measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
// FIXME: factor out powerDivider checks
if (Utils.isUndefined(self._stationInfo.powerDivider)) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider is undefined`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider is undefined`;
logger.error(errMsg);
throw Error(errMsg);
} else if (self._stationInfo.powerDivider && self._stationInfo.powerDivider <= 0) {
- const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ const errMsg = `${self._logPrefix()} MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
logger.error(errMsg);
throw Error(errMsg);
}
}
}
sampledValues.sampledValue.push({
- ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: 'Wh' },
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? { unit: meterValuesTemplate[index].unit } : { unit: MeterValueUnit.WATT_HOUR },
...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
- ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: connector.lastEnergyActiveImportRegisterValue },
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: connector.lastEnergyActiveImportRegisterValue.toString() },
});
const sampledValuesIndex = sampledValues.sampledValue.length - 1;
const maxConsumption = Math.round(self._stationInfo.maxPower * 3600 / (self._stationInfo.powerDivider * interval));
- if (sampledValues.sampledValue[sampledValuesIndex].value > maxConsumption || debug) {
- logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : 'Energy.Active.Import.Register'}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxConsumption}`);
+ if (Utils.convertToFloat(sampledValues.sampledValue[sampledValuesIndex].value) > maxConsumption || debug) {
+ logger.error(`${self._logPrefix()} MeterValues measurand ${sampledValues.sampledValue[sampledValuesIndex].measurand ? sampledValues.sampledValue[sampledValuesIndex].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${sampledValues.sampledValue[sampledValuesIndex].value}/${maxConsumption}`);
}
// Unsupported measurand
} else {
- logger.info(`${self._logPrefix()} Unsupported MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : 'Energy.Active.Import.Register'} on connectorId ${connectorId}`);
+ logger.info(`${self._logPrefix()} Unsupported MeterValues measurand ${meterValuesTemplate[index].measurand ? meterValuesTemplate[index].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER} on connectorId ${connectorId}`);
}
}
}
}
- async sendError(messageId, err: Error|OCPPError, commandName) {
+ async sendError(messageId, err: Error | OCPPError, commandName): Promise<unknown> {
// Check exception type: only OCPP error are accepted
const error = err instanceof OCPPError ? err : new OCPPError(Constants.OCPP_ERROR_INTERNAL_ERROR, err.message, err.stack && err.stack);
// Send error
return this.sendMessage(messageId, error, Constants.OCPP_JSON_CALL_ERROR_MESSAGE, commandName);
}
- async sendMessage(messageId, commandParams, messageType = Constants.OCPP_JSON_CALL_RESULT_MESSAGE, commandName: string) {
+ async sendMessage(messageId, commandParams, messageType = Constants.OCPP_JSON_CALL_RESULT_MESSAGE, commandName: string): Promise<unknown> {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
// Send a message through wsConnection
});
}
- handleResponse(commandName: string, payload, requestPayload) {
+ handleResponse(commandName: string, payload, requestPayload): void {
const responseCallbackFn = 'handleResponse' + commandName;
if (typeof this[responseCallbackFn] === 'function') {
this[responseCallbackFn](payload, requestPayload);
}
}
- handleResponseBootNotification(payload, requestPayload) {
+ handleResponseBootNotification(payload, requestPayload): void {
if (payload.status === 'Accepted') {
this._heartbeatInterval = payload.interval * 1000;
- this._addConfigurationKey('HeartBeatInterval', Utils.convertToInt(payload.interval));
- this._addConfigurationKey('HeartbeatInterval', Utils.convertToInt(payload.interval), false, false);
+ this._addConfigurationKey('HeartBeatInterval', payload.interval);
+ this._addConfigurationKey('HeartbeatInterval', payload.interval, false, false);
this._startMessageSequence();
} else if (payload.status === 'Pending') {
logger.info(this._logPrefix() + ' Charging station in pending state on the central server');
}
}
- _initTransactionOnConnector(connectorId) {
+ _initTransactionOnConnector(connectorId: number): void {
this.getConnector(connectorId).transactionStarted = false;
this.getConnector(connectorId).transactionId = null;
this.getConnector(connectorId).idTag = null;
this.getConnector(connectorId).lastEnergyActiveImportRegisterValue = -1;
}
- _resetTransactionOnConnector(connectorId) {
+ _resetTransactionOnConnector(connectorId: number): void {
this._initTransactionOnConnector(connectorId);
if (this.getConnector(connectorId).transactionSetInterval) {
clearInterval(this.getConnector(connectorId).transactionSetInterval);
}
}
- handleResponseStartTransaction(payload, requestPayload) {
+ handleResponseStartTransaction(payload, requestPayload): void {
if (this.getConnector(requestPayload.connectorId).transactionStarted) {
logger.debug(this._logPrefix() + ' Try to start a transaction on an already used connector ' + requestPayload.connectorId + ': %s', this.getConnector(requestPayload.connectorId));
return;
}
}
- handleResponseStopTransaction(payload, requestPayload) {
+ handleResponseStopTransaction(payload, requestPayload): void {
let transactionConnectorId;
for (const connector in this._connectors) {
if (this.getConnector(Utils.convertToInt(connector)).transactionId === requestPayload.transactionId) {
}
}
- handleResponseStatusNotification(payload, requestPayload) {
+ handleResponseStatusNotification(payload, requestPayload): void {
logger.debug(this._logPrefix() + ' Status notification response received: %j to StatusNotification request: %j', payload, requestPayload);
}
- handleResponseMeterValues(payload, requestPayload) {
+ handleResponseMeterValues(payload, requestPayload): void {
logger.debug(this._logPrefix() + ' MeterValues response received: %j to MeterValues request: %j', payload, requestPayload);
}
- handleResponseHeartbeat(payload, requestPayload) {
+ handleResponseHeartbeat(payload, requestPayload): void {
logger.debug(this._logPrefix() + ' Heartbeat response received: %j to Heartbeat request: %j', payload, requestPayload);
}
- async handleRequest(messageId, commandName, commandPayload) {
+ async handleRequest(messageId, commandName, commandPayload): Promise<void> {
let response;
// Call
if (typeof this['handleRequest' + commandName] === 'function') {
}
// Simulate charging station restart
- async handleRequestReset(commandPayload) {
+ handleRequestReset(commandPayload) {
setImmediate(async () => {
await this.stop(commandPayload.type + 'Reset');
await Utils.sleep(this._stationInfo.resetTime);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
- _getConfigurationKey(key) {
+ _getConfigurationKey(key: string) {
return this._configuration.configurationKey.find((configElement) => configElement.key === key);
}
- _addConfigurationKey(key, value, readonly = false, visible = true, reboot = false) {
+ _addConfigurationKey(key: string, value: string, readonly = false, visible = true, reboot = false): void {
const keyFound = this._getConfigurationKey(key);
if (!keyFound) {
this._configuration.configurationKey.push({
}
}
- _setConfigurationKeyValue(key, value) {
+ _setConfigurationKeyValue(key: string, value: string): void {
const keyFound = this._getConfigurationKey(key);
if (keyFound) {
const keyIndex = this._configuration.configurationKey.indexOf(keyFound);
}
}
- async handleRequestGetConfiguration(commandPayload) {
+ handleRequestGetConfiguration(commandPayload) {
const configurationKey = [];
const unknownKey = [];
if (Utils.isEmptyArray(commandPayload.key)) {
};
}
- async handleRequestChangeConfiguration(commandPayload) {
+ handleRequestChangeConfiguration(commandPayload) {
const keyToChange = this._getConfigurationKey(commandPayload.key);
if (!keyToChange) {
return { status: Constants.OCPP_ERROR_NOT_SUPPORTED };
export default class Constants {
- static REST_RESPONSE_SUCCESS = { status: 'Success' };
-
- static CONN_STATUS_AVAILABLE = 'Available';
- static CONN_STATUS_OCCUPIED = 'Occupied';
-
- static STATS_GROUP_BY_CONSUMPTION = 'C';
- static STATS_GROUP_BY_USAGE = 'U';
-
- // Statuses
- static ENTITY_SITE = 'Site';
- static ENTITY_SITES = 'Sites';
- static ENTITY_SITE_AREA = 'SiteArea';
- static ENTITY_SITE_AREAS = 'SiteAreas';
- static ENTITY_COMPANY = 'Company';
- static ENTITY_COMPANIES = 'Companies';
- static ENTITY_CHARGING_STATION = 'ChargingStation';
- static ENTITY_CHARGING_STATIONS = 'ChargingStations';
- static ENTITY_TENANT = 'Tenant';
- static ENTITY_TENANTS = 'Tenants';
- static ENTITY_TRANSACTION = 'Transaction';
- static ENTITY_TRANSACTIONS = 'Transactions';
- static ENTITY_TRANSACTION_METER_VALUES = 'MeterValues';
- static ENTITY_TRANSACTION_STOP = 'Stop';
- static ENTITY_USER = 'User';
- static ENTITY_USERS = 'Users';
- static ENTITY_VEHICLE_MANUFACTURER = 'VehicleManufacturer';
- static ENTITY_VEHICLE_MANUFACTURERS = 'VehicleManufacturers';
- static ENTITY_VEHICLES = 'Vehicles';
- static ENTITY_VEHICLE = 'Vehicle';
- static ENTITY_LOGGINGS = 'Loggings';
- static ENTITY_LOGGING = 'Logging';
- static ENTITY_PRICING = 'Pricing';
-
- static NOTIFICATION_TYPE_CHARGING_STATION_CONFIGURATION = 'Configuration';
-
- static ACTION_READ = 'Read';
- static ACTION_CREATE = 'Create';
- static ACTION_UPDATE = 'Update';
- static ACTION_DELETE = 'Delete';
-
- static NO_LIMIT = 0;
-
- static CENTRAL_SERVER = 'Central Server';
-
- static WITH_CONNECTORS = true;
- static WITHOUT_CONNECTORS = false;
-
- static WITH_CHARGING_STATIONS = true;
- static WITHOUT_CHARGING_STATIONS = false;
- static WITH_SITE = true;
- static WITHOUT_SITE = false;
-
- static VEHICLE_TYPE_CAR = 'C';
-
- // Statuses
- static USER_STATUS_PENDING = 'P';
- static USER_STATUS_ACTIVE = 'A';
- static USER_STATUS_DELETED = 'D';
- static USER_STATUS_INACTIVE = 'I';
- static USER_STATUS_BLOCKED = 'B';
- static USER_STATUS_LOCKED = 'L';
-
- // Roles
- static ROLE_SUPER_ADMIN = 'S';
- static ROLE_ADMIN = 'A';
- static ROLE_BASIC = 'B';
- static ROLE_DEMO = 'D';
- static ACTION_LOGOUT = 'Logout';
- static ACTION_LIST = 'List';
- static ACTION_RESET = 'Reset';
- static ACTION_AUTHORIZE = 'Authorize';
- static ACTION_CLEAR_CACHE = 'ClearCache';
- static ACTION_STOP_TRANSACTION = 'StopTransaction';
- static ACTION_START_TRANSACTION = 'StartTransaction';
- static ACTION_REFUND_TRANSACTION = 'RefundTransaction';
- static ACTION_UNLOCK_CONNECTOR = 'UnlockConnector';
- static ACTION_GET_CONFIGURATION = 'GetConfiguration';
-
- // Password constants
- static PWD_MIN_LENGTH = 15;
- static PWD_MAX_LENGTH = 20;
- static PWD_UPPERCASE_MIN_COUNT = 1;
- static PWD_LOWERCASE_MIN_COUNT = 1;
- static PWD_NUMBER_MIN_COUNT = 1;
- static PWD_SPECIAL_MIN_COUNT = 1;
-
- static PWD_UPPERCASE_RE = /([A-Z])/g;
- static PWD_LOWERCASE_RE = /([a-z])/g;
- static PWD_NUMBER_RE = /([\d])/g;
- static PWD_SPECIAL_CHAR_RE = /([!#$%^&*.?-])/g;
-
- static DEFAULT_LOCALE = 'en_US';
-
- static ANONYMIZED_VALUE = '####';
-
- static DEFAULT_DB_LIMIT = 100;
-
- static METER_VALUE_CTX_SAMPLE_PERIODIC = 'Sample.Periodic';
- static METER_VALUE_CTX_SAMPLE_CLOCK = 'Sample.Clock';
-
- static WS_UNSUPPORTED_DATA = 1007;
-
- static OCPP_RESPONSE_ACCEPTED = { status: 'Accepted' };
- static OCPP_RESPONSE_REJECTED = { status: 'Rejected' };
- static OCPP_RESPONSE_REBOOT_REQUIRED = { status: 'RebootRequired' };
- static OCPP_SOCKET_TIMEOUT = 60000; // 60 sec
- static OCPP_JSON_CALL_MESSAGE = 2; // Caller to callee
- static OCPP_JSON_CALL_RESULT_MESSAGE = 3; // Callee to caller
- static OCPP_JSON_CALL_ERROR_MESSAGE = 4; // Callee to caller
+ static readonly ENTITY_CHARGING_STATION = 'ChargingStation';
+ static readonly ENTITY_AUTOMATIC_TRANSACTION_GENERATOR = 'AutomaticTransactionGenerator';
+
+ static readonly WS_UNSUPPORTED_DATA = 1007;
+
+ static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: 'Accepted' });
+ static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: 'Rejected' });
+ static readonly OCPP_RESPONSE_REBOOT_REQUIRED = Object.freeze({ status: 'RebootRequired' });
+ static readonly OCPP_SOCKET_TIMEOUT = 60000; // 60 sec
+ static readonly OCPP_JSON_CALL_MESSAGE = 2; // Caller to callee
+ static readonly OCPP_JSON_CALL_RESULT_MESSAGE = 3; // Callee to caller
+ static readonly OCPP_JSON_CALL_ERROR_MESSAGE = 4; // Callee to caller
// Requested Action is not known by receiver
- static OCPP_ERROR_NOT_IMPLEMENTED = 'NotImplemented';
+ static readonly OCPP_ERROR_NOT_IMPLEMENTED = 'NotImplemented';
// Requested Action is recognized but not supported by the receiver
- static OCPP_ERROR_NOT_SUPPORTED = 'NotSupported';
+ static readonly OCPP_ERROR_NOT_SUPPORTED = 'NotSupported';
// An internal error occurred and the receiver was not able to process the requested Action successfully
- static OCPP_ERROR_INTERNAL_ERROR = 'InternalError';
+ static readonly OCPP_ERROR_INTERNAL_ERROR = 'InternalError';
// Payload for Action is incomplete
- static OCPP_ERROR_PROTOCOL_ERROR = 'ProtocolError';
+ static readonly OCPP_ERROR_PROTOCOL_ERROR = 'ProtocolError';
// During the processing of Action a security issue occurred preventing receiver from completing the Action successfully
- static OCPP_ERROR_SECURITY_ERROR = 'SecurityError';
+ static readonly OCPP_ERROR_SECURITY_ERROR = 'SecurityError';
// Payload for Action is syntactically incorrect or not conform the PDU structure for Action
- static OCPP_ERROR_FORMATION_VIOLATION = 'FormationViolation';
+ static readonly OCPP_ERROR_FORMATION_VIOLATION = 'FormationViolation';
// Payload is syntactically correct but at least one field contains an invalid value
- static OCPP_ERROR_PROPERTY_RAINT_VIOLATION = 'PropertyraintViolation';
+ static readonly OCPP_ERROR_PROPERTY_RAINT_VIOLATION = 'PropertyraintViolation';
// Payload for Action is syntactically correct but at least one of the fields violates occurrence raints
- static OCPP_ERROR_OCCURENCE_RAINT_VIOLATION = 'OccurenceraintViolation';
+ static readonly OCPP_ERROR_OCCURENCE_RAINT_VIOLATION = 'OccurenceraintViolation';
// Payload for Action is syntactically correct but at least one of the fields violates data type raints (e.g. “somestring” = 12)
- static OCPP_ERROR_TYPERAINT_VIOLATION = 'TyperaintViolation';
+ static readonly OCPP_ERROR_TYPERAINT_VIOLATION = 'TyperaintViolation';
// Any other error not covered by the previous ones
- static OCPP_ERROR_GENERIC_ERROR = 'GenericError';
-
- static OCPP_PROTOCOL_JSON = 'json';
- static OCPP_PROTOCOL_SOAP = 'soap';
- static OCPP_VERSION_12 = '1.2';
- static OCPP_VERSION_15 = '1.5';
- static OCPP_VERSION_16 = '1.6';
- static OCPP_VERSION_20 = '2.0';
+ static readonly OCPP_ERROR_GENERIC_ERROR = 'GenericError';
- static STATUS_NOTIFICATION_TIMEOUT = 500;
- static START_TRANSACTION_TIMEOUT = 500;
+ static readonly OCPP_PROTOCOL_JSON = 'json';
+ static readonly OCPP_PROTOCOL_SOAP = 'soap';
+ static readonly OCPP_VERSION_12 = '1.2';
+ static readonly OCPP_VERSION_15 = '1.5';
+ static readonly OCPP_VERSION_16 = '1.6';
+ static readonly OCPP_VERSION_20 = '2.0';
- static CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms
- static CHARGING_STATION_ATG_WAIT_TIME = 2000; // Ms
+ static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms
+ static readonly CHARGING_STATION_ATG_WAIT_TIME = 2000; // Ms
}