1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
5 OCPP16AuthorizeResponse
,
6 OCPP16StartTransactionResponse
,
7 OCPP16StopTransactionReason
,
8 OCPP16StopTransactionResponse
,
9 StartTransactionRequest
,
10 StopTransactionRequest
,
11 } from
'../../../types/ocpp/1.6/Transaction';
13 DiagnosticsStatusNotificationRequest
,
15 OCPP16BootNotificationRequest
,
17 StatusNotificationRequest
,
18 } from
'../../../types/ocpp/1.6/Requests';
19 import { MeterValuesRequest
, OCPP16MeterValue
} from
'../../../types/ocpp/1.6/MeterValues';
20 import { ResponseType
, SendParams
} from
'../../../types/ocpp/Requests';
22 import type ChargingStation from
'../../ChargingStation';
23 import Constants from
'../../../utils/Constants';
24 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
25 import { JsonType
} from
'../../../types/JsonType';
26 import { OCPP16ChargePointErrorCode
} from
'../../../types/ocpp/1.6/ChargePointErrorCode';
27 import { OCPP16ChargePointStatus
} from
'../../../types/ocpp/1.6/ChargePointStatus';
28 import { OCPP16DiagnosticsStatus
} from
'../../../types/ocpp/1.6/DiagnosticsStatus';
29 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
30 import OCPPError from
'../../../exception/OCPPError';
31 import OCPPRequestService from
'../OCPPRequestService';
32 import type OCPPResponseService from
'../OCPPResponseService';
33 import Utils from
'../../../utils/Utils';
35 const moduleName
= 'OCPP16RequestService';
37 export default class OCPP16RequestService
extends OCPPRequestService
{
38 public constructor(chargingStation
: ChargingStation
, ocppResponseService
: OCPPResponseService
) {
39 if (new.target
?.name
=== moduleName
) {
40 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
42 super(chargingStation
, ocppResponseService
);
45 public async sendMessageHandler(
46 commandName
: OCPP16RequestCommand
,
47 commandParams
?: JsonType
,
49 ): Promise
<ResponseType
> {
50 if (Object.values(OCPP16RequestCommand
).includes(commandName
)) {
51 return this.sendMessage(
53 this.buildCommandPayload(commandName
, commandParams
),
59 ErrorType
.NOT_SUPPORTED
,
60 `${moduleName}.sendMessageHandler: Unsupported OCPP command ${commandName}`,
66 public async sendAuthorize(
69 ): Promise
<OCPP16AuthorizeResponse
> {
70 const payload
: AuthorizeRequest
= {
71 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
73 this.chargingStation
.getConnectorStatus(connectorId
).authorizeIdTag
= idTag
;
74 return (await this.sendMessage(
77 OCPP16RequestCommand
.AUTHORIZE
78 )) as OCPP16AuthorizeResponse
;
81 public async sendStartTransaction(
84 ): Promise
<OCPP16StartTransactionResponse
> {
85 const payload
: StartTransactionRequest
= {
87 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
88 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(connectorId
),
89 timestamp
: new Date().toISOString(),
91 return (await this.sendMessage(
94 OCPP16RequestCommand
.START_TRANSACTION
95 )) as OCPP16StartTransactionResponse
;
98 public async sendStopTransaction(
99 transactionId
: number,
102 reason
: OCPP16StopTransactionReason
= OCPP16StopTransactionReason
.NONE
103 ): Promise
<OCPP16StopTransactionResponse
> {
104 let connectorId
: number;
105 for (const id
of this.chargingStation
.connectors
.keys()) {
106 if (id
> 0 && this.chargingStation
.getConnectorStatus(id
)?.transactionId
=== transactionId
) {
111 const transactionEndMeterValue
= OCPP16ServiceUtils
.buildTransactionEndMeterValue(
112 this.chargingStation
,
116 // FIXME: should be a callback, each OCPP commands implementation must do only one job
117 this.chargingStation
.getBeginEndMeterValues() &&
118 this.chargingStation
.getOcppStrictCompliance() &&
119 !this.chargingStation
.getOutOfOrderEndMeterValues() &&
120 (await this.sendTransactionEndMeterValues(
123 transactionEndMeterValue
125 const payload
: StopTransactionRequest
= {
127 ...(!Utils
.isUndefined(idTag
) && { idTag
}),
129 timestamp
: new Date().toISOString(),
130 ...(reason
&& { reason
}),
131 ...(this.chargingStation
.getTransactionDataMeterValues() && {
132 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
133 this.chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
134 transactionEndMeterValue
138 return (await this.sendMessage(
139 Utils
.generateUUID(),
141 OCPP16RequestCommand
.STOP_TRANSACTION
142 )) as OCPP16StartTransactionResponse
;
145 public async sendMeterValues(
147 transactionId
: number,
150 const meterValue
: OCPP16MeterValue
= OCPP16ServiceUtils
.buildMeterValue(
151 this.chargingStation
,
156 const payload
: MeterValuesRequest
= {
159 meterValue
: [meterValue
],
161 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
164 public async sendTransactionBeginMeterValues(
166 transactionId
: number,
167 beginMeterValue
: OCPP16MeterValue
169 const payload
: MeterValuesRequest
= {
172 meterValue
: [beginMeterValue
],
174 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
177 public async sendTransactionEndMeterValues(
179 transactionId
: number,
180 endMeterValue
: OCPP16MeterValue
182 const payload
: MeterValuesRequest
= {
185 meterValue
: [endMeterValue
],
187 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
190 public async sendDiagnosticsStatusNotification(
191 diagnosticsStatus
: OCPP16DiagnosticsStatus
193 const payload
: DiagnosticsStatusNotificationRequest
= {
194 status: diagnosticsStatus
,
196 await this.sendMessage(
197 Utils
.generateUUID(),
199 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
203 private buildCommandPayload(
204 commandName
: OCPP16RequestCommand
,
205 commandParams
?: JsonType
207 switch (commandName
) {
208 case OCPP16RequestCommand
.AUTHORIZE
:
210 ...(!Utils
.isUndefined(commandParams
?.idTag
)
211 ? { idTag
: commandParams
.idTag
}
212 : { idTag
: Constants
.DEFAULT_IDTAG
}),
213 } as AuthorizeRequest
;
214 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
216 chargePointModel
: commandParams
?.chargePointModel
,
217 chargePointVendor
: commandParams
?.chargePointVendor
,
218 ...(!Utils
.isUndefined(commandParams
?.chargeBoxSerialNumber
) && {
219 chargeBoxSerialNumber
: commandParams
.chargeBoxSerialNumber
,
221 ...(!Utils
.isUndefined(commandParams
?.chargePointSerialNumber
) && {
222 chargePointSerialNumber
: commandParams
.chargePointSerialNumber
,
224 ...(!Utils
.isUndefined(commandParams
?.firmwareVersion
) && {
225 firmwareVersion
: commandParams
.firmwareVersion
,
227 ...(!Utils
.isUndefined(commandParams
?.iccid
) && { iccid
: commandParams
.iccid
}),
228 ...(!Utils
.isUndefined(commandParams
?.imsi
) && { imsi
: commandParams
.imsi
}),
229 ...(!Utils
.isUndefined(commandParams
?.meterSerialNumber
) && {
230 meterSerialNumber
: commandParams
.meterSerialNumber
,
232 ...(!Utils
.isUndefined(commandParams
?.meterType
) && {
233 meterType
: commandParams
.meterType
,
235 } as OCPP16BootNotificationRequest
;
236 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
238 status: commandParams
?.diagnosticsStatus
,
239 } as DiagnosticsStatusNotificationRequest
;
240 case OCPP16RequestCommand
.HEARTBEAT
:
241 return {} as HeartbeatRequest
;
242 case OCPP16RequestCommand
.METER_VALUES
:
244 connectorId
: commandParams
?.connectorId
,
245 transactionId
: commandParams
?.transactionId
,
246 meterValue
: Array.isArray(commandParams
?.meterValues
)
247 ? commandParams
?.meterValues
248 : [commandParams
?.meterValue
],
249 } as MeterValuesRequest
;
250 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
252 connectorId
: commandParams
?.connectorId
,
253 status: commandParams
?.status,
254 errorCode
: commandParams
?.errorCode
,
255 } as StatusNotificationRequest
;
256 case OCPP16RequestCommand
.START_TRANSACTION
:
258 connectorId
: commandParams
?.connectorId
,
259 ...(!Utils
.isUndefined(commandParams
?.idTag
)
260 ? { idTag
: commandParams
?.idTag
}
261 : { idTag
: Constants
.DEFAULT_IDTAG
}),
262 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(
263 commandParams
?.connectorId
as number
265 timestamp
: new Date().toISOString(),
266 } as StartTransactionRequest
;
267 case OCPP16RequestCommand
.STOP_TRANSACTION
:
269 transactionId
: commandParams
?.transactionId
,
270 ...(!Utils
.isUndefined(commandParams
?.idTag
) && { idTag
: commandParams
.idTag
}),
271 meterStop
: commandParams
?.meterStop
,
272 timestamp
: new Date().toISOString(),
273 ...(commandParams
?.reason
&& { reason
: commandParams
.reason
}),
274 ...(this.chargingStation
.getTransactionDataMeterValues() && {
275 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
276 this.chargingStation
.getConnectorStatus(commandParams
?.connectorId
as number)
277 .transactionBeginMeterValue
,
278 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
279 this.chargingStation
,
280 commandParams
?.connectorId
as number,
281 commandParams
?.meterStop
as number
285 } as StopTransactionRequest
;
288 ErrorType
.NOT_SUPPORTED
,
289 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
290 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,