}
} catch (error) {
// Log
- logger.error('%s Incoming OCPP message %j matching cached request %j processing error %j', this.logPrefix(), data, this.requests.get(messageId), error);
+ logger.error('%s Incoming OCPP message %j matching cached request %j processing error %j', this.logPrefix(), data.toString(), this.requests.get(messageId), error);
// Send error
messageType === MessageType.CALL_MESSAGE && await this.ocppRequestService.sendError(messageId, error, commandName);
}
import OCPPError from './OCPPError';
import OCPPResponseService from './OCPPResponseService';
import PerformanceStatistics from '../../performance/PerformanceStatistics';
+import Utils from '../../utils/Utils';
import logger from '../../utils/Logger';
export default abstract class OCPPRequestService {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
// Send a message through wsConnection
- return new Promise((resolve, reject) => {
+ return Utils.promiseWithTimeout(new Promise((resolve, reject) => {
const messageToSend = this.buildMessageToSend(messageId, commandParams, messageType, commandName, responseCallback, rejectCallback);
if (this.chargingStation.getEnableStatistics()) {
this.chargingStation.performanceStatistics.addRequestStatistic(commandName, messageType);
// Yes: send Ok
return resolve(commandParams);
}
- // Send timeout
- setTimeout(() => rejectCallback(new OCPPError(ErrorType.GENERIC_ERROR, `Timeout for message id '${messageId}' with content '${messageToSend}'`, commandParams?.details ?? {}), false), Constants.OCPP_SOCKET_TIMEOUT);
/**
* Function that will receive the request's response
self.chargingStation.requests.delete(messageId);
reject(error);
}
+ }), Constants.OCPP_WEBSOCKET_TIMEOUT, new OCPPError(ErrorType.GENERIC_ERROR, `Timeout for message id '${messageId}'`, commandParams?.details ?? {}), () => {
+ messageType === MessageType.CALL_MESSAGE && this.chargingStation.requests.delete(messageId);
});
}
static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED = Object.freeze({ status: TriggerMessageStatus.NOT_IMPLEMENTED });
static readonly OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000; // Ms
- static readonly OCPP_SOCKET_TIMEOUT = 60000; // Ms
+ static readonly OCPP_WEBSOCKET_TIMEOUT = 60000; // Ms
static readonly OCPP_TRIGGER_MESSAGE_DELAY = 2000; // Ms
static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms
return Configuration.getWorkerProcess() === WorkerProcessType.DYNAMIC_POOL;
}
+ public static async promiseWithTimeout<T>(
+ promise: Promise<T>,
+ timeoutMs: number,
+ timeoutError: Error,
+ timeoutCallback: () => void = () => { /* This is intentional */ }
+ ): Promise<T> {
+ // Create a timeout promise that rejects in timeout milliseconds
+ const timeoutPromise = new Promise<never>((_, reject) => {
+ setTimeout(() => {
+ timeoutCallback;
+ reject(timeoutError);
+ }, timeoutMs);
+ });
+
+ // Returns a race between timeout promise and the passed promise
+ return Promise.race<T>([promise, timeoutPromise]);
+ }
+
/**
* Generate a cryptographically secure random number in the [0,1[ range
*