From 52ff5d9d90d36bba3bae6a89d4d364a1e4a24e5d Mon Sep 17 00:00:00 2001 From: Adrian Baumgart Date: Wed, 8 May 2024 18:34:10 +0200 Subject: [PATCH] added USBDMX In -> Artnet Out --- .github/workflows/main.yml | 8 ++-- src/ConvertHandler.ts | 81 ++++++++++++++++++++++++++++++-------- src/controlscreen.ts | 18 ++++++--- src/index.ts | 4 +- src/usbdmx/DMXInterface.ts | 9 +++-- 5 files changed, 88 insertions(+), 32 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a4ab2ef..e71bf27 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,8 +1,8 @@ name: Build app -on: - push: - branches: - - main +#on: +# push: +# branches: +# - main jobs: build: diff --git a/src/ConvertHandler.ts b/src/ConvertHandler.ts index 23c8c0e..c2fa2d5 100644 --- a/src/ConvertHandler.ts +++ b/src/ConvertHandler.ts @@ -1,4 +1,4 @@ -import {dmxnet, receiver} from "dmxnet"; +import {dmxnet, receiver, sender} from "dmxnet"; import {DetectedInterface, DMXInterface, getConnectedInterfaces} from "./usbdmx"; import {clearInterval} from "timers"; @@ -8,6 +8,7 @@ import {clearInterval} from "timers"; export default class ConvertHandler { dmxnetManager: dmxnet; artNetReceiver: receiver; + artNetSender: sender; recentDMXArray: number[] = Array(512).fill(0); @@ -16,39 +17,71 @@ export default class ConvertHandler { dmxInterface: DMXInterface | undefined; outputAllowed = false; - incomingDataCounter = 0; - sentDataCounter = 0; dataPerSecTimer: NodeJS.Timeout; - incomingDataHistory: number[] = []; - sentDataHistory: number[] = []; + + private artnetInCounter = 0; + private artnetOutCounter = 0; + private usbdmxInCounter = 0; + private usbdmxOutCounter = 0; + + artnetInCountHistory: number[] = []; + artnetOutCountHistory: number[] = []; + usbdmxInCountHistory: number[] = []; + usbdmxOutCountHistory: number[] = []; /** * Starts up the Art-Net receiver */ startArtNetReceiver = () => { this.dmxnetManager = new dmxnet({ - log: {level: "error"} + log: {level: "error"}, + sName: "usbdmx", + lName: "ArtNet-USBDMX-Converter", }); this.artNetReceiver = this.dmxnetManager.newReceiver(); + this.artNetSender = this.dmxnetManager.newSender({ + ip: "255.255.255.255", //IP to send to, default 255.255.255.255 + subnet: 0, //Destination subnet, default 0 + universe: 0, //Destination universe, default 0 + net: 0, //Destination net, default 0 + port: 6454, //Destination UDP Port, default 6454 + base_refresh_interval: 1000 // Default interval for sending unchanged ArtDmx + }); this.artNetReceiver.on("data", this.handleIncomingArtNetData); } /** - * Handles incoming Art-Net dara and writes it to the DMX interface + * Handles incoming Art-Net dara and writes it to the DMX interface. * @param data Art-Net data */ // eslint-disable-next-line @typescript-eslint/no-explicit-any handleIncomingArtNetData = (data: any) => { - this.incomingDataCounter++; + this.artnetInCounter++; if (JSON.stringify(data) != JSON.stringify(this.recentDMXArray)) { if (this.dmxInterface && this.outputAllowed) { - this.sentDataCounter++; + this.usbdmxOutCounter++; this.dmxInterface.writeMap(data); } this.recentDMXArray = data; } } + /** + * Handles incoming data from the interface and sends it out via Art-Net. + * @param startChannel first channel number of the data array + * @param data Array with dmx values + */ + sendIncomingUSBDMXData = (startChannel: number, data: number[]) => { + this.usbdmxInCounter++; + if (this.outputAllowed) { + for (let i = 0; i < data.length; i++) { + this.artNetSender.prepChannel(startChannel + i, data[i]); + } + this.artnetOutCounter++; + this.artNetSender.transmit(); + } + } + /** * Gets available DMX interfaces connected to the computer */ @@ -75,6 +108,7 @@ export default class ConvertHandler { try { this.dmxInterface = await DMXInterface.open(interfacePath, serial, manufacturer, product); + this.dmxInterface.usbdmxInputCallback = this.sendIncomingUSBDMXData; return new Promise((resolve) => { setTimeout( () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -108,16 +142,29 @@ export default class ConvertHandler { * Processes incoming and sent data history for visualization */ parseRequestTimer = () => { - this.incomingDataHistory.push(this.incomingDataCounter); - if (this.incomingDataHistory.length > 20) { - this.incomingDataHistory = this.incomingDataHistory.slice(1) + this.artnetInCountHistory.push(this.artnetInCounter); + if (this.artnetInCountHistory.length > 20) { + this.artnetInCountHistory = this.artnetInCountHistory.slice(1) } - this.sentDataHistory.push(this.sentDataCounter); - if (this.sentDataHistory.length > 20) { - this.sentDataHistory = this.sentDataHistory.slice(1) + this.artnetOutCountHistory.push(this.artnetOutCounter); + if (this.artnetOutCountHistory.length > 20) { + this.artnetOutCountHistory = this.artnetOutCountHistory.slice(1) } - this.incomingDataCounter = 0; - this.sentDataCounter = 0; + + this.usbdmxInCountHistory.push(this.usbdmxInCounter); + if (this.usbdmxInCountHistory.length > 20) { + this.usbdmxInCountHistory = this.usbdmxInCountHistory.slice(1) + } + + this.usbdmxOutCountHistory.push(this.usbdmxOutCounter); + if (this.usbdmxOutCountHistory.length > 20) { + this.usbdmxOutCountHistory = this.usbdmxOutCountHistory.slice(1) + } + + this.artnetInCounter = 0; + this.artnetOutCounter = 0; + this.usbdmxInCounter = 0; + this.usbdmxOutCounter = 0; } } \ No newline at end of file diff --git a/src/controlscreen.ts b/src/controlscreen.ts index 2f4241a..a1e62fd 100644 --- a/src/controlscreen.ts +++ b/src/controlscreen.ts @@ -36,13 +36,19 @@ export default async function renderControlScreen() { `${modeToString(defaultConvertHandler.dmxInterface?.currentMode ?? 0)}`) console.log("=================") - const incomingDataSparkline = Sparkline(defaultConvertHandler.incomingDataHistory, "req/sec"); - const sentDataSparkline = Sparkline(defaultConvertHandler.sentDataHistory, "req/sec"); + const artnetInSparkline = Sparkline(defaultConvertHandler.artnetInCountHistory, "req/sec"); + const artnetOutSparkline = Sparkline(defaultConvertHandler.artnetOutCountHistory, "req/sec"); + const usbdmxInSparkline = Sparkline(defaultConvertHandler.usbdmxInCountHistory, "req/sec"); + const usbdmxOutSparkline = Sparkline(defaultConvertHandler.usbdmxOutCountHistory, "req/sec"); - process.stdout.write("Incoming Data ") - process.stdout.write(incomingDataSparkline); - process.stdout.write("\nOutgoing Data ") - process.stdout.write(sentDataSparkline); + process.stdout.write("ArtNet In\t") + process.stdout.write(artnetInSparkline); + process.stdout.write("\nArtNet Out\t") + process.stdout.write(artnetOutSparkline); + process.stdout.write("\nUSBDMX In\t") + process.stdout.write(usbdmxInSparkline); + process.stdout.write("\nUSBDMX Out\t") + process.stdout.write(usbdmxOutSparkline); console.log("\n"); console.log(chalk.yellow( diff --git a/src/index.ts b/src/index.ts index 2084bd5..a855be8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,7 +18,7 @@ async function main() { "Starting ArtNet..." )); console.log(chalk.yellow( - "Nimm bitte eventuell erscheinende Firewall-Hinweise an" + "Please accept any firewall requests" )) defaultConvertHandler.startArtNetReceiver(); @@ -42,7 +42,7 @@ async function main() { ); renderControlScreenTimer = setInterval(() => { renderControlScreen(); - }, 1000); + }, 1000) } } diff --git a/src/usbdmx/DMXInterface.ts b/src/usbdmx/DMXInterface.ts index 7faed06..106e650 100644 --- a/src/usbdmx/DMXInterface.ts +++ b/src/usbdmx/DMXInterface.ts @@ -22,7 +22,8 @@ class DMXInterface { currentMode = 0; hidDevice: HID.HID; dmxout: number[]; - dataCallback: (value: DMXCommand) => void; + + usbdmxInputCallback: (start: number, values: number[]) => void; constructor( path: string, @@ -35,14 +36,16 @@ class DMXInterface { this.manufacturer = manufacturer; this.product = product; - this.dataCallback = () => {}; this.hidDevice = new HID.HID(path); this.hidDevice.on("data", (data: Buffer) => { // received buffer contains 33 bytes, the first one (data[0]) is the page and the rest are the dmx channel values // this means we get 32 dmx channels in one package + + const values: number[] = []; for (let i = 1; i < 33; i++) { - this.dataCallback({channel: data[0] * 32 + i, value: data[i]}); + values.push(data[i]); } + this.usbdmxInputCallback(data[0] * 32, values); }) this.dmxout = Array(512).fill(0);