import logger from '../utils/Logger';
export default class ChargingStation {
- private _index: number;
- private _stationTemplateFile: string;
- private _stationInfo: ChargingStationInfo;
- private _bootNotificationRequest: BootNotificationRequest;
- private _bootNotificationResponse: BootNotificationResponse;
- private _connectors: Connectors;
- private _configuration: ChargingStationConfiguration;
- private _connectorsConfigurationHash: string;
- private _supervisionUrl: string;
- private _wsConnectionUrl: string;
- private _wsConnection: WebSocket;
- private _hasStopped: boolean;
- private _hasSocketRestarted: boolean;
- private _autoReconnectRetryCount: number;
- private _requests: Requests;
- private _messageQueue: string[];
- private _automaticTransactionGeneration: AutomaticTransactionGenerator;
- private _authorizedTags: string[];
- private _heartbeatSetInterval: NodeJS.Timeout;
- private _webSocketPingSetInterval: NodeJS.Timeout;
- private _statistics: Statistics;
- private _performanceObserver: PerformanceObserver;
+ public stationInfo: ChargingStationInfo;
+ public connectors: Connectors;
+ public statistics: Statistics;
+ private index: number;
+ private stationTemplateFile: string;
+ private bootNotificationRequest: BootNotificationRequest;
+ private bootNotificationResponse: BootNotificationResponse;
+ private configuration: ChargingStationConfiguration;
+ private connectorsConfigurationHash: string;
+ private supervisionUrl: string;
+ private wsConnectionUrl: string;
+ private wsConnection: WebSocket;
+ private hasStopped: boolean;
+ private hasSocketRestarted: boolean;
+ private autoReconnectRetryCount: number;
+ private requests: Requests;
+ private messageQueue: string[];
+ private automaticTransactionGeneration: AutomaticTransactionGenerator;
+ private authorizedTags: string[];
+ private heartbeatSetInterval: NodeJS.Timeout;
+ private webSocketPingSetInterval: NodeJS.Timeout;
+ private performanceObserver: PerformanceObserver;
constructor(index: number, stationTemplateFile: string) {
- this._index = index;
- this._stationTemplateFile = stationTemplateFile;
- this._connectors = {} as Connectors;
+ this.index = index;
+ this.stationTemplateFile = stationTemplateFile;
+ this.connectors = {} as Connectors;
this._initialize();
- this._hasStopped = false;
- this._hasSocketRestarted = false;
- this._autoReconnectRetryCount = 0;
+ this.hasStopped = false;
+ this.hasSocketRestarted = false;
+ this.autoReconnectRetryCount = 0;
- this._requests = {} as Requests;
- this._messageQueue = [] as string[];
+ this.requests = {} as Requests;
+ this.messageQueue = [] as string[];
- this._authorizedTags = this._loadAndGetAuthorizedTags();
+ this.authorizedTags = this._loadAndGetAuthorizedTags();
}
_getChargingStationId(stationTemplate: ChargingStationTemplate): string {
const idSuffix = stationTemplate.nameSuffix ? stationTemplate.nameSuffix : '';
- return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex.toString() + ('000000000' + this._index.toString()).substr(('000000000' + this._index.toString()).length - 4) + idSuffix;
+ return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex.toString() + ('000000000' + this.index.toString()).substr(('000000000' + this.index.toString()).length - 4) + idSuffix;
}
_buildStationInfo(): ChargingStationInfo {
let stationTemplateFromFile: ChargingStationTemplate;
try {
// Load template file
- const fileDescriptor = fs.openSync(this._stationTemplateFile, 'r');
+ const fileDescriptor = fs.openSync(this.stationTemplateFile, 'r');
stationTemplateFromFile = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as ChargingStationTemplate;
fs.closeSync(fileDescriptor);
} catch (error) {
- logger.error('Template file ' + this._stationTemplateFile + ' loading error: %j', error);
+ logger.error('Template file ' + this.stationTemplateFile + ' loading error: %j', error);
throw error;
}
const stationInfo: ChargingStationInfo = stationTemplateFromFile || {} as ChargingStationInfo;
return stationInfo;
}
- get stationInfo(): ChargingStationInfo {
- return this._stationInfo;
- }
-
_initialize(): void {
- this._stationInfo = this._buildStationInfo();
- this._bootNotificationRequest = {
- chargePointModel: this._stationInfo.chargePointModel,
- chargePointVendor: this._stationInfo.chargePointVendor,
- ...!Utils.isUndefined(this._stationInfo.chargeBoxSerialNumberPrefix) && { chargeBoxSerialNumber: this._stationInfo.chargeBoxSerialNumberPrefix },
- ...!Utils.isUndefined(this._stationInfo.firmwareVersion) && { firmwareVersion: this._stationInfo.firmwareVersion },
+ this.stationInfo = this._buildStationInfo();
+ this.bootNotificationRequest = {
+ chargePointModel: this.stationInfo.chargePointModel,
+ chargePointVendor: this.stationInfo.chargePointVendor,
+ ...!Utils.isUndefined(this.stationInfo.chargeBoxSerialNumberPrefix) && { chargeBoxSerialNumber: this.stationInfo.chargeBoxSerialNumberPrefix },
+ ...!Utils.isUndefined(this.stationInfo.firmwareVersion) && { firmwareVersion: this.stationInfo.firmwareVersion },
};
- this._configuration = this._getTemplateChargingStationConfiguration();
- this._supervisionUrl = this._getSupervisionURL();
- this._wsConnectionUrl = this._supervisionUrl + '/' + this._stationInfo.chargingStationId;
+ this.configuration = this._getTemplateChargingStationConfiguration();
+ this.supervisionUrl = this._getSupervisionURL();
+ this.wsConnectionUrl = this.supervisionUrl + '/' + this.stationInfo.chargingStationId;
// Build connectors if needed
const maxConnectors = this._getMaxNumberOfConnectors();
if (maxConnectors <= 0) {
- logger.warn(`${this._logPrefix()} Charging station template ${this._stationTemplateFile} with ${maxConnectors} connectors`);
+ logger.warn(`${this._logPrefix()} Charging station template ${this.stationTemplateFile} with ${maxConnectors} connectors`);
}
const templateMaxConnectors = this._getTemplateMaxNumberOfConnectors();
if (templateMaxConnectors <= 0) {
- logger.warn(`${this._logPrefix()} Charging station template ${this._stationTemplateFile} with no connector configuration`);
+ logger.warn(`${this._logPrefix()} Charging station template ${this.stationTemplateFile} with no connector configuration`);
}
- if (!this._stationInfo.Connectors[0]) {
- logger.warn(`${this._logPrefix()} Charging station template ${this._stationTemplateFile} with no connector Id 0 configuration`);
+ if (!this.stationInfo.Connectors[0]) {
+ logger.warn(`${this._logPrefix()} Charging station template ${this.stationTemplateFile} with no connector Id 0 configuration`);
}
// Sanity check
- if (maxConnectors > (this._stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) && !this._stationInfo.randomConnectors) {
- logger.warn(`${this._logPrefix()} Number of connectors exceeds the number of connector configurations in template ${this._stationTemplateFile}, forcing random connector configurations affectation`);
- this._stationInfo.randomConnectors = true;
+ if (maxConnectors > (this.stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) && !this.stationInfo.randomConnectors) {
+ logger.warn(`${this._logPrefix()} Number of connectors exceeds the number of connector configurations in template ${this.stationTemplateFile}, forcing random connector configurations affectation`);
+ this.stationInfo.randomConnectors = true;
}
- const connectorsConfigHash = crypto.createHash('sha256').update(JSON.stringify(this._stationInfo.Connectors) + maxConnectors.toString()).digest('hex');
+ const connectorsConfigHash = crypto.createHash('sha256').update(JSON.stringify(this.stationInfo.Connectors) + maxConnectors.toString()).digest('hex');
// FIXME: Handle shrinking the number of connectors
- if (!this._connectors || (this._connectors && this._connectorsConfigurationHash !== connectorsConfigHash)) {
- this._connectorsConfigurationHash = connectorsConfigHash;
+ if (!this.connectors || (this.connectors && this.connectorsConfigurationHash !== connectorsConfigHash)) {
+ this.connectorsConfigurationHash = connectorsConfigHash;
// Add connector Id 0
let lastConnector = '0';
- for (lastConnector in this._stationInfo.Connectors) {
- if (Utils.convertToInt(lastConnector) === 0 && this._getUseConnectorId0() && this._stationInfo.Connectors[lastConnector]) {
- this._connectors[lastConnector] = Utils.cloneObject<Connector>(this._stationInfo.Connectors[lastConnector]);
- this._connectors[lastConnector].availability = AvailabilityType.OPERATIVE;
+ for (lastConnector in this.stationInfo.Connectors) {
+ if (Utils.convertToInt(lastConnector) === 0 && this._getUseConnectorId0() && this.stationInfo.Connectors[lastConnector]) {
+ this.connectors[lastConnector] = Utils.cloneObject<Connector>(this.stationInfo.Connectors[lastConnector]);
+ this.connectors[lastConnector].availability = AvailabilityType.OPERATIVE;
}
}
// Generate all connectors
- if ((this._stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) > 0) {
+ 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<Connector>(this._stationInfo.Connectors[randConnectorID]);
- this._connectors[index].availability = AvailabilityType.OPERATIVE;
+ const randConnectorID = this.stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index;
+ this.connectors[index] = Utils.cloneObject<Connector>(this.stationInfo.Connectors[randConnectorID]);
+ this.connectors[index].availability = AvailabilityType.OPERATIVE;
}
}
}
// Avoid duplication of connectors related information
- delete this._stationInfo.Connectors;
+ delete this.stationInfo.Connectors;
// Initialize transaction attributes on connectors
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && !this.getConnector(Utils.convertToInt(connector)).transactionStarted) {
this._initTransactionOnConnector(Utils.convertToInt(connector));
}
if (!this._getConfigurationKey(StandardParametersKey.MeterValuesSampledData)) {
this._addConfigurationKey(StandardParametersKey.MeterValuesSampledData, MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER);
}
- this._stationInfo.powerDivider = this._getPowerDivider();
+ this.stationInfo.powerDivider = this._getPowerDivider();
if (this.getEnableStatistics()) {
- this._statistics = Statistics.getInstance();
- this._statistics.objName = this._stationInfo.chargingStationId;
- this._performanceObserver = new PerformanceObserver((list) => {
+ this.statistics = Statistics.getInstance();
+ this.statistics.objName = this.stationInfo.chargingStationId;
+ this.performanceObserver = new PerformanceObserver((list) => {
const entry = list.getEntries()[0];
- this._statistics.logPerformance(entry, Constants.ENTITY_CHARGING_STATION);
- this._performanceObserver.disconnect();
+ this.statistics.logPerformance(entry, Constants.ENTITY_CHARGING_STATION);
+ this.performanceObserver.disconnect();
});
}
}
- get connectors(): Connectors {
- return this._connectors;
- }
-
- get statistics(): Statistics {
- return this._statistics;
- }
-
_logPrefix(): string {
- return Utils.logPrefix(` ${this._stationInfo.chargingStationId}:`);
+ return Utils.logPrefix(` ${this.stationInfo.chargingStationId}:`);
}
_isWebSocketOpen(): boolean {
- return this._wsConnection?.readyState === WebSocket.OPEN;
+ return this.wsConnection?.readyState === WebSocket.OPEN;
}
_isRegistered(): boolean {
- return this._bootNotificationResponse?.status === RegistrationStatus.ACCEPTED;
+ return this.bootNotificationResponse?.status === RegistrationStatus.ACCEPTED;
}
_getTemplateChargingStationConfiguration(): ChargingStationConfiguration {
- return this._stationInfo.Configuration ? this._stationInfo.Configuration : {} as ChargingStationConfiguration;
+ return this.stationInfo.Configuration ? this.stationInfo.Configuration : {} as ChargingStationConfiguration;
}
_getAuthorizationFile(): string {
- return this._stationInfo.authorizationFile && this._stationInfo.authorizationFile;
+ return this.stationInfo.authorizationFile && this.stationInfo.authorizationFile;
}
_getUseConnectorId0(): boolean {
- return !Utils.isUndefined(this._stationInfo.useConnectorId0) ? this._stationInfo.useConnectorId0 : true;
+ return !Utils.isUndefined(this.stationInfo.useConnectorId0) ? this.stationInfo.useConnectorId0 : true;
}
_loadAndGetAuthorizedTags(): string[] {
throw error;
}
} else {
- logger.info(this._logPrefix() + ' No authorization file given in template file ' + this._stationTemplateFile);
+ logger.info(this._logPrefix() + ' No authorization file given in template file ' + this.stationTemplateFile);
}
return authorizedTags;
}
getRandomTagId(): string {
- const index = Math.floor(Math.random() * this._authorizedTags.length);
- return this._authorizedTags[index];
+ const index = Math.floor(Math.random() * this.authorizedTags.length);
+ return this.authorizedTags[index];
}
hasAuthorizedTags(): boolean {
- return !Utils.isEmptyArray(this._authorizedTags);
+ return !Utils.isEmptyArray(this.authorizedTags);
}
getEnableStatistics(): boolean {
- return !Utils.isUndefined(this._stationInfo.enableStatistics) ? this._stationInfo.enableStatistics : true;
+ return !Utils.isUndefined(this.stationInfo.enableStatistics) ? this.stationInfo.enableStatistics : true;
}
_getNumberOfPhases(): number {
switch (this._getPowerOutType()) {
case PowerOutType.AC:
- return !Utils.isUndefined(this._stationInfo.numberOfPhases) ? this._stationInfo.numberOfPhases : 3;
+ return !Utils.isUndefined(this.stationInfo.numberOfPhases) ? this.stationInfo.numberOfPhases : 3;
case PowerOutType.DC:
return 0;
}
_getNumberOfRunningTransactions(): number {
let trxCount = 0;
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector)).transactionStarted) {
trxCount++;
}
// 0 for disabling
_getConnectionTimeout(): number {
- if (!Utils.isUndefined(this._stationInfo.connectionTimeout)) {
- return this._stationInfo.connectionTimeout;
+ if (!Utils.isUndefined(this.stationInfo.connectionTimeout)) {
+ return this.stationInfo.connectionTimeout;
}
if (!Utils.isUndefined(Configuration.getConnectionTimeout())) {
return Configuration.getConnectionTimeout();
// -1 for unlimited, 0 for disabling
_getAutoReconnectMaxRetries(): number {
- if (!Utils.isUndefined(this._stationInfo.autoReconnectMaxRetries)) {
- return this._stationInfo.autoReconnectMaxRetries;
+ if (!Utils.isUndefined(this.stationInfo.autoReconnectMaxRetries)) {
+ return this.stationInfo.autoReconnectMaxRetries;
}
if (!Utils.isUndefined(Configuration.getAutoReconnectMaxRetries())) {
return Configuration.getAutoReconnectMaxRetries();
// 0 for disabling
_getRegistrationMaxRetries(): number {
- if (!Utils.isUndefined(this._stationInfo.registrationMaxRetries)) {
- return this._stationInfo.registrationMaxRetries;
+ if (!Utils.isUndefined(this.stationInfo.registrationMaxRetries)) {
+ return this.stationInfo.registrationMaxRetries;
}
return -1;
}
_getPowerDivider(): number {
let powerDivider = this._getNumberOfConnectors();
- if (this._stationInfo.powerSharedByConnectors) {
+ if (this.stationInfo.powerSharedByConnectors) {
powerDivider = this._getNumberOfRunningTransactions();
}
return powerDivider;
}
getConnector(id: number): Connector {
- return this._connectors[id];
+ return this.connectors[id];
}
_isConnectorAvailable(id: number): boolean {
}
_getTemplateMaxNumberOfConnectors(): number {
- return Object.keys(this._stationInfo.Connectors).length;
+ return Object.keys(this.stationInfo.Connectors).length;
}
_getMaxNumberOfConnectors(): number {
let maxConnectors = 0;
- if (!Utils.isEmptyArray(this._stationInfo.numberOfConnectors)) {
- const numberOfConnectors = this._stationInfo.numberOfConnectors as number[];
+ if (!Utils.isEmptyArray(this.stationInfo.numberOfConnectors)) {
+ const numberOfConnectors = this.stationInfo.numberOfConnectors as number[];
// Distribute evenly the number of connectors
- maxConnectors = numberOfConnectors[(this._index - 1) % numberOfConnectors.length];
- } else if (!Utils.isUndefined(this._stationInfo.numberOfConnectors)) {
- maxConnectors = this._stationInfo.numberOfConnectors as number;
+ maxConnectors = numberOfConnectors[(this.index - 1) % numberOfConnectors.length];
+ } else if (!Utils.isUndefined(this.stationInfo.numberOfConnectors)) {
+ maxConnectors = this.stationInfo.numberOfConnectors as number;
} else {
- maxConnectors = this._stationInfo.Connectors[0] ? this._getTemplateMaxNumberOfConnectors() - 1 : this._getTemplateMaxNumberOfConnectors();
+ maxConnectors = this.stationInfo.Connectors[0] ? this._getTemplateMaxNumberOfConnectors() - 1 : this._getTemplateMaxNumberOfConnectors();
}
return maxConnectors;
}
_getNumberOfConnectors(): number {
- return this._connectors[0] ? Object.keys(this._connectors).length - 1 : Object.keys(this._connectors).length;
+ return this.connectors[0] ? Object.keys(this.connectors).length - 1 : Object.keys(this.connectors).length;
}
_getVoltageOut(): number {
- const errMsg = `${this._logPrefix()} Unknown ${this._getPowerOutType()} powerOutType in template file ${this._stationTemplateFile}, cannot define default voltage out`;
+ const errMsg = `${this._logPrefix()} Unknown ${this._getPowerOutType()} powerOutType in template file ${this.stationTemplateFile}, cannot define default voltage out`;
let defaultVoltageOut: number;
switch (this._getPowerOutType()) {
case PowerOutType.AC:
logger.error(errMsg);
throw Error(errMsg);
}
- return !Utils.isUndefined(this._stationInfo.voltageOut) ? this._stationInfo.voltageOut : defaultVoltageOut;
+ return !Utils.isUndefined(this.stationInfo.voltageOut) ? this.stationInfo.voltageOut : defaultVoltageOut;
}
_getTransactionIdTag(transactionId: number): string {
- for (const connector in this._connectors) {
+ 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;
}
}
_getTransactionMeterStop(transactionId: number): number {
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector)).transactionId === transactionId) {
return this.getConnector(Utils.convertToInt(connector)).lastEnergyActiveImportRegisterValue;
}
}
_getPowerOutType(): PowerOutType {
- return !Utils.isUndefined(this._stationInfo.powerOutType) ? this._stationInfo.powerOutType : PowerOutType.AC;
+ return !Utils.isUndefined(this.stationInfo.powerOutType) ? this.stationInfo.powerOutType : PowerOutType.AC;
}
_getSupervisionURL(): string {
- const supervisionUrls = Utils.cloneObject<string | string[]>(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs());
+ const supervisionUrls = Utils.cloneObject<string | string[]>(this.stationInfo.supervisionURL ? this.stationInfo.supervisionURL : Configuration.getSupervisionURLs());
let indexUrl = 0;
if (!Utils.isEmptyArray(supervisionUrls)) {
if (Configuration.getDistributeStationsToTenantsEqually()) {
- indexUrl = this._index % supervisionUrls.length;
+ indexUrl = this.index % supervisionUrls.length;
} else {
// Get a random url
indexUrl = Math.floor(Math.random() * supervisionUrls.length);
}
_getReconnectExponentialDelay(): boolean {
- return !Utils.isUndefined(this._stationInfo.reconnectExponentialDelay) ? this._stationInfo.reconnectExponentialDelay : false;
+ return !Utils.isUndefined(this.stationInfo.reconnectExponentialDelay) ? this.stationInfo.reconnectExponentialDelay : false;
}
_getHeartbeatInterval(): number {
// Start heartbeat
this._startHeartbeat();
// Initialize connectors status
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) === 0) {
continue;
- } else if (!this._hasStopped && !this.getConnector(Utils.convertToInt(connector))?.status && this.getConnector(Utils.convertToInt(connector))?.bootStatus) {
+ } else if (!this.hasStopped && !this.getConnector(Utils.convertToInt(connector))?.status && this.getConnector(Utils.convertToInt(connector))?.bootStatus) {
// Send status in template at startup
await this.sendStatusNotification(Utils.convertToInt(connector), this.getConnector(Utils.convertToInt(connector)).bootStatus);
- } else if (this._hasStopped && this.getConnector(Utils.convertToInt(connector))?.bootStatus) {
+ } else if (this.hasStopped && this.getConnector(Utils.convertToInt(connector))?.bootStatus) {
// Send status in template after reset
await this.sendStatusNotification(Utils.convertToInt(connector), this.getConnector(Utils.convertToInt(connector)).bootStatus);
- } else if (!this._hasStopped && this.getConnector(Utils.convertToInt(connector))?.status) {
+ } else if (!this.hasStopped && this.getConnector(Utils.convertToInt(connector))?.status) {
// Send previous status at template reload
await this.sendStatusNotification(Utils.convertToInt(connector), this.getConnector(Utils.convertToInt(connector)).status);
} else {
}
}
// Start the ATG
- if (this._stationInfo.AutomaticTransactionGenerator.enable) {
- if (!this._automaticTransactionGeneration) {
- this._automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
+ if (this.stationInfo.AutomaticTransactionGenerator.enable) {
+ if (!this.automaticTransactionGeneration) {
+ this.automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
}
- if (this._automaticTransactionGeneration.timeToStop) {
- this._automaticTransactionGeneration.start();
+ if (this.automaticTransactionGeneration.timeToStop) {
+ this.automaticTransactionGeneration.start();
}
}
if (this.getEnableStatistics()) {
- this._statistics.start();
+ this.statistics.start();
}
}
// Stop heartbeat
this._stopHeartbeat();
// Stop the ATG
- if (this._stationInfo.AutomaticTransactionGenerator.enable &&
- this._automaticTransactionGeneration &&
- !this._automaticTransactionGeneration.timeToStop) {
- await this._automaticTransactionGeneration.stop(reason);
+ if (this.stationInfo.AutomaticTransactionGenerator.enable &&
+ this.automaticTransactionGeneration &&
+ !this.automaticTransactionGeneration.timeToStop) {
+ await this.automaticTransactionGeneration.stop(reason);
} else {
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector)).transactionStarted) {
await this.sendStopTransaction(this.getConnector(Utils.convertToInt(connector)).transactionId, reason);
}
_startWebSocketPing(): void {
const webSocketPingInterval: number = this._getConfigurationKey(StandardParametersKey.WebSocketPingInterval) ? Utils.convertToInt(this._getConfigurationKey(StandardParametersKey.WebSocketPingInterval).value) : 0;
- if (webSocketPingInterval > 0 && !this._webSocketPingSetInterval) {
- this._webSocketPingSetInterval = setInterval(() => {
+ if (webSocketPingInterval > 0 && !this.webSocketPingSetInterval) {
+ this.webSocketPingSetInterval = setInterval(() => {
if (this._isWebSocketOpen()) {
- this._wsConnection.ping((): void => { });
+ this.wsConnection.ping((): void => { });
}
}, webSocketPingInterval * 1000);
logger.info(this._logPrefix() + ' WebSocket ping started every ' + Utils.secondsToHHMMSS(webSocketPingInterval));
- } else if (this._webSocketPingSetInterval) {
+ } else if (this.webSocketPingSetInterval) {
logger.info(this._logPrefix() + ' WebSocket ping every ' + Utils.secondsToHHMMSS(webSocketPingInterval) + ' already started');
} else {
logger.error(`${this._logPrefix()} WebSocket ping interval set to ${webSocketPingInterval ? Utils.secondsToHHMMSS(webSocketPingInterval) : webSocketPingInterval}, not starting the WebSocket ping`);
}
_stopWebSocketPing(): void {
- if (this._webSocketPingSetInterval) {
- clearInterval(this._webSocketPingSetInterval);
- this._webSocketPingSetInterval = null;
+ if (this.webSocketPingSetInterval) {
+ clearInterval(this.webSocketPingSetInterval);
+ this.webSocketPingSetInterval = null;
}
}
}
_startHeartbeat(): void {
- if (this._getHeartbeatInterval() && this._getHeartbeatInterval() > 0 && !this._heartbeatSetInterval) {
- this._heartbeatSetInterval = setInterval(async () => {
+ if (this._getHeartbeatInterval() && this._getHeartbeatInterval() > 0 && !this.heartbeatSetInterval) {
+ this.heartbeatSetInterval = setInterval(async () => {
await this.sendHeartbeat();
}, this._getHeartbeatInterval());
logger.info(this._logPrefix() + ' Heartbeat started every ' + Utils.milliSecondsToHHMMSS(this._getHeartbeatInterval()));
- } else if (this._heartbeatSetInterval) {
+ } else if (this.heartbeatSetInterval) {
logger.info(this._logPrefix() + ' Heartbeat every ' + Utils.milliSecondsToHHMMSS(this._getHeartbeatInterval()) + ' already started');
} else {
logger.error(`${this._logPrefix()} Heartbeat interval set to ${this._getHeartbeatInterval() ? Utils.milliSecondsToHHMMSS(this._getHeartbeatInterval()) : this._getHeartbeatInterval()}, not starting the heartbeat`);
}
_stopHeartbeat(): void {
- if (this._heartbeatSetInterval) {
- clearInterval(this._heartbeatSetInterval);
- this._heartbeatSetInterval = null;
+ if (this.heartbeatSetInterval) {
+ clearInterval(this.heartbeatSetInterval);
+ this.heartbeatSetInterval = null;
}
}
try {
logger.debug(this._logPrefix() + ' Authorization file ' + this._getAuthorizationFile() + ' have changed, reload');
// Initialize _authorizedTags
- this._authorizedTags = this._loadAndGetAuthorizedTags();
+ this.authorizedTags = this._loadAndGetAuthorizedTags();
} catch (error) {
logger.error(this._logPrefix() + ' Authorization file monitoring error: %j', error);
}
}
_startStationTemplateFileMonitoring(): void {
- fs.watch(this._stationTemplateFile).on('change', (e) => {
+ fs.watch(this.stationTemplateFile).on('change', (e) => {
try {
- logger.debug(this._logPrefix() + ' Template file ' + this._stationTemplateFile + ' have changed, reload');
+ logger.debug(this._logPrefix() + ' Template file ' + this.stationTemplateFile + ' have changed, reload');
// Initialize
this._initialize();
// Stop the ATG
- if (!this._stationInfo.AutomaticTransactionGenerator.enable &&
- this._automaticTransactionGeneration) {
- this._automaticTransactionGeneration.stop().catch(() => { });
+ if (!this.stationInfo.AutomaticTransactionGenerator.enable &&
+ this.automaticTransactionGeneration) {
+ this.automaticTransactionGeneration.stop().catch(() => { });
}
// Start the ATG
- if (this._stationInfo.AutomaticTransactionGenerator.enable) {
- if (!this._automaticTransactionGeneration) {
- this._automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
+ if (this.stationInfo.AutomaticTransactionGenerator.enable) {
+ if (!this.automaticTransactionGeneration) {
+ this.automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
}
- if (this._automaticTransactionGeneration.timeToStop) {
- this._automaticTransactionGeneration.start();
+ if (this.automaticTransactionGeneration.timeToStop) {
+ this.automaticTransactionGeneration.start();
}
}
// FIXME?: restart heartbeat and WebSocket ping when their interval values have changed
this.getConnector(connectorId).transactionSetInterval = setInterval(async () => {
if (this.getEnableStatistics()) {
const sendMeterValues = performance.timerify(this.sendMeterValues);
- this._performanceObserver.observe({
+ this.performanceObserver.observe({
entryTypes: ['function'],
});
await sendMeterValues(connectorId, interval, this);
options.handshakeTimeout = this._getConnectionTimeout() * 1000;
}
if (this._isWebSocketOpen() && forceCloseOpened) {
- this._wsConnection.close();
+ this.wsConnection.close();
}
- this._wsConnection = new WebSocket(this._wsConnectionUrl, 'ocpp' + Constants.OCPP_VERSION_16, options);
- logger.info(this._logPrefix() + ' Will communicate through URL ' + this._supervisionUrl);
+ this.wsConnection = new WebSocket(this.wsConnectionUrl, 'ocpp' + Constants.OCPP_VERSION_16, options);
+ logger.info(this._logPrefix() + ' Will communicate through URL ' + this.supervisionUrl);
}
start(): void {
// Monitor station template file
this._startStationTemplateFileMonitoring();
// Handle Socket incoming messages
- this._wsConnection.on('message', this.onMessage.bind(this));
+ this.wsConnection.on('message', this.onMessage.bind(this));
// Handle Socket error
- this._wsConnection.on('error', this.onError.bind(this));
+ this.wsConnection.on('error', this.onError.bind(this));
// Handle Socket close
- this._wsConnection.on('close', this.onClose.bind(this));
+ this.wsConnection.on('close', this.onClose.bind(this));
// Handle Socket opening connection
- this._wsConnection.on('open', this.onOpen.bind(this));
+ this.wsConnection.on('open', this.onOpen.bind(this));
// Handle Socket ping
- this._wsConnection.on('ping', this.onPing.bind(this));
+ this.wsConnection.on('ping', this.onPing.bind(this));
// Handle Socket pong
- this._wsConnection.on('pong', this.onPong.bind(this));
+ this.wsConnection.on('pong', this.onPong.bind(this));
}
async stop(reason: StopTransactionReason = StopTransactionReason.NONE): Promise<void> {
// Stop message sequence
await this._stopMessageSequence(reason);
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0) {
await this.sendStatusNotification(Utils.convertToInt(connector), ChargePointStatus.UNAVAILABLE);
}
}
if (this._isWebSocketOpen()) {
- this._wsConnection.close();
+ this.wsConnection.close();
}
- this._bootNotificationResponse = null;
- this._hasStopped = true;
+ this.bootNotificationResponse = null;
+ this.hasStopped = true;
}
async _reconnect(error): Promise<void> {
// Stop heartbeat
this._stopHeartbeat();
// Stop the ATG if needed
- if (this._stationInfo.AutomaticTransactionGenerator.enable &&
- this._stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure &&
- this._automaticTransactionGeneration &&
- !this._automaticTransactionGeneration.timeToStop) {
- this._automaticTransactionGeneration.stop().catch(() => { });
- }
- if (this._autoReconnectRetryCount < this._getAutoReconnectMaxRetries() || this._getAutoReconnectMaxRetries() === -1) {
- this._autoReconnectRetryCount++;
- const reconnectDelay = (this._getReconnectExponentialDelay() ? Utils.exponentialDelay(this._autoReconnectRetryCount) : this._getConnectionTimeout() * 1000);
+ if (this.stationInfo.AutomaticTransactionGenerator.enable &&
+ this.stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure &&
+ this.automaticTransactionGeneration &&
+ !this.automaticTransactionGeneration.timeToStop) {
+ this.automaticTransactionGeneration.stop().catch(() => { });
+ }
+ if (this.autoReconnectRetryCount < this._getAutoReconnectMaxRetries() || this._getAutoReconnectMaxRetries() === -1) {
+ this.autoReconnectRetryCount++;
+ const reconnectDelay = (this._getReconnectExponentialDelay() ? Utils.exponentialDelay(this.autoReconnectRetryCount) : this._getConnectionTimeout() * 1000);
logger.error(`${this._logPrefix()} Socket: connection retry in ${Utils.roundTo(reconnectDelay, 2)}ms, timeout ${reconnectDelay - 100}ms`);
await Utils.sleep(reconnectDelay);
- logger.error(this._logPrefix() + ' Socket: reconnecting try #' + this._autoReconnectRetryCount.toString());
+ logger.error(this._logPrefix() + ' Socket: reconnecting try #' + this.autoReconnectRetryCount.toString());
this._openWSConnection({ handshakeTimeout: reconnectDelay - 100 });
- this._hasSocketRestarted = true;
+ this.hasSocketRestarted = true;
} else if (this._getAutoReconnectMaxRetries() !== -1) {
- logger.error(`${this._logPrefix()} Socket reconnect failure: max retries reached (${this._autoReconnectRetryCount}) or retry disabled (${this._getAutoReconnectMaxRetries()})`);
+ logger.error(`${this._logPrefix()} Socket reconnect failure: max retries reached (${this.autoReconnectRetryCount}) or retry disabled (${this._getAutoReconnectMaxRetries()})`);
}
}
async onOpen(): Promise<void> {
- logger.info(`${this._logPrefix()} Is connected to server through ${this._wsConnectionUrl}`);
+ logger.info(`${this._logPrefix()} Is connected to server through ${this.wsConnectionUrl}`);
if (!this._isRegistered()) {
// Send BootNotification
let registrationRetryCount = 0;
do {
- this._bootNotificationResponse = await this.sendBootNotification();
+ this.bootNotificationResponse = await this.sendBootNotification();
if (!this._isRegistered()) {
registrationRetryCount++;
- await Utils.sleep(this._bootNotificationResponse?.interval ? this._bootNotificationResponse.interval * 1000 : Constants.OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL);
+ await Utils.sleep(this.bootNotificationResponse?.interval ? this.bootNotificationResponse.interval * 1000 : Constants.OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL);
}
} while (!this._isRegistered() && (registrationRetryCount <= this._getRegistrationMaxRetries() || this._getRegistrationMaxRetries() === -1));
}
if (this._isRegistered()) {
await this._startMessageSequence();
- if (this._hasSocketRestarted && this._isWebSocketOpen()) {
- if (!Utils.isEmptyArray(this._messageQueue)) {
- this._messageQueue.forEach((message, index) => {
- this._messageQueue.splice(index, 1);
- this._wsConnection.send(message);
+ if (this.hasSocketRestarted && this._isWebSocketOpen()) {
+ if (!Utils.isEmptyArray(this.messageQueue)) {
+ this.messageQueue.forEach((message, index) => {
+ this.messageQueue.splice(index, 1);
+ this.wsConnection.send(message);
});
}
}
} else {
logger.error(`${this._logPrefix()} Registration failure: max retries reached (${this._getRegistrationMaxRetries()}) or retry disabled (${this._getRegistrationMaxRetries()})`);
}
- this._autoReconnectRetryCount = 0;
- this._hasSocketRestarted = false;
+ this.autoReconnectRetryCount = 0;
+ this.hasSocketRestarted = false;
}
async onError(errorEvent): Promise<void> {
case WebSocketCloseEventStatusCode.CLOSE_NORMAL: // Normal close
case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS:
logger.info(`${this._logPrefix()} Socket normally closed with status '${Utils.getWebSocketCloseEventStatusString(closeEvent)}'`);
- this._autoReconnectRetryCount = 0;
+ this.autoReconnectRetryCount = 0;
break;
default: // Abnormal close
logger.error(`${this._logPrefix()} Socket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString(closeEvent)}'`);
// Incoming Message
case MessageType.CALL_MESSAGE:
if (this.getEnableStatistics()) {
- this._statistics.addMessage(commandName, messageType);
+ this.statistics.addMessage(commandName, messageType);
}
// Process the call
await this.handleRequest(messageId, commandName, commandPayload);
// Outcome Message
case MessageType.CALL_RESULT_MESSAGE:
// Respond
- if (Utils.isIterable(this._requests[messageId])) {
- [responseCallback, , requestPayload] = this._requests[messageId];
+ if (Utils.isIterable(this.requests[messageId])) {
+ [responseCallback, , requestPayload] = this.requests[messageId];
} else {
throw new Error(`Response request for message id ${messageId} is not iterable`);
}
// Error
throw new Error(`Response request for unknown message id ${messageId}`);
}
- delete this._requests[messageId];
+ delete this.requests[messageId];
responseCallback(commandName, requestPayload);
break;
// Error Message
case MessageType.CALL_ERROR_MESSAGE:
- if (!this._requests[messageId]) {
+ if (!this.requests[messageId]) {
// Error
throw new Error(`Error request for unknown message id ${messageId}`);
}
- if (Utils.isIterable(this._requests[messageId])) {
- [, rejectCallback] = this._requests[messageId];
+ if (Utils.isIterable(this.requests[messageId])) {
+ [, rejectCallback] = this.requests[messageId];
} else {
throw new Error(`Error request for message id ${messageId} is not iterable`);
}
- delete this._requests[messageId];
+ delete this.requests[messageId];
rejectCallback(new OCPPError(commandName, commandPayload.toString(), errorDetails));
break;
// Error
}
} 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 message %j processing error %j on request content type %j', this._logPrefix(), messageEvent, error, this.requests[messageId]);
// Send error
messageType !== MessageType.CALL_ERROR_MESSAGE && await this.sendError(messageId, error, commandName);
}
async sendBootNotification(): Promise<BootNotificationResponse> {
try {
- return await this.sendMessage(Utils.generateUUID(), this._bootNotificationRequest, MessageType.CALL_MESSAGE, RequestCommand.BOOT_NOTIFICATION) as BootNotificationResponse;
+ return await this.sendMessage(Utils.generateUUID(), this.bootNotificationRequest, MessageType.CALL_MESSAGE, RequestCommand.BOOT_NOTIFICATION) as BootNotificationResponse;
} catch (error) {
this.handleRequestError(RequestCommand.BOOT_NOTIFICATION, error);
}
// Request
case MessageType.CALL_MESSAGE:
// Build request
- this._requests[messageId] = [responseCallback, rejectCallback, commandParams] as Request;
+ this.requests[messageId] = [responseCallback, rejectCallback, commandParams] as Request;
messageToSend = JSON.stringify([messageType, messageId, commandName, commandParams]);
break;
// Response
// Check if wsConnection opened and charging station registered
if (this._isWebSocketOpen() && (this._isRegistered() || commandName === RequestCommand.BOOT_NOTIFICATION)) {
if (this.getEnableStatistics()) {
- this._statistics.addMessage(commandName, messageType);
+ this.statistics.addMessage(commandName, messageType);
}
// Yes: Send Message
- this._wsConnection.send(messageToSend);
+ this.wsConnection.send(messageToSend);
} else if (commandName !== RequestCommand.BOOT_NOTIFICATION) {
let dups = false;
// Handle dups in buffer
- for (const message of this._messageQueue) {
+ for (const message of this.messageQueue) {
// Same message
if (messageToSend === message) {
dups = true;
}
if (!dups) {
// Buffer message
- this._messageQueue.push(messageToSend);
+ this.messageQueue.push(messageToSend);
}
// Reject it
return rejectCallback(new OCPPError(commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : `WebSocket closed for message id '${messageId}' with content '${messageToSend}', message buffered`, commandParams.details ? commandParams.details : {}));
// Function that will receive the request's response
async function responseCallback(payload: Record<string, unknown> | string, requestPayload: Record<string, unknown>): Promise<void> {
if (self.getEnableStatistics()) {
- self._statistics.addMessage(commandName, messageType);
+ self.statistics.addMessage(commandName, messageType);
}
// Send the response
await self.handleResponse(commandName as RequestCommand, payload, requestPayload);
// Function that will receive the request's rejection
function rejectCallback(error: OCPPError): void {
if (self.getEnableStatistics()) {
- self._statistics.addMessage(commandName, messageType);
+ self.statistics.addMessage(commandName, messageType);
}
logger.debug(`${self._logPrefix()} Error: %j occurred when calling command %s with parameters: %j`, error, commandName, commandParams);
// Build Exception
// eslint-disable-next-line no-empty-function
- self._requests[messageId] = [() => { }, () => { }, {}]; // Properly format the request
+ self.requests[messageId] = [() => { }, () => { }, {}]; // Properly format the request
// Send error
reject(error);
}
handleResponseBootNotification(payload: BootNotificationResponse, requestPayload: BootNotificationRequest): void {
if (payload.status === RegistrationStatus.ACCEPTED) {
- this._heartbeatSetInterval ? this._restartHeartbeat() : this._startHeartbeat();
+ this.heartbeatSetInterval ? this._restartHeartbeat() : this._startHeartbeat();
this._addConfigurationKey(StandardParametersKey.HeartBeatInterval, payload.interval.toString());
this._addConfigurationKey(StandardParametersKey.HeartbeatInterval, payload.interval.toString(), false, false);
- this._hasStopped && (this._hasStopped = false);
+ this.hasStopped && (this.hasStopped = false);
} else if (payload.status === RegistrationStatus.PENDING) {
logger.info(this._logPrefix() + ' Charging station in pending state on the central server');
} else {
const connectorId = requestPayload.connectorId;
let transactionConnectorId: number;
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && Utils.convertToInt(connector) === connectorId) {
transactionConnectorId = Utils.convertToInt(connector);
break;
this.getConnector(connectorId).idTag = requestPayload.idTag;
this.getConnector(connectorId).lastEnergyActiveImportRegisterValue = 0;
await this.sendStatusNotification(connectorId, ChargePointStatus.CHARGING);
- logger.info(this._logPrefix() + ' Transaction ' + payload.transactionId.toString() + ' STARTED on ' + this._stationInfo.chargingStationId + '#' + connectorId.toString() + ' for idTag ' + requestPayload.idTag);
- if (this._stationInfo.powerSharedByConnectors) {
- this._stationInfo.powerDivider++;
+ logger.info(this._logPrefix() + ' Transaction ' + payload.transactionId.toString() + ' STARTED on ' + this.stationInfo.chargingStationId + '#' + connectorId.toString() + ' for idTag ' + requestPayload.idTag);
+ if (this.stationInfo.powerSharedByConnectors) {
+ this.stationInfo.powerDivider++;
}
const configuredMeterValueSampleInterval = this._getConfigurationKey(StandardParametersKey.MeterValueSampleInterval);
this._startMeterValues(connectorId,
async handleResponseStopTransaction(payload: StopTransactionResponse, requestPayload: StopTransactionRequest): Promise<void> {
let transactionConnectorId: number;
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector))?.transactionId === requestPayload.transactionId) {
transactionConnectorId = Utils.convertToInt(connector);
break;
} else {
await this.sendStatusNotification(transactionConnectorId, ChargePointStatus.AVAILABLE);
}
- if (this._stationInfo.powerSharedByConnectors) {
- this._stationInfo.powerDivider--;
+ if (this.stationInfo.powerSharedByConnectors) {
+ this.stationInfo.powerDivider--;
}
- logger.info(this._logPrefix() + ' Transaction ' + requestPayload.transactionId.toString() + ' STOPPED on ' + this._stationInfo.chargingStationId + '#' + transactionConnectorId.toString());
+ logger.info(this._logPrefix() + ' Transaction ' + requestPayload.transactionId.toString() + ' STOPPED on ' + this.stationInfo.chargingStationId + '#' + transactionConnectorId.toString());
this._resetTransactionOnConnector(transactionConnectorId);
} else {
logger.error(this._logPrefix() + ' Stopping transaction id ' + requestPayload.transactionId.toString() + ' REJECTED with status ' + payload.idTagInfo?.status);
handleRequestReset(commandPayload: ResetRequest): DefaultResponse {
setImmediate(async () => {
await this.stop(commandPayload.type + 'Reset' as StopTransactionReason);
- await Utils.sleep(this._stationInfo.resetTime);
+ await Utils.sleep(this.stationInfo.resetTime);
await this.start();
});
- logger.info(`${this._logPrefix()} ${commandPayload.type} reset command received, simulating it. The station will be back online in ${Utils.milliSecondsToHHMMSS(this._stationInfo.resetTime)}`);
+ logger.info(`${this._logPrefix()} ${commandPayload.type} reset command received, simulating it. The station will be back online in ${Utils.milliSecondsToHHMMSS(this.stationInfo.resetTime)}`);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
}
_getConfigurationKey(key: string | StandardParametersKey, caseInsensitive = false): ConfigurationKey {
- const configurationKey: ConfigurationKey = this._configuration.configurationKey.find((configElement) => {
+ const configurationKey: ConfigurationKey = this.configuration.configurationKey.find((configElement) => {
if (caseInsensitive) {
return configElement.key.toLowerCase() === key.toLowerCase();
}
_addConfigurationKey(key: string | StandardParametersKey, value: string, readonly = false, visible = true, reboot = false): void {
const keyFound = this._getConfigurationKey(key);
if (!keyFound) {
- this._configuration.configurationKey.push({
+ this.configuration.configurationKey.push({
key,
readonly,
value,
_setConfigurationKeyValue(key: string | StandardParametersKey, value: string): void {
const keyFound = this._getConfigurationKey(key);
if (keyFound) {
- const keyIndex = this._configuration.configurationKey.indexOf(keyFound);
- this._configuration.configurationKey[keyIndex].value = value;
+ const keyIndex = this.configuration.configurationKey.indexOf(keyFound);
+ this.configuration.configurationKey[keyIndex].value = value;
} else {
logger.error(`${this._logPrefix()} Trying to set a value on a non existing configuration key: %j`, { key, value });
}
const configurationKey: OCPPConfigurationKey[] = [];
const unknownKey: string[] = [];
if (Utils.isEmptyArray(commandPayload.key)) {
- for (const configuration of this._configuration.configurationKey) {
+ for (const configuration of this.configuration.configurationKey) {
if (Utils.isUndefined(configuration.visible)) {
configuration.visible = true;
}
} else if (keyToChange && keyToChange.readonly) {
return Constants.OCPP_CONFIGURATION_RESPONSE_REJECTED;
} else if (keyToChange && !keyToChange.readonly) {
- const keyIndex = this._configuration.configurationKey.indexOf(keyToChange);
+ const keyIndex = this.configuration.configurationKey.indexOf(keyToChange);
let valueChanged = false;
- if (this._configuration.configurationKey[keyIndex].value !== commandPayload.value) {
- this._configuration.configurationKey[keyIndex].value = commandPayload.value;
+ if (this.configuration.configurationKey[keyIndex].value !== commandPayload.value) {
+ this.configuration.configurationKey[keyIndex].value = commandPayload.value;
valueChanged = true;
}
let triggerHeartbeatRestart = false;
const chargePointStatus: ChargePointStatus = commandPayload.type === AvailabilityType.OPERATIVE ? ChargePointStatus.AVAILABLE : ChargePointStatus.UNAVAILABLE;
if (connectorId === 0) {
let response: ChangeAvailabilityResponse = Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED;
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (this.getConnector(Utils.convertToInt(connector)).transactionStarted) {
response = Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED;
}
if (this._isChargingStationAvailable() && this._isConnectorAvailable(transactionConnectorID)) {
if (this._getAuthorizeRemoteTxRequests() && this._getLocalAuthListEnabled() && this.hasAuthorizedTags()) {
// Check if authorized
- if (this._authorizedTags.find((value) => value === commandPayload.idTag)) {
+ if (this.authorizedTags.find((value) => value === commandPayload.idTag)) {
await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING);
// Authorization successful start transaction
await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag);
- logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.chargingStationId + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag);
+ logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this.stationInfo.chargingStationId + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
logger.error(this._logPrefix() + ' Remote starting transaction REJECTED on connector Id ' + transactionConnectorID.toString() + ', idTag ' + commandPayload.idTag);
await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING);
// No local authorization check required => start transaction
await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag);
- logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.chargingStationId + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag);
+ logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this.stationInfo.chargingStationId + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag);
return Constants.OCPP_RESPONSE_ACCEPTED;
}
logger.error(this._logPrefix() + ' Remote starting transaction REJECTED on unavailable connector Id ' + transactionConnectorID.toString() + ', idTag ' + commandPayload.idTag);
async handleRequestRemoteStopTransaction(commandPayload: RemoteStopTransactionRequest): Promise<DefaultResponse> {
const transactionId = commandPayload.transactionId;
- for (const connector in this._connectors) {
+ for (const connector in this.connectors) {
if (Utils.convertToInt(connector) > 0 && this.getConnector(Utils.convertToInt(connector))?.transactionId === transactionId) {
await this.sendStatusNotification(Utils.convertToInt(connector), ChargePointStatus.FINISHING);
await this.sendStopTransaction(transactionId);
// Power.Active.Import measurand
} else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.POWER_ACTIVE_IMPORT && self._getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(MeterValueMeasurand.POWER_ACTIVE_IMPORT)) {
// FIXME: factor out powerDivider checks
- if (Utils.isUndefined(self._stationInfo.powerDivider)) {
+ if (Utils.isUndefined(self.stationInfo.powerDivider)) {
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 : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ } else if (self.stationInfo.powerDivider && self.stationInfo.powerDivider <= 0) {
+ 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 : 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 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());
+ 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 PowerOutType.AC:
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
// Current.Import measurand
} else if (meterValuesTemplate[index].measurand && meterValuesTemplate[index].measurand === MeterValueMeasurand.CURRENT_IMPORT && self._getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(MeterValueMeasurand.CURRENT_IMPORT)) {
// FIXME: factor out powerDivider checks
- if (Utils.isUndefined(self._stationInfo.powerDivider)) {
+ if (Utils.isUndefined(self.stationInfo.powerDivider)) {
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 : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ } else if (self.stationInfo.powerDivider && self.stationInfo.powerDivider <= 0) {
+ 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 : 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 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: MeasurandValues = {} as MeasurandValues;
let maxAmperage: number;
switch (self._getPowerOutType()) {
case PowerOutType.AC:
- maxAmperage = ElectricUtils.ampPerPhaseFromPower(self._getNumberOfPhases(), self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut());
+ 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;
}
break;
case PowerOutType.DC:
- maxAmperage = ElectricUtils.ampTotalFromPower(self._stationInfo.maxPower / self._stationInfo.powerDivider, self._getVoltageOut());
+ maxAmperage = ElectricUtils.ampTotalFromPower(self.stationInfo.maxPower / self.stationInfo.powerDivider, self._getVoltageOut());
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
currentMeasurandValues.allPhases = Utils.getRandomFloatRounded(maxAmperage);
}
// Energy.Active.Import.Register measurand (default)
} else if (!meterValuesTemplate[index].measurand || meterValuesTemplate[index].measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
// FIXME: factor out powerDivider checks
- if (Utils.isUndefined(self._stationInfo.powerDivider)) {
+ if (Utils.isUndefined(self.stationInfo.powerDivider)) {
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 : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${self._stationInfo.powerDivider}`;
+ } else if (self.stationInfo.powerDivider && self.stationInfo.powerDivider <= 0) {
+ 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);
}
if (Utils.isUndefined(meterValuesTemplate[index].value)) {
- const measurandValue = Utils.getRandomInt(self._stationInfo.maxPower / (self._stationInfo.powerDivider * 3600000) * interval);
+ const measurandValue = Utils.getRandomInt(self.stationInfo.maxPower / (self.stationInfo.powerDivider * 3600000) * interval);
// Persist previous value in connector
if (connector && !Utils.isNullOrUndefined(connector.lastEnergyActiveImportRegisterValue) && connector.lastEnergyActiveImportRegisterValue >= 0) {
connector.lastEnergyActiveImportRegisterValue += measurandValue;
{ value: connector.lastEnergyActiveImportRegisterValue.toString() },
});
const sampledValuesIndex = meterValue.sampledValue.length - 1;
- const maxConsumption = Math.round(self._stationInfo.maxPower * 3600 / (self._stationInfo.powerDivider * interval));
+ const maxConsumption = Math.round(self.stationInfo.maxPower * 3600 / (self.stationInfo.powerDivider * interval));
if (Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) > maxConsumption || debug) {
logger.error(`${self._logPrefix()} MeterValues measurand ${meterValue.sampledValue[sampledValuesIndex].measurand ? meterValue.sampledValue[sampledValuesIndex].measurand : MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${meterValue.sampledValue[sampledValuesIndex].value}/${maxConsumption}`);
}