feat: add template example with evses configuration
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16RequestService.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
c8eeb62b 2
6c1761d4 3import type { JSONSchemaType } from 'ajv';
b52c969d 4
2896e06d 5import type { ChargingStation } from '../../../charging-station';
268a74bb 6import { OCPPError } from '../../../exception';
b52c969d 7import {
268a74bb
JB
8 ErrorType,
9 type JsonObject,
10 type JsonType,
11 type OCPP16AuthorizeRequest,
27782dbc
JB
12 type OCPP16BootNotificationRequest,
13 type OCPP16DataTransferRequest,
c9a4f9ea 14 type OCPP16DiagnosticsStatusNotificationRequest,
e9a4164c 15 type OCPP16FirmwareStatusNotificationRequest,
27782dbc 16 type OCPP16HeartbeatRequest,
268a74bb 17 type OCPP16MeterValuesRequest,
b52c969d 18 OCPP16RequestCommand,
268a74bb 19 type OCPP16StartTransactionRequest,
27782dbc 20 type OCPP16StatusNotificationRequest,
268a74bb
JB
21 type OCPP16StopTransactionRequest,
22 OCPPVersion,
23 type RequestParams,
24} from '../../../types';
60a74391 25import { Constants, Utils } from '../../../utils';
2896e06d 26import {
d8b1fab1 27 OCPP16Constants,
2896e06d 28 OCPP16ServiceUtils,
2896e06d
JB
29 OCPPRequestService,
30 type OCPPResponseService,
31} from '../internal';
c0560973 32
909dcf2d
JB
33const moduleName = 'OCPP16RequestService';
34
268a74bb 35export class OCPP16RequestService extends OCPPRequestService {
b3fc3ff5 36 protected jsonSchemas: Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>;
b52c969d 37
08f130a0 38 public constructor(ocppResponseService: OCPPResponseService) {
b768993d
JB
39 // if (new.target?.name === moduleName) {
40 // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
41 // }
d270cc87 42 super(OCPPVersion.VERSION_16, ocppResponseService);
b52c969d
JB
43 this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>([
44 [
45 OCPP16RequestCommand.AUTHORIZE,
130783a7 46 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
1b271a54
JB
47 '../../../assets/json-schemas/ocpp/1.6/Authorize.json',
48 moduleName,
49 'constructor'
e9a4164c 50 ),
b52c969d
JB
51 ],
52 [
53 OCPP16RequestCommand.BOOT_NOTIFICATION,
130783a7 54 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
1b271a54
JB
55 '../../../assets/json-schemas/ocpp/1.6/BootNotification.json',
56 moduleName,
57 'constructor'
e9a4164c 58 ),
b52c969d
JB
59 ],
60 [
61 OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
130783a7 62 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
1b271a54
JB
63 '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
64 moduleName,
65 'constructor'
e9a4164c 66 ),
b52c969d
JB
67 ],
68 [
69 OCPP16RequestCommand.HEARTBEAT,
130783a7 70 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
1b271a54
JB
71 '../../../assets/json-schemas/ocpp/1.6/Heartbeat.json',
72 moduleName,
73 'constructor'
e9a4164c 74 ),
b52c969d
JB
75 ],
76 [
77 OCPP16RequestCommand.METER_VALUES,
130783a7 78 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
1b271a54
JB
79 '../../../assets/json-schemas/ocpp/1.6/MeterValues.json',
80 moduleName,
81 'constructor'
e9a4164c 82 ),
b52c969d
JB
83 ],
84 [
85 OCPP16RequestCommand.STATUS_NOTIFICATION,
130783a7 86 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
1b271a54
JB
87 '../../../assets/json-schemas/ocpp/1.6/StatusNotification.json',
88 moduleName,
89 'constructor'
e9a4164c 90 ),
b52c969d
JB
91 ],
92 [
93 OCPP16RequestCommand.START_TRANSACTION,
130783a7 94 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
1b271a54
JB
95 '../../../assets/json-schemas/ocpp/1.6/StartTransaction.json',
96 moduleName,
97 'constructor'
e9a4164c 98 ),
b52c969d
JB
99 ],
100 [
101 OCPP16RequestCommand.STOP_TRANSACTION,
130783a7 102 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
1b271a54
JB
103 '../../../assets/json-schemas/ocpp/1.6/StopTransaction.json',
104 moduleName,
105 'constructor'
e9a4164c 106 ),
b52c969d 107 ],
91a7d3ea
JB
108 [
109 OCPP16RequestCommand.DATA_TRANSFER,
130783a7 110 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
1b271a54
JB
111 '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json',
112 moduleName,
113 'constructor'
e9a4164c 114 ),
91a7d3ea 115 ],
c9a4f9ea
JB
116 [
117 OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
130783a7 118 OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
1b271a54
JB
119 '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
120 moduleName,
121 'constructor'
e9a4164c 122 ),
c9a4f9ea 123 ],
b52c969d 124 ]);
31f59c6d
JB
125 this.buildRequestPayload = this.buildRequestPayload.bind(this) as <Request extends JsonType>(
126 chargingStation: ChargingStation,
127 commandName: OCPP16RequestCommand,
128 commandParams?: JsonType
129 ) => Request;
9f2e3130
JB
130 }
131
6c1761d4 132 public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
08f130a0 133 chargingStation: ChargingStation,
94a464f9 134 commandName: OCPP16RequestCommand,
5cc4b63b 135 commandParams?: JsonType,
be9b0d50 136 params?: RequestParams
6c1761d4 137 ): Promise<ResponseType> {
62340a29 138 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
ed6cfcff 139 if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) {
f22266fd 140 return (await this.sendMessage(
08f130a0 141 chargingStation,
94a464f9 142 Utils.generateUUID(),
18bf8274 143 this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
94a464f9
JB
144 commandName,
145 params
617cad0c 146 )) as ResponseType;
94a464f9 147 }
e909d2a7 148 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
94a464f9
JB
149 throw new OCPPError(
150 ErrorType.NOT_SUPPORTED,
6c8f5d90 151 `Unsupported OCPP command '${commandName}'`,
94a464f9 152 commandName,
7369e417 153 commandParams
94a464f9 154 );
c0560973
JB
155 }
156
5cc4b63b 157 private buildRequestPayload<Request extends JsonType>(
08f130a0 158 chargingStation: ChargingStation,
78085c42 159 commandName: OCPP16RequestCommand,
5cc4b63b 160 commandParams?: JsonType
f22266fd 161 ): Request {
68c993d5 162 let connectorId: number;
cf058664 163 let energyActiveImportRegister: number;
5cc4b63b 164 commandParams = commandParams as JsonObject;
78085c42 165 switch (commandName) {
78085c42 166 case OCPP16RequestCommand.BOOT_NOTIFICATION:
78085c42 167 case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
22e0d48e 168 case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
78085c42 169 case OCPP16RequestCommand.METER_VALUES:
78085c42 170 case OCPP16RequestCommand.STATUS_NOTIFICATION:
36c462a4
JB
171 case OCPP16RequestCommand.DATA_TRANSFER:
172 return commandParams as unknown as Request;
173 case OCPP16RequestCommand.AUTHORIZE:
78085c42 174 return {
36c462a4
JB
175 idTag: Constants.DEFAULT_IDTAG,
176 ...commandParams,
f22266fd 177 } as unknown as Request;
36c462a4 178 case OCPP16RequestCommand.HEARTBEAT:
d8b1fab1 179 return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request;
78085c42
JB
180 case OCPP16RequestCommand.START_TRANSACTION:
181 return {
36c462a4
JB
182 idTag: Constants.DEFAULT_IDTAG,
183 meterStart: chargingStation.getEnergyActiveImportRegisterByConnectorId(
18bf8274
JB
184 commandParams?.connectorId as number,
185 true
36c462a4
JB
186 ),
187 timestamp: new Date(),
188 ...commandParams,
f22266fd 189 } as unknown as Request;
78085c42 190 case OCPP16RequestCommand.STOP_TRANSACTION:
f1e731bd 191 chargingStation.getTransactionDataMeterValues() &&
f1e731bd
JB
192 (connectorId = chargingStation.getConnectorIdByTransactionId(
193 commandParams?.transactionId as number
194 ));
36c462a4
JB
195 energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId(
196 commandParams?.transactionId as number,
197 true
198 );
78085c42 199 return {
36c462a4
JB
200 idTag: chargingStation.getTransactionIdTag(commandParams?.transactionId as number),
201 meterStop: energyActiveImportRegister,
202 timestamp: new Date(),
203 ...(chargingStation.getTransactionDataMeterValues() && {
204 transactionData: OCPP16ServiceUtils.buildTransactionDataMeterValues(
205 chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue,
206 OCPP16ServiceUtils.buildTransactionEndMeterValue(
207 chargingStation,
208 connectorId,
209 energyActiveImportRegister
210 )
211 ),
78085c42 212 }),
36c462a4 213 ...commandParams,
f22266fd 214 } as unknown as Request;
78085c42 215 default:
e909d2a7 216 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
78085c42
JB
217 throw new OCPPError(
218 ErrorType.NOT_SUPPORTED,
219 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
6c8f5d90 220 `Unsupported OCPP command '${commandName}'`,
78085c42 221 commandName,
7369e417 222 commandParams
78085c42
JB
223 );
224 }
225 }
c0560973 226}