Handle charge point + logs in json client
MODIFY
src/client/ocpp/json/JsonRestChargingStationClient.ts
src/client/ocpp/json/JsonRestChargingStationClient.ts
@@ -15,7 +15,7 @@ const MODULE_NAME = 'JsonRestChargingStationClient';
export default class JsonRestChargingStationClient extends ChargingStationClient {
private serverURL: string;
private chargingStation: ChargingStation;
- private requests: any;
+ private requests: { [messageUID: string]: { resolve?: (result: object) => void; reject?: (error: object) => void; command: ServerAction } };
private wsConnection: WSClient;
private tenantID: string;
@@ -160,17 +160,10 @@ export default class JsonRestChargingStationClient extends ChargingStationClient
try {
// Parse the message
const messageJson = JSON.parse(message.data);
- // Log
- Logging.logDebug({
- tenantID: this.tenantID,
- source: this.chargingStation.id,
- action: ServerAction.WS_REST_CLIENT_MESSAGE,
- module: MODULE_NAME, method: 'onMessage',
- message: `Received message '${message.data}'`,
- detailedMessages: { messageJson }
- });
// Check if this corresponds to a request
if (this.requests[messageJson[1]]) {
+ // Log
+ Logging.logReceivedAction(MODULE_NAME, this.tenantID, this.chargingStation.id, this.requests[messageJson[1]].command, messageJson);
// Check message type
if (messageJson[0] === Constants.OCPP_JSON_CALL_ERROR_MESSAGE) {
// Error message
@@ -190,6 +183,16 @@ export default class JsonRestChargingStationClient extends ChargingStationClient
}
// Close WS
this._closeConnection();
+ } else {
+ // Error message
+ Logging.logError({
+ tenantID: this.tenantID,
+ source: this.chargingStation.id,
+ action: ServerAction.WS_REST_CLIENT_ERROR_RESPONSE,
+ module: MODULE_NAME, method: 'onMessage',
+ message: 'Received unknown message',
+ detailedMessages: { messageJson }
+ });
}
} catch (error) {
// Log
@@ -222,25 +225,17 @@ export default class JsonRestChargingStationClient extends ChargingStationClient
private async _sendMessage(request): Promise<any> {
// Return a promise
- // eslint-disable-next-line no-undef
const promise = await new Promise(async (resolve, reject) => {
// Open WS Connection
await this._openConnection();
// Check if wsConnection in ready
if (this.wsConnection.isConnectionOpen()) {
// Log
- Logging.logDebug({
- tenantID: this.tenantID,
- source: this.chargingStation.id,
- action: ServerAction.WS_REST_CLIENT_SEND_MESSAGE,
- module: MODULE_NAME, method: 'SendMessage',
- message: `Send message '${request[2]}'`,
- detailedMessages: { request }
- });
+ Logging.logSendAction(MODULE_NAME, this.tenantID, this.chargingStation.id, request[2], request);
// Send
await this.wsConnection.send(JSON.stringify(request));
// Set the resolve function
- this.requests[request[1]] = { resolve, reject };
+ this.requests[request[1]] = { resolve, reject, command: request[2] };
} else {
// Reject it
return reject(`Socket is closed for message ${request[2]}`);
@@ -251,10 +246,6 @@ export default class JsonRestChargingStationClient extends ChargingStationClient
private _buildRequest(command, params = {}) {
// Build the request
- return [
- Constants.OCPP_JSON_CALL_MESSAGE,
- uuid(),
- command,
- params];
+ return [Constants.OCPP_JSON_CALL_MESSAGE, uuid(), command, params];
}
}

MODIFY
src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts
src/integration/charging-station-vendor/ChargingStationVendorIntegration.ts
-import ChargingStationClientFactory from '../../client/ocpp/ChargingStationClientFactory';
-import BackendError from '../../exception/BackendError';
-import OCPPUtils from '../../server/ocpp/utils/OCPPUtils';
-import ChargingStationStorage from '../../storage/mongodb/ChargingStationStorage';
-import { ChargingProfile } from '../../types/ChargingProfile';
+import { ChargingProfile, ChargingSchedule } from '../../types/ChargingProfile';
import ChargingStation, { ConnectorCurrentLimit, ConnectorCurrentLimitSource, StaticLimitAmps } from '../../types/ChargingStation';
import { OCPPChangeConfigurationCommandResult, OCPPChargingProfileStatus, OCPPClearChargingProfileCommandResult, OCPPClearChargingProfileStatus, OCPPConfigurationStatus, OCPPGetCompositeScheduleCommandResult, OCPPGetCompositeScheduleStatus, OCPPSetChargingProfileCommandResult } from '../../types/ocpp/OCPPClient';
-import { ServerAction } from '../../types/Server';
+
+import BackendError from '../../exception/BackendError';
+import ChargingStationClientFactory from '../../client/ocpp/ChargingStationClientFactory';
+import ChargingStationStorage from '../../storage/mongodb/ChargingStationStorage';
import Logging from '../../utils/Logging';
+import OCPPUtils from '../../server/ocpp/utils/OCPPUtils';
+import { ServerAction } from '../../types/Server';
import Utils from '../../utils/Utils';
const MODULE_NAME = 'ChargingStationVendor';
@@ -320,7 +321,7 @@ export default abstract class ChargingStationVendorIntegration {
}
// Reapply the current limitation
await this.setPowerLimitation(tenantID, chargingStation, 0,
- Utils.getTotalAmpsOfChargingStation(chargingStation));
+ Utils.getTotalAmpLimitOfChargingStation(chargingStation));
Logging.logDebug({
tenantID: tenantID,
source: chargingStation.id,
@@ -334,7 +335,7 @@ export default abstract class ChargingStationVendorIntegration {
// Reapply the current limitation
if (result.status === OCPPClearChargingProfileStatus.ACCEPTED) {
await this.setPowerLimitation(tenantID, chargingStation, 0,
- Utils.getTotalAmpsOfChargingStation(chargingStation));
+ Utils.getTotalAmpLimitOfChargingStation(chargingStation));
}
Logging.logDebug({
tenantID: tenantID,
@@ -354,7 +355,7 @@ export default abstract class ChargingStationVendorIntegration {
if (result.status === OCPPClearChargingProfileStatus.ACCEPTED) {
// Reapply the current limitation
await this.setPowerLimitation(tenantID, chargingStation, 0,
- Utils.getTotalAmpsOfChargingStation(chargingStation));
+ Utils.getTotalAmpLimitOfChargingStation(chargingStation));
}
Logging.logDebug({
tenantID: tenantID,
@@ -429,12 +430,14 @@ export default abstract class ChargingStationVendorIntegration {
const results = [] as OCPPGetCompositeScheduleCommandResult[];
for (const connector of chargingStation.connectors) {
// Get the Composite Schedule
- const ret = await chargingStationClient.getCompositeSchedule({
+ const connectorResult = await chargingStationClient.getCompositeSchedule({
connectorId: connector.connectorId,
duration: durationSecs,
chargingRateUnit: chargingStation.powerLimitUnit
});
- results.push(ret);
+ // Convert
+ connectorResult.chargingSchedule = this.convertFromVendorChargingSchedule(chargingStation, connectorResult.chargingSchedule);
+ results.push(connectorResult);
}
Logging.logDebug({
tenantID: tenantID,
@@ -454,6 +457,8 @@ export default abstract class ChargingStationVendorIntegration {
module: MODULE_NAME, method: 'getCompositeSchedule',
detailedMessages: { result }
});
+ // Convert
+ result.chargingSchedule = this.convertFromVendorChargingSchedule(chargingStation, result.chargingSchedule);
return result;
}
// Connector ID > 0
@@ -471,6 +476,8 @@ export default abstract class ChargingStationVendorIntegration {
module: MODULE_NAME, method: 'getCompositeSchedule',
detailedMessages: { result }
});
+ // Convert
+ result.chargingSchedule = this.convertFromVendorChargingSchedule(chargingStation, result.chargingSchedule);
return result;
} catch (error) {
Logging.logError({
@@ -530,7 +537,7 @@ export default abstract class ChargingStationVendorIntegration {
}
const result: ConnectorCurrentLimit = {
limitAmps: connectorLimitAmps,
- limitWatts: Utils.convertAmpToPowerWatts(chargingStation, connectorID, connectorLimitAmps),
+ limitWatts: Utils.convertAmpToWatt(chargingStation, connectorID, connectorLimitAmps),
limitSource: ConnectorCurrentLimitSource.CHARGING_PROFILE,
};
Logging.logDebug({
@@ -558,7 +565,7 @@ export default abstract class ChargingStationVendorIntegration {
}
const result: ConnectorCurrentLimit = {
limitAmps: connectorLimitAmps,
- limitWatts: Utils.convertAmpToPowerWatts(chargingStation, connectorID, connectorLimitAmps),
+ limitWatts: Utils.convertAmpToWatt(chargingStation, connectorID, connectorLimitAmps),
limitSource: ConnectorCurrentLimitSource.STATIC_LIMITATION,
};
Logging.logDebug({
@@ -604,5 +611,7 @@ export default abstract class ChargingStationVendorIntegration {
public abstract getOCPPParamValueForChargingLimitation(chargingStation: ChargingStation, limitAmp: number);
public abstract convertToVendorChargingProfile(chargingStation: ChargingStation, chargingProfile: ChargingProfile): ChargingProfile;
+
+ public abstract convertFromVendorChargingSchedule(chargingStation: ChargingStation, connectorID: number, vendorSpecificChargingSchedule: ChargingSchedule): ChargingSchedule;
}

MODIFY
src/integration/charging-station-vendor/delta/DeltaChargingStationVendorIntegration.ts
src/integration/charging-station-vendor/delta/DeltaChargingStationVendorIntegration.ts
-import { ChargingProfile } from '../../../types/ChargingProfile';
-import ChargingStation from '../../../types/ChargingStation';
+import { ChargingProfile, ChargingRateUnitType, ChargingSchedule } from '../../../types/ChargingProfile';
+import ChargingStation, { PowerLimitUnits } from '../../../types/ChargingStation';
+
import ChargingStationVendorIntegration from '../ChargingStationVendorIntegration';
+import Utils from '../../../utils/Utils';
export default class DeltaChargingStationVendorIntegration extends ChargingStationVendorIntegration {
constructor(chargingStation: ChargingStation) {
@@ -12,14 +14,7 @@ export default class DeltaChargingStationVendorIntegration extends ChargingStati
}
public getOCPPParamValueForChargingLimitation(chargingStation: ChargingStation, limitAmp: number): number {
- let numberOfPhase = 1;
- for (const connector of chargingStation.connectors) {
- if (connector && connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- break;
- }
- }
- return limitAmp / chargingStation.connectors.length / numberOfPhase;
+ return limitAmp / chargingStation.connectors.length / Utils.getNumberOfConnectedPhases(chargingStation);
}
public convertToVendorChargingProfile(chargingStation: ChargingStation, chargingProfile: ChargingProfile): ChargingProfile {
@@ -27,19 +22,42 @@ export default class DeltaChargingStationVendorIntegration extends ChargingStati
const vendorSpecificChargingProfile = JSON.parse(JSON.stringify(chargingProfile));
// Check connector
if (chargingStation.connectors && vendorSpecificChargingProfile.profile && vendorSpecificChargingProfile.profile.chargingSchedule) {
- let numberOfPhase = 1;
- // Check the Connector
- for (const connector of chargingStation.connectors) {
- if (connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- }
+ // Convert to Watts?
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ chargingProfile.profile.chargingSchedule.chargingRateUnit = ChargingRateUnitType.WATT;
}
// Divide the power by the number of connectors and number of phases
for (const schedulePeriod of vendorSpecificChargingProfile.profile.chargingSchedule.chargingSchedulePeriod) {
schedulePeriod.limit = schedulePeriod.limit / (vendorSpecificChargingProfile.connectorID === 0 ?
- chargingStation.connectors.length : 1) / numberOfPhase;
+ chargingStation.connectors.length : 1) / Utils.getNumberOfConnectedPhases(chargingStation, chargingProfile.connectorID);
+ // Check Unit
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ schedulePeriod.limit = Utils.convertAmpToWatt(chargingStation, schedulePeriod.limit);
+ }
}
}
return vendorSpecificChargingProfile;
}
+
+ public convertFromVendorChargingSchedule(chargingStation: ChargingStation, connectorID: number, chargingSchedule: ChargingSchedule): ChargingSchedule {
+ // Get vendor specific charging profile
+ if (!chargingSchedule) {
+ return chargingSchedule;
+ }
+ if (chargingSchedule.chargingSchedulePeriod) {
+ for (const chargingSchedulePeriod of chargingSchedule.chargingSchedulePeriod) {
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedulePeriod.limit = Utils.convertWattToAmp(chargingStation, chargingSchedulePeriod.limit);
+ }
+ // Limit is per connector and per phase Convert to max Amp
+ chargingSchedulePeriod.limit = chargingSchedulePeriod.limit * (connectorID === 0 ?
+ chargingStation.connectors.length : 1) * Utils.getNumberOfConnectedPhases(chargingStation, connectorID);
+ }
+ }
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedule.chargingRateUnit = ChargingRateUnitType.AMPERE;
+ }
+ }
}

MODIFY
src/integration/charging-station-vendor/schneider/SchneiderChargingStationVendorIntegration.ts
src/integration/charging-station-vendor/schneider/SchneiderChargingStationVendorIntegration.ts
-import { ChargingProfile } from '../../../types/ChargingProfile';
-import ChargingStation from '../../../types/ChargingStation';
+import { ChargingProfile, ChargingRateUnitType, ChargingSchedule } from '../../../types/ChargingProfile';
+import ChargingStation, { PowerLimitUnits } from '../../../types/ChargingStation';
+
import ChargingStationVendorIntegration from '../ChargingStationVendorIntegration';
+import Utils from '../../../utils/Utils';
export default class SchneiderChargingStationVendorIntegration extends ChargingStationVendorIntegration {
constructor(chargingStation: ChargingStation) {
@@ -12,14 +14,7 @@ export default class SchneiderChargingStationVendorIntegration extends ChargingS
}
public getOCPPParamValueForChargingLimitation(chargingStation: ChargingStation, limitAmp: number): number {
- let numberOfPhase = 1;
- for (const connector of chargingStation.connectors) {
- if (connector && connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- break;
- }
- }
- return limitAmp / chargingStation.connectors.length / numberOfPhase;
+ return limitAmp / chargingStation.connectors.length / Utils.getNumberOfConnectedPhases(chargingStation);
}
public convertToVendorChargingProfile(chargingStation: ChargingStation, chargingProfile: ChargingProfile): ChargingProfile {
@@ -27,19 +22,42 @@ export default class SchneiderChargingStationVendorIntegration extends ChargingS
const vendorSpecificChargingProfile = JSON.parse(JSON.stringify(chargingProfile));
// Check connector
if (chargingStation.connectors && vendorSpecificChargingProfile.profile && vendorSpecificChargingProfile.profile.chargingSchedule) {
- let numberOfPhase = 1;
- // Check the Connector
- for (const connector of chargingStation.connectors) {
- if (connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- }
+ // Convert to Watts?
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ chargingProfile.profile.chargingSchedule.chargingRateUnit = ChargingRateUnitType.WATT;
}
// Divide the power by the number of connectors and number of phases
for (const schedulePeriod of vendorSpecificChargingProfile.profile.chargingSchedule.chargingSchedulePeriod) {
schedulePeriod.limit = schedulePeriod.limit / (vendorSpecificChargingProfile.connectorID === 0 ?
- chargingStation.connectors.length : 1) / numberOfPhase;
+ chargingStation.connectors.length : 1) / Utils.getNumberOfConnectedPhases(chargingStation, chargingProfile.connectorID);
+ // Check Unit
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ schedulePeriod.limit = Utils.convertAmpToWatt(chargingStation, schedulePeriod.limit);
+ }
}
}
return vendorSpecificChargingProfile;
}
+
+ public convertFromVendorChargingSchedule(chargingStation: ChargingStation, connectorID: number, chargingSchedule: ChargingSchedule): ChargingSchedule {
+ // Get vendor specific charging profile
+ if (!chargingSchedule) {
+ return chargingSchedule;
+ }
+ if (chargingSchedule.chargingSchedulePeriod) {
+ for (const chargingSchedulePeriod of chargingSchedule.chargingSchedulePeriod) {
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedulePeriod.limit = Utils.convertWattToAmp(chargingStation, chargingSchedulePeriod.limit);
+ }
+ // Limit is per connector and per phase Convert to max Amp
+ chargingSchedulePeriod.limit = chargingSchedulePeriod.limit * (connectorID === 0 ?
+ chargingStation.connectors.length : 1) * Utils.getNumberOfConnectedPhases(chargingStation, connectorID);
+ }
+ }
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedule.chargingRateUnit = ChargingRateUnitType.AMPERE;
+ }
+ }
}

MODIFY
src/integration/charging-station-vendor/webasto/WebastoChargingStationVendorIntegration.ts
src/integration/charging-station-vendor/webasto/WebastoChargingStationVendorIntegration.ts
-import { ChargingProfile } from '../../../types/ChargingProfile';
-import ChargingStation from '../../../types/ChargingStation';
+import { ChargingProfile, ChargingRateUnitType, ChargingSchedule } from '../../../types/ChargingProfile';
+import ChargingStation, { PowerLimitUnits } from '../../../types/ChargingStation';
+
import ChargingStationVendorIntegration from '../ChargingStationVendorIntegration';
+import Utils from '../../../utils/Utils';
export default class WebastoChargingStationVendorIntegration extends ChargingStationVendorIntegration {
constructor(chargingStation: ChargingStation) {
@@ -12,14 +14,7 @@ export default class WebastoChargingStationVendorIntegration extends ChargingSta
}
public getOCPPParamValueForChargingLimitation(chargingStation: ChargingStation, limitAmp: number): number {
- let numberOfPhase = 1;
- for (const connector of chargingStation.connectors) {
- if (connector && connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- break;
- }
- }
- return limitAmp / chargingStation.connectors.length / numberOfPhase;
+ return limitAmp / chargingStation.connectors.length / Utils.getNumberOfConnectedPhases(chargingStation);
}
public convertToVendorChargingProfile(chargingStation: ChargingStation, chargingProfile: ChargingProfile): ChargingProfile {
@@ -27,19 +22,42 @@ export default class WebastoChargingStationVendorIntegration extends ChargingSta
const vendorSpecificChargingProfile = JSON.parse(JSON.stringify(chargingProfile));
// Check connector
if (chargingStation.connectors && vendorSpecificChargingProfile.profile && vendorSpecificChargingProfile.profile.chargingSchedule) {
- let numberOfPhase = 1;
- // Check the Connector
- for (const connector of chargingStation.connectors) {
- if (connector.numberOfConnectedPhase > 0) {
- numberOfPhase = connector.numberOfConnectedPhase;
- }
+ // Convert to Watts?
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ chargingProfile.profile.chargingSchedule.chargingRateUnit = ChargingRateUnitType.WATT;
}
// Divide the power by the number of connectors and number of phases
for (const schedulePeriod of vendorSpecificChargingProfile.profile.chargingSchedule.chargingSchedulePeriod) {
schedulePeriod.limit = schedulePeriod.limit / (vendorSpecificChargingProfile.connectorID === 0 ?
- chargingStation.connectors.length : 1) / numberOfPhase;
+ chargingStation.connectors.length : 1) / Utils.getNumberOfConnectedPhases(chargingStation, chargingProfile.connectorID);
+ // Check Unit
+ if (chargingStation.powerLimitUnit === PowerLimitUnits.WATT) {
+ schedulePeriod.limit = Utils.convertAmpToWatt(chargingStation, schedulePeriod.limit);
+ }
}
}
return vendorSpecificChargingProfile;
}
+
+ public convertFromVendorChargingSchedule(chargingStation: ChargingStation, connectorID: number, chargingSchedule: ChargingSchedule): ChargingSchedule {
+ // Get vendor specific charging profile
+ if (!chargingSchedule) {
+ return chargingSchedule;
+ }
+ if (chargingSchedule.chargingSchedulePeriod) {
+ for (const chargingSchedulePeriod of chargingSchedule.chargingSchedulePeriod) {
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedulePeriod.limit = Utils.convertWattToAmp(chargingStation, chargingSchedulePeriod.limit);
+ }
+ // Limit is per connector and per phase Convert to max Amp
+ chargingSchedulePeriod.limit = chargingSchedulePeriod.limit * (connectorID === 0 ?
+ chargingStation.connectors.length : 1) * Utils.getNumberOfConnectedPhases(chargingStation, connectorID);
+ }
+ }
+ // Convert to Amps?
+ if (chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT) {
+ chargingSchedule.chargingRateUnit = ChargingRateUnitType.AMPERE;
+ }
+ }
}

MODIFY
src/integration/smart-charging/sap-smart-charging
src/integration/smart-charging/sap-smart-charging
-Subproject commit 879f094b38825db4e1ef871cdbbf052b2c5ecd9b
+Subproject commit b08f0ce79d8cf373c2c77fc38157cfaf844f9a96

MODIFY
src/migration/tasks/UpdateChargingStationTemplatesTask.ts
src/migration/tasks/UpdateChargingStationTemplatesTask.ts
@@ -38,7 +38,7 @@ export default class UpdateChargingStationTemplatesTask extends MigrationTask {
}
getVersion() {
- return '1.894';
+ return '1.897';
}
private async updateChargingStationsOCPPParametersInTemplate(tenant: Tenant) {

MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -75,6 +75,9 @@ export default class OCPPUtils {
if (Utils.objectHasProperty(chargingStationTemplate.technical, 'powerLimitUnit')) {
chargingStation.powerLimitUnit = chargingStationTemplate.technical.powerLimitUnit;
}
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'voltage')) {
+ chargingStation.voltage = chargingStationTemplate.technical.voltage;
+ }
// Enrich connectors
if (chargingStation.connectors) {
for (const connector of chargingStation.connectors) {
@@ -186,7 +189,6 @@ export default class OCPPUtils {
detailedMessages: { chargingStation }
});
return false;
-
}
public static async enrichChargingStationConnectorWithTemplate(

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -487,6 +487,7 @@ export default class ChargingStationStorage {
maximumPower: Utils.convertToInt(chargingStationToSave.maximumPower),
excludeFromPowerLimitation: Utils.convertToBoolean(chargingStationToSave.excludeFromPowerLimitation),
powerLimitUnit: chargingStationToSave.powerLimitUnit,
+ voltage: Utils.convertToInt(chargingStationToSave.voltage),
chargePoints: chargingStationToSave.chargePoints ? chargingStationToSave.chargePoints : null,
connectors: chargingStationToSave.connectors,
coordinates: chargingStationToSave.coordinates,

MODIFY
src/types/ChargingStation.ts
src/types/ChargingStation.ts
+import { ChargePointStatus, OCPPFirmwareStatus, OCPPProtocol, OCPPVersion } from './ocpp/OCPPServer';
+
import CreatedUpdatedProps from './CreatedUpdatedProps';
+import { InactivityStatus } from './Transaction';
import { KeyValue } from './GlobalType';
import { OCPIEvse } from './ocpi/OCPIEvse';
-import { ChargePointStatus, OCPPFirmwareStatus, OCPPProtocol, OCPPVersion } from './ocpp/OCPPServer';
import SiteArea from './SiteArea';
-import { InactivityStatus } from './Transaction';
export default interface ChargingStation extends CreatedUpdatedProps {
id?: string;
@@ -168,6 +169,7 @@ export interface ChargingStationTemplate {
};
technical: {
maximumPower: number;
+ voltage?: number;
excludeFromPowerLimitation: boolean;
powerLimitUnit: PowerLimitUnits;
chargePoints?: ChargingStationChargePoint[];

MODIFY
src/utils/Logging.ts
src/utils/Logging.ts
@@ -136,31 +136,28 @@ export default class Logging {
Logging.logError(log);
}
- // Log
public static logReceivedAction(module: string, tenantID: string, chargeBoxID: string, action: ServerAction, payload: any): void {
Logging.logDebug({
tenantID: tenantID,
source: chargeBoxID,
module: module, method: action,
- message: '>> OCPP Request Received',
+ message: `>> OCPP Request '${action}' Received`,
action: action,
detailedMessages: { payload }
});
}
- // Log
public static logSendAction(module: string, tenantID: string, chargeBoxID: string, action: ServerAction, args: any): void {
Logging.logDebug({
tenantID: tenantID,
source: chargeBoxID,
module: module, method: action,
- message: '>> OCPP Request Sent',
+ message: `<< OCPP Request '${action}' Sent`,
action: action,
detailedMessages: { args }
});
}
- // Log
public static logReturnedAction(module: string, tenantID: string, chargeBoxID: string, action: ServerAction, detailedMessages: any): void {
if (detailedMessages && detailedMessages['status'] && detailedMessages['status'] === 'Rejected') {
Logging.logError({

MODIFY
src/utils/Utils.ts
src/utils/Utils.ts
-import fs from 'fs';
-import path from 'path';
-import url from 'url';
-
-import bcrypt from 'bcryptjs';
-import { Request } from 'express';
-import _ from 'lodash';
-import moment from 'moment';
-import { ObjectID } from 'mongodb';
-import passwordGenerator from 'password-generator';
-import tzlookup from 'tz-lookup';
-import { v4 as uuid } from 'uuid';
-import validator from 'validator';
+import { ChargePointStatus, OCPPProtocol, OCPPVersion } from '../types/ocpp/OCPPServer';
+import ChargingStation, { ConnectorCurrentType, StaticLimitAmps } from '../types/ChargingStation';
+import User, { UserRole, UserStatus } from '../types/User';
-import Authorizations from '../authorization/Authorizations';
+import { ActionsResponse } from '../types/GlobalType';
import AppError from '../exception/AppError';
-import BackendError from '../exception/BackendError';
-import TenantStorage from '../storage/mongodb/TenantStorage';
-import UserStorage from '../storage/mongodb/UserStorage';
import Asset from '../types/Asset';
+import Authorizations from '../authorization/Authorizations';
+import BackendError from '../exception/BackendError';
import { Car } from '../types/Car';
import { ChargingProfile } from '../types/ChargingProfile';
-import ChargingStation, { ConnectorCurrentType, StaticLimitAmps } from '../types/ChargingStation';
import Company from '../types/Company';
+import Configuration from './Configuration';
import ConnectorStats from '../types/ConnectorStats';
-import { ActionsResponse } from '../types/GlobalType';
+import Constants from './Constants';
+import Cypher from './Cypher';
import { HTTPError } from '../types/HTTPError';
+import { InactivityStatus } from '../types/Transaction';
+import Logging from './Logging';
import OCPIEndpoint from '../types/ocpi/OCPIEndpoint';
-import { ChargePointStatus, OCPPProtocol, OCPPVersion } from '../types/ocpp/OCPPServer';
+import { ObjectID } from 'mongodb';
+import { Request } from 'express';
import { ServerAction } from '../types/Server';
import { SettingDBContent } from '../types/Setting';
import Site from '../types/Site';
@@ -34,13 +27,19 @@ import SiteArea from '../types/SiteArea';
import Tag from '../types/Tag';
import Tenant from '../types/Tenant';
import TenantComponents from '../types/TenantComponents';
-import { InactivityStatus } from '../types/Transaction';
-import User, { UserRole, UserStatus } from '../types/User';
+import TenantStorage from '../storage/mongodb/TenantStorage';
+import UserStorage from '../storage/mongodb/UserStorage';
import UserToken from '../types/UserToken';
-import Configuration from './Configuration';
-import Constants from './Constants';
-import Cypher from './Cypher';
-import Logging from './Logging';
+import _ from 'lodash';
+import bcrypt from 'bcryptjs';
+import fs from 'fs';
+import moment from 'moment';
+import passwordGenerator from 'password-generator';
+import path from 'path';
+import tzlookup from 'tz-lookup';
+import url from 'url';
+import { v4 as uuid } from 'uuid';
+import validator from 'validator';
const _centralSystemFrontEndConfig = Configuration.getCentralSystemFrontEndConfig();
const _tenants = [];
@@ -236,10 +235,13 @@ export default class Utils {
public static checkAndUpdateConnectorsStatus(chargingStation: ChargingStation) {
// Cannot charge in //
- if (chargingStation.cannotChargeInParallel) {
+ if (chargingStation.chargePoints) {
+ for (const chargePoint of chargingStation.chargePoints) {
+ if (chargePoint.cannotChargeInParallel) {
let lockAllConnectors = false;
// Check
- for (const connector of chargingStation.connectors) {
+ for (const connectorID of chargePoint.connectorIDs) {
+ const connector = chargingStation.connectors[connectorID];
if (!connector) {
continue;
}
@@ -250,7 +252,8 @@ export default class Utils {
}
// Lock?
if (lockAllConnectors) {
- for (const connector of chargingStation.connectors) {
+ for (const connectorID of chargePoint.connectorIDs) {
+ const connector = chargingStation.connectors[connectorID];
if (!connector) {
continue;
}
@@ -268,6 +271,8 @@ export default class Utils {
}
}
}
+ }
+ }
public static getLanguageFromLocale(locale: string) {
let language = Constants.DEFAULT_LANGUAGE;
@@ -473,17 +478,7 @@ export default class Utils {
return userID;
}
- public static convertAmpToPowerWatts(chargingStation: ChargingStation, connectorID: number, ampValue: number): number {
- // AC Chargers?
- if (chargingStation &&
- chargingStation.connectors && chargingStation.connectors.length > 0 &&
- chargingStation.connectors[connectorID - 1].currentType === ConnectorCurrentType.AC,chargingStation.connectors[connectorID - 1].numberOfConnectedPhase) {
- return this.convertAmpToWatt(chargingStation.connectors[connectorID - 1].numberOfConnectedPhase, ampValue);
- }
- return 0;
- }
-
- public static getTotalAmpsOfChargingStation(chargingStation: ChargingStation): number {
+ public static getTotalAmpLimitOfChargingStation(chargingStation: ChargingStation): number {
let totalAmps = 0;
for (const connector of chargingStation.connectors) {
totalAmps += connector.amperageLimit;
@@ -491,27 +486,86 @@ export default class Utils {
return totalAmps;
}
- public static convertAmpToWatt(numberOfConnectedPhase: number, maxIntensityInAmper: number): number {
- // Compute it
- if (numberOfConnectedPhase === 0) {
- return Math.floor(230 * maxIntensityInAmper * 3);
+ public static convertAmpToWatt(chargingStation: ChargingStation, ampValue: number): number {
+ const voltage = Utils.getChargingStationVoltage(chargingStation);
+ if (voltage > 0) {
+ return voltage * ampValue;
}
- if (numberOfConnectedPhase === 3) {
- return Math.floor(230 * maxIntensityInAmper * 3);
+ return 0;
}
- return Math.floor(230 * maxIntensityInAmper);
+
+ public static convertWattToAmp(chargingStation: ChargingStation, wattValue: number): number {
+ const voltage = Utils.getChargingStationVoltage(chargingStation);
+ if (voltage > 0) {
+ return Math.floor(wattValue / voltage);
+ }
+ return 0;
}
- public static convertWattToAmp(numberOfConnectedPhase: number, maxIntensityInWatt: number): number {
- // Compute it
- if (numberOfConnectedPhase === 0) {
- return Math.floor(maxIntensityInWatt / 230 / 3);
+ public static getNumberOfConnectedPhases(chargingStation: ChargingStation, connectorId = 0): number {
+ if (chargingStation) {
+ // Check phase at charge point level
+ if (chargingStation.chargePoints) {
+ for (const chargePoint of chargingStation.chargePoints) {
+ // Take the first
+ if (connectorId === 0 && chargePoint.numberOfConnectedPhase > 0) {
+ return chargePoint.numberOfConnectedPhase;
}
- if (numberOfConnectedPhase === 3) {
- return Math.floor(maxIntensityInWatt / 230 / 3);
+ if (chargePoint.connectorIDs.includes(connectorId) && chargePoint.numberOfConnectedPhase > 0) {
+ return chargePoint.numberOfConnectedPhase;
}
- return Math.floor(maxIntensityInWatt / 230);
}
+ }
+ // Check phases at connector level
+ if (chargingStation.connectors) {
+ for (const connector of chargingStation.connectors) {
+ // Take the first
+ if (connectorId === 0 && connector.numberOfConnectedPhase > 0) {
+ return connector.numberOfConnectedPhase;
+ }
+ if (connector.connectorId === connectorId && connector.numberOfConnectedPhase > 0) {
+ return connector.numberOfConnectedPhase;
+ }
+ }
+ }
+ }
+ return 1;
+ }
+
+ public static getChargingStationVoltage(chargingStation: ChargingStation, connectorId = 0): number {
+ if (chargingStation) {
+ // Check voltage at charging station level
+ if (connectorId === 0 && chargingStation.voltage > 0) {
+ return chargingStation.voltage;
+ }
+ // Check voltage at charge point level
+ if (chargingStation.chargePoints) {
+ for (const chargePoint of chargingStation.chargePoints) {
+ // Take the first
+ if (connectorId === 0 && chargePoint.voltage > 0) {
+ return chargePoint.voltage;
+ }
+ if (chargePoint.connectorIDs.includes(connectorId) && chargePoint.voltage > 0) {
+ return chargePoint.voltage;
+ }
+ }
+ }
+ // Check voltage at connector level
+ if (chargingStation.connectors) {
+ for (const connector of chargingStation.connectors) {
+ // Take the first
+ if (connectorId === 0 && connector.voltage > 0) {
+ return connector.voltage;
+ }
+ if (connector.connectorId === connectorId && connector.voltage > 0) {
+ return connector.voltage;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
public static isEmptyArray(array): boolean {
if (Array.isArray(array) && array.length > 0) {

Handle charge point + logs in json client