Optimized Charging Station
MODIFY
package.json
package.json
"autocannon": "autocannon",
"mochatest": "cross-env TS_NODE_FILES=true mocha test/**/*Test.ts",
"mochatest:parallel": "cross-env TS_NODE_FILES=true mocha-parallel-tests test/**/*Test.ts",
- "mochatest:charger": "cross-env TS_NODE_FILES=true mocha test/**/OCPP*Test.ts",
+ "mochatest:chargingStation": "cross-env TS_NODE_FILES=true mocha test/**/OCPP*Test.ts",
"mochatest:ocpi": "cross-env TS_NODE_FILES=true mocha test/**/OCPI*Test.ts",
"mochatest:tenant": "cross-env TS_NODE_FILES=true mocha test/**/*TenantTest.ts",
"mochatest:org": "cross-env TS_NODE_FILES=true mocha test/**/*OrgTest.ts",

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -242,8 +242,7 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.UPDATE,
- entity: Entity.CHARGING_STATION,
+ action: Action.UPDATE, entity: Entity.CHARGING_STATION,
module: MODULE_NAME, method: 'handleChargingStationLimitPower',
value: chargingStation.id
});
@@ -356,12 +355,16 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.LIST,
- entity: Entity.CHARGING_PROFILES,
- module: MODULE_NAME,
- method: 'handleGetChargingProfiles'
+ action: Action.LIST, entity: Entity.CHARGING_PROFILES,
+ module: MODULE_NAME, method: 'handleGetChargingProfiles'
});
}
+ // Profiles of the charging station?
+ let profilesProject: string[] = [ 'profile.chargingProfileKind', 'profile.chargingProfilePurpose', 'profile.stackLevel' ];
+ if (filteredRequest.ChargeBoxID) {
+ // Enhanced the projection
+ profilesProject = ['profile'];
+ }
// Get the profiles
const chargingProfiles = await ChargingStationStorage.getChargingProfiles(req.user.tenantID,
{ search: filteredRequest.Search,
@@ -370,9 +373,13 @@ export default class ChargingStationService {
withChargingStation: filteredRequest.WithChargingStation,
withSiteArea: true,
siteIDs: Authorizations.getAuthorizedSiteIDs(req.user, filteredRequest.SiteID ? filteredRequest.SiteID.split('|') : null), },
- { limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort, onlyRecordCount: filteredRequest.OnlyRecordCount });
+ { limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort, onlyRecordCount: filteredRequest.OnlyRecordCount },
+ [
+ 'id', 'chargingStationID', 'chargePointID', 'connectorID', 'chargingStation.id',
+ 'chargingStation.siteArea.id', 'chargingStation.siteArea.name', 'chargingStation.siteArea.maximumPower',
+ ...profilesProject
+ ]);
// Build the result
- ChargingStationSecurity.filterChargingProfilesResponse(chargingProfiles, req.user);
res.json(chargingProfiles);
next();
}
@@ -393,10 +400,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.UPDATE,
- entity: Entity.SITE_AREA,
- module: MODULE_NAME,
- method: 'handleTriggerSmartCharging',
+ action: Action.UPDATE, entity: Entity.SITE_AREA,
+ module: MODULE_NAME, method: 'handleTriggerSmartCharging',
value: filteredRequest.siteAreaID
});
}
@@ -471,10 +476,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.UPDATE,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleUpdateChargingProfile',
+ action: Action.UPDATE, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleUpdateChargingProfile',
value: chargingStation.id
});
}
@@ -530,8 +533,7 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.UPDATE,
- entity: Entity.CHARGING_STATION,
+ action: Action.UPDATE, entity: Entity.CHARGING_STATION,
module: MODULE_NAME, method: 'handleDeleteChargingProfile',
value: chargingStation.id
});
@@ -570,10 +572,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.READ,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleGetChargingStationOcppParameters',
+ action: Action.READ, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleGetChargingStationOcppParameters',
value: chargingStation.id
});
}
@@ -593,10 +593,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.READ,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleRequestChargingStationOcppParameters',
+ action: Action.READ, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleRequestChargingStationOcppParameters',
value: filteredRequest.chargeBoxID
});
}
@@ -645,10 +643,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.DELETE,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleDeleteChargingStation',
+ action: Action.DELETE, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleDeleteChargingStation',
value: chargingStationID
});
}
@@ -719,15 +715,22 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.READ,
- entity: Entity.CHARGING_STATION,
- module: MODULE_NAME,
- method: 'handleGetChargingStation',
+ action: Action.READ, entity: Entity.CHARGING_STATION,
+ module: MODULE_NAME, method: 'handleGetChargingStation',
value: filteredRequest.ID
});
}
// Query charging station
- const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.ID);
+ const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, filteredRequest.ID, {},
+ [
+ 'id', 'inactive', 'public', 'chargingStationURL', 'issuer', 'maximumPower', 'excludeFromSmartCharging', 'lastReboot',
+ 'siteAreaID', 'siteArea.id', 'siteArea.name', 'siteArea.smartCharging', 'siteArea.siteID',
+ 'siteArea.site.id', 'siteArea.site.name', 'voltage', 'coordinates', 'forceInactive',
+ 'capabilities', 'endpoint', 'chargePointVendor', 'chargePointModel', 'ocppVersion', 'ocppProtocol', 'lastHeartBeat',
+ 'firmwareVersion', 'currentIPAddress', 'ocppStandardParameters', 'ocppVendorParameters', 'connectors', 'chargePoints',
+ 'createdOn', 'chargeBoxSerialNumber', 'chargePointSerialNumber', 'powerLimitUnit'
+ ]
+ );
UtilsService.assertObjectExists(action, chargingStation, `Charging Station '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleGetChargingStation', req.user);
// Deleted?
@@ -741,10 +744,7 @@ export default class ChargingStationService {
user: req.user
});
}
- res.json(
- // Filter
- ChargingStationSecurity.filterChargingStationResponse(chargingStation, req.user)
- );
+ res.json(chargingStation);
next();
}
@@ -804,10 +804,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.LIST,
- entity: Entity.CHARGING_STATIONS,
- module: MODULE_NAME,
- method: 'handleGetChargingStations'
+ action: Action.LIST, entity: Entity.CHARGING_STATIONS,
+ module: MODULE_NAME, method: 'handleGetChargingStations'
});
}
// Filter
@@ -841,14 +839,12 @@ export default class ChargingStationService {
skip: filteredRequest.Skip,
sort: filteredRequest.Sort,
onlyRecordCount: filteredRequest.OnlyRecordCount
- }
+ },
+ [
+ 'id', 'inactive', 'connectorsStatus', 'connectorsConsumption', 'public', 'errorCodeDetails', 'errorCode', 'lastHeartBeat',
+ 'connectors.connectorId', 'connectors.status', 'connectors.type', 'connectors.power', 'connectors.errorCode',
+ ]
);
- // Build the result
- ChargingStationSecurity.filterChargingStationsResponse(chargingStations, req.user);
- // Limit to 100
- if (chargingStations.result.length > 100) {
- chargingStations.result.length = 100;
- }
// Return
res.json(chargingStations);
next();
@@ -860,10 +856,8 @@ export default class ChargingStationService {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
user: req.user,
- action: Action.LIST,
- entity: Entity.CHARGING_STATIONS,
- module: MODULE_NAME,
- method: 'handleGetStatusNotifications'
+ action: Action.LIST, entity: Entity.CHARGING_STATIONS,
+ module: MODULE_NAME, method: 'handleGetStatusNotifications'
});
}
// Filter
@@ -871,8 +865,6 @@ export default class ChargingStationService {
// Get all Status Notifications
const statusNotifications = await OCPPStorage.getStatusNotifications(req.user.tenantID, {},
{ limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort });
- // Set
- statusNotifications.result = ChargingStationSecurity.filterStatusNotificationsResponse(statusNotifications.result, req.user);
// Return
res.json(statusNotifications);
next();
@@ -883,11 +875,9 @@ export default class ChargingStationService {
if (!Authorizations.canListChargingStations(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.ERROR,
- user: req.user,
- action: Action.LIST,
+ user: req.user, action: Action.LIST,
entity: Entity.CHARGING_STATIONS,
- module: MODULE_NAME,
- method: 'handleGetBootNotifications'
+ module: MODULE_NAME, method: 'handleGetBootNotifications'
});
}
// Filter
@@ -895,8 +885,6 @@ export default class ChargingStationService {
// Get all Status Notifications
const bootNotifications = await OCPPStorage.getBootNotifications(req.user.tenantID, {},
{ limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort });
- // Set
- bootNotifications.result = ChargingStationSecurity.filterBootNotificationsResponse(bootNotifications.result, req.user);
// Return
res.json(bootNotifications);
next();
@@ -1193,6 +1181,11 @@ export default class ChargingStationService {
}
// Filter
const filteredRequest = ChargingStationSecurity.filterChargingStationsRequest(req.query);
+ // Check Users
+ let userProject: string[] = [];
+ if (Authorizations.canListUsers(req.user)) {
+ userProject = [ 'connectors.user.id', 'connectors.user.name', 'connectors.user.firstName', 'connectors.user.email' ];
+ }
// Get Charging Stations
const chargingStations = await ChargingStationStorage.getChargingStations(req.user.tenantID,
{
@@ -1213,10 +1206,17 @@ export default class ChargingStationService {
skip: filteredRequest.Skip,
sort: filteredRequest.Sort,
onlyRecordCount: filteredRequest.OnlyRecordCount
- }
+ },
+ [
+ 'id', 'inactive', 'connectorsStatus', 'connectorsConsumption', 'public', 'firmwareVersion', 'chargePointVendor', 'chargePointModel',
+ 'ocppVersion', 'ocppProtocol', 'lastHeartBeat', 'firmwareUpdateStatus', 'coordinates', 'issuer', 'voltage',
+ 'siteAreaID', 'siteArea.id', 'siteArea.name', 'siteArea.siteID', 'siteArea.site.name',
+ 'connectors.connectorId', 'connectors.status', 'connectors.type', 'connectors.power', 'connectors.errorCode',
+ 'connectors.currentTotalConsumptionWh', 'connectors.currentInstantWatts', 'connectors.currentStateOfCharge',
+ 'connectors.currentTransactionID', 'connectors.currentTotalInactivitySecs', 'connectors.currentTagID',
+ ...userProject
+ ]
);
- // Filter
- ChargingStationSecurity.filterChargingStationsResponse(chargingStations, req.user);
return chargingStations;
}

MODIFY
src/server/rest/v1/service/RegistrationTokenService.ts
src/server/rest/v1/service/RegistrationTokenService.ts
@@ -73,7 +73,7 @@ export default class RegistrationTokenService {
registrationToken.ocpp16SOAPUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_16, OCPPProtocol.SOAP, registrationToken.id);
registrationToken.ocpp16JSONUrl = Utils.buildOCPPServerURL(req.user.tenantID, OCPPVersion.VERSION_16, OCPPProtocol.JSON, registrationToken.id);
// Ok
- res.json(Constants.REST_RESPONSE_SUCCESS);
+ res.json(Object.assign({ id: registrationToken.id }, Constants.REST_RESPONSE_SUCCESS));
next();
}
@@ -215,7 +215,7 @@ export default class RegistrationTokenService {
// Get the tokens
const registrationTokens = await RegistrationTokenStorage.getRegistrationTokens(req.user.tenantID,
{
- siteAreaID: filteredRequest.siteAreaID,
+ siteAreaID: filteredRequest.SiteAreaID,
siteIDs: Authorizations.getAuthorizedSiteAdminIDs(req.user, null),
},
{
@@ -225,7 +225,8 @@ export default class RegistrationTokenService {
onlyRecordCount: filteredRequest.OnlyRecordCount
},
[
- 'id', 'status', 'description', 'createdOn', 'lastChangedOn', 'expirationDate', 'revocationDate', 'siteAreaID', 'siteArea.name',
+ 'id', 'status', 'description', 'createdOn', 'lastChangedOn', 'expirationDate', 'revocationDate',
+ 'siteAreaID', 'siteArea.name',
...userProject
]
);

MODIFY
src/server/rest/v1/service/security/ChargingStationSecurity.ts
src/server/rest/v1/service/security/ChargingStationSecurity.ts
-import { ChargePointStatus, OCPPBootNotificationRequestExtended, OCPPStatusNotificationRequestExtended } from '../../../../../types/ocpp/OCPPServer';
import { ChargingProfile, ChargingSchedule, ChargingSchedulePeriod, Profile } from '../../../../../types/ChargingProfile';
-import ChargingStation, { Command } from '../../../../../types/ChargingStation';
import { HttpChargingProfilesRequest, HttpChargingStationCommandRequest, HttpChargingStationGetFirmwareRequest, HttpChargingStationLimitPowerRequest, HttpChargingStationOcppParametersRequest, HttpChargingStationParamsUpdateRequest, HttpChargingStationRequest, HttpChargingStationSetMaxIntensitySocketRequest, HttpChargingStationsRequest, HttpIsAuthorizedRequest, HttpTriggerSmartChargingRequest } from '../../../../../types/requests/HttpChargingStationRequest';
+import { OCPPBootNotificationRequestExtended, OCPPStatusNotificationRequestExtended } from '../../../../../types/ocpp/OCPPServer';
import Authorizations from '../../../../../authorization/Authorizations';
-import { ChargingStationInError } from '../../../../../types/InError';
+import { Command } from '../../../../../types/ChargingStation';
import { DataResult } from '../../../../../types/DataResult';
import HttpByIDRequest from '../../../../../types/requests/HttpByIDRequest';
import HttpDatabaseRequest from '../../../../../types/requests/HttpDatabaseRequest';
-import SiteAreaSecurity from './SiteAreaSecurity';
-import TenantComponents from '../../../../../types/TenantComponents';
-import UserSecurity from './UserSecurity';
import UserToken from '../../../../../types/UserToken';
import Utils from '../../../../../utils/Utils';
import UtilsSecurity from './UtilsSecurity';
@@ -27,249 +23,6 @@ export default class ChargingStationSecurity {
};
}
- public static filterChargingStationResponse(chargingStation: ChargingStation, loggedUser: UserToken): ChargingStation | ChargingStationInError {
- let filteredChargingStation: ChargingStation;
- if (!chargingStation) {
- return null;
- }
- const siteID = chargingStation.siteArea ? chargingStation.siteArea.siteID : null;
- if (Utils.isComponentActiveFromToken(loggedUser, TenantComponents.ORGANIZATION) &&
- !Authorizations.canReadSiteArea(loggedUser, siteID)) {
- return null;
- }
- // Check connectors
- Utils.checkAndUpdateConnectorsStatus(chargingStation);
- // Check Auth
- if (Authorizations.canReadChargingStation(loggedUser)) {
- filteredChargingStation = {} as ChargingStation;
- if (Authorizations.canUpdateChargingStation(loggedUser, siteID)) {
- filteredChargingStation.capabilities = chargingStation.capabilities;
- filteredChargingStation.firmwareUpdateStatus = chargingStation.firmwareUpdateStatus;
- filteredChargingStation.firmwareVersion = chargingStation.firmwareVersion;
- filteredChargingStation.ocppProtocol = chargingStation.ocppProtocol;
- filteredChargingStation.ocppVersion = chargingStation.ocppVersion;
- filteredChargingStation.chargeBoxSerialNumber = chargingStation.chargeBoxSerialNumber;
- filteredChargingStation.chargePointSerialNumber = chargingStation.chargePointSerialNumber;
- filteredChargingStation.ocppProtocol = chargingStation.ocppProtocol;
- filteredChargingStation.ocppVersion = chargingStation.ocppVersion;
- filteredChargingStation.chargingStationURL = chargingStation.chargingStationURL;
- filteredChargingStation.currentIPAddress = chargingStation.currentIPAddress;
- filteredChargingStation.endpoint = chargingStation.endpoint;
- filteredChargingStation.ocppStandardParameters = chargingStation.ocppStandardParameters;
- filteredChargingStation.ocppVendorParameters = chargingStation.ocppVendorParameters;
- filteredChargingStation.voltage = chargingStation.voltage;
- filteredChargingStation['errorCode'] = chargingStation['errorCode'];
- }
- filteredChargingStation.id = chargingStation.id;
- filteredChargingStation.inactive = chargingStation.inactive;
- filteredChargingStation.powerLimitUnit = chargingStation.powerLimitUnit;
- filteredChargingStation.lastReboot = chargingStation.lastReboot;
- filteredChargingStation.issuer = chargingStation.issuer;
- filteredChargingStation.lastHeartBeat = chargingStation.lastHeartBeat;
- filteredChargingStation.maximumPower = chargingStation.maximumPower;
- filteredChargingStation.chargePointVendor = chargingStation.chargePointVendor;
- filteredChargingStation.chargePointModel = chargingStation.chargePointModel;
- filteredChargingStation.public = chargingStation.public;
- filteredChargingStation.excludeFromSmartCharging = chargingStation.excludeFromSmartCharging;
- filteredChargingStation.forceInactive = chargingStation.forceInactive;
- filteredChargingStation.siteAreaID = chargingStation.siteAreaID;
- filteredChargingStation.coordinates = chargingStation.coordinates;
- if (chargingStation.ocpiData) {
- filteredChargingStation.ocpiData = chargingStation.ocpiData;
- }
- if (Utils.objectHasProperty(chargingStation, 'distanceMeters')) {
- filteredChargingStation.distanceMeters = chargingStation.distanceMeters;
- }
- filteredChargingStation.connectors = chargingStation.connectors.map((connector) => {
- if (!connector) {
- return connector;
- }
- return {
- id: connector.id,
- connectorId: connector.connectorId,
- status: (filteredChargingStation.inactive ? ChargePointStatus.UNAVAILABLE : connector.status),
- currentInstantWatts: (filteredChargingStation.inactive ? 0 : connector.currentInstantWatts),
- currentStateOfCharge: (filteredChargingStation.inactive ? 0 : connector.currentStateOfCharge),
- currentTotalConsumptionWh: (filteredChargingStation.inactive ? 0 : connector.currentTotalConsumptionWh),
- currentTotalInactivitySecs: (filteredChargingStation.inactive ? 0 : connector.currentTotalInactivitySecs),
- currentInactivityStatus: connector.currentInactivityStatus,
- currentTransactionID: connector.currentTransactionID,
- currentTransactionDate: connector.currentTransactionDate,
- currentTagID: connector.currentTagID,
- amperageLimit: connector.amperageLimit,
- errorCode: connector.errorCode,
- type: connector.type,
- power: connector.power,
- numberOfConnectedPhase: connector.numberOfConnectedPhase,
- currentType: connector.currentType,
- voltage: connector.voltage,
- amperage: connector.amperage,
- user: connector.user,
- phaseAssignmentToGrid: connector.phaseAssignmentToGrid
- };
- });
- if (chargingStation.chargePoints) {
- filteredChargingStation.chargePoints = chargingStation.chargePoints.map((chargePoint) => {
- if (!chargePoint) {
- return chargePoint;
- }
- return {
- chargePointID: chargePoint.chargePointID,
- currentType: chargePoint.currentType,
- voltage: chargePoint.voltage,
- amperage: chargePoint.amperage,
- numberOfConnectedPhase: chargePoint.numberOfConnectedPhase,
- cannotChargeInParallel: chargePoint.cannotChargeInParallel,
- sharePowerToAllConnectors: chargePoint.sharePowerToAllConnectors,
- excludeFromPowerLimitation: chargePoint.excludeFromPowerLimitation,
- ocppParamForPowerLimitation: chargePoint.ocppParamForPowerLimitation,
- power: chargePoint.power,
- efficiency: chargePoint.efficiency,
- connectorIDs: chargePoint.connectorIDs
- };
- });
- }
- }
- if (chargingStation.siteArea) {
- filteredChargingStation.siteArea = chargingStation.siteArea;
- }
- // Sort Connector
- filteredChargingStation.connectors.sort(
- (connector1, connector2) => connector1 && connector2 ? connector1.connectorId - connector2.connectorId : 0);
- // Created By / Last Changed By
- UtilsSecurity.filterCreatedAndLastChanged(
- filteredChargingStation, chargingStation, loggedUser);
- return filteredChargingStation;
- }
-
- public static filterMinimalChargingStationResponse(chargingStation: ChargingStation, loggedUser: UserToken): ChargingStation | ChargingStationInError {
- let filteredChargingStation: ChargingStation;
- if (!chargingStation) {
- return null;
- }
- const siteID = chargingStation.siteArea ? chargingStation.siteArea.siteID : null;
- if (Utils.isComponentActiveFromToken(loggedUser, TenantComponents.ORGANIZATION) &&
- !Authorizations.canReadSiteArea(loggedUser, siteID)) {
- return null;
- }
- // Check connectors
- Utils.checkAndUpdateConnectorsStatus(chargingStation);
- // Check Auth
- if (Authorizations.canReadChargingStation(loggedUser)) {
- filteredChargingStation = {} as ChargingStation;
- filteredChargingStation.id = chargingStation.id;
- }
- if (chargingStation.siteArea) {
- filteredChargingStation.siteArea = chargingStation.siteArea;
- }
- return filteredChargingStation;
- }
-
- public static filterChargingStationsResponse(chargingStations: DataResult<ChargingStation>,
- loggedUser: UserToken) {
- const filteredChargingStations: ChargingStation[] | ChargingStationInError[] = [];
- // Check
- if (!chargingStations.result) {
- return null;
- }
- if (!Authorizations.canListChargingStations(loggedUser)) {
- return null;
- }
- for (const chargingStation of chargingStations.result) {
- // Filter
- const filteredChargingStation = ChargingStationSecurity.filterChargingStationResponse(
- chargingStation, loggedUser);
- if (filteredChargingStation) {
- filteredChargingStations.push(filteredChargingStation);
- }
- }
- chargingStations.result = filteredChargingStations;
- }
-
- public static filterChargingProfilesResponse(chargingProfiles: DataResult<ChargingProfile>, loggedUser: UserToken): void {
- const filteredChargingProfiles: ChargingProfile[] = [];
- // Check
- if (!chargingProfiles.result) {
- return null;
- }
- if (!Authorizations.canListChargingProfiles(loggedUser)) {
- return null;
- }
- for (const chargingProfile of chargingProfiles.result) {
- const filteredChargingProfile = this.filterChargingProfileResponse(chargingProfile, loggedUser);
- if (filteredChargingProfile && Object.entries(filteredChargingProfile).length !== 0) {
- filteredChargingProfiles.push(filteredChargingProfile);
- }
- }
- chargingProfiles.count = filteredChargingProfiles.length;
- chargingProfiles.result = filteredChargingProfiles;
- }
-
- static filterChargingProfileResponse(chargingProfile: ChargingProfile, loggedUser: UserToken): ChargingProfile {
- const filteredChargingProfile = {} as ChargingProfile;
- if (!chargingProfile) {
- return null;
- }
- // Check auth
- if (Authorizations.canReadChargingProfile(loggedUser, chargingProfile.chargingStation.siteArea ? chargingProfile.chargingStation.siteArea.siteID : null)) {
- filteredChargingProfile.id = chargingProfile.id;
- filteredChargingProfile.chargingStationID = chargingProfile.chargingStationID;
- filteredChargingProfile.chargePointID = chargingProfile.chargePointID;
- filteredChargingProfile.connectorID = chargingProfile.connectorID;
- filteredChargingProfile.chargingStation = chargingProfile.chargingStation;
- if (filteredChargingProfile.chargingStation) {
- filteredChargingProfile.chargingStation =
- ChargingStationSecurity.filterMinimalChargingStationResponse(chargingProfile.chargingStation, loggedUser);
- }
- filteredChargingProfile.profile = {} as Profile;
- filteredChargingProfile.profile.chargingProfileId = chargingProfile.profile.chargingProfileId;
- filteredChargingProfile.profile.transactionId = chargingProfile.profile.transactionId;
- filteredChargingProfile.profile.stackLevel = chargingProfile.profile.stackLevel;
- filteredChargingProfile.profile.chargingProfilePurpose = chargingProfile.profile.chargingProfilePurpose;
- filteredChargingProfile.profile.chargingProfileKind = chargingProfile.profile.chargingProfileKind;
- filteredChargingProfile.profile.recurrencyKind = chargingProfile.profile.recurrencyKind;
- filteredChargingProfile.profile.validFrom = chargingProfile.profile.validFrom;
- filteredChargingProfile.profile.validTo = chargingProfile.profile.validTo;
- if (Utils.objectHasProperty(chargingProfile.profile, 'chargingSchedule')) {
- const chargingSchedule = {} as ChargingSchedule;
- filteredChargingProfile.profile.chargingSchedule = chargingSchedule;
- chargingSchedule.duration = chargingProfile.profile.chargingSchedule.duration;
- chargingSchedule.startSchedule = chargingProfile.profile.chargingSchedule.startSchedule;
- chargingSchedule.chargingRateUnit = chargingProfile.profile.chargingSchedule.chargingRateUnit;
- chargingSchedule.minChargeRate = chargingProfile.profile.chargingSchedule.minChargeRate;
- filteredChargingProfile.profile.chargingSchedule.chargingSchedulePeriod = [];
- // Check
- for (const chargingSchedulePeriod of chargingProfile.profile.chargingSchedule.chargingSchedulePeriod) {
- const chargingSchedulePeriodNew: ChargingSchedulePeriod = {} as ChargingSchedulePeriod;
- chargingSchedulePeriodNew.startPeriod = sanitize(chargingSchedulePeriod.startPeriod);
- chargingSchedulePeriodNew.limit = sanitize(chargingSchedulePeriod.limit);
- chargingSchedulePeriodNew.numberPhases = sanitize(chargingSchedulePeriod.numberPhases);
- // Add
- filteredChargingProfile.profile.chargingSchedule.chargingSchedulePeriod.push(chargingSchedulePeriodNew);
- }
- }
- }
- return filteredChargingProfile;
- }
-
- public static filterStatusNotificationsResponse(statusNotifications: OCPPStatusNotificationRequestExtended[],
- loggedUser: UserToken): OCPPStatusNotificationRequestExtended[] {
- // Check
- if (!Authorizations.canListChargingStations(loggedUser)) {
- return [];
- }
- return statusNotifications;
- }
-
- public static filterBootNotificationsResponse(bootNotifications: OCPPBootNotificationRequestExtended[],
- loggedUser: UserToken): OCPPBootNotificationRequestExtended[] {
- // Check
- if (!Authorizations.canListChargingStations(loggedUser)) {
- return [];
- }
- return bootNotifications;
- }
-
public static filterChargingStationOcppParametersRequest(request: any): HttpChargingStationRequest {
return { ChargeBoxID: sanitize(request.ChargeBoxID) };
}

MODIFY
src/server/rest/v1/service/security/RegistrationTokenSecurity.ts
src/server/rest/v1/service/security/RegistrationTokenSecurity.ts
@@ -35,7 +35,7 @@ export default class RegistrationTokenSecurity {
static filterRegistrationTokensRequest(request: any): HttpRegistrationTokensRequest {
const filteredRequest = {
- siteAreaID: sanitize(request.siteAreaID)
+ SiteAreaID: sanitize(request.SiteAreaID)
};
UtilsSecurity.filterSkipAndLimit(request, filteredRequest);

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -131,11 +131,11 @@ export default class ChargingStationStorage {
}
public static async getChargingStation(tenantID: string, id: string = Constants.UNKNOWN_STRING_ID,
- params: { includeDeleted?: boolean } = {}): Promise<ChargingStation> {
+ params: { includeDeleted?: boolean } = {}, projectFields?: string[]): Promise<ChargingStation> {
const chargingStationsMDB = await ChargingStationStorage.getChargingStations(tenantID, {
chargingStationIDs: [id],
withSite: true, ...params
- }, Constants.DB_PARAMS_SINGLE_RECORD);
+ }, Constants.DB_PARAMS_SINGLE_RECORD, projectFields);
return chargingStationsMDB.count === 1 ? chargingStationsMDB.result[0] : null;
}
@@ -355,7 +355,7 @@ export default class ChargingStationStorage {
public static async getChargingStationsInError(tenantID: string,
params: { search?: string; siteIDs?: string[]; siteAreaIDs: string[]; errorType?: string[] },
- dbParams: DbParams): Promise<DataResult<ChargingStationInError>> {
+ dbParams: DbParams, projectFields?: string[]): Promise<DataResult<ChargingStationInError>> {
// Debug
const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'getChargingStations');
// Check Tenant
@@ -456,6 +456,8 @@ export default class ChargingStationStorage {
});
// Change ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
+ // Project
+ DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
const chargingStationsMDB = await global.database.getCollection<ChargingStation>(tenantID, 'chargingstations')
.aggregate(aggregation, { collation: { locale: Constants.DEFAULT_LOCALE, strength: 2 } })
@@ -682,7 +684,8 @@ export default class ChargingStationStorage {
public static async getChargingProfiles(tenantID: string,
params: {
search?: string; chargingStationIDs?: string[]; connectorID?: number; chargingProfileID?: string;
- profilePurposeType?: ChargingProfilePurposeType; transactionId?: number; withChargingStation?: boolean; withSiteArea?: boolean; siteIDs?: string[];
+ profilePurposeType?: ChargingProfilePurposeType; transactionId?: number; withChargingStation?: boolean;
+ withSiteArea?: boolean; siteIDs?: string[];
} = {},
dbParams: DbParams, projectFields?: string[]): Promise<DataResult<ChargingProfile>> {
// Debug

MODIFY
src/storage/mongodb/TenantStorage.ts
src/storage/mongodb/TenantStorage.ts
@@ -269,6 +269,8 @@ export default class TenantStorage {
const uniqueTimerID = Logging.traceStart(Constants.DEFAULT_TENANT, MODULE_NAME, 'deleteTenantDB');
// Delete
await global.database.deleteTenantDatabase(id);
+ // Update cache
+ TenantStorage.clearCache(id);
// Debug
Logging.traceEnd(Constants.DEFAULT_TENANT, MODULE_NAME, 'deleteTenantDB', uniqueTimerID, { id });
}

MODIFY
src/types/requests/HttpRegistrationToken.ts
src/types/requests/HttpRegistrationToken.ts
@@ -2,7 +2,7 @@ import HttpDatabaseRequest from './HttpDatabaseRequest';
import RegistrationToken from '../RegistrationToken';
export interface HttpRegistrationTokensRequest extends HttpDatabaseRequest {
- siteAreaID: string;
+ SiteAreaID: string;
}
export interface HttpRegistrationTokensResponse {

MODIFY
src/utils/Utils.ts
src/utils/Utils.ts
@@ -337,7 +337,6 @@ export default class Utils {
continue;
}
// Check connectors
- Utils.checkAndUpdateConnectorsStatus(chargingStation);
connectorStats.totalChargers++;
// Handle Connectors
if (!chargingStation.connectors) {
@@ -395,47 +394,6 @@ export default class Utils {
return config.heartbeatIntervalSecs * 3;
}
- public static checkAndUpdateConnectorsStatus(chargingStation: ChargingStation): void {
- // Cannot charge in //
- if (chargingStation.chargePoints) {
- for (const chargePoint of chargingStation.chargePoints) {
- if (chargePoint.cannotChargeInParallel) {
- let lockAllConnectors = false;
- // Check
- for (const connectorID of chargePoint.connectorIDs) {
- const connector = Utils.getConnectorFromID(chargingStation, connectorID);
- if (!connector) {
- continue;
- }
- if (connector.status !== ChargePointStatus.AVAILABLE) {
- lockAllConnectors = true;
- break;
- }
- }
- // Lock?
- if (lockAllConnectors) {
- for (const connectorID of chargePoint.connectorIDs) {
- const connector = Utils.getConnectorFromID(chargingStation, connectorID);
- if (!connector) {
- continue;
- }
- if (connector.status === ChargePointStatus.AVAILABLE) {
- // Check OCPP Version
- if (chargingStation.ocppVersion === OCPPVersion.VERSION_15) {
- // Set OCPP 1.5 Occupied
- connector.status = ChargePointStatus.OCCUPIED;
- } else {
- // Set OCPP 1.6 Unavailable
- connector.status = ChargePointStatus.UNAVAILABLE;
- }
- }
- }
- }
- }
- }
- }
- }
-
/**
* Map user locale (en_US, fr_FR...) to language (en, fr...)
* @param locale

MODIFY
test/api/AuthenticationTest.ts
test/api/AuthenticationTest.ts
@@ -89,7 +89,7 @@ describe('Authentication Service (tenant utall)', function() {
expect(user.eulaAcceptedOn).to.not.be.null;
expect(user.eulaAcceptedVersion).to.not.be.null;
expect(user.eulaAcceptedVersion).to.be.above(0);
- expect(user.createdBy).to.be.undefined;
+ expect(user.createdBy).to.be.null;
expect(user.createdOn).to.not.be.null;
});

MODIFY
test/api/OCPPCommonTests.ts
test/api/OCPPCommonTests.ts
@@ -1118,7 +1118,7 @@ export default class OCPPCommonTests {
'tagID': this.transactionStartUser.tags[0].id,
'meterStart': meterStart,
'userID': this.transactionStartUser.id,
- 'siteAreaID': this.chargingStationContext.getChargingStation().siteAreaID,
+ 'siteAreaID': this.chargingStationContext.getChargingStation().siteAreaID ? this.chargingStationContext.getChargingStation().siteAreaID : null,
'siteID': this.chargingStationContext.getChargingStation().siteArea ? this.chargingStationContext.getChargingStation().siteArea.siteID : null,
'user': {
'id': this.transactionStartUser.id,

MODIFY
test/api/client/utils/BaseApi.ts
test/api/client/utils/BaseApi.ts
@@ -26,6 +26,16 @@ export default class BaseApi {
t0 = performance.now();
// Execute with Axios
httpResponse = await axiosInstance(httpRequest);
+ // Debug
+ // console.log('HTTP Request ====================================');
+ // console.log(httpRequest.baseURL);
+ // console.log(httpRequest.url);
+ // console.log(httpRequest.method);
+ // console.log(httpRequest.data);
+ // console.log(httpResponse.status);
+ // console.log(httpResponse.statusText);
+ // console.log(httpResponse.data);
+ // console.log('====================================');
t1 = performance.now();
} catch (error) {
// Handle errors

MODIFY
test/api/context/ContextBuilder.ts
test/api/context/ContextBuilder.ts
@@ -113,6 +113,7 @@ export default class ContextBuilder {
}
}
// Check if tenant exists
+ TenantStorage.clearCache();
const existingTenant = await TenantStorage.getTenant(tenantContextDef.id);
if (existingTenant) {
console.log(`Tenant ${tenantContextDef.id} already exist with name ${existingTenant.name}. Please run a destroy context`);

MODIFY
test/api/context/TenantContext.ts
test/api/context/TenantContext.ts
@@ -533,7 +533,7 @@ export default class TenantContext {
}
async getRegistrationToken(siteAreaID: string): Promise<RegistrationToken> {
- const registrationTokenResponse = await this.centralAdminServerService.registrationApi.readAll({ siteAreaID: siteAreaID });
+ const registrationTokenResponse = await this.centralAdminServerService.registrationApi.readAll({ SiteAreaID: siteAreaID });
expect(registrationTokenResponse.status).eq(200);
expect(registrationTokenResponse.data).not.null;
expect(registrationTokenResponse.data.id).not.null;

MODIFY
test/api/ocpp/json/OCPPJsonService16.ts
test/api/ocpp/json/OCPPJsonService16.ts
@@ -8,7 +8,7 @@ import config from '../../../config';
import { performance } from 'perf_hooks';
export default class OCPPJsonService16 extends OCPPService {
- private wsSessions: any;
+ private wsSessions: Map<string, any>;
private requestHandler: any;
public constructor(serverUrl, requestHandler) {
@@ -80,7 +80,6 @@ export default class OCPPJsonService16 extends OCPPService {
public async handleRequest(chargeBoxIdentity, messageId, commandName, commandPayload) {
let result = {};
-
if (this.requestHandler && typeof this.requestHandler['handle' + commandName] === 'function') {
result = await this.requestHandler['handle' + commandName](commandPayload);
}
@@ -146,6 +145,10 @@ export default class OCPPJsonService16 extends OCPPService {
}
private async send(chargeBoxIdentity: string, message: any): Promise<any> {
+ // Debug
+ // console.log('OCPP Request ====================================');
+ // console.log({ chargeBoxIdentity, message });
+ // console.log('====================================');
// WS Opened?
if (!this.wsSessions.get(chargeBoxIdentity)) {
// Open WS

Optimized Charging Station