sacn
Version:
💡 🎠Send and Receive sACN data (DMX over IP)
76 lines (75 loc) • 3.19 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Receiver = void 0;
const dgram_1 = require("dgram");
const events_1 = require("events");
const assert_1 = require("assert");
const packet_1 = require("./packet");
const util_1 = require("./util");
class Receiver extends events_1.EventEmitter {
constructor({ universes = [1], port = 5568, iface = undefined, reuseAddr = false, }) {
super();
this.universes = universes;
this.port = port;
this.iface = iface;
this.socket = (0, dgram_1.createSocket)({ type: 'udp4', reuseAddr });
this.lastSequence = {};
this.socket.on('message', (msg, rinfo) => {
try {
const packet = new packet_1.Packet(msg, rinfo.address);
// somehow we received a packet for a universe we're not listening to
// silently drop this packet
if (!this.universes.includes(packet.universe))
return;
// we keep track of the last sequence per sender and per universe (see #37)
const key = packet.cid.toString('utf8') + packet.universe;
const outOfOrder = this.lastSequence[key] &&
Math.abs(this.lastSequence[key] - packet.sequence) > 20;
const oldSequence = this.lastSequence[key];
this.lastSequence[key] = packet.sequence === 255 ? -1 : packet.sequence;
if (outOfOrder) {
throw new Error(`Packet significantly out of order in universe ${packet.universe} from ${packet.sourceName} (${oldSequence} -> ${packet.sequence})`);
}
this.emit('packet', packet);
}
catch (err) {
const event = err instanceof assert_1.AssertionError
? 'PacketCorruption'
: 'PacketOutOfOrder';
this.emit(event, err);
}
});
this.socket.on('error', (ex) => this.emit('error', ex));
this.socket.bind(this.port, () => {
for (const uni of this.universes) {
try {
this.socket.addMembership((0, util_1.multicastGroup)(uni), this.iface);
}
catch (err) {
this.emit('error', err); // emit errors from socket.addMembership
}
}
});
}
addUniverse(universe) {
// already listening to this one; do nothing
if (this.universes.includes(universe))
return this;
this.socket.addMembership((0, util_1.multicastGroup)(universe), this.iface);
this.universes.push(universe);
return this;
}
removeUniverse(universe) {
// not listening to this one; do nothing
if (!this.universes.includes(universe))
return this;
this.socket.dropMembership((0, util_1.multicastGroup)(universe), this.iface);
this.universes = this.universes.filter((n) => n !== universe);
return this;
}
close(callback) {
this.socket.close(callback);
return this;
}
}
exports.Receiver = Receiver;