Skip to content
This repository has been archived by the owner on Jun 12, 2024. It is now read-only.

Commit

Permalink
Add amperage limitation support via vendor specific OCPP key
Browse files Browse the repository at this point in the history
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
  • Loading branch information
Jérôme Benoit committed Mar 18, 2022
1 parent 7dafa10 commit cc6e8ab
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 55 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ But the modifications to test have to be done to the files in the build result d
| autoReconnectMaxRetries | | -1 (unlimited) | integer | connection retries to the OCPP-J server |
| reconnectExponentialDelay | true/false | false | boolean | connection delay retry to the OCPP-J server |
| registrationMaxRetries | | -1 (unlimited) | integer | charging stations boot notification retries |
| amperageLimitationOcppKey | | undefined | string | charging stations OCPP parameter key used to set the amperage limit, per phase for each connector on AC and global for DC |
| amperageLimitationUnit | A/cA/dA/mA | A | string | charging stations amperage limit unit |
| enableStatistics | true/false | true | boolean | enable charging stations statistics |
| mayAuthorizeAtRemoteStart | true/false | true | boolean | always send authorize at remote start transaction when AuthorizeRemoteTxRequests is enabled |
| beginEndMeterValues | true/false | false | boolean | enable Transaction.{Begin,End} MeterValues |
Expand Down
1 change: 0 additions & 1 deletion src/assets/station-templates/abb-atg.station-template.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"authorizationFile": "authorization-tags.json",
"baseName": "CS-ABB",
"nameSuffix": "-Roaming",
"chargePointModel": "MD_TERRA_53",
"chargePointVendor": "ABB",
"firmwareVersion": "4.0.4.22",
Expand Down
6 changes: 1 addition & 5 deletions src/assets/station-templates/evlink.station-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"numberOfConnectors": 1,
"randomConnectors": false,
"voltageOut": 231,
"amperageLimitationOcppKey": "maxintensitysocket",
"Configuration": {
"configurationKey": [
{
Expand Down Expand Up @@ -44,11 +45,6 @@
"key": "WebSocketPingInterval",
"readonly": false,
"value": "60"
},
{
"key": "maxintensitysocket",
"readonly": false,
"value": "32"
}
]
},
Expand Down
7 changes: 2 additions & 5 deletions src/assets/station-templates/keba.station-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"powerUnit": "W",
"numberOfConnectors": 1,
"randomConnectors": false,
"amperageLimitationOcppKey": "MaxAvailableCurrent",
"amperageLimitationUnit": "mA",
"Configuration": {
"configurationKey": [
{
Expand Down Expand Up @@ -39,11 +41,6 @@
"key": "WebSocketPingInterval",
"readonly": false,
"value": "60"
},
{
"key": "MaxAvailableCurrent",
"readonly": false,
"value": "32000"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"numberOfConnectors": 1,
"randomConnectors": false,
"voltageOut": 231,
"amperageLimitationOcppKey": "maxintensitysocket",
"Configuration": {
"configurationKey": [
{
Expand Down Expand Up @@ -43,11 +44,6 @@
"key": "WebSocketPingInterval",
"readonly": false,
"value": "60"
},
{
"key": "maxintensitysocket",
"readonly": false,
"value": "32"
}
]
},
Expand Down
6 changes: 1 addition & 5 deletions src/assets/station-templates/schneider.station-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"numberOfConnectors": 2,
"randomConnectors": false,
"voltageOut": 231,
"amperageLimitationOcppKey": "maxintensitysocket",
"Configuration": {
"configurationKey": [
{
Expand Down Expand Up @@ -43,11 +44,6 @@
"key": "WebSocketPingInterval",
"readonly": false,
"value": "60"
},
{
"key": "maxintensitysocket",
"readonly": false,
"value": "32"
}
]
},
Expand Down
78 changes: 75 additions & 3 deletions src/charging-station/ChargingStation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.

import { ACElectricUtils, DCElectricUtils } from '../utils/ElectricUtils';
import {
AvailabilityType,
BootNotificationRequest,
Expand All @@ -20,6 +21,7 @@ import ChargingStationOcppConfiguration, {
ConfigurationKey,
} from '../types/ChargingStationOcppConfiguration';
import ChargingStationTemplate, {
AmpereUnits,
CurrentType,
PowerUnits,
Voltage,
Expand Down Expand Up @@ -229,6 +231,22 @@ export default class ChargingStation {
: defaultVoltageOut;
}

public getMaximumConfiguredPower(): number | undefined {
let maximumConfiguredPower =
(this.stationInfo['maxPower'] as number) ?? this.stationInfo.maximumPower;
if (this.getAmperageLimitation() < this.stationInfo.maximumAmperage) {
maximumConfiguredPower =
this.getCurrentOutType() === CurrentType.AC
? ACElectricUtils.powerTotal(
this.getNumberOfPhases(),
this.getVoltageOut(),
this.getAmperageLimitation()
)
: DCElectricUtils.power(this.getVoltageOut(), this.getAmperageLimitation());
}
return maximumConfiguredPower;
}

public getTransactionIdTag(transactionId: number): string | undefined {
for (const connectorId of this.connectors.keys()) {
if (connectorId > 0 && this.getConnectorStatus(connectorId).transactionId === transactionId) {
Expand Down Expand Up @@ -835,13 +853,13 @@ export default class ChargingStation {
if (!Utils.isEmptyArray(stationInfo.power)) {
stationInfo.power = stationInfo.power as number[];
const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationInfo.power.length);
stationInfo.maxPower =
stationInfo.maximumPower =
stationInfo.powerUnit === PowerUnits.KILO_WATT
? stationInfo.power[powerArrayRandomIndex] * 1000
: stationInfo.power[powerArrayRandomIndex];
} else {
stationInfo.power = stationInfo.power as number;
stationInfo.maxPower =
stationInfo.maximumPower =
stationInfo.powerUnit === PowerUnits.KILO_WATT
? stationInfo.power * 1000
: stationInfo.power;
Expand Down Expand Up @@ -954,7 +972,6 @@ export default class ChargingStation {
this.bootNotificationRequest = this.createBootNotificationRequest(this.stationInfo);
this.ocppConfiguration = this.getOcppConfiguration();
delete this.stationInfo.Configuration;
this.saveStationInfo();
// Build connectors if needed
const maxConnectors = this.getMaxNumberOfConnectors();
if (maxConnectors <= 0) {
Expand Down Expand Up @@ -1039,6 +1056,9 @@ export default class ChargingStation {
}
}
}
// The connectors attribute need to be initialized
this.stationInfo.maximumAmperage = this.getMaximumAmperage();
this.saveStationInfo();
// Avoid duplication of connectors related information in RAM
delete this.stationInfo.Connectors;
// Initialize transaction attributes on connectors
Expand Down Expand Up @@ -1098,6 +1118,15 @@ export default class ChargingStation {
) {
this.deleteConfigurationKey(this.getSupervisionUrlOcppKey(), { save: false });
}
if (
this.stationInfo.amperageLimitationOcppKey &&
!this.getConfigurationKey(this.stationInfo.amperageLimitationOcppKey)
) {
this.addConfigurationKey(
this.stationInfo.amperageLimitationOcppKey,
(this.stationInfo.maximumAmperage * this.getAmperageLimitationUnitDivider()).toString()
);
}
if (!this.getConfigurationKey(StandardParametersKey.SupportedFeatureProfiles)) {
this.addConfigurationKey(
StandardParametersKey.SupportedFeatureProfiles,
Expand Down Expand Up @@ -1557,6 +1586,49 @@ export default class ChargingStation {
return maxConnectors;
}

private getMaximumAmperage(): number | undefined {
switch (this.getCurrentOutType()) {
case CurrentType.AC:
return ACElectricUtils.amperagePerPhaseFromPower(
this.getNumberOfPhases(),
(this.stationInfo['maxPower'] as number) ??
this.stationInfo.maximumPower / this.getNumberOfConnectors(),
this.getVoltageOut()
);
case CurrentType.DC:
return DCElectricUtils.amperage(this.stationInfo.maximumPower, this.getVoltageOut());
}
}

private getAmperageLimitationUnitDivider(): number {
let unitDivider = 1;
switch (this.stationInfo.amperageLimitationUnit) {
case AmpereUnits.DECI_AMPERE:
unitDivider = 10;
break;
case AmpereUnits.CENTI_AMPERE:
unitDivider = 100;
break;
case AmpereUnits.MILLI_AMPERE:
unitDivider = 1000;
break;
}
return unitDivider;
}

private getAmperageLimitation(): number | undefined {
if (
this.stationInfo.amperageLimitationOcppKey &&
this.getConfigurationKey(this.stationInfo.amperageLimitationOcppKey)
) {
return (
Utils.convertToInt(
this.getConfigurationKey(this.stationInfo.amperageLimitationOcppKey).value
) / this.getAmperageLimitationUnitDivider()
);
}
}

private async startMessageSequence(): Promise<void> {
if (this.stationInfo.autoRegister) {
await this.ocppRequestService.sendMessageHandler<BootNotificationResponse>(
Expand Down
Loading

0 comments on commit cc6e8ab

Please sign in to comment.