From a493b405928003914199c61abd022f56d96b15d7 Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Wed, 11 Feb 2026 15:59:01 -0600 Subject: [PATCH 1/2] Hue: fix issue with color temp increment of 1K Incrementing or decrementing the color temp by 1 can lead to the driver sending the Hue bridge the same value in mireds as the device is already set to, and the bridge not responding, which in turn leads to a spinning wheel in the app and eventually the value being reset to its previous value. This change emits the capability with the updated value without waiting for a response from the bridge. --- .../philips-hue/src/handlers/commands.lua | 11 +++++ .../src/handlers/grouped_light_commands.lua | 46 ++++++++++++++----- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/SmartThings/philips-hue/src/handlers/commands.lua b/drivers/SmartThings/philips-hue/src/handlers/commands.lua index cf30834a2c..7418175edd 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/commands.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/commands.lua @@ -206,6 +206,7 @@ end ---@param device HueChildDevice ---@param args table local function do_color_temp_action(driver, device, args) + local capabilities = require "st.capabilities" local kelvin = args.args.temperature local id = device.parent_device_id or device:get_field(Fields.PARENT_DEVICE_ID) local bridge_device = utils.get_hue_bridge_for_device(driver, device, id) @@ -238,6 +239,16 @@ local function do_color_temp_action(driver, device, args) local clamped_kelvin = st_utils.clamp_value(kelvin, min, Consts.MAX_TEMP_KELVIN) local mirek = math.floor(utils.kelvin_to_mirek(clamped_kelvin)) + local current_color_temp = device:get_latest_state("main", capabilities.colorTemperature.ID, capabilities.colorTemperature.colorTemperature.NAME) + if current_color_temp then + local current_mirek = math.floor(utils.kelvin_to_mirek(current_color_temp)) + if current_mirek == mirek then + log.debug(string.format("Color temp change from %dK to %dK results in same mirek value (%d), emitting event directly", current_color_temp, clamped_kelvin, mirek)) + device:emit_event(capabilities.colorTemperature.colorTemperature(clamped_kelvin)) + return + end + end + local resp, err = hue_api:set_light_color_temp(light_id, mirek) if not resp or (resp.errors and #resp.errors == 0) then diff --git a/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua b/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua index 1a1099fc5e..6f8d97e2c7 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua @@ -94,7 +94,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common local function do_color_action(driver, bridge_device, group, args, aux) local hue, sat = (args.args.color.hue / 100), (args.args.color.saturation / 100) if hue == 1 then -- 0 and 360 degrees are equivalent in HSV, but not in our conversion function @@ -135,7 +135,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common local function do_setHue_action(driver, bridge_device, group, args, aux) local currentSaturation = aux[Fields.COLOR_SATURATION] or 0 args.args.color = { @@ -149,7 +149,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common local function do_setSaturation_action(driver, bridge_device, group, args, aux) local currentHue = aux[Fields.COLOR_HUE] or 0 args.args.color = { @@ -163,8 +163,9 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common local function do_color_temp_action(driver, bridge_device, group, args, aux) + local capabilities = require "st.capabilities" local kelvin = args.args.temperature local grouped_light_id = group.grouped_light_rid @@ -185,6 +186,29 @@ local function do_color_temp_action(driver, bridge_device, group, args, aux) local clamped_kelvin = st_utils.clamp_value(kelvin, min, Consts.MAX_TEMP_KELVIN) local mirek = math.floor(utils.kelvin_to_mirek(clamped_kelvin)) + local all_same_mirek = true + for _, device in ipairs(group.devices) do + local current_color_temp = device:get_latest_state("main", capabilities.colorTemperature.ID, capabilities.colorTemperature.colorTemperature.NAME) + if current_color_temp then + local current_mirek = math.floor(utils.kelvin_to_mirek(current_color_temp)) + if current_mirek ~= mirek then + all_same_mirek = false + break + end + else + all_same_mirek = false + break + end + end + + if all_same_mirek and #group.devices > 0 then + log.debug(string.format("Color temp change to %dK results in same mirek value (%d) for all devices in group, emitting events directly", clamped_kelvin, mirek)) + for _, device in ipairs(group.devices) do + device:emit_event(capabilities.colorTemperature.colorTemperature(clamped_kelvin)) + end + return + end + local resp, err = hue_api:set_grouped_light_color_temp(grouped_light_id, mirek) if not resp or (resp.errors and #resp.errors == 0) then @@ -203,7 +227,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.switch_on_handler(driver, bridge_device, group, args, aux) do_switch_action(driver, bridge_device, group, args) end @@ -212,7 +236,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.switch_off_handler(driver, bridge_device, group, args, aux) do_switch_action(driver, bridge_device, group, args) end @@ -221,7 +245,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.switch_level_handler(driver, bridge_device, group, args, aux) do_switch_level_action(driver, bridge_device, group, args) end @@ -230,7 +254,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.set_color_handler(driver, bridge_device, group, args, aux) do_color_action(driver, bridge_device, group, args, aux) end @@ -239,7 +263,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.set_hue_handler(driver, bridge_device, group, args, aux) do_setHue_action(driver, bridge_device, group, args, aux) end @@ -248,7 +272,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.set_saturation_handler(driver, bridge_device, group, args, aux) do_setSaturation_action(driver, bridge_device, group, args, aux) end @@ -257,7 +281,7 @@ end ---@param bridge_device HueBridgeDevice ---@param group table ---@param args table ----@param aux table auxilary data needed for the command that the devices all had in common +---@param aux table auxiliary data needed for the command that the devices all had in common function GroupedLightCommandHandlers.set_color_temp_handler(driver, bridge_device, group, args, aux) do_color_temp_action(driver, bridge_device, group, args, aux) end From 38e8c2fa6cb855a76913404d2084b98b04103cc3 Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Fri, 13 Feb 2026 14:36:35 -0600 Subject: [PATCH 2/2] changes based on review feedback --- .../philips-hue/src/handlers/commands.lua | 1 - .../src/handlers/grouped_light_commands.lua | 18 +++--------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/SmartThings/philips-hue/src/handlers/commands.lua b/drivers/SmartThings/philips-hue/src/handlers/commands.lua index 7418175edd..0633afded6 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/commands.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/commands.lua @@ -245,7 +245,6 @@ local function do_color_temp_action(driver, device, args) if current_mirek == mirek then log.debug(string.format("Color temp change from %dK to %dK results in same mirek value (%d), emitting event directly", current_color_temp, clamped_kelvin, mirek)) device:emit_event(capabilities.colorTemperature.colorTemperature(clamped_kelvin)) - return end end diff --git a/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua b/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua index 6f8d97e2c7..6649262024 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/grouped_light_commands.lua @@ -186,29 +186,17 @@ local function do_color_temp_action(driver, bridge_device, group, args, aux) local clamped_kelvin = st_utils.clamp_value(kelvin, min, Consts.MAX_TEMP_KELVIN) local mirek = math.floor(utils.kelvin_to_mirek(clamped_kelvin)) - local all_same_mirek = true for _, device in ipairs(group.devices) do local current_color_temp = device:get_latest_state("main", capabilities.colorTemperature.ID, capabilities.colorTemperature.colorTemperature.NAME) if current_color_temp then local current_mirek = math.floor(utils.kelvin_to_mirek(current_color_temp)) - if current_mirek ~= mirek then - all_same_mirek = false - break + if current_mirek == mirek then + log.debug(string.format("Color temp change from %dK to %dK results in same mirek value (%d), emitting event directly", current_color_temp, clamped_kelvin, mirek)) + device:emit_event(capabilities.colorTemperature.colorTemperature(clamped_kelvin)) end - else - all_same_mirek = false - break end end - if all_same_mirek and #group.devices > 0 then - log.debug(string.format("Color temp change to %dK results in same mirek value (%d) for all devices in group, emitting events directly", clamped_kelvin, mirek)) - for _, device in ipairs(group.devices) do - device:emit_event(capabilities.colorTemperature.colorTemperature(clamped_kelvin)) - end - return - end - local resp, err = hue_api:set_grouped_light_color_temp(grouped_light_id, mirek) if not resp or (resp.errors and #resp.errors == 0) then