-const Configuration = require('../utils/Configuration');
-const logger = require('../utils/Logger');
-const WebSocket = require('ws');
-const Constants = require('../utils/Constants');
-const Utils = require('../utils/Utils');
-const OCPPError = require('./OcppError');
-const AutomaticTransactionGenerator = require('./AutomaticTransactionGenerator');
-const Statistics = require('../utils/Statistics');
-const fs = require('fs');
-const crypto = require('crypto');
-const {performance, PerformanceObserver} = require('perf_hooks');
-
-class ChargingStation {
+import {PerformanceObserver, performance} from 'perf_hooks';
+
+import AutomaticTransactionGenerator from './AutomaticTransactionGenerator.js';
+import Configuration from '../utils/Configuration.js';
+import Constants from '../utils/Constants.js';
+import ElectricUtils from '../utils/ElectricUtils.js';
+import OCPPError from './OcppError.js';
+import Statistics from '../utils/Statistics.js';
+import Utils from '../utils/Utils.js';
+import WebSocket from 'ws';
+import crypto from 'crypto';
+import fs from 'fs';
+import logger from '../utils/Logger.js';
+
+export default class ChargingStation {
constructor(index, stationTemplateFile) {
this._index = index;
this._stationTemplateFile = stationTemplateFile;
this._bootNotificationMessage = {
chargePointModel: this._stationInfo.chargePointModel,
chargePointVendor: this._stationInfo.chargePointVendor,
- chargePointSerialNumber: this._stationInfo.chargePointSerialNumberPrefix ? this._stationInfo.chargePointSerialNumberPrefix : '',
- firmwareVersion: this._stationInfo.firmwareVersion ? this._stationInfo.firmwareVersion : '',
+ ...!Utils.isUndefined(this._stationInfo.chargePointSerialNumberPrefix) && {chargePointSerialNumber: this._stationInfo.chargePointSerialNumberPrefix},
+ ...!Utils.isUndefined(this._stationInfo.firmwareVersion) && {firmwareVersion: this._stationInfo.firmwareVersion},
};
this._configuration = this._getConfiguration();
this._supervisionUrl = this._getSupervisionURL();
// Build connectors if needed
const maxConnectors = this._getMaxNumberOfConnectors();
if (maxConnectors <= 0) {
- const errMsg = `${this._logPrefix()} Charging station template ${this._stationTemplateFile} with ${maxConnectors} connectors`;
- logger.warn(errMsg);
+ logger.warn(`${this._logPrefix()} Charging station template ${this._stationTemplateFile} with ${maxConnectors} connectors`);
}
const templateMaxConnectors = this._getTemplateMaxNumberOfConnectors();
if (templateMaxConnectors <= 0) {
- const errMsg = `${this._logPrefix()} Charging station template ${this._stationTemplateFile} with no connector configurations`;
- logger.warn(errMsg);
+ logger.warn(`${this._logPrefix()} Charging station template ${this._stationTemplateFile} with no connector configurations`);
}
// Sanity check
if (maxConnectors > (this._stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) && !Utils.convertToBoolean(this._stationInfo.randomConnectors)) {
return this._connectors[0] ? Object.keys(this._connectors).length - 1 : Object.keys(this._connectors).length;
}
+ _getVoltageOut() {
+ const errMsg = `${this._logPrefix()} Unknown ${this._getPowerOutType()} powerOutType in template file ${this._stationTemplateFile}, cannot define default voltage out`;
+ let defaultVoltageOut;
+ switch (this._getPowerOutType()) {
+ case 'AC':
+ defaultVoltageOut = 230;
+ break;
+ case 'DC':
+ defaultVoltageOut = 400;
+ break;
+ default:
+ logger.error(errMsg);
+ throw Error(errMsg);
+ }
+ return !Utils.isUndefined(this._stationInfo.voltageOut) ? Utils.convertToInt(this._stationInfo.voltageOut) : defaultVoltageOut;
+ }
+
+ _getPowerOutType() {
+ return !Utils.isUndefined(this._stationInfo.powerOutType) ? this._stationInfo.powerOutType : 'AC';
+ }
+
_getSupervisionURL() {
const supervisionUrls = Utils.cloneObject(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs());
let indexUrl = 0;
}, self._heartbeatInterval);
logger.info(self._logPrefix() + ' Heartbeat started every ' + self._heartbeatInterval + 'ms');
} else {
- logger.error(`${self._logPrefix()} Heartbeat interval set to ${self._heartbeatInterval}, not starting the heartbeat`);
+ logger.error(`${self._logPrefix()} Heartbeat interval set to ${self._heartbeatInterval}ms, not starting the heartbeat`);
}
}
if (Utils.isIterable(this._requests[messageId])) {
[responseCallback, , requestPayload] = this._requests[messageId];
} else {
- throw new Error(`Response request for unknown message id ${messageId} is not iterable`);
+ throw new Error(`Response request for message id ${messageId} is not iterable`);
}
if (!responseCallback) {
// Error
if (Utils.isIterable(this._requests[messageId])) {
[, rejectCallback] = this._requests[messageId];
} else {
- throw new Error(`Error request for unknown message id ${messageId} is not iterable`);
+ throw new Error(`Error request for message id ${messageId} is not iterable`);
}
delete this._requests[messageId];
rejectCallback(new OCPPError(commandName, commandPayload, errorDetails));
}
}
- sendStartTransactionWithTimeout(connectorId, idTag, timeout) {
+ sendStartTransactionWithTimeout(connectorId, idTag, timeout = Constants.START_TRANSACTION_TIMEOUT) {
setTimeout(() => this.sendStartTransaction(connectorId, idTag), timeout);
}
async sendStopTransaction(transactionId, reason = '') {
try {
- let payload;
- if (reason) {
- payload = {
- transactionId,
- meterStop: 0,
- timestamp: new Date().toISOString(),
- reason,
- };
- } else {
- payload = {
- transactionId,
- meterStop: 0,
- timestamp: new Date().toISOString(),
- };
- }
+ const payload = {
+ transactionId,
+ meterStop: 0,
+ timestamp: new Date().toISOString(),
+ ...reason && {reason},
+ };
await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StopTransaction');
} catch (error) {
logger.error(this._logPrefix() + ' Send StopTransaction error: ' + error);
});
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}`);
+ 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`);
}
// Voltage measurand
} else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Voltage' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Voltage')) {
...!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: 230},
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? {value: meterValuesTemplate[index].value} : {value: self._getVoltageOut()},
});
- for (let phase = 1; self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) {
+ for (let phase = 1; self._getPowerOutType() === 'AC' && self._getNumberOfPhases() === 3 && phase <= self._getNumberOfPhases(); phase++) {
const voltageValue = sampledValues.sampledValue[sampledValues.sampledValue.length - 1].value;
let phaseValue;
- if (voltageValue >= 0 && voltageValue <= 240) {
+ if (voltageValue >= 0 && voltageValue <= 250) {
phaseValue = `L${phase}-N`;
- } else if (voltageValue > 240) {
- phaseValue = `L${phase}-L${(phase + 1) % self._getNumberOfPhases() !== 0 ? (phase + 1) % self._getNumberOfPhases() : self._getNumberOfPhases() }`;
+ } 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].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: 230},
+ ...!Utils.isUndefined(meterValuesTemplate[index].value) ? {value: meterValuesTemplate[index].value} : {value: self._getVoltageOut()},
+ phase: phaseValue,
+ });
+ }
+ // Power.Active.Import measurand
+ } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Power.Active.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('Power.Active.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`;
+ 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}`;
+ 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 = {};
+ 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()) {
+ case 'AC':
+ if (Utils.isUndefined(meterValuesTemplate[index].value)) {
+ powerMeasurandValues.L1 = Utils.getRandomFloatRounded(maxPowerPerPhase);
+ powerMeasurandValues.L2 = 0;
+ powerMeasurandValues.L3 = 0;
+ if (self._getNumberOfPhases() === 3) {
+ powerMeasurandValues.L2 = Utils.getRandomFloatRounded(maxPowerPerPhase);
+ powerMeasurandValues.L3 = Utils.getRandomFloatRounded(maxPowerPerPhase);
+ }
+ powerMeasurandValues.all = Utils.roundTo(powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3, 2);
+ }
+ break;
+ case 'DC':
+ if (Utils.isUndefined(meterValuesTemplate[index].value)) {
+ powerMeasurandValues.all = Utils.getRandomFloatRounded(maxPower);
+ }
+ break;
+ default:
+ logger.error(errMsg);
+ throw Error(errMsg);
+ }
+ sampledValues.sampledValue.push({
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? {unit: meterValuesTemplate[index].unit} : {unit: 'W'},
+ ...!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},
+ });
+ 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}`);
+ }
+ for (let phase = 1; self._getPowerOutType() === 'AC' && 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].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,
+ });
+ }
+ // Current.Import measurand
+ } else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === 'Current.Import' && self._getConfigurationKey('MeterValuesSampledData').value.includes('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`;
+ 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}`;
+ 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 currentMeasurandValues = {};
+ let maxAmperage;
+ switch (self._getPowerOutType()) {
+ case 'AC':
+ maxAmperage = ElectricUtils.ampPerPhaseFromPower(self._getNumberOfPhases(), self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut());
+ if (Utils.isUndefined(meterValuesTemplate[index].value)) {
+ currentMeasurandValues.L1 = Utils.getRandomFloatRounded(maxAmperage);
+ currentMeasurandValues.L2 = 0;
+ currentMeasurandValues.L3 = 0;
+ if (self._getNumberOfPhases() === 3) {
+ currentMeasurandValues.L2 = Utils.getRandomFloatRounded(maxAmperage);
+ currentMeasurandValues.L3 = Utils.getRandomFloatRounded(maxAmperage);
+ }
+ currentMeasurandValues.all = 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);
+ }
+ break;
+ default:
+ logger.error(errMsg);
+ throw Error(errMsg);
+ }
+ sampledValues.sampledValue.push({
+ ...!Utils.isUndefined(meterValuesTemplate[index].unit) ? {unit: meterValuesTemplate[index].unit} : {unit: 'A'},
+ ...!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},
+ });
+ 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}`);
+ }
+ for (let phase = 1; self._getPowerOutType() === 'AC' && 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].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,
});
}
// Energy.Active.Import.Register measurand (default)
} else if (!meterValuesTemplate[index].measurand || meterValuesTemplate[index].measurand === '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`;
logger.error(errMsg);
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
const measurandValue = Utils.getRandomInt(self._stationInfo.maxPower / (self._stationInfo.powerDivider * 3600000) * interval);
// Persist previous value in connector
- if (connector && connector.lastEnergyActiveImportRegisterValue >= 0) {
+ if (connector && !Utils.isNullOrUndefined(connector.lastEnergyActiveImportRegisterValue) && connector.lastEnergyActiveImportRegisterValue >= 0) {
connector.lastEnergyActiveImportRegisterValue += measurandValue;
} else {
connector.lastEnergyActiveImportRegisterValue = 0;
...!Utils.isUndefined(meterValuesTemplate[index].value) ? {value: meterValuesTemplate[index].value} : {value: connector.lastEnergyActiveImportRegisterValue},
});
const sampledValuesIndex = sampledValues.sampledValue.length - 1;
- // const measurandValuePerPhase = Utils.roundTo(sampledValues.sampledValue[sampledValuesIndex].value / self._getNumberOfPhases(), 2);
- // 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: 'Wh'},
- // ...!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},
- // value: measurandValuePerPhase,
- // phase: phaseValue,
- // });
- // }
- logger.info(`${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}`);
- const maxConsumption = self._stationInfo.maxPower * 3600 / (self._stationInfo.powerDivider * interval);
+ 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}`);
}
} else if (this._wsConnection && this._wsConnection.readyState === WebSocket.OPEN) {
// Send timeout in case connection is open otherwise wait for ever
// FIXME: Handle message on timeout
- setTimeout(() => rejectCallback(`Timeout for message ${messageId}`), Constants.OCPP_SOCKET_TIMEOUT);
+ setTimeout(() => rejectCallback(new OCPPError(command.code ? command.code : Constants.OCPP_ERROR_GENERIC_ERROR, command.message ? command.message : '', command.details ? command.details : {})), Constants.OCPP_SOCKET_TIMEOUT);
}
// Function that will receive the request's response
function responseCallback(payload, requestPayload) {
- if (self.getEnableStatistics()) {
- self._statistics.addMessage(commandName, true);
- }
- const responseCallbackFn = 'handleResponse' + commandName;
- if (typeof self[responseCallbackFn] === 'function') {
- self[responseCallbackFn](payload, requestPayload, self);
- } else {
- logger.debug(self._logPrefix() + ' Trying to call an undefined response callback function: ' + responseCallbackFn);
- }
+ self.handleResponse(commandName, payload, requestPayload, self);
// Send the response
resolve(payload);
}
// Function that will receive the request's rejection
- function rejectCallback(reason) {
+ function rejectCallback(error) {
+ if (!(error instanceof OCPPError)) {
+ const errMsg = `${self._logPrefix()} Argument error is not an instance of OCPPError in rejectCallback call`;
+ logger.error(errMsg);
+ throw Error(errMsg);
+ }
+ logger.debug(`${self._logPrefix()} Error %j on commandName %s command %j`, error, commandName, command);
if (self.getEnableStatistics()) {
- self._statistics.addMessage(`Error ${command.code ? command.code : Constants.OCPP_ERROR_GENERIC_ERROR} on ${commandName}`, true);
+ self._statistics.addMessage(`Error on commandName ${commandName}`, true);
}
// Build Exception
// eslint-disable-next-line no-empty-function
self._requests[messageId] = [() => { }, () => { }, '']; // Properly format the request
- const error = reason instanceof OCPPError ? reason : new Error(reason);
// Send error
reject(error);
}
});
}
+ // eslint-disable-next-line class-methods-use-this
+ handleResponse(commandName, payload, requestPayload, self) {
+ if (self.getEnableStatistics()) {
+ self._statistics.addMessage(commandName, true);
+ }
+ const responseCallbackFn = 'handleResponse' + commandName;
+ if (typeof self[responseCallbackFn] === 'function') {
+ self[responseCallbackFn](payload, requestPayload, self);
+ } else {
+ logger.error(self._logPrefix() + ' Trying to call an undefined response callback function: ' + responseCallbackFn);
+ }
+ }
+
handleResponseBootNotification(payload) {
if (payload.status === 'Accepted') {
this._heartbeatInterval = payload.interval * 1000;
if (this.getEnableStatistics()) {
this._statistics.addMessage(commandName, true);
}
- let result;
+ let response;
// Call
if (typeof this['handle' + commandName] === 'function') {
try {
- // Call the method
- result = await this['handle' + commandName](commandPayload);
+ // Call the method to build the response
+ response = await this['handle' + commandName](commandPayload);
} catch (error) {
// Log
logger.error(this._logPrefix() + ' Handle request error: ' + error);
throw new Error(`${commandName} is not implemented ${JSON.stringify(commandPayload, null, ' ')}`);
}
// Send response
- await this.sendMessage(messageId, result, Constants.OCPP_JSON_CALL_RESULT_MESSAGE);
+ await this.sendMessage(messageId, response, Constants.OCPP_JSON_CALL_RESULT_MESSAGE);
}
async handleReset(commandPayload) {
// Check if authorized
if (this._authorizedTags.find((value) => value === commandPayload.idTag)) {
// Authorization successful start transaction
- this.sendStartTransactionWithTimeout(transactionConnectorID, commandPayload.idTag, Constants.START_TRANSACTION_TIMEOUT);
+ this.sendStartTransactionWithTimeout(transactionConnectorID, commandPayload.idTag);
logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID + ' for idTag ' + commandPayload.idTag);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
return Constants.OCPP_RESPONSE_REJECTED;
}
// No local authorization check required => start transaction
- this.sendStartTransactionWithTimeout(transactionConnectorID, commandPayload.idTag, Constants.START_TRANSACTION_TIMEOUT);
+ this.sendStartTransactionWithTimeout(transactionConnectorID, commandPayload.idTag);
logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID + ' for idTag ' + commandPayload.idTag);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
}
}
-module.exports = ChargingStation;