diff --git a/drivers/SmartThings/philips-hue/src/fields.lua b/drivers/SmartThings/philips-hue/src/fields.lua index 0df3c06aec..1d3f012e4f 100644 --- a/drivers/SmartThings/philips-hue/src/fields.lua +++ b/drivers/SmartThings/philips-hue/src/fields.lua @@ -30,7 +30,10 @@ local Fields = { PARENT_DEVICE_ID = "parent_device_id_local", RESOURCE_ID = "rid", RETRY_MIGRATION = "retry_migration", - WRAPPED_HUE = "_wrapped_hue" + WRAPPED_HUE = "_wrapped_hue", + COLOR_SATURATION = "color_saturation", + COLOR_HUE = "color_hue", + SWITCH_STATE = "switch_state_cache", } return Fields diff --git a/drivers/SmartThings/philips-hue/src/handlers/attribute_emitters.lua b/drivers/SmartThings/philips-hue/src/handlers/attribute_emitters.lua index 80f98e65a8..066d2f3264 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/attribute_emitters.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/attribute_emitters.lua @@ -35,8 +35,10 @@ local function _emit_light_events_inner(light_device, light_repr) if light_repr.on and light_repr.on.on then light_device:emit_event(capabilities.switch.switch.on()) + light_device:set_field(Fields.SWITCH_STATE, "on", {persist = true}) elseif light_repr.on and not light_repr.on.on then light_device:emit_event(capabilities.switch.switch.off()) + light_device:set_field(Fields.SWITCH_STATE, "off", {persist = true}) end if light_repr.dimming then @@ -96,6 +98,7 @@ local function _emit_light_events_inner(light_device, light_repr) ) else light_device:emit_event(capabilities.colorControl.hue(adjusted_hue)) + light_device:set_field(Fields.COLOR_HUE, adjusted_hue, {persist = true}) end if utils.is_nan(adjusted_sat) then @@ -107,6 +110,7 @@ local function _emit_light_events_inner(light_device, light_repr) ) else light_device:emit_event(capabilities.colorControl.saturation(adjusted_sat)) + light_device:set_field(Fields.COLOR_SATURATION, adjusted_sat, {persist = true}) end end end diff --git a/drivers/SmartThings/philips-hue/src/handlers/commands.lua b/drivers/SmartThings/philips-hue/src/handlers/commands.lua index 817bde6744..2b79a22e29 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/commands.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/commands.lua @@ -1,4 +1,3 @@ -local capabilities = require "st.capabilities" local log = require "log" local st_utils = require "st.utils" @@ -92,8 +91,7 @@ local function do_switch_level_action(driver, device, args) return end - local is_off = device:get_latest_state( - "main", capabilities.switch.ID, capabilities.switch.switch.NAME) == "off" + local is_off = device:get_field(Fields.SWITCH_STATE) == "off" if is_off then local resp, err = hue_api:set_light_on_state(light_id, true) @@ -178,7 +176,7 @@ end local function do_setHue_action(driver, device, args) -- Use existing 'saturation' value for device or set to 0 and pass arg values to function 'do_color_action' - local currentSaturation = device:get_latest_state("main", capabilities.colorControl.ID, capabilities.colorControl.saturation.NAME, 0) + local currentSaturation = device:get_field(Fields.COLOR_SATURATION) or 0 args.args.color = { hue = args.args.hue, saturation = currentSaturation @@ -193,7 +191,7 @@ end local function do_setSaturation_action(driver, device, args) -- Use existing 'hue' value for device or set to 0 and pass arg values to function 'do_color_action' - local currentHue = device:get_latest_state("main", capabilities.colorControl.ID, capabilities.colorControl.hue.NAME, 0) + local currentHue = device:get_field(Fields.COLOR_HUE) or 0 args.args.color = { hue = currentHue, saturation = args.args.saturation diff --git a/drivers/SmartThings/philips-hue/src/handlers/lifecycle_handlers/init.lua b/drivers/SmartThings/philips-hue/src/handlers/lifecycle_handlers/init.lua index e285bb5b1e..4b148a115a 100644 --- a/drivers/SmartThings/philips-hue/src/handlers/lifecycle_handlers/init.lua +++ b/drivers/SmartThings/philips-hue/src/handlers/lifecycle_handlers/init.lua @@ -1,5 +1,6 @@ local log = require "log" local st_utils = require "st.utils" +local capabilities = require "st.capabilities" local Discovery = require "disco" local Fields = require "fields" @@ -43,6 +44,19 @@ local migration_handlers = utils.lazy_handler_loader("handlers.migration_handler ---@class LifecycleHandlers local LifecycleHandlers = {} +local function emit_component_event_no_cache(device, component, capability_event) + if not device:supports_capability(capability_event.capability, component.id) then + local err_msg = string.format("Attempted to generate event for %s.%s but it does not support capability %s", device.id, component.id, capability_event.capability.NAME) + log.warn_with({ hub_logs = true }, err_msg) + return false, err_msg + end + local event, err = capabilities.emit_event(device, component.id, device.capability_channel, capability_event) + if err ~= nil then + log.warn_with({ hub_logs = true }, err) + end + return event, err +end + ---@param driver HueDriver ---@param device HueDevice ---@param ... any arguments for device specific handler @@ -55,6 +69,10 @@ function LifecycleHandlers.device_init(driver, device, ...) ) ) inner_handlers[device_type].init(driver, device, ...) + + -- Remove usage of the state cache for hue devices to avoid large datastores + device:set_field("__state_cache", nil, {persist = true}) + device:extend_device("emit_component_event", emit_component_event_no_cache) end ---@param driver HueDriver diff --git a/drivers/SmartThings/sonos/src/init.lua b/drivers/SmartThings/sonos/src/init.lua index 07e38f3b92..4b338c44f4 100644 --- a/drivers/SmartThings/sonos/src/init.lua +++ b/drivers/SmartThings/sonos/src/init.lua @@ -242,12 +242,29 @@ local function device_added(driver, device) _initialize_device(driver, device) end +local function emit_component_event_no_cache(device, component, capability_event) + if not device:supports_capability(capability_event.capability, component.id) then + local err_msg = string.format("Attempted to generate event for %s.%s but it does not support capability %s", device.id, component.id, capability_event.capability.NAME) + log.warn_with({ hub_logs = true }, err_msg) + return false, err_msg + end + local event, err = capabilities.emit_event(device, component.id, device.capability_channel, capability_event) + if err ~= nil then + log.warn_with({ hub_logs = true }, err) + end + return event, err +end + --- @param driver SonosDriver --- @param device SonosDevice local function device_init(driver, device) log.trace(string.format("%s device init", device.label)) _initialize_device(driver, device) + -- Remove usage of the state cache for sonos devices to avoid large datastores + device:set_field("__state_cache", nil, {persist = true}) + device:extend_device("emit_component_event", emit_component_event_no_cache) + device:emit_event(capabilities.mediaPlayback.supportedPlaybackCommands({ capabilities.mediaPlayback.commands.play.NAME, capabilities.mediaPlayback.commands.pause.NAME,