]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/blob - src/charging-station/ocpp/2.0/OCPP20RequestService.ts
e44693658c909b91c6a369d924f1b366a9c610fb
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 2.0 / OCPP20RequestService.ts
1 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
2
3 import type { ValidateFunction } from 'ajv'
4
5 import type { ChargingStation } from '../../../charging-station/index.js'
6 import type { OCPPResponseService } from '../OCPPResponseService.js'
7
8 import { OCPPError } from '../../../exception/index.js'
9 import {
10 ErrorType,
11 type JsonObject,
12 type JsonType,
13 type OCPP20BootNotificationRequest,
14 type OCPP20HeartbeatRequest,
15 OCPP20RequestCommand,
16 type OCPP20StatusNotificationRequest,
17 OCPPVersion,
18 type RequestParams,
19 } from '../../../types/index.js'
20 import { generateUUID } from '../../../utils/index.js'
21 import { OCPPRequestService } from '../OCPPRequestService.js'
22 import { OCPP20Constants } from './OCPP20Constants.js'
23 import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
24
25 const moduleName = 'OCPP20RequestService'
26
27 export class OCPP20RequestService extends OCPPRequestService {
28 protected payloadValidateFunctions: Map<OCPP20RequestCommand, ValidateFunction<JsonType>>
29
30 public constructor (ocppResponseService: OCPPResponseService) {
31 // if (new.target.name === moduleName) {
32 // throw new TypeError(`Cannot construct ${new.target.name} instances directly`)
33 // }
34 super(OCPPVersion.VERSION_201, ocppResponseService)
35 this.payloadValidateFunctions = new Map<OCPP20RequestCommand, ValidateFunction<JsonType>>([
36 [
37 OCPP20RequestCommand.BOOT_NOTIFICATION,
38 this.ajv.compile(
39 OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationRequest>(
40 'assets/json-schemas/ocpp/2.0/BootNotificationRequest.json',
41 moduleName,
42 'constructor'
43 )
44 ),
45 ],
46 [
47 OCPP20RequestCommand.HEARTBEAT,
48 this.ajv.compile(
49 OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatRequest>(
50 'assets/json-schemas/ocpp/2.0/HeartbeatRequest.json',
51 moduleName,
52 'constructor'
53 )
54 ),
55 ],
56 [
57 OCPP20RequestCommand.STATUS_NOTIFICATION,
58 this.ajv.compile(
59 OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationRequest>(
60 'assets/json-schemas/ocpp/2.0/StatusNotificationRequest.json',
61 moduleName,
62 'constructor'
63 )
64 ),
65 ],
66 ])
67 this.buildRequestPayload = this.buildRequestPayload.bind(this)
68 }
69
70 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
71 public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
72 chargingStation: ChargingStation,
73 commandName: OCPP20RequestCommand,
74 commandParams?: RequestType,
75 params?: RequestParams
76 ): Promise<ResponseType> {
77 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
78 if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
79 // TODO: pre request actions hook
80 return (await this.sendMessage(
81 chargingStation,
82 generateUUID(),
83 this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
84 commandName,
85 params
86 )) as ResponseType
87 }
88 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
89 throw new OCPPError(
90 ErrorType.NOT_SUPPORTED,
91 `Unsupported OCPP command ${commandName}`,
92 commandName,
93 commandParams
94 )
95 }
96
97 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
98 private buildRequestPayload<Request extends JsonType>(
99 chargingStation: ChargingStation,
100 commandName: OCPP20RequestCommand,
101 commandParams?: JsonType
102 ): Request {
103 commandParams = commandParams as JsonObject
104 switch (commandName) {
105 case OCPP20RequestCommand.BOOT_NOTIFICATION:
106 return commandParams as unknown as Request
107 case OCPP20RequestCommand.HEARTBEAT:
108 return OCPP20Constants.OCPP_RESPONSE_EMPTY as unknown as Request
109 case OCPP20RequestCommand.STATUS_NOTIFICATION:
110 return {
111 timestamp: new Date(),
112 ...commandParams,
113 } as unknown as Request
114 default:
115 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
116 throw new OCPPError(
117 ErrorType.NOT_SUPPORTED,
118 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
119 `Unsupported OCPP command ${commandName}`,
120 commandName,
121 commandParams
122 )
123 }
124 }
125 }