New template structure handling for Charging Stations
MODIFY
src/migration/tasks/UpdateChargingStationTemplatesTask.ts
src/migration/tasks/UpdateChargingStationTemplatesTask.ts
@@ -14,10 +14,6 @@ import global from './../../types/GlobalType';
const MODULE_NAME = 'UpdateChargingStationTemplatesTask';
export default class UpdateChargingStationTemplatesTask extends MigrationTask {
- getVersion() {
- return '1.7';
- }
-
isAsynchronous() {
return true;
}
@@ -34,7 +30,7 @@ export default class UpdateChargingStationTemplatesTask extends MigrationTask {
const tenants = await TenantStorage.getTenants({}, Constants.DB_PARAMS_MAX_LIMIT);
for (const tenant of tenants.result) {
// Update Charging Station OCPP Params
- await this.updateChargingStationsOCPPParametersInTemplate(tenant);
+ // await this.updateChargingStationsOCPPParametersInTemplate(tenant);
// Update current Charging Station with Template
await this.updateChargingStationsParametersWithTemplate(tenant);
// Remove unused props
@@ -42,6 +38,10 @@ export default class UpdateChargingStationTemplatesTask extends MigrationTask {
}
}
+ getVersion() {
+ return '1.810';
+ }
+
private async updateChargingStationsOCPPParametersInTemplate(tenant: Tenant) {
// Get the charging station
const chargingStations = await ChargingStationStorage.getChargingStations(tenant.id, {
@@ -153,11 +153,14 @@ export default class UpdateChargingStationTemplatesTask extends MigrationTask {
private async removeChargingStationUnusedPropsInDB(tenant: Tenant) {
const result = await global.database.getCollection<any>(tenant.id, 'chargingstations').updateMany(
- { 'inactive': { $exists: true } },
+ { 'ocppAdvancedCommands': { $exists: true } },
{
$unset: {
'numberOfConnectedPhase': '',
- 'inactive': ''
+ 'inactive': '',
+ 'cannotChargeInParallel': '',
+ 'currentType': '',
+ 'ocppAdvancedCommands': '',
}
},
{ upsert: false }

MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -56,20 +56,26 @@ export default class OCPPUtils {
if (chargingStationTemplate) {
// Already updated?
if (chargingStation.templateHash !== chargingStationTemplate.hash) {
+ console.log('Changed in templateHash');
// Set the hash
chargingStation.templateHash = chargingStationTemplate.hash;
- // Assign props
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'cannotChargeInParallel')) {
- chargingStation.cannotChargeInParallel = chargingStationTemplate.template.cannotChargeInParallel;
+ // Check Technical Hash
+ if (chargingStation.templateHashTechnical !== chargingStationTemplate.hashTechnical) {
+ console.log('Changed in templateHashTechnical');
+ // Set the hash
+ chargingStation.templateHashTechnical = chargingStationTemplate.hashTechnical;
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'maximumPower')) {
+ chargingStation.maximumPower = chargingStationTemplate.technical.maximumPower;
}
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'private')) {
- chargingStation.private = chargingStationTemplate.template.private;
+ // Assign props
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'excludeFromPowerLimitation')) {
+ chargingStation.excludeFromPowerLimitation = chargingStationTemplate.technical.excludeFromPowerLimitation;
}
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'maximumPower')) {
- chargingStation.maximumPower = chargingStationTemplate.template.maximumPower;
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'chargePoints')) {
+ chargingStation.chargePoints = chargingStationTemplate.technical.chargePoints;
}
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'currentType')) {
- chargingStation.currentType = chargingStationTemplate.template.currentType;
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'powerLimitUnit')) {
+ chargingStation.powerLimitUnit = chargingStationTemplate.technical.powerLimitUnit;
}
// Enrich connectors
if (chargingStation.connectors) {
@@ -78,13 +84,14 @@ export default class OCPPUtils {
tenantID, chargingStation, connector.connectorId, chargingStationTemplate);
}
}
+ }
// Handle capabilities
chargingStation.capabilities = {} as ChargingStationCapabilities;
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'capabilities')) {
+ if (Utils.objectHasProperty(chargingStationTemplate, 'capabilities')) {
let matchFirmware = true;
let matchOcpp = true;
// Search Firmware/Ocpp match
- for (const capabilities of chargingStationTemplate.template.capabilities) {
+ for (const capabilities of chargingStationTemplate.capabilities) {
// Check Firmware version
if (capabilities.supportedFirmwareVersions) {
matchFirmware = capabilities.supportedFirmwareVersions.includes(chargingStation.firmwareVersion);
@@ -100,34 +107,12 @@ export default class OCPPUtils {
}
}
}
- // Handle OCPP Advanced Commands
- chargingStation.ocppAdvancedCommands = [];
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'ocppAdvancedCommands')) {
- let matchFirmware = true;
- let matchOcpp = true;
- // Search Firmware/Ocpp match
- for (const ocppAdvancedCommands of chargingStationTemplate.template.ocppAdvancedCommands) {
- // Check Firmware version
- if (ocppAdvancedCommands.supportedFirmwareVersions) {
- matchFirmware = ocppAdvancedCommands.supportedFirmwareVersions.includes(chargingStation.firmwareVersion);
- }
- // Check Ocpp version
- if (ocppAdvancedCommands.supportedOcppVersions) {
- matchOcpp = ocppAdvancedCommands.supportedOcppVersions.includes(chargingStation.ocppVersion);
- }
- // Found?
- if (matchFirmware && matchOcpp) {
- chargingStation.ocppAdvancedCommands = ocppAdvancedCommands.commands;
- break;
- }
- }
- }
// Handle OCPP Standard Parameters
chargingStation.ocppStandardParameters = [];
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'ocppStandardParameters')) {
+ if (Utils.objectHasProperty(chargingStationTemplate, 'ocppStandardParameters')) {
let matchOcpp = true;
// Search Firmware/Ocpp match
- for (const ocppStandardParameters of chargingStationTemplate.template.ocppStandardParameters) {
+ for (const ocppStandardParameters of chargingStationTemplate.ocppStandardParameters) {
// Check Ocpp version
if (ocppStandardParameters.supportedOcppVersions) {
matchOcpp = ocppStandardParameters.supportedOcppVersions.includes(chargingStation.ocppVersion);
@@ -146,11 +131,11 @@ export default class OCPPUtils {
}
// Handle OCPP Vendor Parameters
chargingStation.ocppVendorParameters = [];
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'ocppVendorParameters')) {
+ if (Utils.objectHasProperty(chargingStationTemplate, 'ocppVendorParameters')) {
let matchFirmware = true;
let matchOcpp = true;
// Search Firmware/Ocpp match
- for (const ocppVendorParameters of chargingStationTemplate.template.ocppVendorParameters) {
+ for (const ocppVendorParameters of chargingStationTemplate.ocppVendorParameters) {
// Check Firmware version
if (ocppVendorParameters.supportedFirmwareVersions) {
matchFirmware = ocppVendorParameters.supportedFirmwareVersions.includes(chargingStation.firmwareVersion);
@@ -213,9 +198,9 @@ export default class OCPPUtils {
// Copy from template
if (chargingStationTemplate) {
// Handle connector
- if (Utils.objectHasProperty(chargingStationTemplate.template, 'connectors')) {
+ if (Utils.objectHasProperty(chargingStationTemplate.technical, 'connectors')) {
// Find the connector in the template
- const templateConnector = chargingStationTemplate.template.connectors.find(
+ const templateConnector = chargingStationTemplate.technical.connectors.find(
(connector) => connector.connectorId === connectorID);
if (!templateConnector) {
// Log
@@ -232,17 +217,43 @@ export default class OCPPUtils {
for (const connector of chargingStation.connectors) {
// Set
if (connector.connectorId === connectorID) {
- connector.power = templateConnector.power;
+ // Assign props
connector.type = templateConnector.type;
+ if (Utils.objectHasProperty(templateConnector, 'power')) {
+ connector.power = templateConnector.power;
+ } else {
+ delete connector.power;
+ }
+ if (Utils.objectHasProperty(templateConnector, 'amperage')) {
+ connector.amperage = templateConnector.amperage;
+ } else {
+ delete connector.amperage;
+ }
+ if (Utils.objectHasProperty(templateConnector, 'chargePointID')) {
+ connector.chargePointID = templateConnector.chargePointID;
+ } else {
+ delete connector.chargePointID;
+ }
+ if (Utils.objectHasProperty(templateConnector, 'voltage')) {
+ connector.voltage = templateConnector.voltage;
+ } else {
+ delete connector.voltage;
+ }
+ if (Utils.objectHasProperty(templateConnector, 'currentType')) {
connector.currentType = templateConnector.currentType;
+ } else {
+ delete connector.currentType;
+ }
+ if (Utils.objectHasProperty(templateConnector, 'numberOfConnectedPhase')) {
connector.numberOfConnectedPhase = templateConnector.numberOfConnectedPhase;
- connector.voltage = templateConnector.voltage;
- connector.amperage = templateConnector.amperage;
- connector.amperageLimit = templateConnector.amperage;
+ } else {
+ delete connector.numberOfConnectedPhase;
+ }
break;
}
}
// Recalculate Max Power
+ // TODO
this.recalculateChargingStationMaxPower(chargingStation);
}
// Log
@@ -444,9 +455,10 @@ export default class OCPPUtils {
public static recalculateChargingStationMaxPower(chargingStation: ChargingStation) {
let maximumPower = 0;
// Only for AC
- if (chargingStation.currentType !== ChargingStationCurrentType.AC) {
- return;
- }
+ // TODO
+ // if (chargingStation.currentType !== ChargingStationCurrentType.AC) {
+ // return;
+ // }
for (const connector of chargingStation.connectors) {
if (Utils.objectHasProperty(connector, 'power')) {
maximumPower += connector.power;

MODIFY
src/server/rest/service/ChargingStationService.ts
src/server/rest/service/ChargingStationService.ts
-import { Action, Entity } from '../../../types/Authorization';
-import ChargingStation, { Command, OCPPParams, StaticLimitAmps } from '../../../types/ChargingStation';
-import { HTTPAuthError, HTTPError } from '../../../types/HTTPError';
-import { HttpChargingStationCommandRequest, HttpIsAuthorizedRequest } from '../../../types/requests/HttpChargingStationRequest';
+import fs from 'fs';
+
import { NextFunction, Request, Response } from 'express';
-import { OCPPConfigurationStatus, OCPPStatus } from '../../../types/ocpp/OCPPClient';
+import sanitize from 'mongo-sanitize';
+import Authorizations from '../../../authorization/Authorizations';
+import ChargingStationClientFactory from '../../../client/ocpp/ChargingStationClientFactory';
import AppAuthError from '../../../exception/AppAuthError';
import AppError from '../../../exception/AppError';
-import Authorizations from '../../../authorization/Authorizations';
import BackendError from '../../../exception/BackendError';
-import { ChargingProfile } from '../../../types/ChargingProfile';
-import ChargingStationClientFactory from '../../../client/ocpp/ChargingStationClientFactory';
-import { ChargingStationInErrorType } from '../../../types/InError';
-import ChargingStationSecurity from './security/ChargingStationSecurity';
-import ChargingStationStorage from '../../../storage/mongodb/ChargingStationStorage';
import ChargingStationVendorFactory from '../../../integration/charging-station-vendor/ChargingStationVendorFactory';
-import Constants from '../../../utils/Constants';
-import { DataResult } from '../../../types/DataResult';
-import I18nManager from '../../../utils/I18nManager';
+import SmartChargingFactory from '../../../integration/smart-charging/SmartChargingFactory';
import LockingHelper from '../../../locking/LockingHelper';
import LockingManager from '../../../locking/LockingManager';
-import Logging from '../../../utils/Logging';
+import ChargingStationStorage from '../../../storage/mongodb/ChargingStationStorage';
import OCPPStorage from '../../../storage/mongodb/OCPPStorage';
-import OCPPUtils from '../../ocpp/utils/OCPPUtils';
-import { ServerAction } from '../../../types/Server';
import SiteAreaStorage from '../../../storage/mongodb/SiteAreaStorage';
import SiteStorage from '../../../storage/mongodb/SiteStorage';
-import SmartChargingFactory from '../../../integration/smart-charging/SmartChargingFactory';
-import TenantComponents from '../../../types/TenantComponents';
import TransactionStorage from '../../../storage/mongodb/TransactionStorage';
+import { Action, Entity } from '../../../types/Authorization';
+import { ChargingProfile } from '../../../types/ChargingProfile';
+import ChargingStation, { Command, OCPPParams, StaticLimitAmps } from '../../../types/ChargingStation';
+import { DataResult } from '../../../types/DataResult';
+import { HTTPAuthError, HTTPError } from '../../../types/HTTPError';
+import { ChargingStationInErrorType } from '../../../types/InError';
+import { OCPPConfigurationStatus, OCPPStatus } from '../../../types/ocpp/OCPPClient';
+import { HttpChargingStationCommandRequest, HttpIsAuthorizedRequest } from '../../../types/requests/HttpChargingStationRequest';
+import { ServerAction } from '../../../types/Server';
+import SiteArea from '../../../types/SiteArea';
+import TenantComponents from '../../../types/TenantComponents';
import UserToken from '../../../types/UserToken';
+import Constants from '../../../utils/Constants';
+import I18nManager from '../../../utils/I18nManager';
+import Logging from '../../../utils/Logging';
import Utils from '../../../utils/Utils';
+import OCPPUtils from '../../ocpp/utils/OCPPUtils';
+import ChargingStationSecurity from './security/ChargingStationSecurity';
import UtilsService from './UtilsService';
-import fs from 'fs';
-import sanitize from 'mongo-sanitize';
const MODULE_NAME = 'ChargingStationService';
@@ -128,26 +130,27 @@ export default class ChargingStationService {
public static async handleUpdateChargingStationParams(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Filter
const filteredRequest = ChargingStationSecurity.filterChargingStationParamsUpdateRequest(req.body);
- // Check existence
+ console.log('====================================');
+ console.log(filteredRequest);
+ console.log('====================================');
+ // Check the Charging Station
const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.id);
- // Check
UtilsService.assertObjectExists(action, chargingStation, `Charging Station '${filteredRequest.id}' doesn't exist.`,
MODULE_NAME, 'handleAssignChargingStationsToSiteArea', req.user);
- let siteID = null;
- if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION)) {
- // Get the Site Area
- const siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, chargingStation.siteAreaID);
- siteID = siteArea ? siteArea.siteID : null;
+ let siteArea: SiteArea = null;
+ // Check the Site Area
+ if (Utils.isComponentActiveFromToken(req.user, TenantComponents.ORGANIZATION) && filteredRequest.siteAreaID) {
+ siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteAreaID);
+ UtilsService.assertObjectExists(action, siteArea, `Site Area '${filteredRequest.siteAreaID}' doesn't exist.`,
+ MODULE_NAME, 'handleAssignChargingStationsToSiteArea', req.user);
}
// Check Auth
- if (!Authorizations.canUpdateChargingStation(req.user, siteID)) {
+ if (!Authorizations.canUpdateChargingStation(req.user, siteArea ? siteArea.siteID : null)) {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.UPDATE,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleUpdateChargingStationParams',
+ action: Action.UPDATE, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleUpdateChargingStationParams',
value: chargingStation.id
});
}
@@ -159,22 +162,14 @@ export default class ChargingStationService {
if (Utils.objectHasProperty(filteredRequest, 'maximumPower')) {
chargingStation.maximumPower = filteredRequest.maximumPower;
}
- // Update Current Type
- if (Utils.objectHasProperty(filteredRequest, 'currentType')) {
- chargingStation.currentType = filteredRequest.currentType;
- }
- // Update Cannot Charge in Parallel
- if (Utils.objectHasProperty(filteredRequest, 'cannotChargeInParallel')) {
- chargingStation.cannotChargeInParallel = filteredRequest.cannotChargeInParallel;
- }
// Update Private property
if (Utils.objectHasProperty(filteredRequest, 'private')) {
chargingStation.private = filteredRequest.private;
}
// Update Site Area
- if (filteredRequest.siteArea) {
- chargingStation.siteArea = await SiteAreaStorage.getSiteArea(req.user.tenantID, filteredRequest.siteArea.id);
- chargingStation.siteAreaID = chargingStation.siteArea.id;
+ if (siteArea) {
+ chargingStation.siteAreaID = siteArea.id;
+ // Check number of phases corresponds to the site area one
if (filteredRequest.connectors) {
for (const connector of filteredRequest.connectors) {
if (connector.numberOfConnectedPhase !== 1 && chargingStation.siteArea.numberOfPhases === 1) {
@@ -192,10 +187,6 @@ export default class ChargingStationService {
} else {
chargingStation.siteAreaID = null;
}
- // Update Site Area
- if (Utils.objectHasProperty(filteredRequest, 'powerLimitUnit')) {
- chargingStation.powerLimitUnit = filteredRequest.powerLimitUnit;
- }
if (filteredRequest.coordinates && filteredRequest.coordinates.length === 2) {
chargingStation.coordinates = [
sanitize(filteredRequest.coordinates[0]),
@@ -204,16 +195,15 @@ export default class ChargingStationService {
}
// Update Connectors
if (filteredRequest.connectors) {
- const chargerConnectors = chargingStation.connectors;
// Assign to Charging Station's connector
- for (const connector of filteredRequest.connectors) {
+ for (const filteredConnector of filteredRequest.connectors) {
// Set
- chargerConnectors[connector.connectorId - 1].power = connector.power;
- chargerConnectors[connector.connectorId - 1].type = connector.type;
- chargerConnectors[connector.connectorId - 1].voltage = connector.voltage;
- chargerConnectors[connector.connectorId - 1].amperage = connector.amperage;
- chargerConnectors[connector.connectorId - 1].currentType = connector.currentType;
- chargerConnectors[connector.connectorId - 1].numberOfConnectedPhase = connector.numberOfConnectedPhase;
+ chargingStation.connectors[filteredConnector.connectorId - 1].type = filteredConnector.type;
+ chargingStation.connectors[filteredConnector.connectorId - 1].power = filteredConnector.power;
+ chargingStation.connectors[filteredConnector.connectorId - 1].amperage = filteredConnector.amperage;
+ chargingStation.connectors[filteredConnector.connectorId - 1].voltage = filteredConnector.voltage;
+ chargingStation.connectors[filteredConnector.connectorId - 1].currentType = filteredConnector.currentType;
+ chargingStation.connectors[filteredConnector.connectorId - 1].numberOfConnectedPhase = filteredConnector.numberOfConnectedPhase;
}
}
// Update timestamp
@@ -1267,7 +1257,7 @@ export default class ChargingStationService {
private static convertToCSV(loggedUser: UserToken, chargingStations: ChargingStation[]): string {
const i18nManager = new I18nManager(loggedUser.locale);
- let csv = `Name${Constants.CSV_SEPARATOR}Created On${Constants.CSV_SEPARATOR}Number of Connectors${Constants.CSV_SEPARATOR}Site Area${Constants.CSV_SEPARATOR}Latitude${Constants.CSV_SEPARATOR}Longitude${Constants.CSV_SEPARATOR}Charge Point S/N${Constants.CSV_SEPARATOR}Model${Constants.CSV_SEPARATOR}Charge Box S/N${Constants.CSV_SEPARATOR}Vendor${Constants.CSV_SEPARATOR}Firmware Version${Constants.CSV_SEPARATOR}OCPP Version${Constants.CSV_SEPARATOR}OCPP Protocol${Constants.CSV_SEPARATOR}Last Heartbeat${Constants.CSV_SEPARATOR}Last Reboot${Constants.CSV_SEPARATOR}Maximum Power (Watt)${Constants.CSV_SEPARATOR}Can Charge In Parallel${Constants.CSV_SEPARATOR}Power Limit Unit\r\n`;
+ let csv = `Name${Constants.CSV_SEPARATOR}Created On${Constants.CSV_SEPARATOR}Number of Connectors${Constants.CSV_SEPARATOR}Site Area${Constants.CSV_SEPARATOR}Latitude${Constants.CSV_SEPARATOR}Longitude${Constants.CSV_SEPARATOR}Charge Point S/N${Constants.CSV_SEPARATOR}Model${Constants.CSV_SEPARATOR}Charge Box S/N${Constants.CSV_SEPARATOR}Vendor${Constants.CSV_SEPARATOR}Firmware Version${Constants.CSV_SEPARATOR}OCPP Version${Constants.CSV_SEPARATOR}OCPP Protocol${Constants.CSV_SEPARATOR}Last Heartbeat${Constants.CSV_SEPARATOR}Last Reboot${Constants.CSV_SEPARATOR}Maximum Power (Watt)${Constants.CSV_SEPARATOR}Power Limit Unit\r\n`;
for (const chargingStation of chargingStations) {
csv += `${chargingStation.id}` + Constants.CSV_SEPARATOR;
csv += `${i18nManager.formatDateTime(chargingStation.createdOn, 'L')} ${i18nManager.formatDateTime(chargingStation.createdOn, 'LT')}` + Constants.CSV_SEPARATOR;
@@ -1289,7 +1279,6 @@ export default class ChargingStationService {
csv += `${i18nManager.formatDateTime(chargingStation.lastHeartBeat, 'L')} ${i18nManager.formatDateTime(chargingStation.lastHeartBeat, 'LT')}` + Constants.CSV_SEPARATOR;
csv += `${i18nManager.formatDateTime(chargingStation.lastReboot, 'L')} ${i18nManager.formatDateTime(chargingStation.lastReboot, 'LT')}` + Constants.CSV_SEPARATOR;
csv += `${chargingStation.maximumPower}` + Constants.CSV_SEPARATOR;
- csv += (!chargingStation.cannotChargeInParallel ? 'yes' : 'no') + Constants.CSV_SEPARATOR;
csv += `${chargingStation.powerLimitUnit}\r\n`;
}
return csv;

MODIFY
src/server/rest/service/security/ChargingStationSecurity.ts
src/server/rest/service/security/ChargingStationSecurity.ts
-import { ChargingProfile, ChargingSchedule, ChargingSchedulePeriod, Profile } from '../../../../types/ChargingProfile';
-import ChargingStation, { Command } from '../../../../types/ChargingStation';
-import { HttpAssignChargingStationToSiteAreaRequest, HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../types/requests/HttpChargingStationRequest';
+import sanitize from 'mongo-sanitize';
import Authorizations from '../../../../authorization/Authorizations';
-import { ChargePointStatus } from '../../../../types/ocpp/OCPPServer';
-import { ChargingStationInError } from '../../../../types/InError';
+import { ChargingProfile, ChargingSchedule, ChargingSchedulePeriod, Profile } from '../../../../types/ChargingProfile';
+import ChargingStation, { Command } from '../../../../types/ChargingStation';
import { DataResult } from '../../../../types/DataResult';
+import { ChargingStationInError } from '../../../../types/InError';
+import { ChargePointStatus } from '../../../../types/ocpp/OCPPServer';
import HttpByIDRequest from '../../../../types/requests/HttpByIDRequest';
+import { HttpAssignChargingStationToSiteAreaRequest, HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../types/requests/HttpChargingStationRequest';
import HttpDatabaseRequest from '../../../../types/requests/HttpDatabaseRequest';
import { InactivityStatus } from '../../../../types/Transaction';
import UserToken from '../../../../types/UserToken';
import Utils from '../../../../utils/Utils';
import UtilsSecurity from './UtilsSecurity';
-import sanitize from 'mongo-sanitize';
export default class ChargingStationSecurity {
@@ -48,7 +48,7 @@ export default class ChargingStationSecurity {
// Yes: set all params
filteredChargingStation = chargingStation;
for (const connector of filteredChargingStation.connectors) {
- if (filteredChargingStation.inactive && connector) {
+ if (connector && filteredChargingStation.inactive) {
connector.status = ChargePointStatus.UNAVAILABLE;
connector.currentConsumption = 0;
connector.totalConsumption = 0;
@@ -67,26 +67,45 @@ export default class ChargingStationSecurity {
return connector;
}
return {
- 'id': connector.id,
- 'connectorId': connector.connectorId,
- 'status': (filteredChargingStation.inactive ? ChargePointStatus.UNAVAILABLE : connector.status),
- 'currentConsumption': (filteredChargingStation.inactive ? 0 : connector.currentConsumption),
- 'currentStateOfCharge': (filteredChargingStation.inactive ? 0 : connector.currentStateOfCharge),
- 'totalConsumption': (filteredChargingStation.inactive ? 0 : connector.totalConsumption),
- 'totalInactivitySecs': (filteredChargingStation.inactive ? 0 : connector.totalInactivitySecs),
- 'inactivityStatus': connector.inactivityStatus,
- 'activeTransactionID': connector.activeTransactionID,
- 'activeTransactionDate': connector.activeTransactionDate,
- 'activeTagID': connector.activeTagID,
- 'errorCode': connector.errorCode,
- 'type': connector.type,
- 'power': connector.power,
- 'numberOfConnectedPhase': connector.numberOfConnectedPhase,
- 'currentType': connector.currentType,
- 'voltage': connector.voltage,
- 'amperage': connector.amperage
+ id: connector.id,
+ connectorId: connector.connectorId,
+ status: (filteredChargingStation.inactive ? ChargePointStatus.UNAVAILABLE : connector.status),
+ currentConsumption: (filteredChargingStation.inactive ? 0 : connector.currentConsumption),
+ currentStateOfCharge: (filteredChargingStation.inactive ? 0 : connector.currentStateOfCharge),
+ totalConsumption: (filteredChargingStation.inactive ? 0 : connector.totalConsumption),
+ totalInactivitySecs: (filteredChargingStation.inactive ? 0 : connector.totalInactivitySecs),
+ inactivityStatus: connector.inactivityStatus,
+ activeTransactionID: connector.activeTransactionID,
+ activeTransactionDate: connector.activeTransactionDate,
+ activeTagID: connector.activeTagID,
+ errorCode: connector.errorCode,
+ type: connector.type,
+ power: connector.power,
+ numberOfConnectedPhase: connector.numberOfConnectedPhase,
+ currentType: connector.currentType,
+ voltage: connector.voltage,
+ amperage: connector.amperage
+ };
+ });
+ if (chargingStation.chargePoints) {
+ filteredChargingStation.chargePoints = chargingStation.chargePoints.map((chargePoint) => {
+ if (!chargePoint) {
+ return chargePoint;
+ }
+ return {
+ currentType: chargePoint.currentType,
+ voltage: chargePoint.voltage,
+ amperage: chargePoint.amperage,
+ numberOfConnectedPhase: chargePoint.numberOfConnectedPhase,
+ cannotChargeInParallel: chargePoint.cannotChargeInParallel,
+ sharePowerToAllConnectors: chargePoint.sharePowerToAllConnectors,
+ excludeFromPowerLimitation: chargePoint.excludeFromPowerLimitation,
+ power: chargePoint.power,
+ efficiency: chargePoint.efficiency,
+ connectorIDs: chargePoint.connectorIDs
};
});
+ }
filteredChargingStation.lastHeartBeat = chargingStation.lastHeartBeat;
filteredChargingStation.maximumPower = chargingStation.maximumPower;
filteredChargingStation.chargePointVendor = chargingStation.chargePointVendor;
@@ -208,8 +227,8 @@ export default class ChargingStationSecurity {
return filteredRequest;
}
- public static filterChargingStationParamsUpdateRequest(request: any): Partial<ChargingStation> {
- const filteredRequest: any = {};
+ public static filterChargingStationParamsUpdateRequest(request: any): HttpChargingStationParamsUpdateRequest {
+ const filteredRequest = {} as HttpChargingStationParamsUpdateRequest;
filteredRequest.id = sanitize(request.id);
if (Utils.objectHasProperty(request, 'chargingStationURL')) {
filteredRequest.chargingStationURL = sanitize(request.chargingStationURL);
@@ -217,20 +236,11 @@ export default class ChargingStationSecurity {
if (Utils.objectHasProperty(request, 'maximumPower')) {
filteredRequest.maximumPower = sanitize(request.maximumPower);
}
- if (Utils.objectHasProperty(request, 'cannotChargeInParallel')) {
- filteredRequest.cannotChargeInParallel = UtilsSecurity.filterBoolean(request.cannotChargeInParallel);
- }
if (Utils.objectHasProperty(request, 'private')) {
filteredRequest.private = UtilsSecurity.filterBoolean(request.private);
}
- if (Utils.objectHasProperty(request, 'siteArea')) {
- filteredRequest.siteArea = sanitize(request.siteArea);
- }
- if (Utils.objectHasProperty(request, 'powerLimitUnit')) {
- filteredRequest.powerLimitUnit = sanitize(request.powerLimitUnit);
- }
- if (Utils.objectHasProperty(request, 'currentType')) {
- filteredRequest.currentType = sanitize(request.currentType);
+ if (Utils.objectHasProperty(request, 'siteAreaID')) {
+ filteredRequest.siteAreaID = sanitize(request.siteAreaID);
}
if (request.coordinates && request.coordinates.length === 2) {
filteredRequest.coordinates = [
@@ -238,12 +248,10 @@ export default class ChargingStationSecurity {
sanitize(request.coordinates[1])
];
}
+ // Filter connectors
if (request.connectors) {
- // Filter
filteredRequest.connectors = request.connectors.map((connector) => {
- if (!connector) {
- return connector;
- }
+ if (connector) {
return {
connectorId: sanitize(connector.connectorId),
power: sanitize(connector.power),
@@ -253,6 +261,8 @@ export default class ChargingStationSecurity {
currentType: sanitize(connector.currentType),
numberOfConnectedPhase: sanitize(connector.numberOfConnectedPhase)
};
+ }
+ return null;
});
}
return filteredRequest;

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -27,7 +27,7 @@ export default class ChargingStationStorage {
// Debug
const uniqueTimerID = Logging.traceStart(MODULE_NAME, 'updateChargingStationTemplatesFromFile');
// Read File
- let chargingStationTemplates;
+ let chargingStationTemplates: ChargingStationTemplate[];
try {
chargingStationTemplates =
JSON.parse(fs.readFileSync(`${global.appRoot}/assets/charging-station-templates/charging-stations.json`, 'utf8'));
@@ -39,8 +39,9 @@ export default class ChargingStationStorage {
// Update Templates
for (const chargingStationTemplate of chargingStationTemplates) {
try {
- // Set the hash
+ // Set the hashes
chargingStationTemplate.hash = Cypher.hash(JSON.stringify(chargingStationTemplate));
+ chargingStationTemplate.hashTechnical = Cypher.hash(JSON.stringify(chargingStationTemplate.technical));
// Save
await ChargingStationStorage.saveChargingStationTemplate(chargingStationTemplate);
} catch (error) {
@@ -429,22 +430,40 @@ export default class ChargingStationStorage {
for (const connector of chargingStationToSave.connectors) {
if (connector) {
connector.connectorId = Utils.convertToInt(connector.connectorId);
+ connector.power = Utils.convertToInt(connector.power);
+ connector.amperage = connector.amperage ? Utils.convertToInt(connector.amperage) : null;
+ connector.voltage = connector.voltage ? Utils.convertToInt(connector.voltage) : null;
+ connector.chargePointID = connector.chargePointID ? Utils.convertToInt(connector.chargePointID) : null;
+ connector.currentType = connector.currentType ? connector.currentType : null;
+ connector.numberOfConnectedPhase = connector.numberOfConnectedPhase ? Utils.convertToInt(connector.numberOfConnectedPhase) : null;
connector.currentConsumption = Utils.convertToFloat(connector.currentConsumption);
connector.totalInactivitySecs = Utils.convertToInt(connector.totalInactivitySecs);
connector.totalConsumption = Utils.convertToFloat(connector.totalConsumption);
- connector.power = Utils.convertToInt(connector.power);
- connector.voltage = Utils.convertToInt(connector.voltage);
- connector.amperage = Utils.convertToInt(connector.amperage);
- connector.numberOfConnectedPhase = Utils.convertToInt(connector.numberOfConnectedPhase);
connector.activeTransactionID = Utils.convertToInt(connector.activeTransactionID);
connector.activeTransactionDate = Utils.convertToDate(connector.activeTransactionDate);
}
}
}
+ if (chargingStationToSave.chargePoints && Array.isArray(chargingStationToSave.chargePoints)) {
+ for (const chargePoint of chargingStationToSave.chargePoints) {
+ if (chargePoint) {
+ chargePoint.voltage = Utils.convertToInt(chargePoint.voltage);
+ chargePoint.amperage = Utils.convertToInt(chargePoint.amperage);
+ chargePoint.numberOfConnectedPhase = Utils.convertToInt(chargePoint.numberOfConnectedPhase);
+ chargePoint.cannotChargeInParallel = Utils.convertToBoolean(chargePoint.cannotChargeInParallel);
+ chargePoint.sharePowerToAllConnectors = Utils.convertToBoolean(chargePoint.sharePowerToAllConnectors);
+ chargePoint.excludeFromPowerLimitation = Utils.convertToBoolean(chargePoint.excludeFromPowerLimitation);
+ chargePoint.power = Utils.convertToInt(chargePoint.power);
+ chargePoint.efficiency = Utils.convertToInt(chargePoint.efficiency);
+ chargePoint.connectorIDs = chargePoint.connectorIDs.map((connectorID) => Utils.convertToInt(connectorID));
+ }
+ }
+ }
// Properties to save
const chargingStationMDB = {
_id: chargingStationToSave.id,
templateHash: chargingStationToSave.templateHash,
+ templateHashTechnical: chargingStationToSave.templateHashTechnical,
issuer: Utils.convertToBoolean(chargingStationToSave.issuer),
private: Utils.convertToBoolean(chargingStationToSave.private),
siteAreaID: Utils.convertToObjectID(chargingStationToSave.siteAreaID),
@@ -466,12 +485,12 @@ export default class ChargingStationStorage {
lastReboot: Utils.convertToDate(chargingStationToSave.lastReboot),
chargingStationURL: chargingStationToSave.chargingStationURL,
maximumPower: Utils.convertToInt(chargingStationToSave.maximumPower),
- cannotChargeInParallel: Utils.convertToBoolean(chargingStationToSave.cannotChargeInParallel),
+ excludeFromPowerLimitation: Utils.convertToBoolean(chargingStationToSave.excludeFromPowerLimitation),
powerLimitUnit: chargingStationToSave.powerLimitUnit,
- coordinates: chargingStationToSave.coordinates,
+ chargePoints: chargingStationToSave.chargePoints ? chargingStationToSave.chargePoints : null,
connectors: chargingStationToSave.connectors,
+ coordinates: chargingStationToSave.coordinates,
remoteAuthorizations: chargingStationToSave.remoteAuthorizations,
- currentType: chargingStationToSave.currentType,
currentIPAddress: chargingStationToSave.currentIPAddress,
capabilities: chargingStationToSave.capabilities,
ocppAdvancedCommands: chargingStationToSave.ocppAdvancedCommands,

MODIFY
src/types/ChargingStation.ts
src/types/ChargingStation.ts
@@ -9,6 +9,7 @@ import SiteArea from './SiteArea';
export default interface ChargingStation extends CreatedUpdatedProps {
id?: string;
templateHash?: string;
+ templateHashTechnical?: string;
issuer: boolean;
private: boolean;
siteAreaID?: string;
@@ -32,9 +33,10 @@ export default interface ChargingStation extends CreatedUpdatedProps {
lastReboot: Date;
chargingStationURL: string;
maximumPower: number;
- cannotChargeInParallel: boolean;
+ excludeFromPowerLimitation?: boolean;
powerLimitUnit: PowerLimitUnits;
coordinates: number[];
+ chargePoints: ChargingStationChargePoint[];
connectors: Connector[];
remoteAuthorizations: RemoteAuthorization[];
currentIPAddress?: string;
@@ -43,7 +45,6 @@ export default interface ChargingStation extends CreatedUpdatedProps {
ocppAdvancedCommands?: OcppAdvancedCommands[];
ocppStandardParameters?: KeyValue[];
ocppVendorParameters?: KeyValue[];
- currentType: ChargingStationCurrentType;
ocpiData?: {
evse?: OCPIEvse;
};
@@ -112,6 +113,7 @@ export interface Connector {
inactivityStatus?: InactivityStatus;
numberOfConnectedPhase?: number;
currentType?: ConnectorCurrentType;
+ chargePointID?: number;
}
export interface RemoteAuthorization {
@@ -143,27 +145,43 @@ export enum ConnectorCurrentType {
DC = 'DC'
}
+export interface ChargingStationChargePoint {
+ currentType: ChargingStationCurrentType;
+ voltage: number;
+ amperage: number;
+ numberOfConnectedPhase: number;
+ cannotChargeInParallel: boolean;
+ sharePowerToAllConnectors: boolean;
+ excludeFromPowerLimitation: boolean;
+ power: number;
+ efficiency: number;
+ connectorIDs: number[];
+}
+
export interface ChargingStationTemplate {
id?: string;
hash?: string;
+ hashTechnical?: string;
chargePointVendor: string;
extraFilters: {
chargeBoxSerialNumber?: string;
};
- template: {
- private: boolean;
- cannotChargeInParallel: boolean;
- currentType: ChargingStationCurrentType;
+ technical: {
maximumPower: number;
+ excludeFromPowerLimitation: boolean;
+ powerLimitUnit: PowerLimitUnits;
+ chargePoints?: ChargingStationChargePoint[];
connectors: {
connectorId: number;
- power: number;
type: ConnectorType;
- currentType: ConnectorCurrentType;
- numberOfConnectedPhase: number;
- voltage: number;
- amperage: number;
+ power?: number;
+ amperage?: number;
+ voltage?: number;
+ chargePointID?: number;
+ currentType?: ConnectorCurrentType;
+ numberOfConnectedPhase?: number;
}[];
+ };
capabilities: {
supportedFirmwareVersions: string[];
supportedOcppVersions: string[];
@@ -183,7 +201,6 @@ export interface ChargingStationTemplate {
supportedOcppVersions: string[];
parameters: object;
}[];
- };
}
export enum ConnectorType {

MODIFY
src/types/requests/HttpChargingStationRequest.ts
src/types/requests/HttpChargingStationRequest.ts
+import { ConnectorCurrentType, ConnectorType } from '../ChargingStation';
import HttpDatabaseRequest from './HttpDatabaseRequest';
export interface HttpAssignChargingStationToSiteAreaRequest {
@@ -34,6 +35,24 @@ export interface HttpChargingStationsRequest extends HttpDatabaseRequest {
ErrorType?: string;
}
+export interface HttpChargingStationParamsUpdateRequest {
+ id: string;
+ chargingStationURL: string;
+ maximumPower: number;
+ private: boolean;
+ siteAreaID: string;
+ coordinates: number[];
+ connectors: {
+ connectorId: number;
+ type: ConnectorType;
+ power: number;
+ amperage: number;
+ voltage: number;
+ currentType: ConnectorCurrentType;
+ numberOfConnectedPhase: number;
+ }[];
+}
+
export interface HttpChargingStationRequest {
ChargeBoxID: string;
}

New template structure handling for Charging Stations