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 sendStatusNotification(
68 status: OCPP16ChargePointStatus
,
69 errorCode
: OCPP16ChargePointErrorCode
= OCPP16ChargePointErrorCode
.NO_ERROR
71 const payload
: StatusNotificationRequest
= {
76 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.STATUS_NOTIFICATION
);
79 public async sendAuthorize(
82 ): Promise
<OCPP16AuthorizeResponse
> {
83 const payload
: AuthorizeRequest
= {
84 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
86 this.chargingStation
.getConnectorStatus(connectorId
).authorizeIdTag
= idTag
;
87 return (await this.sendMessage(
90 OCPP16RequestCommand
.AUTHORIZE
91 )) as OCPP16AuthorizeResponse
;
94 public async sendStartTransaction(
97 ): Promise
<OCPP16StartTransactionResponse
> {
98 const payload
: StartTransactionRequest
= {
100 ...(!Utils
.isUndefined(idTag
) ? { idTag
} : { idTag
: Constants
.DEFAULT_IDTAG
}),
101 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(connectorId
),
102 timestamp
: new Date().toISOString(),
104 return (await this.sendMessage(
105 Utils
.generateUUID(),
107 OCPP16RequestCommand
.START_TRANSACTION
108 )) as OCPP16StartTransactionResponse
;
111 public async sendStopTransaction(
112 transactionId
: number,
115 reason
: OCPP16StopTransactionReason
= OCPP16StopTransactionReason
.NONE
116 ): Promise
<OCPP16StopTransactionResponse
> {
117 let connectorId
: number;
118 for (const id
of this.chargingStation
.connectors
.keys()) {
119 if (id
> 0 && this.chargingStation
.getConnectorStatus(id
)?.transactionId
=== transactionId
) {
124 const transactionEndMeterValue
= OCPP16ServiceUtils
.buildTransactionEndMeterValue(
125 this.chargingStation
,
129 // FIXME: should be a callback, each OCPP commands implementation must do only one job
130 this.chargingStation
.getBeginEndMeterValues() &&
131 this.chargingStation
.getOcppStrictCompliance() &&
132 !this.chargingStation
.getOutOfOrderEndMeterValues() &&
133 (await this.sendTransactionEndMeterValues(
136 transactionEndMeterValue
138 const payload
: StopTransactionRequest
= {
140 ...(!Utils
.isUndefined(idTag
) && { idTag
}),
142 timestamp
: new Date().toISOString(),
143 ...(reason
&& { reason
}),
144 ...(this.chargingStation
.getTransactionDataMeterValues() && {
145 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
146 this.chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
,
147 transactionEndMeterValue
151 return (await this.sendMessage(
152 Utils
.generateUUID(),
154 OCPP16RequestCommand
.STOP_TRANSACTION
155 )) as OCPP16StartTransactionResponse
;
158 public async sendMeterValues(
160 transactionId
: number,
163 const meterValue
: OCPP16MeterValue
= OCPP16ServiceUtils
.buildMeterValue(
164 this.chargingStation
,
169 const payload
: MeterValuesRequest
= {
172 meterValue
: [meterValue
],
174 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
177 public async sendTransactionBeginMeterValues(
179 transactionId
: number,
180 beginMeterValue
: OCPP16MeterValue
182 const payload
: MeterValuesRequest
= {
185 meterValue
: [beginMeterValue
],
187 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
190 public async sendTransactionEndMeterValues(
192 transactionId
: number,
193 endMeterValue
: OCPP16MeterValue
195 const payload
: MeterValuesRequest
= {
198 meterValue
: [endMeterValue
],
200 await this.sendMessage(Utils
.generateUUID(), payload
, OCPP16RequestCommand
.METER_VALUES
);
203 public async sendDiagnosticsStatusNotification(
204 diagnosticsStatus
: OCPP16DiagnosticsStatus
206 const payload
: DiagnosticsStatusNotificationRequest
= {
207 status: diagnosticsStatus
,
209 await this.sendMessage(
210 Utils
.generateUUID(),
212 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
216 private buildCommandPayload(
217 commandName
: OCPP16RequestCommand
,
218 commandParams
?: JsonType
220 switch (commandName
) {
221 case OCPP16RequestCommand
.AUTHORIZE
:
223 ...(!Utils
.isUndefined(commandParams
?.idTag
)
224 ? { idTag
: commandParams
.idTag
}
225 : { idTag
: Constants
.DEFAULT_IDTAG
}),
226 } as AuthorizeRequest
;
227 case OCPP16RequestCommand
.BOOT_NOTIFICATION
:
229 chargePointModel
: commandParams
?.chargePointModel
,
230 chargePointVendor
: commandParams
?.chargePointVendor
,
231 ...(!Utils
.isUndefined(commandParams
?.chargeBoxSerialNumber
) && {
232 chargeBoxSerialNumber
: commandParams
.chargeBoxSerialNumber
,
234 ...(!Utils
.isUndefined(commandParams
?.chargePointSerialNumber
) && {
235 chargePointSerialNumber
: commandParams
.chargePointSerialNumber
,
237 ...(!Utils
.isUndefined(commandParams
?.firmwareVersion
) && {
238 firmwareVersion
: commandParams
.firmwareVersion
,
240 ...(!Utils
.isUndefined(commandParams
?.iccid
) && { iccid
: commandParams
.iccid
}),
241 ...(!Utils
.isUndefined(commandParams
?.imsi
) && { imsi
: commandParams
.imsi
}),
242 ...(!Utils
.isUndefined(commandParams
?.meterSerialNumber
) && {
243 meterSerialNumber
: commandParams
.meterSerialNumber
,
245 ...(!Utils
.isUndefined(commandParams
?.meterType
) && {
246 meterType
: commandParams
.meterType
,
248 } as OCPP16BootNotificationRequest
;
249 case OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
:
251 status: commandParams
?.diagnosticsStatus
,
252 } as DiagnosticsStatusNotificationRequest
;
253 case OCPP16RequestCommand
.HEARTBEAT
:
254 return {} as HeartbeatRequest
;
255 case OCPP16RequestCommand
.METER_VALUES
:
257 connectorId
: commandParams
?.connectorId
,
258 transactionId
: commandParams
?.transactionId
,
259 meterValue
: Array.isArray(commandParams
?.meterValues
)
260 ? commandParams
?.meterValues
261 : [commandParams
?.meterValue
],
262 } as MeterValuesRequest
;
263 case OCPP16RequestCommand
.STATUS_NOTIFICATION
:
265 connectorId
: commandParams
?.connectorId
,
266 errorCode
: commandParams
?.errorCode
,
267 status: commandParams
?.status,
268 } as StatusNotificationRequest
;
269 case OCPP16RequestCommand
.START_TRANSACTION
:
271 connectorId
: commandParams
?.connectorId
,
272 ...(!Utils
.isUndefined(commandParams
?.idTag
)
273 ? { idTag
: commandParams
?.idTag
}
274 : { idTag
: Constants
.DEFAULT_IDTAG
}),
275 meterStart
: this.chargingStation
.getEnergyActiveImportRegisterByConnectorId(
276 commandParams
?.connectorId
as number
278 timestamp
: new Date().toISOString(),
279 } as StartTransactionRequest
;
280 case OCPP16RequestCommand
.STOP_TRANSACTION
:
282 transactionId
: commandParams
?.transactionId
,
283 ...(!Utils
.isUndefined(commandParams
?.idTag
) && { idTag
: commandParams
.idTag
}),
284 meterStop
: commandParams
?.meterStop
,
285 timestamp
: new Date().toISOString(),
286 ...(commandParams
?.reason
&& { reason
: commandParams
.reason
}),
287 ...(this.chargingStation
.getTransactionDataMeterValues() && {
288 transactionData
: OCPP16ServiceUtils
.buildTransactionDataMeterValues(
289 this.chargingStation
.getConnectorStatus(commandParams
?.connectorId
as number)
290 .transactionBeginMeterValue
,
291 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
292 this.chargingStation
,
293 commandParams
?.connectorId
as number,
294 commandParams
?.meterStop
as number
298 } as StopTransactionRequest
;
301 ErrorType
.NOT_SUPPORTED
,
302 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
303 `${moduleName}.buildCommandPayload: Unsupported OCPP command: ${commandName}`,