UNPKG

@evpower/ocpp-ts

Version:

OCPP 1.6: Open Charge Point Protocol

140 lines 11.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Server = void 0; const events_1 = __importDefault(require("events")); const ws_1 = require("ws"); const https_1 = require("https"); const http_1 = require("http"); const schemas_1 = require("./schemas"); const OcppClientConnection_1 = require("../OcppClientConnection"); const Protocol_1 = require("./Protocol"); const status_code_enum_1 = __importDefault(require("status-code-enum")); const DEFAULT_PING_INTERVAL = 30; // seconds class Server extends events_1.default { constructor() { super(...arguments); this.clients = []; this.pingInterval = DEFAULT_PING_INTERVAL; // seconds this.protocolTimeout = 30000; // milliseconds } setPingInterval(pingInterval) { this.pingInterval = pingInterval; } setProtocolTimeout(timeout) { this.protocolTimeout = timeout; } listen(port = 9220, options) { if (options) { this.server = (0, https_1.createServer)(options || {}); } else { this.server = (0, http_1.createServer)(); } const wss = new ws_1.WebSocketServer({ noServer: true, handleProtocols: (protocols) => { if (protocols.has(schemas_1.OCPP_PROTOCOL_1_6)) { return schemas_1.OCPP_PROTOCOL_1_6; } return false; }, }); wss.on('connection', (ws, req) => this.onNewConnection(ws, req)); this.server.on('upgrade', (req, socket, head) => { const 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, (status) => { if (status && status !== status_code_enum_1.default.SuccessOK) { socket.write(`HTTP/1.1 ${status} ${http_1.STATUS_CODES[status]}\r\n\r\n`); socket.destroy(); } else { wss.handleUpgrade(req, socket, head, (ws) => { wss.emit('connection', ws, req); }); } }); } else { wss.handleUpgrade(req, socket, head, (ws) => { wss.emit('connection', ws, req); }); } }); this.server.listen(port); } onNewConnection(socket, req) { const 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; } const client = new OcppClientConnection_1.OcppClientConnection(cpId); client.setHeaders(req.headers); client.setConnection(new Protocol_1.Protocol(client, socket, this.protocolTimeout)); let isAlive = true; socket.on('pong', () => { // console.error('received pong from client', cpId); isAlive = true; }); // console.error(`ping interval set to ${this.pingInterval} seconds for ${cpId}`); const pingTimerInterval = setInterval(() => { if (isAlive === false) { // console.error(`did not get pong, terminating connection in under ${this.pingInterval} seconds`, cpId); socket.terminate(); } else if (socket.readyState < ws_1.CLOSING) { isAlive = false; socket.ping(cpId, false, (err) => { if (err) { // console.info('error on ping', err.message); socket.terminate(); } }); } }, this.pingInterval * 1000); socket.on('error', (err) => { client.emit('error', err); }); socket.on('close', (code, reason) => { clearInterval(pingTimerInterval); const index = this.clients.indexOf(client); this.clients.splice(index, 1); client.emit('close', code, reason); }); this.clients.push(client); this.emit('connection', client); } close() { this.server?.close(); this.clients.forEach((client) => client.close()); } static getCpIdFromUrl(url) { try { if (url) { const encodedCpId = url.split('/') .pop(); if (encodedCpId) { return decodeURI(encodedCpId.split('?')[0]); } } } catch (e) { console.error(e); } return undefined; } } exports.Server = Server; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2ltcGwvU2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG9EQUFrQztBQUNsQywyQkFBeUQ7QUFFekQsaUNBQTBEO0FBQzFELCtCQUE2RztBQUU3Ryx1Q0FBOEM7QUFFOUMsa0VBQStEO0FBQy9ELHlDQUFzQztBQUN0Qyx3RUFBMEM7QUFDMUMsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUMsQ0FBQyxVQUFVO0FBQzVDLE1BQWEsTUFBTyxTQUFRLGdCQUFZO0lBQXhDOztRQUdVLFlBQU8sR0FBa0IsRUFBRSxDQUFDO1FBRTVCLGlCQUFZLEdBQVcscUJBQXFCLENBQUMsQ0FBQyxVQUFVO1FBRXhELG9CQUFlLEdBQVcsS0FBSyxDQUFDLENBQUMsZUFBZTtJQWlJMUQsQ0FBQztJQS9IUSxlQUFlLENBQUMsWUFBb0I7UUFDekMsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQUVNLGtCQUFrQixDQUFDLE9BQWU7UUFDdkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxPQUFPLENBQUM7SUFDakMsQ0FBQztJQUVTLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxFQUFFLE9BQThCO1FBQzFELElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUEsb0JBQWlCLEVBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFBLG1CQUFnQixHQUFFLENBQUM7UUFDbkMsQ0FBQztRQUVELE1BQU0sR0FBRyxHQUFHLElBQUksb0JBQWUsQ0FBQztZQUM5QixRQUFRLEVBQUUsSUFBSTtZQUNkLGVBQWUsRUFBRSxDQUFDLFNBQXNCLEVBQUUsRUFBRTtnQkFDMUMsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLDJCQUFpQixDQUFD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