From e5b3d993bbcc25e96db0d093430b4374a9a1abd8 Mon Sep 17 00:00:00 2001 From: gaosen <0x5e@sina.cn> Date: Tue, 25 Oct 2022 20:30:41 +0800 Subject: [PATCH 1/3] Fix Lightbulb RGBCW work mode not switched properly --- src/accessory/LightAccessory.ts | 99 +++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/src/accessory/LightAccessory.ts b/src/accessory/LightAccessory.ts index 74734f9c..f83a9d67 100644 --- a/src/accessory/LightAccessory.ts +++ b/src/accessory/LightAccessory.ts @@ -129,7 +129,11 @@ export default class LightAccessory extends BaseAccessory { } const { h, s, v } = JSON.parse(status.value as string); - return { h, s, v }; + return { + h: h as number, + s: s as number, + v: v as number, + }; } getColorProperty() { @@ -142,6 +146,30 @@ export default class LightAccessory extends BaseAccessory { }; } + inWhiteMode() { + const mode = this.getWorkModeDeviceFunction(); + if (!mode) { + return false; + } + const status = this.device.getDeviceStatus(mode.code); + if (!status) { + return false; + } + return (status.value === 'white'); + } + + inColorMode() { + const mode = this.getWorkModeDeviceFunction(); + if (!mode) { + return false; + } + const status = this.device.getDeviceStatus(mode.code); + if (!status) { + return false; + } + return (status.value === 'colour'); + } + configureOn() { const service = this.getMainService(); const onFunction = this.getOnDeviceFunction()!; @@ -152,22 +180,46 @@ export default class LightAccessory extends BaseAccessory { return !!status && status!.value; }) .onSet((value) => { + this.log.debug(`Characteristic.On set to: ${value}`); this.addToSendQueue([{ code: onFunction.code, value: value as boolean }]); }); } configureBrightness() { const service = this.getMainService(); - const brightFunction = this.getBrightnessDeviceFunction()!; - const { max } = this.device.getDeviceFunctionProperty(brightFunction.code) as TuyaDeviceFunctionIntegerProperty; service.getCharacteristic(this.Characteristic.Brightness) .onGet(() => { + + // Color mode, get brightness from hsv + if (this.inColorMode()) { + const { max } = this.getColorProperty().v; + const brightStatus = this.getColorValue().v; + const brightPercent = brightStatus / max; + return Math.floor(brightPercent * 100); + } + + const brightFunction = this.getBrightnessDeviceFunction()!; + const { max } = this.device.getDeviceFunctionProperty(brightFunction.code) as TuyaDeviceFunctionIntegerProperty; const brightStatus = this.device.getDeviceStatus(brightFunction.code)!; const brightPercent = brightStatus.value as number / max; return Math.floor(brightPercent * 100); }) .onSet((value) => { + this.log.debug(`Characteristic.Brightness set to: ${value}`); + + // Color mode, set brightness to hsv + if (this.inColorMode()) { + const { max } = this.getColorProperty().v; + const colorFunction = this.getColorDeviceFunction()!; + const colorValue = this.getColorValue(); + colorValue.v = Math.floor(value as number * max / 100); + this.addToSendQueue([{ code: colorFunction.code, value: JSON.stringify(colorValue) }]); + return; + } + + const brightFunction = this.getBrightnessDeviceFunction()!; + const { max } = this.device.getDeviceFunctionProperty(brightFunction.code) as TuyaDeviceFunctionIntegerProperty; const brightValue = Math.floor(value as number * max / 100); this.addToSendQueue([{ code: brightFunction.code, value: brightValue }]); }); @@ -188,11 +240,18 @@ export default class LightAccessory extends BaseAccessory { return miredValue; }) .onSet((value) => { + this.log.debug(`Characteristic.ColorTemperature set to: ${value}`); const temp = Math.floor((1000000 / (value as number) - 2000) * (max - min) / (7142 - 2000) + min); const commands: TuyaDeviceStatus[] = [{ code: tempFunction.code, value: temp, }]; + + const mode = this.getWorkModeDeviceFunction(); + if (mode) { + commands.push({ code: 'work_mode', value: 'white' }); + } + this.addToSendQueue(commands); }); @@ -204,18 +263,30 @@ export default class LightAccessory extends BaseAccessory { const { min, max } = this.getColorProperty().h; service.getCharacteristic(this.Characteristic.Hue) .onGet(() => { + // White mode, return fixed Hue 0 + if (this.inWhiteMode()) { + return 0; + } + let hue = Math.floor(360 * (this.getColorValue().h - min) / (max - min)); hue = Math.max(0, hue); hue = Math.min(360, hue); return hue; }) .onSet((value) => { + this.log.debug(`Characteristic.Hue set to: ${value}`); const colorValue = this.getColorValue(); colorValue.h = Math.floor((value as number / 360) * (max - min) + min); const commands: TuyaDeviceStatus[] = [{ code: colorFunction.code, value: JSON.stringify(colorValue), }]; + + const mode = this.getWorkModeDeviceFunction(); + if (mode) { + commands.push({ code: 'work_mode', value: 'colour' }); + } + this.addToSendQueue(commands); }); } @@ -226,24 +297,40 @@ export default class LightAccessory extends BaseAccessory { const { min, max } = this.getColorProperty().s; service.getCharacteristic(this.Characteristic.Saturation) .onGet(() => { + // White mode, return fixed Saturation 0 + if (this.inWhiteMode()) { + return 0; + } + let saturation = Math.floor(100 * (this.getColorValue().s - min) / (max - min)); saturation = Math.max(0, saturation); - saturation = Math.min(360, saturation); + saturation = Math.min(100, saturation); return saturation; }) .onSet((value) => { + this.log.debug(`Characteristic.Saturation set to: ${value}`); const colorValue = this.getColorValue(); colorValue.s = Math.floor((value as number / 100) * (max - min) + min); const commands: TuyaDeviceStatus[] = [{ code: colorFunction.code, value: JSON.stringify(colorValue), }]; + + const mode = this.getWorkModeDeviceFunction(); + if (mode) { + commands.push({ code: 'work_mode', value: 'colour' }); + } + this.addToSendQueue(commands); }); } sendQueue: TuyaDeviceStatus[] = []; - debounceSendCommands = debounce(this.deviceManager.sendCommands.bind(this.deviceManager), 100); + debounceSendCommands = debounce(async () => { + await this.deviceManager.sendCommands(this.device.id, this.sendQueue); + this.sendQueue = []; + }, 100); + addToSendQueue(commands: TuyaDeviceStatus[]) { for (const newStatus of commands) { // Update cache immediately @@ -261,6 +348,6 @@ export default class LightAccessory extends BaseAccessory { } } - this.debounceSendCommands(this.device.id, this.sendQueue); + this.debounceSendCommands(); } } From 5abb92389c71b09d4215c7168d7bb273c82d9b19 Mon Sep 17 00:00:00 2001 From: gaosen <0x5e@sina.cn> Date: Tue, 25 Oct 2022 20:31:07 +0800 Subject: [PATCH 2/3] Fix Lightbulb RGB don't have brightness --- src/accessory/LightAccessory.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/accessory/LightAccessory.ts b/src/accessory/LightAccessory.ts index f83a9d67..0340222f 100644 --- a/src/accessory/LightAccessory.ts +++ b/src/accessory/LightAccessory.ts @@ -38,10 +38,6 @@ export default class LightAccessory extends BaseAccessory { this.configureColourTemperature(); break; case LightAccessoryType.RGB: - this.configureOn(); - this.configureHue(); - this.configureSaturation(); - break; case LightAccessoryType.RGBC: this.configureOn(); this.configureBrightness(); From 105a093c03c9626b7e2365603e7061e05fc076a2 Mon Sep 17 00:00:00 2001 From: gaosen <0x5e@sina.cn> Date: Tue, 25 Oct 2022 20:34:14 +0800 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68383a80..48217a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,5 +39,4 @@ - [Window] Add Curtain Switch support (`clkg`). ### Known issue -- `LightAccessory` may not work properly, espasially on work mode change. need more test and feedbacks. -- Sometimes mqtt not respond quickly, will influence the accessory status update. still addressing the issue. +- Sometimes mqtt not respond quickly, the older message received later than newer one. This will influence the accessory status update.