mirror of
https://github.com/rainloreley/artnet-usbdmx-converter.git
synced 2024-11-22 02:13:02 +01:00
added USBDMX In -> Artnet Out
This commit is contained in:
parent
876dc890e5
commit
52ff5d9d90
|
@ -1,8 +1,8 @@
|
||||||
name: Build app
|
name: Build app
|
||||||
on:
|
#on:
|
||||||
push:
|
# push:
|
||||||
branches:
|
# branches:
|
||||||
- main
|
# - main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {dmxnet, receiver} from "dmxnet";
|
import {dmxnet, receiver, sender} from "dmxnet";
|
||||||
import {DetectedInterface, DMXInterface, getConnectedInterfaces} from "./usbdmx";
|
import {DetectedInterface, DMXInterface, getConnectedInterfaces} from "./usbdmx";
|
||||||
import {clearInterval} from "timers";
|
import {clearInterval} from "timers";
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {clearInterval} from "timers";
|
||||||
export default class ConvertHandler {
|
export default class ConvertHandler {
|
||||||
dmxnetManager: dmxnet;
|
dmxnetManager: dmxnet;
|
||||||
artNetReceiver: receiver;
|
artNetReceiver: receiver;
|
||||||
|
artNetSender: sender;
|
||||||
|
|
||||||
recentDMXArray: number[] = Array(512).fill(0);
|
recentDMXArray: number[] = Array(512).fill(0);
|
||||||
|
|
||||||
|
@ -16,39 +17,71 @@ export default class ConvertHandler {
|
||||||
dmxInterface: DMXInterface | undefined;
|
dmxInterface: DMXInterface | undefined;
|
||||||
outputAllowed = false;
|
outputAllowed = false;
|
||||||
|
|
||||||
incomingDataCounter = 0;
|
|
||||||
sentDataCounter = 0;
|
|
||||||
dataPerSecTimer: NodeJS.Timeout;
|
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
|
* Starts up the Art-Net receiver
|
||||||
*/
|
*/
|
||||||
startArtNetReceiver = () => {
|
startArtNetReceiver = () => {
|
||||||
this.dmxnetManager = new dmxnet({
|
this.dmxnetManager = new dmxnet({
|
||||||
log: {level: "error"}
|
log: {level: "error"},
|
||||||
|
sName: "usbdmx",
|
||||||
|
lName: "ArtNet-USBDMX-Converter",
|
||||||
});
|
});
|
||||||
this.artNetReceiver = this.dmxnetManager.newReceiver();
|
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);
|
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
|
* @param data Art-Net data
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
handleIncomingArtNetData = (data: any) => {
|
handleIncomingArtNetData = (data: any) => {
|
||||||
this.incomingDataCounter++;
|
this.artnetInCounter++;
|
||||||
if (JSON.stringify(data) != JSON.stringify(this.recentDMXArray)) {
|
if (JSON.stringify(data) != JSON.stringify(this.recentDMXArray)) {
|
||||||
if (this.dmxInterface && this.outputAllowed) {
|
if (this.dmxInterface && this.outputAllowed) {
|
||||||
this.sentDataCounter++;
|
this.usbdmxOutCounter++;
|
||||||
this.dmxInterface.writeMap(data);
|
this.dmxInterface.writeMap(data);
|
||||||
}
|
}
|
||||||
this.recentDMXArray = 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
|
* Gets available DMX interfaces connected to the computer
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +108,7 @@ export default class ConvertHandler {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.dmxInterface = await DMXInterface.open(interfacePath, serial, manufacturer, product);
|
this.dmxInterface = await DMXInterface.open(interfacePath, serial, manufacturer, product);
|
||||||
|
this.dmxInterface.usbdmxInputCallback = this.sendIncomingUSBDMXData;
|
||||||
return new Promise<string>((resolve) => {
|
return new Promise<string>((resolve) => {
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// 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
|
* Processes incoming and sent data history for visualization
|
||||||
*/
|
*/
|
||||||
parseRequestTimer = () => {
|
parseRequestTimer = () => {
|
||||||
this.incomingDataHistory.push(this.incomingDataCounter);
|
this.artnetInCountHistory.push(this.artnetInCounter);
|
||||||
if (this.incomingDataHistory.length > 20) {
|
if (this.artnetInCountHistory.length > 20) {
|
||||||
this.incomingDataHistory = this.incomingDataHistory.slice(1)
|
this.artnetInCountHistory = this.artnetInCountHistory.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sentDataHistory.push(this.sentDataCounter);
|
this.artnetOutCountHistory.push(this.artnetOutCounter);
|
||||||
if (this.sentDataHistory.length > 20) {
|
if (this.artnetOutCountHistory.length > 20) {
|
||||||
this.sentDataHistory = this.sentDataHistory.slice(1)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -36,13 +36,19 @@ export default async function renderControlScreen() {
|
||||||
`${modeToString(defaultConvertHandler.dmxInterface?.currentMode ?? 0)}`)
|
`${modeToString(defaultConvertHandler.dmxInterface?.currentMode ?? 0)}`)
|
||||||
console.log("=================")
|
console.log("=================")
|
||||||
|
|
||||||
const incomingDataSparkline = Sparkline(defaultConvertHandler.incomingDataHistory, "req/sec");
|
const artnetInSparkline = Sparkline(defaultConvertHandler.artnetInCountHistory, "req/sec");
|
||||||
const sentDataSparkline = Sparkline(defaultConvertHandler.sentDataHistory, "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("ArtNet In\t")
|
||||||
process.stdout.write(incomingDataSparkline);
|
process.stdout.write(artnetInSparkline);
|
||||||
process.stdout.write("\nOutgoing Data ")
|
process.stdout.write("\nArtNet Out\t")
|
||||||
process.stdout.write(sentDataSparkline);
|
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("\n");
|
||||||
console.log(chalk.yellow(
|
console.log(chalk.yellow(
|
||||||
|
|
|
@ -18,7 +18,7 @@ async function main() {
|
||||||
"Starting ArtNet..."
|
"Starting ArtNet..."
|
||||||
));
|
));
|
||||||
console.log(chalk.yellow(
|
console.log(chalk.yellow(
|
||||||
"Nimm bitte eventuell erscheinende Firewall-Hinweise an"
|
"Please accept any firewall requests"
|
||||||
))
|
))
|
||||||
defaultConvertHandler.startArtNetReceiver();
|
defaultConvertHandler.startArtNetReceiver();
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
renderControlScreenTimer = setInterval(() => {
|
renderControlScreenTimer = setInterval(() => {
|
||||||
renderControlScreen();
|
renderControlScreen();
|
||||||
}, 1000);
|
}, 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ class DMXInterface {
|
||||||
currentMode = 0;
|
currentMode = 0;
|
||||||
hidDevice: HID.HID;
|
hidDevice: HID.HID;
|
||||||
dmxout: number[];
|
dmxout: number[];
|
||||||
dataCallback: (value: DMXCommand) => void;
|
|
||||||
|
usbdmxInputCallback: (start: number, values: number[]) => void;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
path: string,
|
path: string,
|
||||||
|
@ -35,14 +36,16 @@ class DMXInterface {
|
||||||
this.manufacturer = manufacturer;
|
this.manufacturer = manufacturer;
|
||||||
this.product = product;
|
this.product = product;
|
||||||
|
|
||||||
this.dataCallback = () => {};
|
|
||||||
this.hidDevice = new HID.HID(path);
|
this.hidDevice = new HID.HID(path);
|
||||||
this.hidDevice.on("data", (data: Buffer) => {
|
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
|
// 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
|
// this means we get 32 dmx channels in one package
|
||||||
|
|
||||||
|
const values: number[] = [];
|
||||||
for (let i = 1; i < 33; i++) {
|
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);
|
this.dmxout = Array(512).fill(0);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user