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