1 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
3 import type { ValidateFunction
} from
'ajv'
5 import type { ChargingStation
} from
'../../../charging-station/index.js'
6 import type { OCPPResponseService
} from
'../OCPPResponseService.js'
8 import { OCPPError
} from
'../../../exception/index.js'
13 type OCPP20BootNotificationRequest
,
14 type OCPP20HeartbeatRequest
,
16 type OCPP20StatusNotificationRequest
,
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'
25 const moduleName
= 'OCPP20RequestService'
27 export class OCPP20RequestService
extends OCPPRequestService
{
28 protected payloadValidateFunctions
: Map
<OCPP20RequestCommand
, ValidateFunction
<JsonType
>>
30 public constructor (ocppResponseService
: OCPPResponseService
) {
31 // if (new.target.name === moduleName) {
32 // throw new TypeError(`Cannot construct ${new.target.name} instances directly`)
34 super(OCPPVersion
.VERSION_201
, ocppResponseService
)
35 this.payloadValidateFunctions
= new Map
<OCPP20RequestCommand
, ValidateFunction
<JsonType
>>([
37 OCPP20RequestCommand
.BOOT_NOTIFICATION
,
39 OCPP20ServiceUtils
.parseJsonSchemaFile
<OCPP20BootNotificationRequest
>(
40 'assets/json-schemas/ocpp/2.0/BootNotificationRequest.json',
47 OCPP20RequestCommand
.HEARTBEAT
,
49 OCPP20ServiceUtils
.parseJsonSchemaFile
<OCPP20HeartbeatRequest
>(
50 'assets/json-schemas/ocpp/2.0/HeartbeatRequest.json',
57 OCPP20RequestCommand
.STATUS_NOTIFICATION
,
59 OCPP20ServiceUtils
.parseJsonSchemaFile
<OCPP20StatusNotificationRequest
>(
60 'assets/json-schemas/ocpp/2.0/StatusNotificationRequest.json',
67 this.buildRequestPayload
= this.buildRequestPayload
.bind(this)
70 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
71 private buildRequestPayload
<Request
extends JsonType
>(
72 chargingStation
: ChargingStation
,
73 commandName
: OCPP20RequestCommand
,
74 commandParams
?: JsonType
76 commandParams
= commandParams
as JsonObject
77 switch (commandName
) {
78 case OCPP20RequestCommand
.BOOT_NOTIFICATION
:
79 return commandParams
as unknown
as Request
80 case OCPP20RequestCommand
.HEARTBEAT
:
81 return OCPP20Constants
.OCPP_RESPONSE_EMPTY
as unknown
as Request
82 case OCPP20RequestCommand
.STATUS_NOTIFICATION
:
84 timestamp
: new Date(),
86 } as unknown
as Request
88 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
90 ErrorType
.NOT_SUPPORTED
,
91 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
92 `Unsupported OCPP command ${commandName}`,
99 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
100 public async requestHandler
<RequestType
extends JsonType
, ResponseType
extends JsonType
>(
101 chargingStation
: ChargingStation
,
102 commandName
: OCPP20RequestCommand
,
103 commandParams
?: RequestType
,
104 params
?: RequestParams
105 ): Promise
<ResponseType
> {
106 // FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
107 if (OCPP20ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
)) {
108 // TODO: pre request actions hook
109 return (await this.sendMessage(
112 this.buildRequestPayload
<RequestType
>(chargingStation
, commandName
, commandParams
),
117 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
119 ErrorType
.NOT_SUPPORTED
,
120 `Unsupported OCPP command ${commandName}`,