1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
5 OCPP16StartTransactionResponse
,
6 OCPP16StopTransactionReason
,
7 OCPP16StopTransactionResponse
,
8 StartTransactionRequest
,
9 StopTransactionRequest
,
10 } from
'../../../types/ocpp/1.6/Transaction';
12 DiagnosticsStatusNotificationRequest
,
14 OCPP16BootNotificationRequest
,
16 StatusNotificationRequest
,
17 } from
'../../../types/ocpp/1.6/Requests';
18 import { MeterValuesRequest
, OCPP16MeterValue
} from
'../../../types/ocpp/1.6/MeterValues';
19 import { ResponseType
, SendParams
} from
'../../../types/ocpp/Requests';
21 import type ChargingStation from
'../../ChargingStation';
22 import Constants from
'../../../utils/Constants';
23 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
24 import { JsonType
} from
'../../../types/JsonType';
25 import { OCPP16DiagnosticsStatus
} from
'../../../types/ocpp/1.6/DiagnosticsStatus';
26 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
27 import OCPPError from
'../../../exception/OCPPError';
28 import OCPPRequestService from
'../OCPPRequestService';
29 import type OCPPResponseService from
'../OCPPResponseService';
30 import Utils from
'../../../utils/Utils';
32 const moduleName
= 'OCPP16RequestService';
34 export default class OCPP16RequestService
extends OCPPRequestService
{
35 public constructor(chargingStation
: ChargingStation
, ocppResponseService
: OCPPResponseService
) {
36 if (new.target
?.name
=== moduleName
) {
37 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
39 super(chargingStation
, ocppResponseService
);
42 public async sendMessageHandler(
43 commandName
: OCPP16RequestCommand
,
44 commandParams
?: JsonType
,
46 ): Promise
<ResponseType
> {
47 if (Object.values(OCPP16RequestCommand
).includes(commandName
)) {
48 return this.sendMessage(
50 this.buildCommandPayload(commandName
, commandParams
),
56 ErrorType
.NOT_SUPPORTED
,
57 `${moduleName}.sendMessageHandler: Unsupported OCPP command ${commandName}`,
63 public async sendStartTransaction(
66 ): Promise
<OCPP16StartTransactionResponse
> {
67 const payload
: StartTransactionRequest
= {
69 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
70 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(connectorId
),
71 timestamp
: new Date().toISOString(),
73 return (await this.sendMessage(
76 OCPP16RequestCommand
.START_TRANSACTION
77 )) as OCPP16StartTransactionResponse
;
80 public async sendStopTransaction(
81 transactionId
: number,
84 reason
: OCPP16StopTransactionReason
= OCPP16StopTransactionReason
.NONE
85 ): Promise
<OCPP16StopTransactionResponse
> {
86 let connectorId
: number;
87 for (const id
of this.chargingStation
.connectors
.keys()) {
88 if (id
> 0 && this.chargingStation
.getConnectorStatus(id
)?.transactionId
=== transactionId
) {
93 const transactionEndMeterValue
= OCPP16ServiceUtils
.buildTransactionEndMeterValue(
98 // FIXME: should be a callback, each OCPP commands implementation must do only one job
99 this.chargingStation
.getBeginEndMeterValues() &&
100 this.chargingStation
.getOcppStrictCompliance() &&
101 !this.chargingStation
.getOutOfOrderEndMeterValues() &&
102 (await this.sendTransactionEndMeterValues(
105 transactionEndMeterValue
107 const payload
: StopTransactionRequest
= {
109 ...(!Utils
.isUndefined(idTag
) && { idTag
}),
111 timestamp
: new Date().toISOString(),
112 ...(reason
&& { reason
}),
113 ...(this.chargingStation
.getTransactionDataMeterValues() && {
114 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
115 this.chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
116 transactionEndMeterValue
120 return (await this.sendMessage(
121 Utils
.generateUUID(),
123 OCPP16RequestCommand
.STOP_TRANSACTION
124 )) as OCPP16StartTransactionResponse
;
127 public async sendMeterValues(
129 transactionId
: number,
132 const meterValue
: OCPP16MeterValue
= OCPP16ServiceUtils
.buildMeterValue(
133 this.chargingStation
,
138 const payload
: MeterValuesRequest
= {
141 meterValue
: [meterValue
],
143 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
146 public async sendTransactionBeginMeterValues(
148 transactionId
: number,
149 beginMeterValue
: OCPP16MeterValue
151 const payload
: MeterValuesRequest
= {
154 meterValue
: [beginMeterValue
],
156 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
159 public async sendTransactionEndMeterValues(
161 transactionId
: number,
162 endMeterValue
: OCPP16MeterValue
164 const payload
: MeterValuesRequest
= {
167 meterValue
: [endMeterValue
],
169 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
172 public async sendDiagnosticsStatusNotification(
173 diagnosticsStatus
: OCPP16DiagnosticsStatus
175 const payload
: DiagnosticsStatusNotificationRequest
= {
176 status: diagnosticsStatus
,
178 await this.sendMessage(
179 Utils
.generateUUID(),
181 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
185 private buildCommandPayload(
186 commandName
: OCPP16RequestCommand
,
187 commandParams
?: JsonType
189 switch (commandName
) {
190 case OCPP16RequestCommand
.AUTHORIZE
:
192 ...(!Utils
.isUndefined(commandParams
?.idTag
)
193 ? { idTag
: commandParams
.idTag
}
194 : { idTag
: Constants
.DEFAULT_IDTAG
}),
195 } as AuthorizeRequest
;
196 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
198 chargePointModel
: commandParams
?.chargePointModel
,
199 chargePointVendor
: commandParams
?.chargePointVendor
,
200 ...(!Utils
.isUndefined(commandParams
?.chargeBoxSerialNumber
) && {
201 chargeBoxSerialNumber
: commandParams
.chargeBoxSerialNumber
,
203 ...(!Utils
.isUndefined(commandParams
?.chargePointSerialNumber
) && {
204 chargePointSerialNumber
: commandParams
.chargePointSerialNumber
,
206 ...(!Utils
.isUndefined(commandParams
?.firmwareVersion
) && {
207 firmwareVersion
: commandParams
.firmwareVersion
,
209 ...(!Utils
.isUndefined(commandParams
?.iccid
) && { iccid
: commandParams
.iccid
}),
210 ...(!Utils
.isUndefined(commandParams
?.imsi
) && { imsi
: commandParams
.imsi
}),
211 ...(!Utils
.isUndefined(commandParams
?.meterSerialNumber
) && {
212 meterSerialNumber
: commandParams
.meterSerialNumber
,
214 ...(!Utils
.isUndefined(commandParams
?.meterType
) && {
215 meterType
: commandParams
.meterType
,
217 } as OCPP16BootNotificationRequest
;
218 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
220 status: commandParams
?.diagnosticsStatus
,
221 } as DiagnosticsStatusNotificationRequest
;
222 case OCPP16RequestCommand
.HEARTBEAT
:
223 return {} as HeartbeatRequest
;
224 case OCPP16RequestCommand
.METER_VALUES
:
226 connectorId
: commandParams
?.connectorId
,
227 transactionId
: commandParams
?.transactionId
,
228 meterValue
: Array.isArray(commandParams
?.meterValues
)
229 ? commandParams
?.meterValues
230 : [commandParams
?.meterValue
],
231 } as MeterValuesRequest
;
232 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
234 connectorId
: commandParams
?.connectorId
,
235 status: commandParams
?.status,
236 errorCode
: commandParams
?.errorCode
,
237 } as StatusNotificationRequest
;
238 case OCPP16RequestCommand
.START_TRANSACTION
:
240 connectorId
: commandParams
?.connectorId
,
241 ...(!Utils
.isUndefined(commandParams
?.idTag
)
242 ? { idTag
: commandParams
?.idTag
}
243 : { idTag
: Constants
.DEFAULT_IDTAG
}),
244 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(
245 commandParams
?.connectorId
as number
247 timestamp
: new Date().toISOString(),
248 } as StartTransactionRequest
;
249 case OCPP16RequestCommand
.STOP_TRANSACTION
:
251 transactionId
: commandParams
?.transactionId
,
252 ...(!Utils
.isUndefined(commandParams
?.idTag
) && { idTag
: commandParams
.idTag
}),
253 meterStop
: commandParams
?.meterStop
,
254 timestamp
: new Date().toISOString(),
255 ...(commandParams
?.reason
&& { reason
: commandParams
.reason
}),
256 ...(this.chargingStation
.getTransactionDataMeterValues() && {
257 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
258 this.chargingStation
.getConnectorStatus(commandParams
?.connectorId
as number)
259 .transactionBeginMeterValue
,
260 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
261 this.chargingStation
,
262 commandParams
?.connectorId
as number,
263 commandParams
?.meterStop
as number
267 } as StopTransactionRequest
;
270 ErrorType
.NOT_SUPPORTED
,
271 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
272 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,