From 35bf12dd5ee42301926c0bce3482dff94740a72e Mon Sep 17 00:00:00 2001 From: "Pennaz Software, LLC" Date: Sat, 22 Jul 2023 22:21:22 -0700 Subject: [PATCH] fixed gradient light flickering issue --- README.md | 26 +++- package.json | 2 +- src/dmx.ts | 322 +++++++++++++++++++++------------------ src/platformAccessory.ts | 20 +-- src/sacnUniverse.ts | 26 +++- 5 files changed, 230 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index bbc3a51..ae59518 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,18 @@ In order to configure accessories (i.e., lights, light strands, etc.) you need t "colorOrder": "bgr", "transitionEffect": "gradient", "transitionDuration": 3000 + }, + { + "name": "Single White Lights", + "id": "SWL", + "driverName": "sacn", + "ipAddress": "192.168.1.101", + "dmxStartChannel": 1, + "dmxChannelCount": 100, + "dmxUniverse": 122, + "colorOrder": "w", + "transitionEffect": "", + "transitionDuration": 0 } ] } @@ -88,11 +100,11 @@ In order to configure accessories (i.e., lights, light strands, etc.) you need t - **dmxChannelCount**: The number of channels within the universe to control. For a single light, specify 1. If you are controlling a light strand with 100 lights then specify 100. -- **colorOrder**: The order of RGB colors. Normally, lights are ordered in RGB (red, green and then blue). If the lights are in a different order then specify their order here. If not specified, the default is 'RGB'. +- **colorOrder**: The order of RGB colors. Normally, lights are ordered in RGB (red, green and then blue). If the lights are in a different order then specify their order here. If not specified, the default is 'RGB'. If the lights do not support an RGB configuration (i.e., only utilize one channel) then specify "w" for the color order. - **ipAddress**: If you are using a Streaming ACN (E131) lighting controller then specify the IP Address of the controller. -- **transitionEffect**: Specify an optional transition effect to be applied when lights are turned on or off. Transitions DO NOT apply when making color changes. Transition effects are only supported for SACN devices. Supported Effects: +- **transitionEffect**: Specify an optional transition effect to be applied when lights are turned on or off. Transitions DO NOT apply when making color changes. Transition effects are only supported for SACN devices and do not support a 'colorOrder' configuration of "w". Supported Effects: - **None** or **'blank'**: Do not use any transition effect @@ -116,4 +128,12 @@ In order to configure accessories (i.e., lights, light strands, etc.) you need t - Added gradient, chase and random transition effects when lights change colors. - - Moved IP Address and Serial Port configuration into the definitino for each accessory so that multiple devices can be supported. This is a "Breaking Change" and will require modification of the config JSON in HomeBridge. \ No newline at end of file + - Moved IP Address and Serial Port configuration into the definitino for each accessory so that multiple devices can be supported. This is a "Breaking Change" and will require modification of the config JSON in HomeBridge. + +### 1.2.2 (Jul 22, 2023) + + - Added support for multiple SACN devices with different IP Addresses + + - Added support for single-channel lights (i.e., non-RGB) using a colorOrder of 'w'. Transition effects are not supported in this configuration. + + - Fix Gradient (i.e., fade-in/fade-out) transition effect that was causing lights to flicker during transition. \ No newline at end of file diff --git a/package.json b/package.json index 0028678..f041322 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": false, "displayName": "DMX Light", "name": "homebridge-dmxlight-plugin", - "version": "1.2.1", + "version": "1.2.2", "description": "A Homebridge plugin for controlling lights via DMX.", "license": "Apache-2.0", "repository": { diff --git a/src/dmx.ts b/src/dmx.ts index 6a40dc2..8fabc1d 100644 --- a/src/dmx.ts +++ b/src/dmx.ts @@ -1,7 +1,5 @@ -//const DMX = require('dmx'); // include the dmx lib import { DMX, EnttecUSBDMXProDriver } from 'dmx-ts'; import { Logger } from 'homebridge'; -import { Client } from 'e131'; import { SacnUniverse } from './sacnUniverse'; import Gradient from 'javascript-color-gradient'; import shuffle from 'shuffle-array'; @@ -9,63 +7,53 @@ import shuffle from 'shuffle-array'; export class DmxController { private dmx: DMX; private log: Logger; - private static instance: DmxController; - private universeName = 'dmxLightUniverse'; - private sacnClient: Client; - private sacnUniverseMap: { [id: number]: SacnUniverse } = {}; + private dmxUniverseName = 'dmxLightUniverse'; private updateInterval = 100; + private sacnUniverse: SacnUniverse; + private driverName = ''; + private colorOrder = 'rgb'; // Constructor - private constructor(serialPort: string, ipAddress: string, universe: number, driverName: string, log: Logger) { + constructor(serialPort: string, ipAddress: string, universe: number, driverName: string, + channelStart: number, channelCount: number, colorOrder: string, transitionEffect: string, + transitionEffectDuration: number, log: Logger) { this.log = log; - - // Configure Enttec Pro this.dmx = new DMX(); + this.driverName = driverName; + this.colorOrder = colorOrder; if (serialPort !== '') { - this.dmx.addUniverse(this.universeName, new EnttecUSBDMXProDriver(serialPort)) + // Configure Enttec Pro + this.dmx.addUniverse(this.dmxUniverseName, new EnttecUSBDMXProDriver(serialPort)) .then(() => { - log.info('successfully added universe for Enttec Pro'); + this.log.info('successfully added universe for Enttec Pro'); }) .catch((err) => { - log.error('error adding universe for Enttec Pro: ' + err); + this.log.error('error adding universe for Enttec Pro: ' + err); } ); - } - - // Configure Streaming ACN - if (ipAddress !== '') { - this.sacnClient = new Client(ipAddress); - } else { - this.sacnClient = new Client('localhost'); - } - - this.log.info('Added accessory (' + driverName + ') at ' + serialPort + ipAddress + ' on universe #' + universe); - } - public static getInstance(serialPort: string, ipAddress: string, universe: number, driverName: string, log: Logger): DmxController { - if (!DmxController.instance) { - DmxController.instance = new DmxController(serialPort, ipAddress, universe, driverName, log); + // Create a dummy sacnUniverse to fulfill class requirement + this.sacnUniverse = new SacnUniverse('', 0, 0, 0, '', '', 0, log); + return; } // Initialize SACN Universe if necessary - if (driverName === 'sacn') { - DmxController.instance.sacnUniverseMap[universe] = new SacnUniverse(DmxController.instance.sacnClient, universe, log); - } + this.sacnUniverse = new SacnUniverse(ipAddress, universe, channelStart, channelCount, colorOrder, + transitionEffect, transitionEffectDuration, log); - return DmxController.instance; } - setOn(driverName: string, universeNumber: number, startChannel: number, channelCount: number, colorOrder: string, - hue: number, saturation: number, brightness: number, transitionEffect: string, transitionEffectDuration: number) { + setOn(hue: number, saturation: number, brightness: number) { const rgb = this.HSVtoRGB(hue/360, saturation/100, brightness/100); this.log.info('DMX On with Color: HSV=' + hue + '/' + saturation + '%/' + brightness + '%, RGB=' + rgb.r + '/' + - rgb.g + '/' + rgb.b + ' (Universe #' + universeNumber + ', Channels #' + startChannel + '-' + (startChannel + - channelCount - 1) + ', transition=' + transitionEffect + ', duration=' + transitionEffectDuration + ')'); + rgb.g + '/' + rgb.b + ' (Universe #' + this.sacnUniverse.universe + ', Channels #' + this.sacnUniverse.channelStart + '-' + + (this.sacnUniverse.channelStart + this.sacnUniverse.channelCount - 1) + ', transition=' + this.sacnUniverse.transitionEffect + + ', duration=' + this.sacnUniverse.transitionEffectDuration + ')'); // Remap colors if necessary - const colors = this.mapColors(rgb.r, rgb.g, rgb.b, colorOrder); + const colors = this.mapColors(rgb.r, rgb.g, rgb.b, this.sacnUniverse.colorOrder); // If colors are all off then we need to change them to all on if (colors[0] + colors[1] + colors[2] === 0) { @@ -74,108 +62,114 @@ export class DmxController { colors[2] = 255; } - switch (driverName) { + switch (this.driverName) { case 'enttec-usb-dmx-pro': - this.log.info('setting channels ' + startChannel + '-' + (startChannel+2) + ' on'); + this.log.info('setting channels ' + this.sacnUniverse.channelStart + '-' + (this.sacnUniverse.channelStart+2) + ' on'); // eslint-disable-next-line no-case-declarations - const channel = { [startChannel]: colors[0], [startChannel+1]: colors[1], [startChannel+2]: colors[2] }; - this.dmx.update(this.universeName, channel); + const channel = { [this.sacnUniverse.channelStart]: colors[0], [this.sacnUniverse.channelStart+1]: colors[1], + [this.sacnUniverse.channelStart+2]: colors[2] }; + this.dmx.update(this.dmxUniverseName, channel); break; case 'sacn': - switch (transitionEffect.toLocaleLowerCase()) { + switch (this.sacnUniverse.transitionEffect) { case 'gradient': - this.applyGradientTransition(universeNumber, startChannel, channelCount, colors[0], colors[1], colors[2], - transitionEffectDuration, colorOrder); + this.applyFadeInTransition(colors[0], colors[1], colors[2]); break; case 'random': - this.applyRandomTransition(universeNumber, startChannel, channelCount, colors[0], colors[1], colors[2], - transitionEffectDuration); + this.applyRandomTransition(colors[0], colors[1], colors[2]); break; case 'chase': - this.applyChaseTransition(universeNumber, startChannel, channelCount, colors[0], colors[1], colors[2], - transitionEffectDuration); + this.applyChaseTransition(colors[0], colors[1], colors[2]); break; default: - this.setSacnColor(universeNumber, startChannel, channelCount, colors[0], colors[1], colors[2]); + if (this.sacnUniverse.colorOrder === 'w') { + this.setSacnSingle(255); + } else { + this.setSacnColor(colors[0], colors[1], colors[2]); + } } break; } } - setOff(driverName: string, universeNumber: number, startChannel: number, channelCount: number, colorOrder: string, - transitionEffect: string, transitionEffectDuration: number) { - this.log.info('DMX Off (Universe #' + universeNumber + ', Channels #' + startChannel + '-' + (startChannel + channelCount - 1) + ')'); + setOff() { + this.log.info('DMX Off (Universe #' + this.sacnUniverse.universe + ', Channels #' + this.sacnUniverse.channelStart + '-' + + (this.sacnUniverse.channelStart + this.sacnUniverse.channelCount - 1) + ')'); - switch (driverName) { + switch (this.driverName) { case 'enttec-usb-dmx-pro': // eslint-disable-next-line no-case-declarations - const channel = { [startChannel]: 0, [startChannel+1]: 0, [startChannel+2]: 0 }; - this.dmx.update(this.universeName, channel); + const channel = { [this.sacnUniverse.channelStart]: 0, [this.sacnUniverse.channelStart+1]: 0, + [this.sacnUniverse.channelStart+2]: 0 }; + this.dmx.update(this.dmxUniverseName, channel); break; case 'sacn': - switch (transitionEffect.toLocaleLowerCase()) { + switch (this.sacnUniverse.transitionEffect) { case 'gradient': - this.applyGradientTransition(universeNumber, startChannel, channelCount, 0, 0, 0, transitionEffectDuration, colorOrder); + this.applyFadeOutTransition(0, 0, 0); break; case 'random': - this.applyRandomTransition(universeNumber, startChannel, channelCount, 0, 0, 0, transitionEffectDuration); + this.applyRandomTransition(0, 0, 0); break; case 'chase': - this.applyChaseTransition(universeNumber, startChannel, channelCount, 0, 0, 0, transitionEffectDuration); + this.applyChaseTransition(0, 0, 0); break; default: - this.setSacnColor(universeNumber, startChannel, channelCount, 0, 0, 0); + if (this.sacnUniverse.colorOrder === 'w') { + this.setSacnSingle(0); + } else { + this.setSacnColor(0, 0, 0); + } } break; } } - setHSB(driverName: string, universeNumber: number, startChannel: number, channelCount: number, colorOrder: string, - hue: number, saturation: number, brightness: number) { + setHSB(hue: number, saturation: number, brightness: number) { const rgb = this.HSVtoRGB(hue/360, saturation/100, brightness/100); this.log.info('Set Color: HSV=' + hue + '/' + saturation + '%/' + - brightness + '%, RGB=' + rgb.r + '/' + rgb.g + '/' + rgb.b + ' (Universe #' + universeNumber + - ', Channels #' + startChannel + '-' + (startChannel + channelCount - 1) + ')'); + brightness + '%, RGB=' + rgb.r + '/' + rgb.g + '/' + rgb.b + ' (Universe #' + this.sacnUniverse.universe + + ', Channels #' + this.sacnUniverse.channelStart + '-' + (this.sacnUniverse.channelStart + this.sacnUniverse.channelCount - 1) + ')'); // Remap colors if necessary - const colors = this.mapColors(rgb.r, rgb.g, rgb.b, colorOrder); + const colors = this.mapColors(rgb.r, rgb.g, rgb.b, this.sacnUniverse.colorOrder); - switch (driverName) { + switch (this.driverName) { case 'enttec-usb-dmx-pro': // eslint-disable-next-line no-case-declarations - let channel = { [startChannel]: colors[0]}; - this.dmx.update(this.universeName, channel); + let channel = { [this.sacnUniverse.channelStart]: colors[0]}; + this.dmx.update(this.dmxUniverseName, channel); - channel = { [startChannel+1]: colors[1]}; - this.dmx.update(this.universeName, channel); + channel = { [this.sacnUniverse.channelStart+1]: colors[1]}; + this.dmx.update(this.dmxUniverseName, channel); - channel = { [startChannel+2]: colors[2]}; - this.dmx.update(this.universeName, channel); + channel = { [this.sacnUniverse.channelStart+2]: colors[2]}; + this.dmx.update(this.dmxUniverseName, channel); break; case 'sacn': - this.setSacnColor(universeNumber, startChannel, channelCount, colors[0], colors[1], colors[2]); + this.setSacnColor(colors[0], colors[1], colors[2]); break; } } - private setSacnColor(universeNumber: number, startChannel: number, channelCount: number, r: number, g: number, b: number) { - const endChannel = startChannel-1 + channelCount-1; + private setSacnColor(r: number, g: number, b: number) { + const endChannel = this.sacnUniverse.channelStart-1 + this.sacnUniverse.channelCount-1; //this.log.info('Updating slots buffer from ' + (startChannel-1) + ' - ' + endChannel); //this.log.info('Color set to ' + r + '/' + g + '/' + b); let p = 1; - for (let idx = startChannel-1; idx <= endChannel; idx++) { + for (let idx = this.sacnUniverse.channelStart-1; idx <= endChannel; idx++) { switch (p) { case 1: - this.sacnUniverseMap[universeNumber].sacnSlotsData[idx] = r; + this.sacnUniverse.sacnSlotsData[idx] = r; break; case 2: - this.sacnUniverseMap[universeNumber].sacnSlotsData[idx] = g; + this.sacnUniverse.sacnSlotsData[idx] = g; break; case 3: - this.sacnUniverseMap[universeNumber].sacnSlotsData[idx] = b; + this.sacnUniverse.sacnSlotsData[idx] = b; break; } @@ -185,32 +179,66 @@ export class DmxController { } } - this.sacnClient.send(this.sacnUniverseMap[universeNumber].sacnPacket); + this.sacnUniverse.sacnClient.send(this.sacnUniverse.sacnPacket); } - // applyGradientTransition creates a smooth transition from one color to the next by utilizing a gradient of colors - private applyGradientTransition(universeNumber: number, startChannel: number, channelCount: number, r: number, g: number, b: - number, durationMs: number, colorOrder: string) { - const currentColor = this.getCurrentColor(universeNumber, startChannel, colorOrder); - const currentColorStr = this.rgbToColorString(currentColor[0], currentColor[1], currentColor[2]); - const finalColorStr = this.rgbToColorString(r, g, b); + // applyFadeOutTransition creates a smooth transition from the current color to off + private applyFadeOutTransition(r: number, g: number, b: number) { + const ccRGB = this.getCurrentColor(); + const ccHSV = this.rgbToHsv(ccRGB[0], ccRGB[1], ccRGB[2]); + + // If its already at the target then bail + if (b === ccHSV[2]) { + return; + } + + const fadeInterval = Math.round(this.sacnUniverse.transitionEffectDuration/this.updateInterval); + + let brightness = ccHSV[2]; + const brightnessDelta = Math.abs(brightness - b); + const stepAmount = brightnessDelta / fadeInterval; + const interval = fadeInterval; - const colorPoints = Math.round(durationMs/this.updateInterval); + const timerId = setInterval(() => { + brightness = brightness - stepAmount; + + if (brightness < 0) { + brightness = 0; + } + + const rgb = this.HSVtoRGB(ccHSV[0], ccHSV[1], brightness); + //console.log('h=' + ccHSV[0] + ', s=' + ccHSV[1] + ', v: ' + brightness + ' | r=' + rgb.r + ', g=' + rgb.g + ', b=' + rgb.b); + + this.setSacnColor(rgb.r, rgb.g, rgb.b); + + if (brightness <= 0) { + clearTimeout(timerId); + return; + } + }, interval); + } - const gradientColors = new Gradient(); - gradientColors.setColorGradient(currentColorStr, finalColorStr); - gradientColors.setMidpoint(colorPoints); - const colors = gradientColors.getColors(); + // applyFadeInTransition creates a smooth transition from off to the desired color + private applyFadeInTransition(r: number, g: number, b: number) { + const fadeInterval = Math.round(this.sacnUniverse.transitionEffectDuration/this.updateInterval); + const destColor = this.rgbToHsv(r, g, b); + let brightness = 0; + const brightnessDelta =destColor[2]; + const stepAmount = brightnessDelta / fadeInterval; + const interval = fadeInterval; - const colToStringArray = this.colorStringToArray; - let colorIndex = 0; - const interval = this.updateInterval; const timerId = setInterval(() => { - const rgb = colToStringArray(colors[colorIndex]); - this.setSacnColor(universeNumber, startChannel, channelCount, rgb[0], rgb[1], rgb[2]); - colorIndex += 1; + brightness = brightness + stepAmount; + + if (brightness > 1) { + brightness = 1; + } + + const rgb = this.HSVtoRGB(destColor[0], destColor[1], brightness); + + this.setSacnColor(rgb.r, rgb.g, rgb.b); - if (colorIndex >= colors.length) { + if (brightness >= 1) { clearTimeout(timerId); return; } @@ -218,14 +246,13 @@ export class DmxController { } // applyRandomTransition transitions each light to the desired color one at a time in a random order - private applyRandomTransition(universeNumber: number, startChannel: number, channelCount: number, r: number, g: number, b: number, - durationMs: number) { - const switchOrder = this.createRandomColorSwitchOrder(channelCount); - const timeInterval = Math.round(durationMs/switchOrder.length); + private applyRandomTransition(r: number, g: number, b: number) { + const switchOrder = this.createRandomColorSwitchOrder(this.sacnUniverse.channelCount); + const timeInterval = Math.round(this.sacnUniverse.transitionEffectDuration/switchOrder.length); let index = 0; const timerId = setInterval(() => { - this.setSacnColor(universeNumber, switchOrder[index], 3, r, g, b); + this.setSacnColor(r, g, b); index += 1; if (index >= switchOrder.length) { @@ -236,16 +263,15 @@ export class DmxController { } // applyChaseTransition transitions each light to the desired color one at a time from beginning to end - private applyChaseTransition(universeNumber: number, startChannel: number, channelCount: number, r: number, g: number, b: number, - durationMs: number) { - const timeInterval = Math.round(durationMs/(channelCount/3)); + private applyChaseTransition(r: number, g: number, b: number) { + const timeInterval = Math.round(this.sacnUniverse.transitionEffectDuration/(this.sacnUniverse.channelCount/3)); let channelIndex = 0; const timerId = setInterval(() => { - this.setSacnColor(universeNumber, (startChannel + channelIndex), 3, r, g, b); + this.setSacnColor(r, g, b); channelIndex += 3; - if (channelIndex >= channelCount) { + if (channelIndex >= this.sacnUniverse.channelCount) { clearTimeout(timerId); return; } @@ -316,38 +342,15 @@ export class DmxController { return colors; } - // colorStringToArray converts a color string in the format of "#3F2CAF" to an array of integers: [127, 32, 234] - private colorStringToArray(colorHexString: string) { - - const result: Array = []; - - if (colorHexString.length !== 7) { - return result; - } - - function hexToDecimal(hex: string) { - return parseInt(hex, 16); - } - try { - return [hexToDecimal(colorHexString.substring(1, 3)), hexToDecimal(colorHexString.substring(3, 5)), - hexToDecimal(colorHexString.substring(5, 7))]; - } catch { - this.log.error('failed to convert hex string to number'); - return result; - } - - return result; - } - - private getCurrentColor(universeNumber: number, startChannel: number, colorOrder: string) { - const firstChannel: number = this.sacnUniverseMap[universeNumber].sacnSlotsData[startChannel-1]; - const secondChannel: number = this.sacnUniverseMap[universeNumber].sacnSlotsData[startChannel]; - const thirdChannel: number = this.sacnUniverseMap[universeNumber].sacnSlotsData[startChannel+1]; + private getCurrentColor() { + const firstChannel: number = this.sacnUniverse.sacnSlotsData[this.sacnUniverse.channelStart-1]; + const secondChannel: number = this.sacnUniverse.sacnSlotsData[this.sacnUniverse.channelStart]; + const thirdChannel: number = this.sacnUniverse.sacnSlotsData[this.sacnUniverse.channelStart+1]; let red = firstChannel; let blue = secondChannel; let green = thirdChannel; - switch (colorOrder.toLowerCase().substring(0, 1)) { + switch (this.sacnUniverse.colorOrder.toLowerCase().substring(0, 1)) { case 'r': red = firstChannel; break; @@ -359,7 +362,7 @@ export class DmxController { break; } - switch (colorOrder.toLowerCase().substring(1, 2)) { + switch (this.sacnUniverse.colorOrder.toLowerCase().substring(1, 2)) { case 'r': red = secondChannel; break; @@ -371,7 +374,7 @@ export class DmxController { break; } - switch (colorOrder.toLowerCase().substring(2, 3)) { + switch (this.sacnUniverse.colorOrder.toLowerCase().substring(2, 3)) { case 'r': red = thirdChannel; break; @@ -387,20 +390,45 @@ export class DmxController { return [red, green, blue]; } - private rgbToColorString(r: number, g: number, b: number) { - let colorString = '#'; - colorString += this.intToHexStr(r); - colorString += this.intToHexStr(g); - colorString += this.intToHexStr(b); - return colorString; + private setSacnSingle(amount: number) { + const endChannel = this.sacnUniverse.channelStart-1 + this.sacnUniverse.channelCount-1; + //this.log.info('Updating slots buffer from ' + (startChannel-1) + ' - ' + endChannel); + //this.log.info('Color set to ' + r + '/' + g + '/' + b); + + for (let idx = this.sacnUniverse.channelStart-1; idx <= endChannel; idx++) { + this.sacnUniverse.sacnSlotsData[idx] = amount; + } + + this.sacnUniverse.sacnClient.send(this.sacnUniverse.sacnPacket); } - private intToHexStr(input: number) { - let result = input.toString(16); - if (result.length === 1) { - result += '0'; + private rgbToHsv(r: number, g: number, b: number) { + r /= 255, g /= 255, b /= 255; + + const max = Math.max(r, g, b), min = Math.min(r, g, b); + let h = max; + let s = max; + const v = max; + + const d = max - min; + s = max === 0 ? 0 : d / max; + + if (max === min) { + h = 0; // achromatic + } else { + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + if (h !== undefined) { + h /= 6; + } else { + h = 0; + } } - return result; + return [ h, s, v ]; } } \ No newline at end of file diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts index cd98072..b12e18c 100644 --- a/src/platformAccessory.ts +++ b/src/platformAccessory.ts @@ -56,8 +56,8 @@ export class DMXLightPlatformAccessory { this.serialPortName = serialPortName; // Create the DMX Controller object and initialize it - this.dmxController = DmxController.getInstance(serialPortName, ipAddress, - universeNumber, driverName, this.platform.log); + this.dmxController = new DmxController(serialPortName, ipAddress, universeNumber, driverName, startChannel, channelCount, + colorOrder, transitionEffect, transitionDuration, this.platform.log); // set accessory information this.accessory.getService(this.platform.Service.AccessoryInformation)! @@ -104,12 +104,9 @@ export class DMXLightPlatformAccessory { this.accessoryState.On = value as boolean; if (this.accessoryState.On) { - this.dmxController.setOn(this.driverName, this.universeNumber, this.startChannel, this.channelCount, this.colorOrder, - this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness, this.transitionEffect, - this.transitionDuration); + this.dmxController.setOn(this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); } else { - this.dmxController.setOff(this.driverName, this.universeNumber, this.startChannel, this.channelCount, this.colorOrder, - this.transitionEffect, this.transitionDuration); + this.dmxController.setOff(); } //this.platform.log.info('Set Characteristic On ->', value); @@ -186,8 +183,7 @@ export class DMXLightPlatformAccessory { this.accessoryState.Brightness = value as number; //this.platform.log.info('Set Characteristic Brightness -> ', value); - this.dmxController.setHSB(this.driverName, this.universeNumber, this.startChannel, this.channelCount, this.colorOrder, - this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); + this.dmxController.setHSB(this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); } async setHue(value: CharacteristicValue) { @@ -196,8 +192,7 @@ export class DMXLightPlatformAccessory { //this.platform.log.info('Set Characteristic Hue -> ', value); - this.dmxController.setHSB(this.driverName, this.universeNumber, this.startChannel, this.channelCount, this.colorOrder, - this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); + this.dmxController.setHSB(this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); } async setSaturation(value: CharacteristicValue) { @@ -206,8 +201,7 @@ export class DMXLightPlatformAccessory { //this.platform.log.info('Set Characteristic Saturation -> ', value); - this.dmxController.setHSB(this.driverName, this.universeNumber, this.startChannel, this.channelCount, this.colorOrder, - this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); + this.dmxController.setHSB(this.accessoryState.Hue, this.accessoryState.Saturation, this.accessoryState.Brightness); } getRandomArbitrary(min, max) { diff --git a/src/sacnUniverse.ts b/src/sacnUniverse.ts index e080cb6..4b0646d 100644 --- a/src/sacnUniverse.ts +++ b/src/sacnUniverse.ts @@ -2,16 +2,38 @@ import { Client, IPacket } from 'e131'; import { Logger } from 'homebridge'; export class SacnUniverse { + sacnClient: Client; sacnSlotsData: Array; sacnPacket: IPacket; + universe: number; + channelStart: number; + channelCount: number; + colorOrder: string; + transitionEffect: string; + transitionEffectDuration: number; + + constructor(ipAddress: string, universe: number, channelStart: number, channelCount: number, colorOrder: string, + transitionEffect: string, transitionEffectDuration: number, log: Logger) { + // Configure Streaming ACN + if (ipAddress !== '') { + this.sacnClient = new Client(ipAddress); + } else { + this.sacnClient = new Client('localhost'); + } - constructor(sacnClient: Client, universe: number, log: Logger) { // Create packets to support a full universe of 512 - this.sacnPacket = sacnClient.createPacket(512); + this.sacnPacket = this.sacnClient.createPacket(512); this.sacnPacket.setSourceName('DMXLightPlugin'); this.sacnPacket.setUniverse(universe); this.sacnSlotsData = this.sacnPacket.getSlotsData(); + this.universe = universe; + this.channelStart = channelStart; + this.channelCount = channelCount; + this.colorOrder = colorOrder.toLocaleLowerCase(); + this.transitionEffect = transitionEffect.toLocaleLowerCase(); + this.transitionEffectDuration = transitionEffectDuration; + log.info('Initialized new SACN Universe #' + universe); } } \ No newline at end of file