Skip to content

Commit

Permalink
Improve handling of on/off toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
DallasHoff committed Sep 5, 2022
1 parent ab4f097 commit 5c219fb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 36 deletions.
88 changes: 53 additions & 35 deletions src/platformAccessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';

import { OpenRgbPlatform } from './platform';

import { color, openRgbColor, rgbDeviceContext } from './rgb';
import { color, openRgbColor, rgbDeviceContext, rgbDeviceStates } from './rgb';
import * as ColorConvert from 'color-convert';
import { getDeviceLedRgbColor, findDeviceModeId, isLedOff, createDeviceLedConfig } from './utils';
import { getDeviceLedRgbColor, findDeviceModeId, isLedOff, createDeviceLedConfig, getStateHsvColor } from './utils';
import { CHARACTERISTIC_UPDATE_DELAY } from './settings';

/**
Expand All @@ -15,7 +15,7 @@ import { CHARACTERISTIC_UPDATE_DELAY } from './settings';
export class OpenRgbPlatformAccessory {
private service: Service;

private states = {
private states: rgbDeviceStates = {
On: false,
Hue: 0,
Saturation: 0,
Expand Down Expand Up @@ -131,8 +131,12 @@ export class OpenRgbPlatformAccessory {
const colorRgb = getDeviceLedRgbColor(device);
colorHsv = ColorConvert.rgb.hsv(...colorRgb);

// Update last powered color context value
if (!isLedOff(colorRgb)) {
// Check if lights are off
if (isLedOff(colorRgb)) {
// Lights off: return the previous state to preserve the set color
colorHsv = getStateHsvColor(this.states);
} else {
// Lights on: update last powered color context value
this.accessory.context.lastPoweredRgbColor = colorRgb;
}

Expand Down Expand Up @@ -205,49 +209,63 @@ export class OpenRgbPlatformAccessory {
await new Promise(resolve => setTimeout(() => resolve(0), CHARACTERISTIC_UPDATE_DELAY));

// New state info
const isOn = this.states.On;
const { Hue, Saturation, Brightness } = this.states;
const newColorRgb: color = ColorConvert.hsv.rgb([Hue, Saturation, Brightness]);
const isOn: boolean = this.states.On;
const newColorHsv: color = getStateHsvColor(this.states);
let newColorRgb: color = ColorConvert.hsv.rgb(newColorHsv);
let newMode: number | undefined = undefined;

await this.platform.rgbConnection(this.accessory.context.server, async (client, devices) => {
const device = devices.find(d => this.platform.genUuid(d) === this.accessory.UUID);
if (!device) {
return;
}

// Light color to set
const newLedColors: openRgbColor[] = createDeviceLedConfig(newColorRgb, device);

// Mode info
const offModeId: number | undefined = findDeviceModeId(device, 'Off');
const directModeId: number | undefined = findDeviceModeId(device, 'Direct');
const { lastPoweredModeId } = this.accessory.context;
const offModeId = findDeviceModeId(device, 'Off');
const directModeId = findDeviceModeId(device, 'Direct');
const { lastPoweredModeId, lastPoweredRgbColor } = this.accessory.context;

// Set light mode?
if (togglingPower === true) {
// Turning on or off
if (isOn === true) {
// Turning on
if (lastPoweredModeId !== undefined) {
// Last mode known: restore it
newMode = lastPoweredModeId;
} else if (directModeId !== undefined) {
// Last mode unknown: set to direct mode
newMode = directModeId;
}
if (lastPoweredRgbColor !== undefined) {
// Last color known: set it again
newColorRgb = lastPoweredRgbColor;
}
} else {
// Turning off: set mode to Off and set color to black
if (offModeId !== undefined) {
newMode = offModeId;
}
newColorRgb = [0, 0, 0];
}
} else if (directModeId !== undefined) {
// Changing light color: set mode to Direct
newMode = directModeId;
}

try {
// Set light mode?
if (togglingPower === true) {
// Turning on or off
if (isOn === true) {
// Turning on
if (lastPoweredModeId !== undefined) {
// Last mode known: restore it
await client.updateMode(device.deviceId, lastPoweredModeId);
} else if (directModeId !== undefined) {
// Last mode unknown: set to direct mode
await client.updateMode(device.deviceId, directModeId);
this.accessory.context.lastPoweredModeId = directModeId;
}
} else if (isOn === false && offModeId !== undefined) {
// Turning off: set mode to Off
await client.updateMode(device.deviceId, offModeId);
// Set mode
if (newMode !== undefined) {
await client.updateMode(device.deviceId, newMode);
if (newMode !== offModeId) {
this.accessory.context.lastPoweredModeId = newMode;
}
} else if (directModeId !== undefined) {
// Changing light color: set mode to Direct
await client.updateMode(device.deviceId, directModeId);
this.accessory.context.lastPoweredModeId = directModeId;
}
// Set light colors
const newLedColors: openRgbColor[] = createDeviceLedConfig(newColorRgb, device);
await client.updateLeds(device.deviceId, newLedColors);
if (!isLedOff(newColorRgb)) {
this.accessory.context.lastPoweredRgbColor = newColorRgb;
}
} catch (err) {
this.platform.log.warn(`Failed to set light color on device: ${device.name}`);
}
Expand Down
8 changes: 8 additions & 0 deletions src/rgb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ export interface rgbServer {
port: number;
}

/** State information that HomeKit keeps for accessories */
export interface rgbDeviceStates {
On: boolean;
Hue: number;
Saturation: number;
Brightness: number;
}

/** Context information stored for accessories */
export interface rgbDeviceContext {
device: rgbDevice;
Expand Down
7 changes: 6 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { color, openRgbColor, rgbDevice } from './rgb';
import { color, openRgbColor, rgbDevice, rgbDeviceStates } from './rgb';

/** Gets the RGB color that is set on the provided device */
export function getDeviceLedRgbColor(device: rgbDevice): color {
Expand All @@ -7,6 +7,11 @@ export function getDeviceLedRgbColor(device: rgbDevice): color {
return ledRgb;
}

/** Gets the HSV color that is currently represented by an accessory's state */
export function getStateHsvColor(states: rgbDeviceStates): color {
return [states.Hue, states.Saturation, states.Brightness];
}

/** Determines whether the provided color is black */
export function isLedOff(color: color): boolean {
return color[0] === 0 && color[1] === 0 && color[2] === 0;
Expand Down

0 comments on commit 5c219fb

Please sign in to comment.