Convert sendMeterValues to OCPP message sending handler
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16RequestService.ts
1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
2
3 import {
4 AuthorizeRequest,
5 StartTransactionRequest,
6 StopTransactionRequest,
7 } from '../../../types/ocpp/1.6/Transaction';
8 import {
9 DiagnosticsStatusNotificationRequest,
10 HeartbeatRequest,
11 OCPP16BootNotificationRequest,
12 OCPP16RequestCommand,
13 StatusNotificationRequest,
14 } from '../../../types/ocpp/1.6/Requests';
15 import { MeterValuesRequest, OCPP16MeterValue } from '../../../types/ocpp/1.6/MeterValues';
16 import { ResponseType, SendParams } from '../../../types/ocpp/Requests';
17
18 import type ChargingStation from '../../ChargingStation';
19 import Constants from '../../../utils/Constants';
20 import { ErrorType } from '../../../types/ocpp/ErrorType';
21 import { JsonType } from '../../../types/JsonType';
22 import { OCPP16DiagnosticsStatus } from '../../../types/ocpp/1.6/DiagnosticsStatus';
23 import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
24 import OCPPError from '../../../exception/OCPPError';
25 import OCPPRequestService from '../OCPPRequestService';
26 import type OCPPResponseService from '../OCPPResponseService';
27 import Utils from '../../../utils/Utils';
28
29 const moduleName = 'OCPP16RequestService';
30
31 export default class OCPP16RequestService extends OCPPRequestService {
32 public constructor(chargingStation: ChargingStation, ocppResponseService: OCPPResponseService) {
33 if (new.target?.name === moduleName) {
34 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
35 }
36 super(chargingStation, ocppResponseService);
37 }
38
39 public async sendMessageHandler(
40 commandName: OCPP16RequestCommand,
41 commandParams?: JsonType,
42 params?: SendParams
43 ): Promise<ResponseType> {
44 if (Object.values(OCPP16RequestCommand).includes(commandName)) {
45 return this.sendMessage(
46 Utils.generateUUID(),
47 this.buildCommandPayload(commandName, commandParams),
48 commandName,
49 params
50 );
51 }
52 throw new OCPPError(
53 ErrorType.NOT_SUPPORTED,
54 `${moduleName}.sendMessageHandler: Unsupported OCPP command ${commandName}`,
55 commandName,
56 { commandName }
57 );
58 }
59
60 public async sendTransactionBeginMeterValues(
61 connectorId: number,
62 transactionId: number,
63 beginMeterValue: OCPP16MeterValue
64 ): Promise<void> {
65 const payload: MeterValuesRequest = {
66 connectorId,
67 transactionId,
68 meterValue: [beginMeterValue],
69 };
70 await this.sendMessage(Utils.generateUUID(), payload, OCPP16RequestCommand.METER_VALUES);
71 }
72
73 public async sendTransactionEndMeterValues(
74 connectorId: number,
75 transactionId: number,
76 endMeterValue: OCPP16MeterValue
77 ): Promise<void> {
78 const payload: MeterValuesRequest = {
79 connectorId,
80 transactionId,
81 meterValue: [endMeterValue],
82 };
83 await this.sendMessage(Utils.generateUUID(), payload, OCPP16RequestCommand.METER_VALUES);
84 }
85
86 public async sendDiagnosticsStatusNotification(
87 diagnosticsStatus: OCPP16DiagnosticsStatus
88 ): Promise<void> {
89 const payload: DiagnosticsStatusNotificationRequest = {
90 status: diagnosticsStatus,
91 };
92 await this.sendMessage(
93 Utils.generateUUID(),
94 payload,
95 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
96 );
97 }
98
99 private buildCommandPayload(
100 commandName: OCPP16RequestCommand,
101 commandParams?: JsonType
102 ): JsonType {
103 let connectorId: number;
104 switch (commandName) {
105 case OCPP16RequestCommand.AUTHORIZE:
106 return {
107 ...(!Utils.isUndefined(commandParams?.idTag)
108 ? { idTag: commandParams.idTag }
109 : { idTag: Constants.DEFAULT_IDTAG }),
110 } as AuthorizeRequest;
111 case OCPP16RequestCommand.BOOT_NOTIFICATION:
112 return {
113 chargePointModel: commandParams?.chargePointModel,
114 chargePointVendor: commandParams?.chargePointVendor,
115 ...(!Utils.isUndefined(commandParams?.chargeBoxSerialNumber) && {
116 chargeBoxSerialNumber: commandParams.chargeBoxSerialNumber,
117 }),
118 ...(!Utils.isUndefined(commandParams?.chargePointSerialNumber) && {
119 chargePointSerialNumber: commandParams.chargePointSerialNumber,
120 }),
121 ...(!Utils.isUndefined(commandParams?.firmwareVersion) && {
122 firmwareVersion: commandParams.firmwareVersion,
123 }),
124 ...(!Utils.isUndefined(commandParams?.iccid) && { iccid: commandParams.iccid }),
125 ...(!Utils.isUndefined(commandParams?.imsi) && { imsi: commandParams.imsi }),
126 ...(!Utils.isUndefined(commandParams?.meterSerialNumber) && {
127 meterSerialNumber: commandParams.meterSerialNumber,
128 }),
129 ...(!Utils.isUndefined(commandParams?.meterType) && {
130 meterType: commandParams.meterType,
131 }),
132 } as OCPP16BootNotificationRequest;
133 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
134 return {
135 status: commandParams?.diagnosticsStatus,
136 } as DiagnosticsStatusNotificationRequest;
137 case OCPP16RequestCommand.HEARTBEAT:
138 return {} as HeartbeatRequest;
139 case OCPP16RequestCommand.METER_VALUES:
140 return {
141 connectorId: commandParams?.connectorId,
142 transactionId: commandParams?.transactionId,
143 meterValue: Array.isArray(commandParams?.meterValues)
144 ? commandParams?.meterValues
145 : [commandParams?.meterValue],
146 } as MeterValuesRequest;
147 case OCPP16RequestCommand.STATUS_NOTIFICATION:
148 return {
149 connectorId: commandParams?.connectorId,
150 status: commandParams?.status,
151 errorCode: commandParams?.errorCode,
152 } as StatusNotificationRequest;
153 case OCPP16RequestCommand.START_TRANSACTION:
154 return {
155 connectorId: commandParams?.connectorId,
156 ...(!Utils.isUndefined(commandParams?.idTag)
157 ? { idTag: commandParams?.idTag }
158 : { idTag: Constants.DEFAULT_IDTAG }),
159 meterStart: this.chargingStation.getEnergyActiveImportRegisterByConnectorId(
160 commandParams?.connectorId as number
161 ),
162 timestamp: new Date().toISOString(),
163 } as StartTransactionRequest;
164 case OCPP16RequestCommand.STOP_TRANSACTION:
165 for (const id of this.chargingStation.connectors.keys()) {
166 if (
167 id > 0 &&
168 this.chargingStation.getConnectorStatus(id)?.transactionId ===
169 commandParams?.transactionId
170 ) {
171 connectorId = id;
172 break;
173 }
174 }
175 return {
176 transactionId: commandParams?.transactionId,
177 ...(!Utils.isUndefined(commandParams?.idTag) && { idTag: commandParams.idTag }),
178 meterStop: commandParams?.meterStop,
179 timestamp: new Date().toISOString(),
180 ...(commandParams?.reason && { reason: commandParams.reason }),
181 ...(this.chargingStation.getTransactionDataMeterValues() && {
182 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
183 this.chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue,
184 OCPP16ServiceUtils.buildTransactionEndMeterValue(
185 this.chargingStation,
186 connectorId,
187 commandParams?.meterStop as number
188 )
189 ),
190 }),
191 } as StopTransactionRequest;
192 default:
193 throw new OCPPError(
194 ErrorType.NOT_SUPPORTED,
195 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
196 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,
197 commandName,
198 { commandName }
199 );
200 }
201 }
202 }