Commit | Line | Data |
---|---|---|
c0560973 JB |
1 | import { AuthorizeResponse, StartTransactionResponse, StopTransactionReason, StopTransactionResponse } from '../../types/ocpp/Transaction'; |
2 | import { IncomingRequestCommand, Request, RequestCommand } from '../../types/ocpp/Requests'; | |
3 | ||
4 | import { BootNotificationResponse } from '../../types/ocpp/RequestResponses'; | |
5 | import { ChargePointErrorCode } from '../../types/ocpp/ChargePointErrorCode'; | |
6 | import { ChargePointStatus } from '../../types/ocpp/ChargePointStatus'; | |
7 | import ChargingStation from '../ChargingStation'; | |
8 | import Constants from '../../utils/Constants'; | |
9 | import { ErrorType } from '../../types/ocpp/ErrorType'; | |
10 | import { MessageType } from '../../types/ocpp/MessageType'; | |
11 | import OCPPError from '../OcppError'; | |
12 | import OCPPResponseService from './OCPPResponseService'; | |
13 | import logger from '../../utils/Logger'; | |
14 | ||
15 | export default abstract class OCPPRequestService { | |
16 | public chargingStation: ChargingStation; | |
17 | protected ocppResponseService: OCPPResponseService; | |
18 | ||
19 | constructor(chargingStation: ChargingStation, ocppResponseService: OCPPResponseService) { | |
20 | this.chargingStation = chargingStation; | |
21 | this.ocppResponseService = ocppResponseService; | |
22 | } | |
23 | ||
24 | public async sendMessage(messageId: string, commandParams: any, messageType: MessageType = MessageType.CALL_RESULT_MESSAGE, commandName: RequestCommand | IncomingRequestCommand): Promise<any> { | |
25 | // eslint-disable-next-line @typescript-eslint/no-this-alias | |
26 | const self = this; | |
27 | const chargingStation = this.chargingStation; | |
28 | // Send a message through wsConnection | |
29 | return new Promise((resolve: (value?: any | PromiseLike<any>) => void, reject: (reason?: any) => void) => { | |
30 | let messageToSend: string; | |
31 | // Type of message | |
32 | switch (messageType) { | |
33 | // Request | |
34 | case MessageType.CALL_MESSAGE: | |
35 | // Build request | |
36 | this.chargingStation.requests[messageId] = [responseCallback, rejectCallback, commandParams] as Request; | |
37 | messageToSend = JSON.stringify([messageType, messageId, commandName, commandParams]); | |
38 | break; | |
39 | // Response | |
40 | case MessageType.CALL_RESULT_MESSAGE: | |
41 | // Build response | |
42 | messageToSend = JSON.stringify([messageType, messageId, commandParams]); | |
43 | break; | |
44 | // Error Message | |
45 | case MessageType.CALL_ERROR_MESSAGE: | |
46 | // Build Error Message | |
47 | messageToSend = JSON.stringify([messageType, messageId, commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : '', commandParams.details ? commandParams.details : {}]); | |
48 | break; | |
49 | } | |
50 | // Check if wsConnection opened and charging station registered | |
51 | if (this.chargingStation.isWebSocketOpen() && (this.chargingStation.isRegistered() || commandName === RequestCommand.BOOT_NOTIFICATION)) { | |
52 | if (this.chargingStation.getEnableStatistics()) { | |
53 | this.chargingStation.statistics.addMessage(commandName, messageType); | |
54 | } | |
55 | // Yes: Send Message | |
56 | this.chargingStation.wsConnection.send(messageToSend); | |
57 | } else if (commandName !== RequestCommand.BOOT_NOTIFICATION) { | |
58 | let dups = false; | |
59 | // Handle dups in buffer | |
60 | for (const message of this.chargingStation.messageQueue) { | |
61 | // Same message | |
62 | if (messageToSend === message) { | |
63 | dups = true; | |
64 | break; | |
65 | } | |
66 | } | |
67 | if (!dups) { | |
68 | // Buffer message | |
69 | this.chargingStation.messageQueue.push(messageToSend); | |
70 | } | |
71 | // Reject it | |
72 | return rejectCallback(new OCPPError(commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : `WebSocket closed for message id '${messageId}' with content '${messageToSend}', message buffered`, commandParams.details ? commandParams.details : {})); | |
73 | } | |
74 | // Response? | |
75 | if (messageType === MessageType.CALL_RESULT_MESSAGE) { | |
76 | // Yes: send Ok | |
77 | resolve(); | |
78 | } else if (messageType === MessageType.CALL_ERROR_MESSAGE) { | |
79 | // Send timeout | |
80 | setTimeout(() => rejectCallback(new OCPPError(commandParams.code ? commandParams.code : ErrorType.GENERIC_ERROR, commandParams.message ? commandParams.message : `Timeout for message id '${messageId}' with content '${messageToSend}'`, commandParams.details ? commandParams.details : {})), Constants.OCPP_ERROR_TIMEOUT); | |
81 | } | |
82 | ||
83 | // Function that will receive the request's response | |
84 | async function responseCallback(payload: Record<string, unknown> | string, requestPayload: Record<string, unknown>): Promise<void> { | |
85 | if (chargingStation.getEnableStatistics()) { | |
86 | chargingStation.statistics.addMessage(commandName, messageType); | |
87 | } | |
88 | // Send the response | |
89 | await self.ocppResponseService.handleResponse(commandName as RequestCommand, payload, requestPayload); | |
90 | resolve(payload); | |
91 | } | |
92 | ||
93 | // Function that will receive the request's rejection | |
94 | function rejectCallback(error: OCPPError): void { | |
95 | if (chargingStation.getEnableStatistics()) { | |
96 | chargingStation.statistics.addMessage(commandName, messageType); | |
97 | } | |
98 | logger.debug(`${chargingStation.logPrefix()} Error: %j occurred when calling command %s with parameters: %j`, error, commandName, commandParams); | |
99 | // Build Exception | |
100 | // eslint-disable-next-line no-empty-function | |
101 | chargingStation.requests[messageId] = [() => { }, () => { }, {}]; // Properly format the request | |
102 | // Send error | |
103 | reject(error); | |
104 | } | |
105 | }); | |
106 | } | |
107 | ||
108 | public handleRequestError(commandName: RequestCommand, error: Error): void { | |
109 | logger.error(this.chargingStation.logPrefix() + ' Send ' + commandName + ' error: %j', error); | |
110 | throw error; | |
111 | } | |
112 | ||
113 | public abstract sendHeartbeat(): Promise<void>; | |
114 | public abstract sendBootNotification(chargePointModel: string, chargePointVendor: string, chargeBoxSerialNumber?: string, firmwareVersion?: string, chargePointSerialNumber?: string, iccid?: string, imsi?: string, meterSerialNumber?: string, meterType?: string): Promise<BootNotificationResponse>; | |
115 | public abstract sendStatusNotification(connectorId: number, status: ChargePointStatus, errorCode?: ChargePointErrorCode): Promise<void>; | |
116 | public abstract sendAuthorize(idTag?: string): Promise<AuthorizeResponse>; | |
117 | public abstract sendStartTransaction(connectorId: number, idTag?: string): Promise<StartTransactionResponse>; | |
118 | public abstract sendStopTransaction(transactionId: number, meterStop: number, idTag?: string, reason?: StopTransactionReason): Promise<StopTransactionResponse>; | |
119 | public abstract sendMeterValues(connectorId: number, transactionId: number, interval: number, self: OCPPRequestService): Promise<void>; | |
120 | public abstract sendError(messageId: string, error: OCPPError, commandName: RequestCommand | IncomingRequestCommand): Promise<unknown>; | |
121 | ||
122 | } |