Fixed Charging Profiles
MODIFY
src/assets/server/rest/v1/docs/e-mobility-oas.json
src/assets/server/rest/v1/docs/e-mobility-oas.json
}
}
},
- "/api/chargingstations/smartcharging/checkconnection": {
+ "/api/chargingstations/smartcharging/connection/check": {
"get": {
"security": [
{
}
}
},
- "/api/chargingstations/smartcharging/profiles": {
+ "/api/chargingprofiles": {
"get": {
"security": [
{
"bearerAuth": []
}
],
- "description": "Get Charging Stations profiles",
+ "description": "Get Charging Profiles",
"parameters": [
{
- "$ref": "#/components/parameters/Search"
+ "$ref": "#/components/parameters/ChargingStationID"
},
{
- "in": "query",
- "name": "ChargeBoxID",
- "description": "Charging Station ID",
- "schema": {
- "type": "string"
- }
+ "$ref": "#/components/parameters/ConnectorID"
},
{
- "$ref": "#/components/parameters/connectorID"
+ "$ref": "#/components/parameters/Search"
},
{
"in": "query",
"name": "WithChargingStation",
"description": "With Charging Station attribute",
"schema": {
- "type": "boolean"
+ "type": "boolean",
+ "example": false
}
},
{
"in": "query",
"name": "WithSiteArea",
- "description": "With Site Area",
+ "description": "With Site Area attribute",
"schema": {
- "type": "boolean"
+ "type": "boolean",
+ "example": false
}
},
{
}
],
"tags": [
- "Charging Stations"
+ "Charging Profiles"
],
"responses": {
"200": {
],
"description": "Update a Charging Station profile",
"tags": [
- "Charging Stations"
+ "Charging Profiles"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
- "type": "object",
- "properties": {
- "id": {
- "type": "string"
- },
- "chargingStationID": {
- "type": "string"
- },
- "connectorID": {
- "type": "integer",
- "minimum": 1,
- "example": 1
- },
- "chargePointID": {
- "type": "string"
- },
- "profile": {
"$ref": "#/components/schemas/ChargingProfile"
}
}
}
- }
- }
},
"responses": {
"200": {
}
}
},
- "/api/chargingstations/smartcharging/profiles/{id}": {
+ "/api/chargingprofiles/{id}": {
"delete": {
"security": [
{
"description": "Delete a Charging Station profile",
"parameters": [
{
- "$ref": "#/components/parameters/chargingStationID"
+ "$ref": "#/components/parameters/chargingProfileID"
}
],
"tags": [
- "Charging Stations"
+ "Charging Profiles"
],
"responses": {
"200": {
],
"properties": {
"id": {
- "type": "string"
+ "type": "string",
+ "example": ""
},
"chargingStationID": {
- "type": "string"
+ "type": "string",
+ "example": ""
},
- "chargingStation": {
- "$ref": "#/components/schemas/ChargingStation"
+ "connectorID": {
+ "type": "integer",
+ "example": 0
},
"chargePointID": {
- "type": "number"
- },
- "connectorID": {
- "type": "number"
+ "type": "number",
+ "example": 1
},
"profile": {
"type": "object",
- "required": [
- "chargingProfileId",
- "stackLevel",
- "chargingProfilePurpose",
- "chargingProfileKind",
- "chargingSchedule"
- ],
"properties": {
"chargingProfileId": {
- "type": "number"
+ "type": "number",
+ "description": "Required. Unique identifier for this profile.",
+ "example": 1
},
"transactionId": {
- "type": "number"
+ "type": "number",
+ "description": "Optional. Only valid if ChargingProfilePurpose is set to TxProfile, the transactionId MAY be used to match the profile to a specific transaction."
},
"stackLevel": {
- "type": "number"
+ "type": "number",
+ "description": "Required. Value determining level in hierarchy stack of profiles. Higher values have precedence over lower values. Lowest level is 0.",
+ "example": 3
},
"chargingProfilePurpose": {
"type": "string",
+ "description": "Required. Defines the purpose of the schedule transferred by this message.",
+ "example": "TxDefaultProfile",
"enum": [
"ChargePointMaxProfile",
"TxDefaultProfile",
},
"chargingProfileKind": {
"type": "string",
+ "description": "Required. Indicates the kind of schedule.",
+ "example": "Absolute",
"enum": [
"Absolute",
"Recurring",
},
"recurrencyKind": {
"type": "string",
+ "description": "Optional. Indicates the start point of a recurrence.",
+ "example": "",
"enum": [
"Daily",
"Weekly"
},
"validFrom": {
"type": "string",
+ "description": "Optional. Point in time at which the profile starts to be valid. If absent, the profile is valid as soon as it is received by the Charge Point.",
+ "example": "",
"format": "date-time"
},
"validTo": {
"type": "string",
+ "description": "Optional. Point in time at which the profile stops to be valid. If absent, the profile is valid until it is replaced by another profile.",
+ "example": "",
"format": "date-time"
},
"chargingSchedule": {
"$ref": "#/components/schemas/ChargingSchedule"
}
- }
+ },
+ "required": [
+ "chargingProfileId",
+ "stackLevel",
+ "chargingProfilePurpose",
+ "chargingProfileKind",
+ "chargingSchedule"
+ ]
}
}
},
"ChargingSchedule": {
"type": "object",
- "required": [
- "chargingRateUnit",
- "chargingSchedulePeriod"
- ],
"properties": {
"duration": {
- "type": "number"
+ "type": "number",
+ "description": "Optional. Duration of the charging schedule in seconds. If the duration is left empty, the last period will continue indefinitely or until end of the transaction in case startSchedule is absent."
},
"startSchedule": {
"type": "string",
+ "description": "Optional. Starting point of an absolute schedule. If absent the schedule will be relative to start of charging.",
+ "example": "",
"format": "date-time"
},
"chargingRateUnit": {
- "type": "string"
+ "type": "string",
+ "description": "Required. The unit of measure Limit is expressed in.",
+ "enum": [
+ "A", "W"
+ ],
+ "example": "A"
},
"chargingSchedulePeriod": {
"type": "array",
+ "description": "Required. List of ChargingSchedulePeriod elements defining maximum power or current usage over time. The startSchedule of the first ChargingSchedulePeriod SHALL always be 0.",
"items": {
"type": "object",
- "required": [
- "startPeriod",
- "limit"
- ],
"properties": {
"startPeriod": {
- "type": "number"
+ "type": "number",
+ "description": "Required. Start of the period, in seconds from the start of schedule. The value of StartPeriod also defines the stop time of the previous period.",
+ "example": 0
},
"limit": {
- "type": "number"
+ "type": "number",
+ "description": "Required. Charging rate limit during the schedule period, in the applicable chargingRateUnit, for example in Amperes or Watts. Accepts at most one digit fraction (e.g. 8.1).",
+ "example": 192
},
"numberPhases": {
- "type": "number"
- }
+ "type": "number",
+ "description": "Optional. The number of phases that can be used for charging. If a number of phases is needed, numberPhases=3 will be assumed unless another number is given.",
+ "example": 3
}
+ },
+ "required": [
+ "startPeriod",
+ "limit"
+ ]
}
},
"minChargeRate": {
- "type": "number"
- }
+ "type": "number",
+ "description": "Optional. Minimum charging rate supported by the electric vehicle. The unit of measure is defined by the chargingRateUnit. This parameter is intended to be used by a local smart charging algorithm to optimize the power allocation for in the case a charging process is inefficient at lower charging rates. Accepts at most one digit fraction (e.g. 8.1)"
}
+ },
+ "required": [
+ "chargingRateUnit",
+ "chargingSchedulePeriod"
+ ]
}
},
"parameters": {
"type": "string"
}
},
+ "ConnectorID": {
+ "in": "query",
+ "name": "ConnectorID",
+ "description": "Connector ID",
+ "required": false,
+ "schema": {
+ "type": "number"
+ }
+ },
+ "chargingProfileID": {
+ "in": "path",
+ "name": "id",
+ "description": "Charging Profile ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
"chargingStationID": {
"in": "path",
"name": "id",

MODIFY
src/server/rest/v1/router/api/ChargingStationRouter.ts
src/server/rest/v1/router/api/ChargingStationRouter.ts
@@ -15,11 +15,11 @@ export default class ChargingStationRouter {
public buildRoutes(): express.Router {
this.buildRouteChargingStationsInError();
this.buildRouteChargingStationsExport();
- this.buildRouteChargingStationProfile();
+ this.buildRouteChargingStationGetChargingProfiles();
this.buildRouteChargingStationRequestOCPPParameters();
this.buildRouteChargingStationDownloadFirmware();
- this.buildRouteChargingStationDeleteProfile();
- this.buildRouteChargingStationUpdateProfile();
+ this.buildRouteChargingStationDeleteChargingProfile();
+ this.buildRouteChargingStationUpdateChargingProfiles();
this.buildRouteChargingStationChangeAvailability();
this.buildRouteChargingStationTransactions();
this.buildRouteChargingStations();
@@ -204,19 +204,19 @@ export default class ChargingStationRouter {
});
}
- protected buildRouteChargingStationProfile(): void {
+ protected buildRouteChargingStationGetChargingProfiles(): void {
this.router.get(`/${ServerRoute.REST_CHARGING_PROFILES}`, async (req: Request, res: Response, next: NextFunction) => {
await RouterUtils.handleServerAction(ChargingStationService.handleGetChargingProfiles.bind(this), ServerAction.CHARGING_PROFILES, req, res, next);
});
}
- protected buildRouteChargingStationUpdateProfile(): void {
+ protected buildRouteChargingStationUpdateChargingProfiles(): void {
this.router.put(`/${ServerRoute.REST_CHARGING_PROFILES}`, async (req: Request, res: Response, next: NextFunction) => {
await RouterUtils.handleServerAction(ChargingStationService.handleUpdateChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_UPDATE, req, res, next);
});
}
- protected buildRouteChargingStationDeleteProfile(): void {
+ protected buildRouteChargingStationDeleteChargingProfile(): void {
this.router.delete(`/${ServerRoute.REST_CHARGING_PROFILE}`, async (req: Request, res: Response, next: NextFunction) => {
req.query.ID = req.params.id;
await RouterUtils.handleServerAction(ChargingStationService.handleDeleteChargingProfile.bind(this), ServerAction.CHARGING_PROFILE_DELETE, req, res, next);

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -362,7 +362,7 @@ export default class UtilsService {
source: Constants.CENTRAL_SERVER,
action: ServerAction.CHARGING_PROFILE_UPDATE,
errorCode: HTTPError.GENERAL_ERROR,
- message: 'Charging Profile\'s schedule should not exeed 24 hours',
+ message: 'Charging Profile\'s schedule should not exceed 24 hours',
module: MODULE_NAME, method: 'checkIfChargingProfileIsValid',
user: req.user.id
});

MODIFY
src/server/rest/v1/service/security/ChargingStationSecurity.ts
src/server/rest/v1/service/security/ChargingStationSecurity.ts
@@ -33,8 +33,8 @@ export default class ChargingStationSecurity {
public static filterChargingProfilesRequest(request: any): HttpChargingProfilesRequest {
const filteredRequest: HttpChargingProfilesRequest = {} as HttpChargingProfilesRequest;
filteredRequest.Search = sanitize(request.Search),
- filteredRequest.ChargeBoxID = sanitize(request.ChargeBoxID);
- filteredRequest.ConnectorID = sanitize(request.ConnectorID);
+ filteredRequest.ChargingStationID = sanitize(request.ChargingStationID);
+ filteredRequest.ConnectorID = Utils.convertToInt(sanitize(request.ConnectorID));
filteredRequest.WithChargingStation = UtilsSecurity.filterBoolean(request.WithChargingStation);
filteredRequest.WithSiteArea = UtilsSecurity.filterBoolean(request.WithSiteArea);
filteredRequest.SiteID = sanitize(request.SiteID);

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -770,17 +770,24 @@ export default class ChargingStationStorage {
asField: 'chargingStation', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
// Site Areas
+ if (params.withSiteArea || !Utils.isEmptyArray(params.siteIDs)) {
DatabaseUtils.pushSiteAreaLookupInAggregation({
tenantID, aggregation, localField: 'chargingStation.siteAreaID', foreignField: '_id',
asField: 'chargingStation.siteArea', oneToOneCardinality: true, oneToOneCardinalityNotNull: false
});
- // Check Site ID
+ // Convert
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteArea.siteID');
+ }
+ // Convert
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteAreaID');
+ // TODO: Optimization: add the Site ID to the Charging Profile
+ // Site ID
if (!Utils.isEmptyArray(params.siteIDs)) {
// Build filter
aggregation.push({
$match: {
'chargingStation.siteArea.siteID': {
- $in: params.siteIDs.map((siteID) => Utils.convertToObjectID(siteID))
+ $in: params.siteIDs
}
}
});
@@ -828,9 +835,6 @@ export default class ChargingStationStorage {
aggregation.push({
$limit: dbParams.limit
});
- // Convert
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteAreaID');
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'chargingStation.siteArea.siteID');
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -426,9 +426,10 @@ export enum ServerRoute {
REST_CHARGING_STATIONS_IN_ERROR = 'chargingstations/status/in-error',
REST_CHARGING_STATIONS_EXPORT = 'chargingstations/export',
- REST_CHARGING_STATION_CHECK_SMART_CHARGING_CONNECTION = 'chargingstations/smartcharging/checkconnection',
- REST_CHARGING_PROFILES = 'chargingstations/smartcharging/profiles',
- REST_CHARGING_PROFILE = 'chargingstations/smartcharging/profiles/:id',
+ REST_CHARGING_STATION_CHECK_SMART_CHARGING_CONNECTION = 'chargingstations/smartcharging/connection/check',
+
+ REST_CHARGING_PROFILES = 'chargingprofiles',
+ REST_CHARGING_PROFILE = 'chargingprofiles/:id',
REST_PING = 'ping',

MODIFY
src/types/requests/HttpChargingStationRequest.ts
src/types/requests/HttpChargingStationRequest.ts
@@ -15,7 +15,7 @@ export interface HttpChargingStationLimitPowerRequest {
export interface HttpChargingProfilesRequest extends HttpDatabaseRequest {
Search?: string;
- ChargeBoxID?: string;
+ ChargingStationID?: string;
ConnectorID?: number;
WithChargingStation?: boolean;
WithSiteArea?: boolean;

Fixed Charging Profiles