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 { OCPP16BootNotificationResponse
} from
'../../../types/ocpp/1.6/Responses';
27 import { OCPP16ChargePointErrorCode
} from
'../../../types/ocpp/1.6/ChargePointErrorCode';
28 import { OCPP16ChargePointStatus
} from
'../../../types/ocpp/1.6/ChargePointStatus';
29 import { OCPP16DiagnosticsStatus
} from
'../../../types/ocpp/1.6/DiagnosticsStatus';
30 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
31 import OCPPError from
'../../../exception/OCPPError';
32 import OCPPRequestService from
'../OCPPRequestService';
33 import type OCPPResponseService from
'../OCPPResponseService';
34 import Utils from
'../../../utils/Utils';
36 const moduleName
= 'OCPP16RequestService';
38 export default class OCPP16RequestService
extends OCPPRequestService
{
39 public constructor(chargingStation
: ChargingStation
, ocppResponseService
: OCPPResponseService
) {
40 if (new.target
?.name
=== moduleName
) {
41 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
43 super(chargingStation
, ocppResponseService
);
46 public async sendMessageHandler(
47 commandName
: OCPP16RequestCommand
,
48 commandParams
?: JsonType
,
50 ): Promise
<ResponseType
> {
51 if (Object.values(OCPP16RequestCommand
).includes(commandName
)) {
52 return this.sendMessage(
54 this.buildCommandPayload(commandName
, commandParams
),
60 ErrorType
.NOT_SUPPORTED
,
61 `${moduleName}.sendMessageHandler: Unsupported OCPP command ${commandName}`,
67 public async sendBootNotification(
68 chargePointModel
: string,
69 chargePointVendor
: string,
70 chargeBoxSerialNumber
?: string,
71 firmwareVersion
?: string,
72 chargePointSerialNumber
?: string,
75 meterSerialNumber
?: string,
78 ): Promise
<OCPP16BootNotificationResponse
> {
79 const payload
: OCPP16BootNotificationRequest
= {
82 ...(!Utils
.isUndefined(chargeBoxSerialNumber
) && { chargeBoxSerialNumber
}),
83 ...(!Utils
.isUndefined(chargePointSerialNumber
) && { chargePointSerialNumber
}),
84 ...(!Utils
.isUndefined(firmwareVersion
) && { firmwareVersion
}),
85 ...(!Utils
.isUndefined(iccid
) && { iccid
}),
86 ...(!Utils
.isUndefined(imsi
) && { imsi
}),
87 ...(!Utils
.isUndefined(meterSerialNumber
) && { meterSerialNumber
}),
88 ...(!Utils
.isUndefined(meterType
) && { meterType
}),
90 return (await this.sendMessage(
93 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
94 { ...params
, skipBufferingOnError
: true }
95 )) as OCPP16BootNotificationResponse
;
98 public async sendStatusNotification(
100 status: OCPP16ChargePointStatus
,
101 errorCode
: OCPP16ChargePointErrorCode
= OCPP16ChargePointErrorCode
.NO_ERROR
103 const payload
: StatusNotificationRequest
= {
108 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.STATUS_NOTIFICATION
);
111 public async sendAuthorize(
114 ): Promise
<OCPP16AuthorizeResponse
> {
115 const payload
: AuthorizeRequest
= {
116 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
118 this.chargingStation
.getConnectorStatus(connectorId
).authorizeIdTag
= idTag
;
119 return (await this.sendMessage(
120 Utils
.generateUUID(),
122 OCPP16RequestCommand
.AUTHORIZE
123 )) as OCPP16AuthorizeResponse
;
126 public async sendStartTransaction(
129 ): Promise
<OCPP16StartTransactionResponse
> {
130 const payload
: StartTransactionRequest
= {
132 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
133 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(connectorId
),
134 timestamp
: new Date().toISOString(),
136 return (await this.sendMessage(
137 Utils
.generateUUID(),
139 OCPP16RequestCommand
.START_TRANSACTION
140 )) as OCPP16StartTransactionResponse
;
143 public async sendStopTransaction(
144 transactionId
: number,
147 reason
: OCPP16StopTransactionReason
= OCPP16StopTransactionReason
.NONE
148 ): Promise
<OCPP16StopTransactionResponse
> {
149 let connectorId
: number;
150 for (const id
of this.chargingStation
.connectors
.keys()) {
151 if (id
> 0 && this.chargingStation
.getConnectorStatus(id
)?.transactionId
=== transactionId
) {
156 const transactionEndMeterValue
= OCPP16ServiceUtils
.buildTransactionEndMeterValue(
157 this.chargingStation
,
161 // FIXME: should be a callback, each OCPP commands implementation must do only one job
162 this.chargingStation
.getBeginEndMeterValues() &&
163 this.chargingStation
.getOcppStrictCompliance() &&
164 !this.chargingStation
.getOutOfOrderEndMeterValues() &&
165 (await this.sendTransactionEndMeterValues(
168 transactionEndMeterValue
170 const payload
: StopTransactionRequest
= {
172 ...(!Utils
.isUndefined(idTag
) && { idTag
}),
174 timestamp
: new Date().toISOString(),
175 ...(reason
&& { reason
}),
176 ...(this.chargingStation
.getTransactionDataMeterValues() && {
177 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
178 this.chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
179 transactionEndMeterValue
183 return (await this.sendMessage(
184 Utils
.generateUUID(),
186 OCPP16RequestCommand
.STOP_TRANSACTION
187 )) as OCPP16StartTransactionResponse
;
190 public async sendMeterValues(
192 transactionId
: number,
195 const meterValue
: OCPP16MeterValue
= OCPP16ServiceUtils
.buildMeterValue(
196 this.chargingStation
,
201 const payload
: MeterValuesRequest
= {
204 meterValue
: [meterValue
],
206 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
209 public async sendTransactionBeginMeterValues(
211 transactionId
: number,
212 beginMeterValue
: OCPP16MeterValue
214 const payload
: MeterValuesRequest
= {
217 meterValue
: [beginMeterValue
],
219 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
222 public async sendTransactionEndMeterValues(
224 transactionId
: number,
225 endMeterValue
: OCPP16MeterValue
227 const payload
: MeterValuesRequest
= {
230 meterValue
: [endMeterValue
],
232 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
235 public async sendDiagnosticsStatusNotification(
236 diagnosticsStatus
: OCPP16DiagnosticsStatus
238 const payload
: DiagnosticsStatusNotificationRequest
= {
239 status: diagnosticsStatus
,
241 await this.sendMessage(
242 Utils
.generateUUID(),
244 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
248 private buildCommandPayload(
249 commandName
: OCPP16RequestCommand
,
250 commandParams
?: JsonType
252 switch (commandName
) {
253 case OCPP16RequestCommand
.AUTHORIZE
:
255 ...(!Utils
.isUndefined(commandParams
?.idTag
)
256 ? { idTag
: commandParams
.idTag
}
257 : { idTag
: Constants
.DEFAULT_IDTAG
}),
258 } as AuthorizeRequest
;
259 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
261 chargePointModel
: commandParams
?.chargePointModel
,
262 chargePointVendor
: commandParams
?.chargePointVendor
,
263 ...(!Utils
.isUndefined(commandParams
?.chargeBoxSerialNumber
) && {
264 chargeBoxSerialNumber
: commandParams
.chargeBoxSerialNumber
,
266 ...(!Utils
.isUndefined(commandParams
?.chargePointSerialNumber
) && {
267 chargePointSerialNumber
: commandParams
.chargePointSerialNumber
,
269 ...(!Utils
.isUndefined(commandParams
?.firmwareVersion
) && {
270 firmwareVersion
: commandParams
.firmwareVersion
,
272 ...(!Utils
.isUndefined(commandParams
?.iccid
) && { iccid
: commandParams
.iccid
}),
273 ...(!Utils
.isUndefined(commandParams
?.imsi
) && { imsi
: commandParams
.imsi
}),
274 ...(!Utils
.isUndefined(commandParams
?.meterSerialNumber
) && {
275 meterSerialNumber
: commandParams
.meterSerialNumber
,
277 ...(!Utils
.isUndefined(commandParams
?.meterType
) && {
278 meterType
: commandParams
.meterType
,
280 } as OCPP16BootNotificationRequest
;
281 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
283 status: commandParams
?.diagnosticsStatus
,
284 } as DiagnosticsStatusNotificationRequest
;
285 case OCPP16RequestCommand
.HEARTBEAT
:
286 return {} as HeartbeatRequest
;
287 case OCPP16RequestCommand
.METER_VALUES
:
289 connectorId
: commandParams
?.connectorId
,
290 transactionId
: commandParams
?.transactionId
,
291 meterValue
: Array.isArray(commandParams
?.meterValues
)
292 ? commandParams
?.meterValues
293 : [commandParams
?.meterValue
],
294 } as MeterValuesRequest
;
295 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
297 connectorId
: commandParams
?.connectorId
,
298 errorCode
: commandParams
?.errorCode
,
299 status: commandParams
?.status,
300 } as StatusNotificationRequest
;
301 case OCPP16RequestCommand
.START_TRANSACTION
:
303 connectorId
: commandParams
?.connectorId
,
304 ...(!Utils
.isUndefined(commandParams
?.idTag
)
305 ? { idTag
: commandParams
?.idTag
}
306 : { idTag
: Constants
.DEFAULT_IDTAG
}),
307 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(
308 commandParams
?.connectorId
as number
310 timestamp
: new Date().toISOString(),
311 } as StartTransactionRequest
;
312 case OCPP16RequestCommand
.STOP_TRANSACTION
:
314 transactionId
: commandParams
?.transactionId
,
315 ...(!Utils
.isUndefined(commandParams
?.idTag
) && { idTag
: commandParams
.idTag
}),
316 meterStop
: commandParams
?.meterStop
,
317 timestamp
: new Date().toISOString(),
318 ...(commandParams
?.reason
&& { reason
: commandParams
.reason
}),
319 ...(this.chargingStation
.getTransactionDataMeterValues() && {
320 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
321 this.chargingStation
.getConnectorStatus(commandParams
?.connectorId
as number)
322 .transactionBeginMeterValue
,
323 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
324 this.chargingStation
,
325 commandParams
?.connectorId
as number,
326 commandParams
?.meterStop
as number
330 } as StopTransactionRequest
;
333 ErrorType
.NOT_SUPPORTED
,
334 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
335 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,