UNPKG

@evpower/ocpp-ts

Version:

OCPP 1.6: Open Charge Point Protocol

162 lines 6.59 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Server = void 0; var events_1 = __importDefault(require("events")); var ws_1 = require("ws"); var https_1 = require("https"); var http_1 = require("http"); var schemas_1 = require("./schemas"); var OcppClientConnection_1 = require("../OcppClientConnection"); var Protocol_1 = require("./Protocol"); var DEFAULT_PING_INTERVAL = 30; // seconds var Server = /** @class */ (function (_super) { __extends(Server, _super); function Server() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.clients = []; _this.pingInterval = DEFAULT_PING_INTERVAL; // seconds return _this; } Server.prototype.setPingInterval = function (pingInterval) { this.pingInterval = pingInterval; }; Server.prototype.listen = function (port, options) { var _this = this; if (port === void 0) { port = 9220; } if (options) { this.server = (0, https_1.createServer)(options || {}); } else { this.server = (0, http_1.createServer)(); } var wss = new ws_1.WebSocketServer({ noServer: true, handleProtocols: function (protocols) { if (protocols.has(schemas_1.OCPP_PROTOCOL_1_6)) { return schemas_1.OCPP_PROTOCOL_1_6; } return false; }, }); wss.on('connection', function (ws, req) { return _this.onNewConnection(ws, req); }); this.server.on('upgrade', function (req, socket, head) { var cpId = Server.getCpIdFromUrl(req.url); if (!cpId) { socket.write('HTTP/1.1 400 Bad Request\r\n\r\n'); socket.destroy(); } else if (_this.listenerCount('authorization')) { _this.emit('authorization', cpId, req, function (err) { if (err) { socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); socket.destroy(); } else { wss.handleUpgrade(req, socket, head, function (ws) { wss.emit('connection', ws, req); }); } }); } else { wss.handleUpgrade(req, socket, head, function (ws) { wss.emit('connection', ws, req); }); } }); this.server.listen(port); }; Server.prototype.onNewConnection = function (socket, req) { var _this = this; var cpId = Server.getCpIdFromUrl(req.url); if (!socket.protocol || !cpId) { // From Spec: If the Central System does not agree to using one of the subprotocols offered // by the client, it MUST complete the WebSocket handshake with a response without a // Sec-WebSocket-Protocol header and then immediately close the WebSocket connection. console.info('Closed connection due to unsupported protocol'); socket.close(); return; } var client = new OcppClientConnection_1.OcppClientConnection(cpId); client.setHeaders(req.headers); client.setConnection(new Protocol_1.Protocol(client, socket)); var isAlive = true; socket.on('pong', function () { // console.info('received pong from client', cpId); isAlive = true; }); var isPingPongTerminated = false; var pingTimerInterval = setInterval(function () { if (isAlive === false) { // console.info('did not get pong, terminating connection', cpId); isPingPongTerminated = true; socket.terminate(); return; } if (socket.readyState < ws_1.CLOSING) { isAlive = false; socket.ping(cpId, false, function (err) { if (err) { // console.info('error on ping', err.message); isPingPongTerminated = true; socket.terminate(); } }); } }, this.pingInterval * 1000); socket.on('error', function (err) { console.info(err.message, socket.readyState); client.emit('error', err); }); socket.on('close', function (code, reason) { clearInterval(pingTimerInterval); var index = _this.clients.indexOf(client); _this.clients.splice(index, 1); var r = isPingPongTerminated ? Buffer.from("Did not received pong for ".concat(_this.pingInterval, " seconds")) : reason; client.emit('close', code, r); }); this.clients.push(client); this.emit('connection', client); }; Server.prototype.close = function () { var _a; (_a = this.server) === null || _a === void 0 ? void 0 : _a.close(); this.clients.forEach(function (client) { return client.close(); }); }; Server.getCpIdFromUrl = function (url) { try { if (url) { var encodedCpId = url.split('/') .pop(); if (encodedCpId) { return decodeURI(encodedCpId.split('?')[0]); } } } catch (e) { console.error(e); } return undefined; }; return Server; }(events_1.default)); exports.Server = Server; //# sourceMappingURL=Server.js.map