Convert sendStopTransaction 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 sendMeterValues(
61 connectorId: number,
62 transactionId: number,
63 interval: number
64 ): Promise<void> {
65 const meterValue: OCPP16MeterValue = OCPP16ServiceUtils.buildMeterValue(
66 this.chargingStation,
67 connectorId,
68 transactionId,
69 interval
70 );
71 const payload: MeterValuesRequest = {
72 connectorId,
73 transactionId,
74 meterValue: [meterValue],
75 };
76 await this.sendMessage(Utils.generateUUID(), payload, OCPP16RequestCommand.METER_VALUES);
77 }
78
79 public async sendTransactionBeginMeterValues(
80 connectorId: number,
81 transactionId: number,
82 beginMeterValue: OCPP16MeterValue
83 ): Promise<void> {
84 const payload: MeterValuesRequest = {
85 connectorId,
86 transactionId,
87 meterValue: [beginMeterValue],
88 };
89 await this.sendMessage(Utils.generateUUID(), payload, OCPP16RequestCommand.METER_VALUES);
90 }
91
92 public async sendTransactionEndMeterValues(
93 connectorId: number,
94 transactionId: number,
95 endMeterValue: OCPP16MeterValue
96 ): Promise<void> {
97 const payload: MeterValuesRequest = {
98 connectorId,
99 transactionId,
100 meterValue: [endMeterValue],
101 };
102 await this.sendMessage(Utils.generateUUID(), payload, OCPP16RequestCommand.METER_VALUES);
103 }
104
105 public async sendDiagnosticsStatusNotification(
106 diagnosticsStatus: OCPP16DiagnosticsStatus
107 ): Promise<void> {
108 const payload: DiagnosticsStatusNotificationRequest = {
109 status: diagnosticsStatus,
110 };
111 await this.sendMessage(
112 Utils.generateUUID(),
113 payload,
114 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
115 );
116 }
117
118 private buildCommandPayload(
119 commandName: OCPP16RequestCommand,
120 commandParams?: JsonType
121 ): JsonType {
122 let connectorId: number;
123 switch (commandName) {
124 case OCPP16RequestCommand.AUTHORIZE:
125 return {
126 ...(!Utils.isUndefined(commandParams?.idTag)
127 ? { idTag: commandParams.idTag }
128 : { idTag: Constants.DEFAULT_IDTAG }),
129 } as AuthorizeRequest;
130 case OCPP16RequestCommand.BOOT_NOTIFICATION:
131 return {
132 chargePointModel: commandParams?.chargePointModel,
133 chargePointVendor: commandParams?.chargePointVendor,
134 ...(!Utils.isUndefined(commandParams?.chargeBoxSerialNumber) && {
135 chargeBoxSerialNumber: commandParams.chargeBoxSerialNumber,
136 }),
137 ...(!Utils.isUndefined(commandParams?.chargePointSerialNumber) && {
138 chargePointSerialNumber: commandParams.chargePointSerialNumber,
139 }),
140 ...(!Utils.isUndefined(commandParams?.firmwareVersion) && {
141 firmwareVersion: commandParams.firmwareVersion,
142 }),
143 ...(!Utils.isUndefined(commandParams?.iccid) && { iccid: commandParams.iccid }),
144 ...(!Utils.isUndefined(commandParams?.imsi) && { imsi: commandParams.imsi }),
145 ...(!Utils.isUndefined(commandParams?.meterSerialNumber) && {
146 meterSerialNumber: commandParams.meterSerialNumber,
147 }),
148 ...(!Utils.isUndefined(commandParams?.meterType) && {
149 meterType: commandParams.meterType,
150 }),
151 } as OCPP16BootNotificationRequest;
152 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
153 return {
154 status: commandParams?.diagnosticsStatus,
155 } as DiagnosticsStatusNotificationRequest;
156 case OCPP16RequestCommand.HEARTBEAT:
157 return {} as HeartbeatRequest;
158 case OCPP16RequestCommand.METER_VALUES:
159 return {
160 connectorId: commandParams?.connectorId,
161 transactionId: commandParams?.transactionId,
162 meterValue: Array.isArray(commandParams?.meterValues)
163 ? commandParams?.meterValues
164 : [commandParams?.meterValue],
165 } as MeterValuesRequest;
166 case OCPP16RequestCommand.STATUS_NOTIFICATION:
167 return {
168 connectorId: commandParams?.connectorId,
169 status: commandParams?.status,
170 errorCode: commandParams?.errorCode,
171 } as StatusNotificationRequest;
172 case OCPP16RequestCommand.START_TRANSACTION:
173 return {
174 connectorId: commandParams?.connectorId,
175 ...(!Utils.isUndefined(commandParams?.idTag)
176 ? { idTag: commandParams?.idTag }
177 : { idTag: Constants.DEFAULT_IDTAG }),
178 meterStart: this.chargingStation.getEnergyActiveImportRegisterByConnectorId(
179 commandParams?.connectorId as number
180 ),
181 timestamp: new Date().toISOString(),
182 } as StartTransactionRequest;
183 case OCPP16RequestCommand.STOP_TRANSACTION:
184 for (const id of this.chargingStation.connectors.keys()) {
185 if (
186 id > 0 &&
187 this.chargingStation.getConnectorStatus(id)?.transactionId ===
188 commandParams?.transactionId
189 ) {
190 connectorId = id;
191 break;
192 }
193 }
194 return {
195 transactionId: commandParams?.transactionId,
196 ...(!Utils.isUndefined(commandParams?.idTag) && { idTag: commandParams.idTag }),
197 meterStop: commandParams?.meterStop,
198 timestamp: new Date().toISOString(),
199 ...(commandParams?.reason && { reason: commandParams.reason }),
200 ...(this.chargingStation.getTransactionDataMeterValues() && {
201 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
202 this.chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue,
203 OCPP16ServiceUtils.buildTransactionEndMeterValue(
204 this.chargingStation,
205 connectorId,
206 commandParams?.meterStop as number
207 )
208 ),
209 }),
210 } as StopTransactionRequest;
211 default:
212 throw new OCPPError(
213 ErrorType.NOT_SUPPORTED,
214 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
215 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,
216 commandName,
217 { commandName }
218 );
219 }
220 }
221 }