repositories
/
e-mobility-charging-stations-simulator.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Add runtime persitence on OCPP parameters.
[e-mobility-charging-stations-simulator.git]
/
src
/
charging-station
/
ChargingStation.js
diff --git
a/src/charging-station/ChargingStation.js
b/src/charging-station/ChargingStation.js
index 4ebb52af4b3d21ae2c26b2fb216ba6cfaeaacfc0..0411a1a1f12c88bb457b4246f10d7b30131e37a9 100644
(file)
--- a/
src/charging-station/ChargingStation.js
+++ b/
src/charging-station/ChargingStation.js
@@
-1,14
+1,7
@@
const Configuration = require('../utils/Configuration');
const logger = require('../utils/Logger');
const WebSocket = require('ws');
const Configuration = require('../utils/Configuration');
const logger = require('../utils/Logger');
const WebSocket = require('ws');
-const {
- OCPP_JSON_CALL_MESSAGE,
- OCPP_JSON_CALL_RESULT_MESSAGE,
- OCPP_JSON_CALL_ERROR_MESSAGE,
- OCPP_ERROR_INTERNAL_ERROR,
- OCPP_SOCKET_TIMEOUT,
- OCPP_ERROR_NOT_IMPLEMENTED,
-} = require('../utils/Constants');
+const Constants = require('../utils/Constants');
const Utils = require('../utils/Utils');
const OCPPError = require('./OcppError');
const {v4: uuid} = require('uuid');
const Utils = require('../utils/Utils');
const OCPPError = require('./OcppError');
const {v4: uuid} = require('uuid');
@@
-79,7
+72,7
@@
class ChargingStation {
_getAuthorizeRemoteTxRequests() {
const authorizeRemoteTxRequests = this._configuration.configurationKey.find((configElement) => configElement.key === 'AuthorizeRemoteTxRequests');
_getAuthorizeRemoteTxRequests() {
const authorizeRemoteTxRequests = this._configuration.configurationKey.find((configElement) => configElement.key === 'AuthorizeRemoteTxRequests');
- return authorizeRemoteTxRequests ?
authorizeRemoteTxRequests.value
: false;
+ return authorizeRemoteTxRequests ?
Utils.convertToBoolean(authorizeRemoteTxRequests.value)
: false;
}
_buildChargingStation(index, stationTemplate) {
}
_buildChargingStation(index, stationTemplate) {
@@
-145,9
+138,9
@@
class ChargingStation {
});
}
} else {
});
}
} else {
- // At first start, send Boot
n
otification
+ // At first start, send Boot
N
otification
try {
try {
- this.sendMessage(uuid(), this._bootNotificationMessage, OCPP_JSON_CALL_MESSAGE, 'BootNotification');
+ this.sendMessage(uuid(), this._bootNotificationMessage,
Constants.
OCPP_JSON_CALL_MESSAGE, 'BootNotification');
} catch (error) {
logger.error(this._basicFormatLog() + ' Send boot notification error: ' + error);
}
} catch (error) {
logger.error(this._basicFormatLog() + ' Send boot notification error: ' + error);
}
@@
-187,20
+180,21
@@
class ChargingStation {
}
async onMessage(message) {
}
async onMessage(message) {
- // Parse the message
- const [messageType, messageId, commandName, commandPayload, errorDetails] = JSON.parse(message);
-
+ let [messageType, messageId, commandName, commandPayload, errorDetails] = [0, '', Constants.ENTITY_CHARGING_STATION, '', ''];
try {
try {
+ // Parse the message
+ [messageType, messageId, commandName, commandPayload, errorDetails] = JSON.parse(message);
+
// Check the Type of message
switch (messageType) {
// Incoming Message
// Check the Type of message
switch (messageType) {
// Incoming Message
- case OCPP_JSON_CALL_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_MESSAGE:
// Process the call
this._statistics.addMessage(commandName);
await this.handleRequest(messageId, commandName, commandPayload);
break;
// Outcome Message
// Process the call
this._statistics.addMessage(commandName);
await this.handleRequest(messageId, commandName, commandPayload);
break;
// Outcome Message
- case OCPP_JSON_CALL_RESULT_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_RESULT_MESSAGE:
// Respond
// eslint-disable-next-line no-case-declarations
let responseCallback; let requestPayload;
// Respond
// eslint-disable-next-line no-case-declarations
let responseCallback; let requestPayload;
@@
-218,7
+212,7
@@
class ChargingStation {
responseCallback(commandName, requestPayload);
break;
// Error Message
responseCallback(commandName, requestPayload);
break;
// Error Message
- case OCPP_JSON_CALL_ERROR_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_ERROR_MESSAGE:
if (!this._requests[messageId]) {
// Error
throw new Error(`Error for unknown message id ${messageId}`);
if (!this._requests[messageId]) {
// Error
throw new Error(`Error for unknown message id ${messageId}`);
@@
-270,19
+264,19
@@
class ChargingStation {
}
}
}
}
- send(command, messageType = OCPP_JSON_CALL_MESSAGE) {
+ send(command, messageType =
Constants.
OCPP_JSON_CALL_MESSAGE) {
// Send Message
return this.sendMessage(uuid(), command, messageType);
}
sendError(messageId, err) {
// Check exception: only OCPP error are accepted
// Send Message
return this.sendMessage(uuid(), command, messageType);
}
sendError(messageId, err) {
// Check exception: only OCPP error are accepted
- const error = (err instanceof OCPPError ? err : new OCPPError(OCPP_ERROR_INTERNAL_ERROR, err.message));
+ const error = (err instanceof OCPPError ? err : new OCPPError(
Constants.
OCPP_ERROR_INTERNAL_ERROR, err.message));
// Send error
// Send error
- return this.sendMessage(messageId, error, OCPP_JSON_CALL_ERROR_MESSAGE);
+ return this.sendMessage(messageId, error,
Constants.
OCPP_JSON_CALL_ERROR_MESSAGE);
}
}
- sendMessage(messageId, command, messageType = OCPP_JSON_CALL_RESULT_MESSAGE, commandName = '') {
+ sendMessage(messageId, command, messageType =
Constants.
OCPP_JSON_CALL_RESULT_MESSAGE, commandName = '') {
// Send a message through wsConnection
const self = this;
// Create a promise
// Send a message through wsConnection
const self = this;
// Create a promise
@@
-291,28
+285,22
@@
class ChargingStation {
// Type of message
switch (messageType) {
// Request
// Type of message
switch (messageType) {
// Request
- case OCPP_JSON_CALL_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_MESSAGE:
this._statistics.addMessage(commandName);
// Build request
this._requests[messageId] = [responseCallback, rejectCallback, command];
messageToSend = JSON.stringify([messageType, messageId, commandName, command]);
break;
// Response
this._statistics.addMessage(commandName);
// Build request
this._requests[messageId] = [responseCallback, rejectCallback, command];
messageToSend = JSON.stringify([messageType, messageId, commandName, command]);
break;
// Response
- case OCPP_JSON_CALL_RESULT_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_RESULT_MESSAGE:
// Build response
messageToSend = JSON.stringify([messageType, messageId, command]);
break;
// Error Message
// Build response
messageToSend = JSON.stringify([messageType, messageId, command]);
break;
// Error Message
- case OCPP_JSON_CALL_ERROR_MESSAGE:
+ case
Constants.
OCPP_JSON_CALL_ERROR_MESSAGE:
// Build Message
// Build Message
- // eslint-disable-next-line no-case-declarations
- const {
- code,
- message,
- details,
- } = command;
- this._statistics.addMessage(`Error ${code}`);
- messageToSend = JSON.stringify([messageType, messageId, code, message, details]);
+ this._statistics.addMessage(`Error ${command.code}`);
+ messageToSend = JSON.stringify([messageType, messageId, command.code ? command.code : Constants.OCPP_ERROR_GENERIC_ERROR, command.message ? command.message : '', command.details ? command.details : {}]);
break;
}
// Check if wsConnection in ready
break;
}
// Check if wsConnection in ready
@@
-324,13
+312,13
@@
class ChargingStation {
this._messageQueue.push(messageToSend);
}
// Request?
this._messageQueue.push(messageToSend);
}
// Request?
- if (messageType !== OCPP_JSON_CALL_MESSAGE) {
+ if (messageType !==
Constants.
OCPP_JSON_CALL_MESSAGE) {
// Yes: send Ok
resolve();
} else if (this._wsConnection.readyState === WebSocket.OPEN) {
// Send timeout in case connection is open otherwise wait for ever
// FIXME: Handle message on timeout
// Yes: send Ok
resolve();
} else if (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}`), OCPP_SOCKET_TIMEOUT);
+ setTimeout(() => rejectCallback(`Timeout for message ${messageId}`),
Constants.
OCPP_SOCKET_TIMEOUT);
}
// Function that will receive the request's response
}
// Function that will receive the request's response
@@
-373,7
+361,7
@@
class ChargingStation {
// determine number of customized connectors
let lastConnector;
for (lastConnector in connectorsConfig) {
// determine number of customized connectors
let lastConnector;
for (lastConnector in connectorsConfig) {
- if (
lastConnector
=== 0 && this._stationInfo.usedConnectorId0) {
+ if (
Utils.convertToInt(lastConnector)
=== 0 && this._stationInfo.usedConnectorId0) {
this._connectors[lastConnector] = connectorsConfig[lastConnector];
}
}
this._connectors[lastConnector] = connectorsConfig[lastConnector];
}
}
@@
-413,29
+401,29
@@
class ChargingStation {
}
handleResponseStartTransaction(payload, requestPayload) {
}
handleResponseStartTransaction(payload, requestPayload) {
- this._connectors[requestPayload.connectorId] = {
- transactionStarted: false,
- idTag: requestPayload.idTag,
- };
+ // Reset connector transaction related attributes
+ this._connectors[requestPayload.connectorId].transactionStarted = false;
+ this._connectors[requestPayload.connectorId].idTag = requestPayload.idTag;
+
if (payload.idTagInfo.status === 'Accepted') {
for (const connector in this._connectors) {
if (payload.idTagInfo.status === 'Accepted') {
for (const connector in this._connectors) {
- if (
connector
=== requestPayload.connectorId) {
+ if (
Utils.convertToInt(connector)
=== requestPayload.connectorId) {
this._connectors[connector].transactionStarted = true;
this._connectors[connector].transactionId = payload.transactionId;
this._connectors[connector].lastConsumptionValue = 0;
this._connectors[connector].lastSoC = 0;
this._connectors[connector].transactionStarted = true;
this._connectors[connector].transactionId = payload.transactionId;
this._connectors[connector].lastConsumptionValue = 0;
this._connectors[connector].lastSoC = 0;
- logger.info(this._basicFormatLog() + ' Transaction ' + this._connectors[connector].transactionId + ' STARTED on ' + this._stationInfo.name + '#' + requestPayload.connectorId);
+ logger.info(this._basicFormatLog() + ' Transaction ' + this._connectors[connector].transactionId + ' STARTED on ' + this._stationInfo.name + '#' + requestPayload.connectorId
+ ' with idTag ' + requestPayload.idTag
);
this.sendStatusNotification(requestPayload.connectorId, 'Charging');
this.sendStatusNotification(requestPayload.connectorId, 'Charging');
- const configuredMeter
Interval = this._configuration.configurationKey.find((value) => value.key === 'meterValu
eInterval');
+ const configuredMeter
ValueSampleInterval = this._configuration.configurationKey.find((value) => value.key === 'MeterValueSampl
eInterval');
this.startMeterValues(requestPayload.connectorId,
this.startMeterValues(requestPayload.connectorId,
- (configuredMeter
Interval ? configuredMeter
Interval.value * 1000 : 60000),
+ (configuredMeter
ValueSampleInterval ? configuredMeterValueSample
Interval.value * 1000 : 60000),
this);
}
}
} else {
logger.error(this._basicFormatLog() + ' Starting transaction id ' + payload.transactionId + ' REJECTED with status ' + payload.idTagInfo.status + ', idTag ' + requestPayload.idTag);
for (const connector in this._connectors) {
this);
}
}
} else {
logger.error(this._basicFormatLog() + ' Starting transaction id ' + payload.transactionId + ' REJECTED with status ' + payload.idTagInfo.status + ', idTag ' + requestPayload.idTag);
for (const connector in this._connectors) {
- if (
connector
=== requestPayload.connectorId) {
+ if (
Utils.convertToInt(connector)
=== requestPayload.connectorId) {
this._resetTransactionOnConnector(connector);
}
}
this._resetTransactionOnConnector(connector);
}
}
@@
-450,7
+438,7
@@
class ChargingStation {
errorCode,
status,
};
errorCode,
status,
};
- await this.sendMessage(uuid(), payload, OCPP_JSON_CALL_MESSAGE, 'StatusNotification');
+ await this.sendMessage(uuid(), payload,
Constants.
OCPP_JSON_CALL_MESSAGE, 'StatusNotification');
} catch (error) {
logger.error(this._basicFormatLog() + ' Send status error: ' + error);
}
} catch (error) {
logger.error(this._basicFormatLog() + ' Send status error: ' + error);
}
@@
-465,7
+453,7
@@
class ChargingStation {
const payload = {
currentTime: new Date().toISOString(),
};
const payload = {
currentTime: new Date().toISOString(),
};
- self.sendMessage(uuid(), payload, OCPP_JSON_CALL_MESSAGE, 'Heartbeat');
+ self.sendMessage(uuid(), payload,
Constants.
OCPP_JSON_CALL_MESSAGE, 'Heartbeat');
} catch (error) {
logger.error(self._basicFormatLog() + ' Send heartbeat error: ' + error);
}
} catch (error) {
logger.error(self._basicFormatLog() + ' Send heartbeat error: ' + error);
}
@@
-490,12
+478,12
@@
class ChargingStation {
await this.sendError(messageId, error);
}
} else {
await this.sendError(messageId, error);
}
} else {
- // Throw
E
xception
- await this.sendError(messageId, new OCPPError(OCPP_ERROR_NOT_IMPLEMENTED, 'Not implemented', {}));
+ // Throw
e
xception
+ await this.sendError(messageId, new OCPPError(
Constants.
OCPP_ERROR_NOT_IMPLEMENTED, 'Not implemented', {}));
throw new Error(`${commandName} is not implemented ${JSON.stringify(commandPayload, null, ' ')}`);
}
throw new Error(`${commandName} is not implemented ${JSON.stringify(commandPayload, null, ' ')}`);
}
- // Send
R
esponse
- await this.sendMessage(messageId, result, OCPP_JSON_CALL_RESULT_MESSAGE);
+ // Send
r
esponse
+ await this.sendMessage(messageId, result,
Constants.
OCPP_JSON_CALL_RESULT_MESSAGE);
}
async handleGetConfiguration() {
}
async handleGetConfiguration() {
@@
-504,38
+492,32
@@
class ChargingStation {
async handleChangeConfiguration(commandPayload) {
const keyToChange = this._configuration.configurationKey.find((element) => element.key === commandPayload.key);
async handleChangeConfiguration(commandPayload) {
const keyToChange = this._configuration.configurationKey.find((element) => element.key === commandPayload.key);
- if (keyToChange) {
- keyToChange.value = commandPayload.value;
- return {
- status: 'Accepted',
- };
+ if (keyToChange && !Utils.convertToBoolean(keyToChange.readonly)) {
+ const keyIndex = this._configuration.configurationKey.indexOf(keyToChange);
+ this._configuration.configurationKey[keyIndex].value = commandPayload.value;
+ return Constants.OCPP_RESPONSE_ACCEPTED;
}
}
- return {
- status: 'Rejected',
- };
+ return Constants.OCPP_RESPONSE_REJECTED;
}
async handleRemoteStartTransaction(commandPayload) {
const transactionConnectorID = (commandPayload.connectorId ? commandPayload.connectorId : '1');
if (this.isAuthorizationRequested() && this._authorizeRemoteTxRequests) {
}
async handleRemoteStartTransaction(commandPayload) {
const transactionConnectorID = (commandPayload.connectorId ? commandPayload.connectorId : '1');
if (this.isAuthorizationRequested() && this._authorizeRemoteTxRequests) {
- //
c
heck if authorized
+ //
C
heck if authorized
if (this._authorizedKeys.find((value) => value === commandPayload.idTag)) {
// Authorization successful start transaction
setTimeout(() => this.sendStartTransaction(transactionConnectorID, commandPayload.idTag), 500);
if (this._authorizedKeys.find((value) => value === commandPayload.idTag)) {
// Authorization successful start transaction
setTimeout(() => this.sendStartTransaction(transactionConnectorID, commandPayload.idTag), 500);
- return {
- status: 'Accepted',
- };
+ logger.info(this._basicFormatLog() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID + ' with idTag ' + commandPayload.idTag);
+ return Constants.OCPP_RESPONSE_ACCEPTED;
}
// Start authorization checks
}
// Start authorization checks
- return {
- status: 'Rejected',
- };
+ logger.error(this._basicFormatLog() + ' Remote starting transaction REJECTED with status ' + commandPayload.idTagInfo.status + ', idTag ' + commandPayload.idTag);
+ return Constants.OCPP_RESPONSE_REJECTED;
}
}
- //
n
o local authorization check required => start transaction
+ //
N
o local authorization check required => start transaction
setTimeout(() => this.sendStartTransaction(transactionConnectorID, commandPayload.idTag), 500);
setTimeout(() => this.sendStartTransaction(transactionConnectorID, commandPayload.idTag), 500);
- return {
- status: 'Accepted',
- };
+ logger.info(this._basicFormatLog() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID + ' with idTag ' + commandPayload.idTag);
+ return Constants.OCPP_RESPONSE_ACCEPTED;
}
async sendStartTransaction(connectorID, idTag) {
}
async sendStartTransaction(connectorID, idTag) {
@@
-546,7
+528,7
@@
class ChargingStation {
meterStart: 0,
timestamp: new Date().toISOString(),
};
meterStart: 0,
timestamp: new Date().toISOString(),
};
- return await this.sendMessage(uuid(), payload, OCPP_JSON_CALL_MESSAGE, 'StartTransaction');
+ return await this.sendMessage(uuid(), payload,
Constants.
OCPP_JSON_CALL_MESSAGE, 'StartTransaction');
} catch (error) {
logger.error(this._basicFormatLog() + ' Send start transaction error: ' + error);
this._resetTransactionOnConnector(connectorID);
} catch (error) {
logger.error(this._basicFormatLog() + ' Send start transaction error: ' + error);
this._resetTransactionOnConnector(connectorID);
@@
-561,7
+543,7
@@
class ChargingStation {
meterStop: 0,
timestamp: new Date().toISOString(),
};
meterStop: 0,
timestamp: new Date().toISOString(),
};
- await this.sendMessage(uuid(), payload, OCPP_JSON_CALL_MESSAGE, 'StopTransaction');
+ await this.sendMessage(uuid(), payload,
Constants.
OCPP_JSON_CALL_MESSAGE, 'StopTransaction');
logger.info(this._basicFormatLog() + ' Transaction ' + this._connectors[connectorID].transactionId + ' STOPPED on ' + this._stationInfo.name + '#' + connectorID);
this.sendStatusNotification(connectorID, 'Available');
} catch (error) {
logger.info(this._basicFormatLog() + ' Transaction ' + this._connectors[connectorID].transactionId + ' STOPPED on ' + this._stationInfo.name + '#' + connectorID);
this.sendStatusNotification(connectorID, 'Available');
} catch (error) {
@@
-606,7
+588,7
@@
class ChargingStation {
// Persist previous value in connector
const connector = self._connectors[connectorID];
let consumption;
// Persist previous value in connector
const connector = self._connectors[connectorID];
let consumption;
- consumption = Utils.getRandomInt(self._stationInfo.maxPower / 3600000 * interval,
3
);
+ consumption = Utils.getRandomInt(self._stationInfo.maxPower / 3600000 * interval,
4
);
if (connector && connector.lastConsumptionValue >= 0) {
connector.lastConsumptionValue += consumption;
} else {
if (connector && connector.lastConsumptionValue >= 0) {
connector.lastConsumptionValue += consumption;
} else {
@@
-628,18
+610,18
@@
class ChargingStation {
transactionId: self._connectors[connectorID].transactionId,
meterValue: [sampledValueLcl],
};
transactionId: self._connectors[connectorID].transactionId,
meterValue: [sampledValueLcl],
};
- await self.sendMessage(uuid(), payload, OCPP_JSON_CALL_MESSAGE, 'MeterValues');
+ await self.sendMessage(uuid(), payload,
Constants.
OCPP_JSON_CALL_MESSAGE, 'MeterValues');
} catch (error) {
logger.error(self._basicFormatLog() + ' Send meter values error: ' + error);
}
}
async startMeterValues(connectorID, interval, self) {
} catch (error) {
logger.error(self._basicFormatLog() + ' Send meter values error: ' + error);
}
}
async startMeterValues(connectorID, interval, self) {
-
//
if (!this._connectors[connectorID].transactionStarted) {
-
//
logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction`);
-
//
} else if (this._connectors[connectorID].transactionStarted && !this._connectors[connectorID].transactionId) {
-
//
logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction id`);
-
//
}
+ if (!this._connectors[connectorID].transactionStarted) {
+ logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction`);
+ } else if (this._connectors[connectorID].transactionStarted && !this._connectors[connectorID].transactionId) {
+ logger.debug(`${self._basicFormatLog()} Trying to start meter values on connector ID ${connectorID} with no transaction id`);
+ }
this._connectors[connectorID].transactionInterval = setInterval(async () => {
const sendMeterValues = performance.timerify(this.sendMeterValues);
this._performanceObserver.observe({
this._connectors[connectorID].transactionInterval = setInterval(async () => {
const sendMeterValues = performance.timerify(this.sendMeterValues);
this._performanceObserver.observe({
@@
-655,9
+637,7
@@
class ChargingStation {
this.sendStopTransaction(commandPayload.transactionId, connector);
}
}
this.sendStopTransaction(commandPayload.transactionId, connector);
}
}
- return {
- status: 'Accepted',
- };
+ return Constants.OCPP_RESPONSE_ACCEPTED;
}
isAuthorizationRequested() {
}
isAuthorizationRequested() {