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