1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
3 import { MeterValueContext
, MeterValueLocation
, MeterValueUnit
, OCPP16MeterValue
, OCPP16MeterValueMeasurand
, OCPP16MeterValuePhase
, OCPP16SampledValue
} from
'../../../types/ocpp/1.6/MeterValues';
5 import ChargingStation from
'../../ChargingStation';
6 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
7 import OCPPError from
'../OCPPError';
8 import { RequestCommand
} from
'../../../types/ocpp/Requests';
9 import { SampledValueTemplate
} from
'../../../types/Connectors';
10 import Utils from
'../../../utils/Utils';
11 import logger from
'../../../utils/Logger';
13 export class OCPP16ServiceUtils
{
14 public static checkMeasurandPowerDivider(chargingStation
: ChargingStation
, measurandType
: OCPP16MeterValueMeasurand
): void {
15 if (Utils
.isUndefined(chargingStation
.stationInfo
.powerDivider
)) {
16 const errMsg
= `${chargingStation.logPrefix()} MeterValues measurand ${measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider is undefined`;
18 throw new OCPPError(ErrorType
.INTERNAL_ERROR
, errMsg
, RequestCommand
.METER_VALUES
);
19 } else if (chargingStation
.stationInfo
?.powerDivider
<= 0) {
20 const errMsg
= `${chargingStation.logPrefix()} MeterValues measurand ${measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER}: powerDivider have zero or below value ${chargingStation.stationInfo.powerDivider}`;
22 throw new OCPPError(ErrorType
.INTERNAL_ERROR
, errMsg
, RequestCommand
.METER_VALUES
);
26 public static buildSampledValue(sampledValueTemplate
: SampledValueTemplate
, value
: number, context
?: MeterValueContext
, phase
?: OCPP16MeterValuePhase
): OCPP16SampledValue
{
27 const sampledValueValue
= value
?? (sampledValueTemplate
?.value
?? null);
28 const sampledValueContext
= context
?? (sampledValueTemplate
?.context
?? null);
29 const sampledValueLocation
= sampledValueTemplate
?.location
?? OCPP16ServiceUtils
.getMeasurandDefaultLocation(sampledValueTemplate
?.measurand
?? null);
30 const sampledValuePhase
= phase
?? (sampledValueTemplate
?.phase
?? null);
32 ...!Utils
.isNullOrUndefined(sampledValueTemplate
.unit
) && { unit
: sampledValueTemplate
.unit
},
33 ...!Utils
.isNullOrUndefined(sampledValueContext
) && { context
: sampledValueContext
},
34 ...!Utils
.isNullOrUndefined(sampledValueTemplate
.measurand
) && { measurand
: sampledValueTemplate
.measurand
},
35 ...!Utils
.isNullOrUndefined(sampledValueLocation
) && { location
: sampledValueLocation
},
36 ...!Utils
.isNullOrUndefined(sampledValueValue
) && { value
: sampledValueValue
.toString() },
37 ...!Utils
.isNullOrUndefined(sampledValuePhase
) && { phase
: sampledValuePhase
},
41 public static getMeasurandDefaultUnit(measurandType
: OCPP16MeterValueMeasurand
): MeterValueUnit
| undefined {
42 switch (measurandType
) {
43 case OCPP16MeterValueMeasurand
.CURRENT_EXPORT
:
44 case OCPP16MeterValueMeasurand
.CURRENT_IMPORT
:
45 case OCPP16MeterValueMeasurand
.CURRENT_OFFERED
:
46 return MeterValueUnit
.AMP
;
47 case OCPP16MeterValueMeasurand
.ENERGY_ACTIVE_EXPORT_REGISTER
:
48 case OCPP16MeterValueMeasurand
.ENERGY_ACTIVE_IMPORT_REGISTER
:
49 return MeterValueUnit
.WATT_HOUR
;
50 case OCPP16MeterValueMeasurand
.POWER_ACTIVE_EXPORT
:
51 case OCPP16MeterValueMeasurand
.POWER_ACTIVE_IMPORT
:
52 case OCPP16MeterValueMeasurand
.POWER_OFFERED
:
53 return MeterValueUnit
.WATT
;
54 case OCPP16MeterValueMeasurand
.STATE_OF_CHARGE
:
55 return MeterValueUnit
.PERCENT
;
56 case OCPP16MeterValueMeasurand
.VOLTAGE
:
57 return MeterValueUnit
.VOLT
;
61 public static getMeasurandDefaultLocation(measurandType
: OCPP16MeterValueMeasurand
): MeterValueLocation
| undefined {
62 switch (measurandType
) {
63 case OCPP16MeterValueMeasurand
.STATE_OF_CHARGE
:
64 return MeterValueLocation
.EV
;
68 public static buildTransactionBeginMeterValue(chargingStation
: ChargingStation
, connectorId
: number, meterBegin
: number): OCPP16MeterValue
{
69 const meterValue
: OCPP16MeterValue
= {
70 timestamp
: new Date().toISOString(),
73 // Energy.Active.Import.Register measurand (default)
74 const sampledValueTemplate
= chargingStation
.getSampledValueTemplate(connectorId
);
75 const unitDivider
= sampledValueTemplate
?.unit
=== MeterValueUnit
.KILO_WATT_HOUR
? 1000 : 1;
76 meterValue
.sampledValue
.push(OCPP16ServiceUtils
.buildSampledValue(sampledValueTemplate
, Utils
.roundTo(meterBegin
/ unitDivider
, 4), MeterValueContext
.TRANSACTION_BEGIN
));
80 public static buildTransactionEndMeterValue(chargingStation
: ChargingStation
, connectorId
: number, meterEnd
: number): OCPP16MeterValue
{
81 const meterValue
: OCPP16MeterValue
= {
82 timestamp
: new Date().toISOString(),
85 // Energy.Active.Import.Register measurand (default)
86 const sampledValueTemplate
= chargingStation
.getSampledValueTemplate(connectorId
);
87 const unitDivider
= sampledValueTemplate
?.unit
=== MeterValueUnit
.KILO_WATT_HOUR
? 1000 : 1;
88 meterValue
.sampledValue
.push(OCPP16ServiceUtils
.buildSampledValue(sampledValueTemplate
, Utils
.roundTo(meterEnd
/ unitDivider
, 4), MeterValueContext
.TRANSACTION_END
));
92 public static buildTransactionDataMeterValues(transactionBeginMeterValue
: OCPP16MeterValue
, transactionEndMeterValue
: OCPP16MeterValue
): OCPP16MeterValue
[] {
93 const meterValues
: OCPP16MeterValue
[] = [];
94 meterValues
.push(transactionBeginMeterValue
);
95 meterValues
.push(transactionEndMeterValue
);