UNPKG

5.82 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.EnttecOpenDMXUSBDevice = exports.PRODUCT_ID = exports.VENDOR_ID = void 0;
7const eventemitter3_1 = require("eventemitter3");
8const serialport_1 = __importDefault(require("serialport"));
9exports.VENDOR_ID = "0403"; // Enttec
10exports.PRODUCT_ID = "6001"; // Open DMX USB
11class EnttecOpenDMXUSBDevice extends eventemitter3_1.EventEmitter {
12 /**
13 * @param {string} path A path returned by {@link EnttecOpenDMXUSBDevice.listDevices} or
14 * {@link EnttecOpenDMXUSBDevice.getFirstAvailableDevice}.
15 * @param {boolean} [startSending=true] If the device should start sending as soon as it is ready.
16 */
17 constructor(path, startSending = true) {
18 super();
19 this.shouldBeSending = false;
20 this.sendTimeout = null;
21 this.buffer = Buffer.alloc(513);
22 this.port = new serialport_1.default(path, {
23 baudRate: 250000,
24 dataBits: 8,
25 stopBits: 2,
26 parity: "none",
27 autoOpen: true
28 });
29 this.port.on("open", () => {
30 this.emit("ready");
31 if (startSending)
32 this.startSending(0);
33 });
34 }
35 /**
36 * Starts sending.
37 * @param {number} [interval=0] The time between each attempt to send.
38 * @throws Error If the device is not ready yet.
39 */
40 startSending(interval = 0) {
41 if (!this.port.isOpen)
42 throw new Error("The device is not ready yet. Wait for the 'ready' event.");
43 this.shouldBeSending = true;
44 // eslint-disable-next-line unicorn/consistent-function-scoping
45 const send = () => {
46 this.sendUniverse()
47 .then(() => {
48 if (this.shouldBeSending)
49 // eslint-disable-next-line @typescript-eslint/no-misused-promises
50 this.sendTimeout = setTimeout(send, interval);
51 })
52 .catch(error => this.emit("error", error));
53 };
54 send();
55 }
56 /**
57 * Stops sending.
58 */
59 stopSending() {
60 this.shouldBeSending = false;
61 if (this.sendTimeout !== null)
62 clearTimeout(this.sendTimeout);
63 }
64 /**
65 * Sets the channel values.
66 * If channels is an Object, the keys are the channel numbers.
67 *
68 * @param {Buffer|Object|Array} channels
69 * @param {boolean} [clear=false] Whether all previously assigned channels should be set to 0
70 */
71 setChannels(channels, clear = false) {
72 if (clear) {
73 this.buffer = Buffer.alloc(513);
74 this.buffer[0] = 0;
75 }
76 if (Buffer.isBuffer(channels)) {
77 if (channels.length > 512)
78 throw new Error("The maximum size of an DMX universe is 512 channels.");
79 channels.copy(this.buffer, 1);
80 }
81 else if (Array.isArray(channels)) {
82 if (channels.length > 512)
83 throw new Error("The maximum size of an DMX universe is 512 channels.");
84 channels.forEach((value, index) => {
85 if (value > 0xFF || value < 0)
86 throw new Error("All values must be between 0 and 255.");
87 this.buffer[index + 1] = value;
88 });
89 }
90 else if (typeof channels === "object") {
91 Object.entries(channels).forEach(([channel, value]) => {
92 let channelNumber;
93 try {
94 channelNumber = Number.parseInt(channel, 10);
95 }
96 catch {
97 throw new Error("Only channel numbers are supported.");
98 }
99 if (channelNumber > 512 || channelNumber < 1)
100 throw new Error("All channel numbers must be between 1 and 512.");
101 else if (value > 0xFF || value < 0)
102 throw new Error("All values must be between 0 and 255.");
103 this.buffer[channelNumber] = value;
104 });
105 }
106 else
107 throw new TypeError("data must be of type Buffer, Object or Array.");
108 }
109 /**
110 * @returns {Promise} Resolves when the whole universe was send.
111 * @private
112 */
113 async sendUniverse() {
114 return new Promise(resolve => {
115 this.port.set({ brk: true, rts: false }, () => {
116 setTimeout(() => {
117 this.port.set({ brk: false, rts: false }, () => {
118 setTimeout(() => {
119 this.port.write(this.buffer, () => resolve());
120 }, 0);
121 });
122 }, 0);
123 });
124 });
125 }
126 /**
127 * Lists the paths of all available devices.
128 * @returns {Promise<string[]>}
129 */
130 static async listDevices() {
131 const allPorts = await serialport_1.default.list();
132 return allPorts
133 .filter(device => device.vendorId === exports.VENDOR_ID && device.productId === exports.PRODUCT_ID)
134 .map(device => device.path);
135 }
136 /**
137 * Gets the path of the first available device found.
138 * @throws Error when no device is found.
139 * @returns {Promise<string>}
140 */
141 static async getFirstAvailableDevice() {
142 const devices = await EnttecOpenDMXUSBDevice.listDevices();
143 if (devices.length === 0)
144 throw new Error("No device found.");
145 else
146 return devices[0];
147 }
148}
149exports.EnttecOpenDMXUSBDevice = EnttecOpenDMXUSBDevice;