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