From 32a1eb7ab66964e5beb8b79082782761329e0705 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 1 Jan 2021 00:34:36 +0100 Subject: [PATCH] Improve charging station registration handling. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- package-lock.json | 102 ++++++++++++------------ package.json | 8 +- src/charging-station/ChargingStation.ts | 87 +++++++++++--------- src/types/ChargingStationTemplate.ts | 1 + src/types/WebSocket.ts | 37 +++++++++ src/utils/Constants.ts | 2 - src/utils/Utils.ts | 23 +++++- 7 files changed, 166 insertions(+), 94 deletions(-) create mode 100644 src/types/WebSocket.ts diff --git a/package-lock.json b/package-lock.json index 6e921dec..52473840 100644 --- a/package-lock.json +++ b/package-lock.json @@ -592,28 +592,28 @@ } }, "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", + "@nodelib/fs.stat": "2.0.4", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", + "@nodelib/fs.scandir": "2.1.4", "fastq": "^1.6.0" } }, @@ -659,9 +659,9 @@ "dev": true }, "@types/node": { - "version": "14.14.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz", - "integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw==", + "version": "14.14.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.17.tgz", + "integrity": "sha512-G0lD1/7qD60TJ/mZmhog76k7NcpLWkPVGgzkRy3CTlnFu4LUQh5v2Wa661z6vnXmD8EQrnALUyf0VRtrACYztw==", "dev": true }, "@types/offscreencanvas": { @@ -725,13 +725,13 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.0.tgz", - "integrity": "sha512-x4arJMXBxyD6aBXLm3W7mSDZRiABzy+2PCLJbL7OPqlp53VXhaA1HKK7R2rTee5OlRhnUgnp8lZyVIqjnyPT6g==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.1.tgz", + "integrity": "sha512-fABclAX2QIEDmTMk6Yd7Muv1CzFLwWM4505nETzRHpP3br6jfahD9UUJkhnJ/g2m7lwfz8IlswcwGGPGiq9exw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.11.0", - "@typescript-eslint/scope-manager": "4.11.0", + "@typescript-eslint/experimental-utils": "4.11.1", + "@typescript-eslint/scope-manager": "4.11.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", @@ -766,55 +766,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.0.tgz", - "integrity": "sha512-1VC6mSbYwl1FguKt8OgPs8xxaJgtqFpjY/UzUYDBKq4pfQ5lBvN2WVeqYkzf7evW42axUHYl2jm9tNyFsb8oLg==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.1.tgz", + "integrity": "sha512-mAlWowT4A6h0TC9F+J5pdbEhjNiEMO+kqPKQ4sc3fVieKL71dEqfkKgtcFVSX3cjSBwYwhImaQ/mXQF0oaI38g==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.11.0", - "@typescript-eslint/types": "4.11.0", - "@typescript-eslint/typescript-estree": "4.11.0", + "@typescript-eslint/scope-manager": "4.11.1", + "@typescript-eslint/types": "4.11.1", + "@typescript-eslint/typescript-estree": "4.11.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.11.0.tgz", - "integrity": "sha512-NBTtKCC7ZtuxEV5CrHUO4Pg2s784pvavc3cnz6V+oJvVbK4tH9135f/RBP6eUA2KHiFKAollSrgSctQGmHbqJQ==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.11.1.tgz", + "integrity": "sha512-BJ3jwPQu1jeynJ5BrjLuGfK/UJu6uwHxJ/di7sanqmUmxzmyIcd3vz58PMR7wpi8k3iWq2Q11KMYgZbUpRoIPw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.11.0", - "@typescript-eslint/types": "4.11.0", - "@typescript-eslint/typescript-estree": "4.11.0", + "@typescript-eslint/scope-manager": "4.11.1", + "@typescript-eslint/types": "4.11.1", + "@typescript-eslint/typescript-estree": "4.11.1", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.11.0.tgz", - "integrity": "sha512-6VSTm/4vC2dHM3ySDW9Kl48en+yLNfVV6LECU8jodBHQOhO8adAVizaZ1fV0QGZnLQjQ/y0aBj5/KXPp2hBTjA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.11.1.tgz", + "integrity": "sha512-Al2P394dx+kXCl61fhrrZ1FTI7qsRDIUiVSuN6rTwss6lUn8uVO2+nnF4AvO0ug8vMsy3ShkbxLu/uWZdTtJMQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.11.0", - "@typescript-eslint/visitor-keys": "4.11.0" + "@typescript-eslint/types": "4.11.1", + "@typescript-eslint/visitor-keys": "4.11.1" } }, "@typescript-eslint/types": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.11.0.tgz", - "integrity": "sha512-XXOdt/NPX++txOQHM1kUMgJUS43KSlXGdR/aDyEwuAEETwuPt02Nc7v+s57PzuSqMbNLclblQdv3YcWOdXhQ7g==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.11.1.tgz", + "integrity": "sha512-5kvd38wZpqGY4yP/6W3qhYX6Hz0NwUbijVsX2rxczpY6OXaMxh0+5E5uLJKVFwaBM7PJe1wnMym85NfKYIh6CA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.0.tgz", - "integrity": "sha512-eA6sT5dE5RHAFhtcC+b5WDlUIGwnO9b0yrfGa1mIOIAjqwSQCpXbLiFmKTdRbQN/xH2EZkGqqLDrKUuYOZ0+Hg==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.1.tgz", + "integrity": "sha512-tC7MKZIMRTYxQhrVAFoJq/DlRwv1bnqA4/S2r3+HuHibqvbrPcyf858lNzU7bFmy4mLeIHFYr34ar/1KumwyRw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.11.0", - "@typescript-eslint/visitor-keys": "4.11.0", + "@typescript-eslint/types": "4.11.1", + "@typescript-eslint/visitor-keys": "4.11.1", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -870,12 +870,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.0.tgz", - "integrity": "sha512-tRYKyY0i7cMk6v4UIOCjl1LhuepC/pc6adQqJk4Is3YcC6k46HvsV9Wl7vQoLbm9qADgeujiT7KdLrylvFIQ+A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.1.tgz", + "integrity": "sha512-IrlBhD9bm4bdYcS8xpWarazkKXlE7iYb1HzRuyBP114mIaj5DJPo11Us1HgH60dTt41TCZXMaTCAW+OILIYPOg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.11.0", + "@typescript-eslint/types": "4.11.1", "eslint-visitor-keys": "^2.0.0" } }, @@ -11491,9 +11491,9 @@ } }, "ws": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", - "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==" + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", + "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==" }, "xdg-basedir": { "version": "3.0.0", diff --git a/package.json b/package.json index d29aa2df..538e20c8 100644 --- a/package.json +++ b/package.json @@ -51,19 +51,19 @@ "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.0", "worker-threads-pool": "^2.0.0", - "ws": "^7.4.1" + "ws": "^7.4.2" }, "optionalDependencies": { "bufferutil": "^4.0.2", "utf-8-validate": "^5.0.3" }, "devDependencies": { - "@types/node": "^14.14.16", + "@types/node": "^14.14.17", "@types/uuid": "^8.3.0", "@types/worker-threads-pool": "^2.0.0", "@types/ws": "^7.4.0", - "@typescript-eslint/eslint-plugin": "^4.11.0", - "@typescript-eslint/parser": "^4.11.0", + "@typescript-eslint/eslint-plugin": "^4.11.1", + "@typescript-eslint/parser": "^4.11.1", "clinic": "^8.0.1", "cross-env": "^7.0.3", "eslint": "^7.16.0", diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 4c042eaa..7bdcf6e1 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -20,6 +20,7 @@ import MeasurandValues from '../types/MeasurandValues'; import OCPPError from './OcppError'; import Statistics from '../utils/Statistics'; import Utils from '../utils/Utils'; +import { WebSocketCloseEventStatusCode } from '../types/WebSocket'; import crypto from 'crypto'; import fs from 'fs'; import logger from '../utils/Logger'; @@ -109,8 +110,8 @@ export default class ChargingStation { this._configuration = this._getTemplateChargingStationConfiguration(); this._supervisionUrl = this._getSupervisionURL(); this._wsConnectionUrl = this._supervisionUrl + '/' + this._stationInfo.name; - this._connectionTimeout = this._getConnectionTimeout() * 1000; // Ms, zero for disabling - this._autoReconnectMaxRetries = this._getAutoReconnectMaxRetries(); // -1 for unlimited + this._connectionTimeout = this._getConnectionTimeout() * 1000; // Ms, 0 for disabling + this._autoReconnectMaxRetries = this._getAutoReconnectMaxRetries(); // -1 for unlimited, 0 for disabling // Build connectors if needed const maxConnectors = this._getMaxNumberOfConnectors(); if (maxConnectors <= 0) { @@ -143,7 +144,7 @@ export default class ChargingStation { if ((this._stationInfo.Connectors[0] ? templateMaxConnectors - 1 : templateMaxConnectors) > 0) { for (let index = 1; index <= maxConnectors; index++) { const randConnectorID = this._stationInfo.randomConnectors ? Utils.getRandomInt(Utils.convertToInt(lastConnector), 1) : index; - this._connectors[index] = Utils.cloneObject(this._stationInfo.Connectors[randConnectorID]) ; + this._connectors[index] = Utils.cloneObject(this._stationInfo.Connectors[randConnectorID]); } } } @@ -184,6 +185,14 @@ export default class ChargingStation { return Utils.logPrefix(` ${this._stationInfo.name}:`); } + _isWebSocketOpen(): boolean { + return this._wsConnection?.readyState === WebSocket.OPEN; + } + + _isRegistered(): boolean { + return this._bootNotificationResponse?.status === RegistrationStatus.ACCEPTED; + } + _getTemplateChargingStationConfiguration(): ChargingStationConfiguration { return this._stationInfo.Configuration ? this._stationInfo.Configuration : {} as ChargingStationConfiguration; } @@ -267,6 +276,13 @@ export default class ChargingStation { return -1; } + _getRegistrationMaxRetries(): number { + if (!Utils.isUndefined(this._stationInfo.registrationMaxRetries)) { + return this._stationInfo.registrationMaxRetries; + } + return -1; + } + _getPowerDivider(): number { let powerDivider = this._getNumberOfConnectors(); if (this._stationInfo.powerSharedByConnectors) { @@ -339,7 +355,7 @@ export default class ChargingStation { } _getSupervisionURL(): string { - const supervisionUrls = Utils.cloneObject(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs()) ; + const supervisionUrls = Utils.cloneObject(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs()); let indexUrl = 0; if (!Utils.isEmptyArray(supervisionUrls)) { if (Configuration.getDistributeStationsToTenantsEqually()) { @@ -427,7 +443,7 @@ export default class ChargingStation { const webSocketPingInterval: number = this._getConfigurationKey('WebSocketPingInterval') ? Utils.convertToInt(this._getConfigurationKey('WebSocketPingInterval').value) : 0; if (webSocketPingInterval > 0 && !this._webSocketPingSetInterval) { this._webSocketPingSetInterval = setInterval(() => { - if (this._wsConnection?.readyState === WebSocket.OPEN) { + if (this._isWebSocketOpen()) { this._wsConnection.ping((): void => { }); } }, webSocketPingInterval * 1000); @@ -543,7 +559,7 @@ export default class ChargingStation { if (Utils.isUndefined(options.handshakeTimeout)) { options.handshakeTimeout = this._connectionTimeout; } - if (this._wsConnection?.readyState === WebSocket.OPEN && forceCloseOpened) { + if (this._isWebSocketOpen() && forceCloseOpened) { this._wsConnection.close(); } this._wsConnection = new WebSocket(this._wsConnectionUrl, 'ocpp' + Constants.OCPP_VERSION_16, options); @@ -578,7 +594,7 @@ export default class ChargingStation { await this.sendStatusNotification(Utils.convertToInt(connector), ChargePointStatus.UNAVAILABLE); } } - if (this._wsConnection?.readyState === WebSocket.OPEN) { + if (this._isWebSocketOpen()) { this._wsConnection.close(); } this._bootNotificationResponse = null; @@ -586,7 +602,6 @@ export default class ChargingStation { } async _reconnect(error): Promise { - logger.error(this._logPrefix() + ' Socket: abnormally closed: %j', error); // Stop heartbeat this._stopHeartbeat(); // Stop the ATG if needed @@ -611,52 +626,52 @@ export default class ChargingStation { async onOpen(): Promise { logger.info(`${this._logPrefix()} Is connected to server through ${this._wsConnectionUrl}`); - if (!this._hasSocketRestarted || this._hasStopped) { + if (!this._isRegistered()) { // Send BootNotification - this._bootNotificationResponse = await this.sendBootNotification(); - } - if (this._bootNotificationResponse.status === RegistrationStatus.ACCEPTED) { - await this._startMessageSequence(); - } else { + let registrationRetryCount = 0; do { - await Utils.sleep(this._bootNotificationResponse.interval * 1000); - // Resend BootNotification this._bootNotificationResponse = await this.sendBootNotification(); - } while (this._bootNotificationResponse.status !== RegistrationStatus.ACCEPTED); + if (!this._isRegistered()) { + registrationRetryCount++; + await Utils.sleep(this._bootNotificationResponse.interval * 1000); + } + } while (!this._isRegistered() && (registrationRetryCount <= this._getRegistrationMaxRetries() || this._getRegistrationMaxRetries() === -1)); } - if (this._hasSocketRestarted && this._bootNotificationResponse.status === RegistrationStatus.ACCEPTED) { - if (!Utils.isEmptyArray(this._messageQueue)) { - this._messageQueue.forEach((message, index) => { - if (this._wsConnection?.readyState === WebSocket.OPEN) { + if (this._isRegistered()) { + await this._startMessageSequence(); + if (this._hasSocketRestarted && this._isWebSocketOpen()) { + if (!Utils.isEmptyArray(this._messageQueue)) { + this._messageQueue.forEach((message, index) => { this._messageQueue.splice(index, 1); this._wsConnection.send(message); - } - }); + }); + } } + } else { + logger.error(`${this._logPrefix()} Registration: max retries reached (${this._getRegistrationMaxRetries()}) or retry disabled (${this._getRegistrationMaxRetries()})`); } this._autoReconnectRetryCount = 0; this._hasSocketRestarted = false; } async onError(errorEvent): Promise { - switch (errorEvent.code) { - case 'ECONNREFUSED': - await this._reconnect(errorEvent); - break; - default: - logger.error(this._logPrefix() + ' Socket error: %j', errorEvent); - break; - } + logger.error(this._logPrefix() + ' Socket error: %j', errorEvent); + // pragma switch (errorEvent.code) { + // case 'ECONNREFUSED': + // await this._reconnect(errorEvent); + // break; + // } } async onClose(closeEvent): Promise { switch (closeEvent) { - case 1000: // Normal close - case 1005: - logger.info(this._logPrefix() + ' Socket normally closed: %j', closeEvent); + case WebSocketCloseEventStatusCode.CLOSE_NORMAL: // Normal close + case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS: + logger.info(`${this._logPrefix()} Socket normally closed with status '${Utils.getWebSocketCloseEventStatusString(closeEvent)}'`); this._autoReconnectRetryCount = 0; break; default: // Abnormal close + logger.error(`${this._logPrefix()} Socket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString(closeEvent)}'`); await this._reconnect(closeEvent); break; } @@ -1053,8 +1068,8 @@ export default class ChargingStation { messageToSend = JSON.stringify([messageType, messageId, commandParams.code ? commandParams.code : Constants.OCPP_ERROR_GENERIC_ERROR, commandParams.message ? commandParams.message : '', commandParams.details ? commandParams.details : {}]); break; } - // Check if wsConnection is ready - if (this._wsConnection?.readyState === WebSocket.OPEN) { + // Check if wsConnection opened and charging station registered + if (this._isWebSocketOpen() && (this._isRegistered() || commandName === 'BootNotification')) { if (this.getEnableStatistics()) { this._statistics.addMessage(commandName, messageType); } diff --git a/src/types/ChargingStationTemplate.ts b/src/types/ChargingStationTemplate.ts index 59eebc40..9af61810 100644 --- a/src/types/ChargingStationTemplate.ts +++ b/src/types/ChargingStationTemplate.ts @@ -42,6 +42,7 @@ export default interface ChargingStationTemplate { resetTime?: number; connectionTimeout?: number; autoReconnectMaxRetries?: number; + registrationMaxRetries?: number; reconnectExponentialDelay?: boolean; enableStatistics?: boolean; voltageOut?: number; diff --git a/src/types/WebSocket.ts b/src/types/WebSocket.ts new file mode 100644 index 00000000..0799f7b4 --- /dev/null +++ b/src/types/WebSocket.ts @@ -0,0 +1,37 @@ +export const WebSocketCloseEventStatusString: Record = Object.freeze({ + 1000: 'Normal Closure', + 1001: 'Going Away', + 1002: 'Protocol Error', + 1003: 'Unsupported Frame Data', + 1004: 'Reserved', + 1005: 'No Status Received', + 1006: 'Abnormal Closure', + 1007: 'Invalid Frame Payload Data', + 1008: 'Policy Violation', + 1009: 'Message Too Large', + 1010: 'Missing Extension', + 1011: 'Server Internal Error', + 1012: 'Service Restart', + 1013: 'Try Again Later', + 1014: 'Bad Gateway', + 1015: 'TLS Handshake' +}); + +export enum WebSocketCloseEventStatusCode { + CLOSE_NORMAL = 1000, + CLOSE_GOING_AWAY = 1001, + CLOSE_PROTOCOL_ERROR = 1002, + CLOSE_UNSUPPORTED = 1003, + CLOSE_RESERVED = 1004, + CLOSE_NO_STATUS = 1005, + CLOSE_ABNORMAL = 1006, + CLOSE_INVALID_PAYLOAD = 1007, + CLOSE_POLICY_VIOLATION = 1008, + CLOSE_TOO_LARGE = 1009, + CLOSE_MISSING_EXTENSION = 1010, + CLOSE_SERVER_INTERNAL_ERROR = 1011, + CLOSE_SERVICE_RESTART = 1012, + CLOSE_TRY_AGAIN_LATER = 1013, + CLOSE_BAD_GATEWAY = 1014, + CLOSE_TLS_HANDSHAKE = 1015 +} diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index c61a3197..812b3227 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -4,8 +4,6 @@ export default class Constants { static readonly ENTITY_CHARGING_STATION = 'ChargingStation'; static readonly ENTITY_AUTOMATIC_TRANSACTION_GENERATOR = 'AutomaticTransactionGenerator'; - static readonly WS_UNSUPPORTED_DATA = 1007; - static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: DefaultStatus.ACCEPTED }); static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: DefaultStatus.REJECTED }); static readonly OCPP_CONFIGURATION_RESPONSE_ACCEPTED = Object.freeze({ status: ConfigurationStatus.ACCEPTED }); diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 226f54c4..9969e229 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,3 +1,4 @@ +import { WebSocketCloseEventStatusString } from '../types/WebSocket'; import { v4 as uuid } from 'uuid'; export default class Utils { @@ -156,7 +157,7 @@ export default class Utils { } static isNullOrUndefined(value): boolean { - // eslint-disable-next-line no-eq-null + // eslint-disable-next-line no-eq-null, eqeqeq if (value == null) { return true; } @@ -188,4 +189,24 @@ export default class Utils { const randomSum = delay * 0.2 * Math.random(); // 0-20% of the delay return delay + randomSum; } + + static getWebSocketCloseEventStatusString(code: number): string { + if (code >= 0 && code <= 999) { + return '(Unused)'; + } else if (code >= 1016) { + if (code <= 1999) { + return '(For WebSocket standard)'; + } else if (code <= 2999) { + return '(For WebSocket extensions)'; + } else if (code <= 3999) { + return '(For libraries and frameworks)'; + } else if (code <= 4999) { + return '(For applications)'; + } + } + if (!Utils.isUndefined(WebSocketCloseEventStatusString[code])) { + return WebSocketCloseEventStatusString[code]; + } + return '(Unknown)'; + } } -- 2.34.1