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