Apply prettier formating
[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 {
4 MeterValueContext,
5 MeterValueLocation,
6 MeterValueUnit,
7 OCPP16MeterValue,
8 OCPP16MeterValueMeasurand,
9 OCPP16MeterValuePhase,
10 OCPP16SampledValue,
11 } from '../../../types/ocpp/1.6/MeterValues';
12
13 import type ChargingStation from '../../ChargingStation';
14 import { ErrorType } from '../../../types/ocpp/ErrorType';
15 import OCPPError from '../../../exception/OCPPError';
16 import { RequestCommand } from '../../../types/ocpp/Requests';
17 import { SampledValueTemplate } from '../../../types/MeasurandPerPhaseSampledValueTemplates';
18 import Utils from '../../../utils/Utils';
19 import logger from '../../../utils/Logger';
20
21 export class OCPP16ServiceUtils {
22 public static checkMeasurandPowerDivider(
23 chargingStation: ChargingStation,
24 measurandType: OCPP16MeterValueMeasurand
25 ): void {
26 if (Utils.isUndefined(chargingStation.stationInfo.powerDivider)) {
27 const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
28 measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
29 }: powerDivider is undefined`;
30 logger.error(errMsg);
31 throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
32 } else if (chargingStation.stationInfo?.powerDivider <= 0) {
33 const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
34 measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
35 }: powerDivider have zero or below value ${chargingStation.stationInfo.powerDivider}`;
36 logger.error(errMsg);
37 throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES);
38 }
39 }
40
41 public static buildSampledValue(
42 sampledValueTemplate: SampledValueTemplate,
43 value: number,
44 context?: MeterValueContext,
45 phase?: OCPP16MeterValuePhase
46 ): OCPP16SampledValue {
47 const sampledValueValue = value ?? sampledValueTemplate?.value ?? null;
48 const sampledValueContext = context ?? sampledValueTemplate?.context ?? null;
49 const sampledValueLocation =
50 sampledValueTemplate?.location ??
51 OCPP16ServiceUtils.getMeasurandDefaultLocation(sampledValueTemplate?.measurand ?? null);
52 const sampledValuePhase = phase ?? sampledValueTemplate?.phase ?? null;
53 return {
54 ...(!Utils.isNullOrUndefined(sampledValueTemplate.unit) && {
55 unit: sampledValueTemplate.unit,
56 }),
57 ...(!Utils.isNullOrUndefined(sampledValueContext) && { context: sampledValueContext }),
58 ...(!Utils.isNullOrUndefined(sampledValueTemplate.measurand) && {
59 measurand: sampledValueTemplate.measurand,
60 }),
61 ...(!Utils.isNullOrUndefined(sampledValueLocation) && { location: sampledValueLocation }),
62 ...(!Utils.isNullOrUndefined(sampledValueValue) && { value: sampledValueValue.toString() }),
63 ...(!Utils.isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase }),
64 };
65 }
66
67 public static getMeasurandDefaultUnit(
68 measurandType: OCPP16MeterValueMeasurand
69 ): MeterValueUnit | undefined {
70 switch (measurandType) {
71 case OCPP16MeterValueMeasurand.CURRENT_EXPORT:
72 case OCPP16MeterValueMeasurand.CURRENT_IMPORT:
73 case OCPP16MeterValueMeasurand.CURRENT_OFFERED:
74 return MeterValueUnit.AMP;
75 case OCPP16MeterValueMeasurand.ENERGY_ACTIVE_EXPORT_REGISTER:
76 case OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER:
77 return MeterValueUnit.WATT_HOUR;
78 case OCPP16MeterValueMeasurand.POWER_ACTIVE_EXPORT:
79 case OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT:
80 case OCPP16MeterValueMeasurand.POWER_OFFERED:
81 return MeterValueUnit.WATT;
82 case OCPP16MeterValueMeasurand.STATE_OF_CHARGE:
83 return MeterValueUnit.PERCENT;
84 case OCPP16MeterValueMeasurand.VOLTAGE:
85 return MeterValueUnit.VOLT;
86 }
87 }
88
89 public static getMeasurandDefaultLocation(
90 measurandType: OCPP16MeterValueMeasurand
91 ): MeterValueLocation | undefined {
92 switch (measurandType) {
93 case OCPP16MeterValueMeasurand.STATE_OF_CHARGE:
94 return MeterValueLocation.EV;
95 }
96 }
97
98 public static buildTransactionBeginMeterValue(
99 chargingStation: ChargingStation,
100 connectorId: number,
101 meterBegin: number
102 ): OCPP16MeterValue {
103 const meterValue: OCPP16MeterValue = {
104 timestamp: new Date().toISOString(),
105 sampledValue: [],
106 };
107 // Energy.Active.Import.Register measurand (default)
108 const sampledValueTemplate = chargingStation.getSampledValueTemplate(connectorId);
109 const unitDivider = sampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
110 meterValue.sampledValue.push(
111 OCPP16ServiceUtils.buildSampledValue(
112 sampledValueTemplate,
113 Utils.roundTo(meterBegin / unitDivider, 4),
114 MeterValueContext.TRANSACTION_BEGIN
115 )
116 );
117 return meterValue;
118 }
119
120 public static buildTransactionEndMeterValue(
121 chargingStation: ChargingStation,
122 connectorId: number,
123 meterEnd: number
124 ): OCPP16MeterValue {
125 const meterValue: OCPP16MeterValue = {
126 timestamp: new Date().toISOString(),
127 sampledValue: [],
128 };
129 // Energy.Active.Import.Register measurand (default)
130 const sampledValueTemplate = chargingStation.getSampledValueTemplate(connectorId);
131 const unitDivider = sampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
132 meterValue.sampledValue.push(
133 OCPP16ServiceUtils.buildSampledValue(
134 sampledValueTemplate,
135 Utils.roundTo(meterEnd / unitDivider, 4),
136 MeterValueContext.TRANSACTION_END
137 )
138 );
139 return meterValue;
140 }
141
142 public static buildTransactionDataMeterValues(
143 transactionBeginMeterValue: OCPP16MeterValue,
144 transactionEndMeterValue: OCPP16MeterValue
145 ): OCPP16MeterValue[] {
146 const meterValues: OCPP16MeterValue[] = [];
147 meterValues.push(transactionBeginMeterValue);
148 meterValues.push(transactionEndMeterValue);
149 return meterValues;
150 }
151 }