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';
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 { OCPP16BootNotificationResponse
} from
'../../../types/ocpp/1.6/Responses';
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 { SendParams
} from
'../../../types/ocpp/Requests';
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 sendHeartbeat(params
?: SendParams
): Promise
<void> {
47 const payload
: HeartbeatRequest
= {};
48 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.HEARTBEAT
, params
);
51 public async sendBootNotification(
52 chargePointModel
: string,
53 chargePointVendor
: string,
54 chargeBoxSerialNumber
?: string,
55 firmwareVersion
?: string,
56 chargePointSerialNumber
?: string,
59 meterSerialNumber
?: string,
62 ): Promise
<OCPP16BootNotificationResponse
> {
63 const payload
: OCPP16BootNotificationRequest
= {
66 ...(!Utils
.isUndefined(chargeBoxSerialNumber
) && { chargeBoxSerialNumber
}),
67 ...(!Utils
.isUndefined(chargePointSerialNumber
) && { chargePointSerialNumber
}),
68 ...(!Utils
.isUndefined(firmwareVersion
) && { firmwareVersion
}),
69 ...(!Utils
.isUndefined(iccid
) && { iccid
}),
70 ...(!Utils
.isUndefined(imsi
) && { imsi
}),
71 ...(!Utils
.isUndefined(meterSerialNumber
) && { meterSerialNumber
}),
72 ...(!Utils
.isUndefined(meterType
) && { meterType
}),
74 return (await this.sendMessage(
77 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
78 { ...params
, skipBufferingOnError
: true }
79 )) as OCPP16BootNotificationResponse
;
82 public async sendStatusNotification(
84 status: OCPP16ChargePointStatus
,
85 errorCode
: OCPP16ChargePointErrorCode
= OCPP16ChargePointErrorCode
.NO_ERROR
87 const payload
: StatusNotificationRequest
= {
92 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.STATUS_NOTIFICATION
);
95 public async sendAuthorize(
98 ): Promise
<OCPP16AuthorizeResponse
> {
99 const payload
: AuthorizeRequest
= {
100 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
102 this.chargingStation
.getConnectorStatus(connectorId
).authorizeIdTag
= idTag
;
103 return (await this.sendMessage(
104 Utils
.generateUUID(),
106 OCPP16RequestCommand
.AUTHORIZE
107 )) as OCPP16AuthorizeResponse
;
110 public async sendStartTransaction(
113 ): Promise
<OCPP16StartTransactionResponse
> {
114 const payload
: StartTransactionRequest
= {
116 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
117 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(connectorId
),
118 timestamp
: new Date().toISOString(),
120 return (await this.sendMessage(
121 Utils
.generateUUID(),
123 OCPP16RequestCommand
.START_TRANSACTION
124 )) as OCPP16StartTransactionResponse
;
127 public async sendStopTransaction(
128 transactionId
: number,
131 reason
: OCPP16StopTransactionReason
= OCPP16StopTransactionReason
.NONE
132 ): Promise
<OCPP16StopTransactionResponse
> {
133 let connectorId
: number;
134 for (const id
of this.chargingStation
.connectors
.keys()) {
135 if (id
> 0 && this.chargingStation
.getConnectorStatus(id
)?.transactionId
=== transactionId
) {
140 const transactionEndMeterValue
= OCPP16ServiceUtils
.buildTransactionEndMeterValue(
141 this.chargingStation
,
145 // FIXME: should be a callback, each OCPP commands implementation must do only one job
146 this.chargingStation
.getBeginEndMeterValues() &&
147 this.chargingStation
.getOcppStrictCompliance() &&
148 !this.chargingStation
.getOutOfOrderEndMeterValues() &&
149 (await this.sendTransactionEndMeterValues(
152 transactionEndMeterValue
154 const payload
: StopTransactionRequest
= {
156 ...(!Utils
.isUndefined(idTag
) && { idTag
}),
158 timestamp
: new Date().toISOString(),
159 ...(reason
&& { reason
}),
160 ...(this.chargingStation
.getTransactionDataMeterValues() && {
161 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
162 this.chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
163 transactionEndMeterValue
167 return (await this.sendMessage(
168 Utils
.generateUUID(),
170 OCPP16RequestCommand
.STOP_TRANSACTION
171 )) as OCPP16StartTransactionResponse
;
174 public async sendMeterValues(
176 transactionId
: number,
179 const meterValue
= OCPP16ServiceUtils
.buildMeterValue(
180 this.chargingStation
,
185 const payload
: MeterValuesRequest
= {
188 meterValue
: [meterValue
],
190 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
193 public async sendTransactionBeginMeterValues(
195 transactionId
: number,
196 beginMeterValue
: OCPP16MeterValue
198 const payload
: MeterValuesRequest
= {
201 meterValue
: [beginMeterValue
],
203 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
206 public async sendTransactionEndMeterValues(
208 transactionId
: number,
209 endMeterValue
: OCPP16MeterValue
211 const payload
: MeterValuesRequest
= {
214 meterValue
: [endMeterValue
],
216 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
219 public async sendDiagnosticsStatusNotification(
220 diagnosticsStatus
: OCPP16DiagnosticsStatus
222 const payload
: DiagnosticsStatusNotificationRequest
= {
223 status: diagnosticsStatus
,
225 await this.sendMessage(
226 Utils
.generateUUID(),
228 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
232 private buildCommandPayload(
233 commandName
: OCPP16RequestCommand
,
234 commandParams
: JsonType
236 switch (commandName
) {
237 case OCPP16RequestCommand
.AUTHORIZE
:
239 ...(!Utils
.isUndefined(commandParams
?.idTag
)
240 ? { idTag
: commandParams
.idTag
}
241 : { idTag
: Constants
.DEFAULT_IDTAG
}),
242 } as AuthorizeRequest
;
243 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
245 chargePointModel
: commandParams
?.chargePointModel
,
246 chargePointVendor
: commandParams
?.chargePointVendor
,
247 ...(!Utils
.isUndefined(commandParams
?.chargeBoxSerialNumber
) && {
248 chargeBoxSerialNumber
: commandParams
.chargeBoxSerialNumber
,
250 ...(!Utils
.isUndefined(commandParams
?.chargePointSerialNumber
) && {
251 chargePointSerialNumber
: commandParams
.chargePointSerialNumber
,
253 ...(!Utils
.isUndefined(commandParams
?.firmwareVersion
) && {
254 firmwareVersion
: commandParams
.firmwareVersion
,
256 ...(!Utils
.isUndefined(commandParams
?.iccid
) && { iccid
: commandParams
.iccid
}),
257 ...(!Utils
.isUndefined(commandParams
?.imsi
) && { imsi
: commandParams
.imsi
}),
258 ...(!Utils
.isUndefined(commandParams
?.meterSerialNumber
) && {
259 meterSerialNumber
: commandParams
.meterSerialNumber
,
261 ...(!Utils
.isUndefined(commandParams
?.meterType
) && {
262 meterType
: commandParams
.meterType
,
264 } as OCPP16BootNotificationRequest
;
265 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
267 status: commandParams
?.diagnosticsStatus
,
268 } as DiagnosticsStatusNotificationRequest
;
269 case OCPP16RequestCommand
.HEARTBEAT
:
270 return {} as HeartbeatRequest
;
271 case OCPP16RequestCommand
.METER_VALUES
:
273 connectorId
: commandParams
?.connectorId
,
274 transactionId
: commandParams
?.transactionId
,
275 meterValue
: Array.isArray(commandParams
?.meterValues
)
276 ? commandParams
?.meterValues
277 : [commandParams
?.meterValue
],
278 } as MeterValuesRequest
;
279 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
281 connectorId
: commandParams
?.connectorId
,
282 errorCode
: commandParams
?.errorCode
,
283 status: commandParams
?.status,
284 } as StatusNotificationRequest
;
285 case OCPP16RequestCommand
.START_TRANSACTION
:
287 connectorId
: commandParams
?.connectorId
,
288 ...(!Utils
.isUndefined(commandParams
?.idTag
)
289 ? { idTag
: commandParams
?.idTag
}
290 : { idTag
: Constants
.DEFAULT_IDTAG
}),
291 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(
292 commandParams
?.connectorId
as number
294 timestamp
: new Date().toISOString(),
295 } as StartTransactionRequest
;
296 case OCPP16RequestCommand
.STOP_TRANSACTION
:
298 transactionId
: commandParams
?.transactionId
,
299 ...(!Utils
.isUndefined(commandParams
?.idTag
) && { idTag
: commandParams
.idTag
}),
300 meterStop
: commandParams
?.meterStop
,
301 timestamp
: new Date().toISOString(),
302 ...(commandParams
?.reason
&& { reason
: commandParams
.reason
}),
303 ...(this.chargingStation
.getTransactionDataMeterValues() && {
304 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
305 this.chargingStation
.getConnectorStatus(commandParams
?.connectorId
as number)
306 .transactionBeginMeterValue
,
307 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
308 this.chargingStation
,
309 commandParams
?.connectorId
as number,
310 commandParams
?.meterStop
as number
314 } as StopTransactionRequest
;
317 ErrorType
.NOT_SUPPORTED
,
318 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
319 `Unsupported OCPP command: ${commandName}`,