@evpower/ocpp-ts
Version:
OCPP 1.6: Open Charge Point Protocol
140 lines • 11.2 kB
JavaScript
;
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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