UNPKG

ts-bacnet

Version:

The BACnet protocol library written in pure JavaScript.

88 lines (87 loc) 3.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const dgram_1 = require("dgram"); const events_1 = __importDefault(require("events")); const EventEmitter = events_1.default.EventEmitter; const debug_1 = __importDefault(require("debug")); const debug = (0, debug_1.default)("bacnet:client:debug"); const DEFAULT_BACNET_PORT = 47808; class Transport extends EventEmitter { constructor(settings) { super(); this._lastSendMessages = {}; this._settings = settings; this._server = (0, dgram_1.createSocket)({ type: "udp4", reuseAddr: settings.reuseAddr, }); this._server.on("message", (msg, rinfo) => { // Check for pot. duplicate messages if (this.ownAddress.port === rinfo.port) { for (let [messageKey, earlierSentBuffer] of Object.entries(this._lastSendMessages)) { if (msg.equals(earlierSentBuffer)) { debug(`server IGNORE message from ${rinfo.address}:${rinfo.port} (${messageKey}): ${msg.toString("hex")}`); return; } } } debug(`server got message from ${rinfo.address}:${rinfo.port}: ${msg.toString("hex")}`); this.emit("message", msg, rinfo.address + (rinfo.port === DEFAULT_BACNET_PORT ? "" : ":" + rinfo.port)); }); this._server.on("listening", () => { this.ownAddress = this._server.address(); debug(`server listening on ${this.ownAddress.address}:${this.ownAddress.port}`); this.emit("listening", this.ownAddress); }); this._server.on("error", (err) => { debug("transport error", err.message); this.emit("error", err); }); this._server.on("close", () => { debug("transport closed"); this.emit("close"); // close is to do by the client.close() which calls the transport.close which calls the _server.close }); } getBroadcastAddress() { return this._settings.broadcastAddress; } getMaxPayload() { return 1482; } send(buffer, offset, receiver) { if (!receiver) { receiver = this.getBroadcastAddress(); const dataToSend = Buffer.alloc(offset); // Sort out broadcasted messages that we also receive // TODO Find a better way? const hrTime = process.hrtime(); const messageKey = hrTime[0] * 1000000000 + hrTime[1]; buffer.copy(dataToSend, 0, 0, offset); this._lastSendMessages[messageKey] = dataToSend; setTimeout(() => { delete this._lastSendMessages[messageKey]; }, 10000); // delete after 10s, hopefully all cases are handled by that } const receiverAddress = typeof receiver === "string" ? receiver : receiver.address; const [address, port] = receiverAddress.split(":"); debug("Send packet to " + receiver + ": " + buffer.toString("hex").substr(0, offset * 2)); this._server.send(buffer, 0, offset, +port || DEFAULT_BACNET_PORT, address); } open() { this._server.bind(this._settings.port, this._settings.interface, () => { this._server.setBroadcast(true); }); } close() { this._server.close(); } } exports.default = Transport;