Skip to content

Commit

Permalink
Skip processing bridges as deletion candidates
Browse files Browse the repository at this point in the history
This removes the API version guard on the auto add/delete scan during
event stream connection and instead skips to the next element in the
iterator if it detects that the current iteration target is a device
record that represents a bridge.

We do this because we *do* want the auto-add/auto-delete routine to
run on older firmware, as the delete function does feature detection
on the lua libs and uses `device:offline()` as a fallback. Plus, auto
add will work on all firmware versions, so this is the better UX all
around.
  • Loading branch information
dljsjr committed Feb 7, 2024
1 parent 33e54cd commit 3979f46
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 12 deletions.
5 changes: 4 additions & 1 deletion drivers/SmartThings/philips-hue/src/disco.lua
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,17 @@ function HueDiscovery.search_bridge_for_supported_devices(driver, bridge_id, api

if do_delete then
for _, device in ipairs(driver:get_devices()) do ---@cast device HueDevice
-- We're only interested in processing child/non-bridge devices here.
if utils.is_bridge(driver, device) then goto continue end
local not_known_to_bridge = device_is_joined_to_bridge[device:get_field(Fields.HUE_DEVICE_ID) or ""]
local parent_device_id = device.parent_device_id or device:get_field(Fields.PARENT_DEVICE_ID) or ""
local parent_bridge_device = driver:get_device_info(parent_device_id)
local is_child_of_bridge = parent_bridge_device and (parent_bridge_device:get_field(Fields.BRIDGE_ID) == bridge_id)
if is_child_of_bridge and not not_known_to_bridge then
if parent_bridge_device and is_child_of_bridge and not not_known_to_bridge then
device.log.info(string.format("Device is no longer joined to Hue Bridge %q, deleting", parent_bridge_device.label))
driver:do_hue_light_delete(device)
end
::continue::
end
end
end
Expand Down
9 changes: 1 addition & 8 deletions drivers/SmartThings/philips-hue/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ local utils = require "utils"
local syncCapabilityId = "samsungim.hueSyncMode"
local hueSyncMode = capabilities[syncCapabilityId]

local api_version = require("version").api

local StrayDeviceMessageTypes = {
FoundBridge = "FOUND_BRIDGE",
NewStrayLight = "NEW_STRAY_LIGHT",
Expand Down Expand Up @@ -717,12 +715,7 @@ local function do_bridge_network_init(driver, bridge_device, bridge_url, api_key

local bridge_api = bridge_device:get_field(Fields.BRIDGE_API)
cosock.spawn(function()
-- auto-add/auto-delete is only supported with newer lua libs. We do a conditional
-- check in the delete routine, but we try to avoid doing it at all here with an
-- additional defensive check against the Lua Libs API version.
if api_version >= 9 then
Discovery.scan_bridge_and_update_devices(driver, bridge_device:get_field(Fields.BRIDGE_ID))
end
Discovery.scan_bridge_and_update_devices(driver, bridge_device:get_field(Fields.BRIDGE_ID))
local child_device_map = {}
local children = bridge_device:get_child_list()
bridge_device.log.debug(string.format("Scanning connectivity of %s child devices", #children))
Expand Down
26 changes: 23 additions & 3 deletions drivers/SmartThings/philips-hue/src/utils.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local Fields = require "hue.fields"
local log = require "log"
---@module 'utils'
---@class hue.utils
local utils = {}

local MAC_ADDRESS_STR_LEN = 12
Expand Down Expand Up @@ -27,15 +28,34 @@ function utils.is_nan(number)
return tostring(number) == tostring(0 / 0)
end

--- Only checked during `added` callback

--- Attempts an exhaustive check of all the ways a device
--- can indicate that it represents a Hue Bridge.
---@param driver HueDriver
---@param device HueDevice
---@return boolean is_bridge true if the device record represents a Hue Bridge
function utils.is_bridge(driver, device)
return (device:get_field(Fields.DEVICE_TYPE) == "bridge")
or (driver.datastore.bridge_netinfo[device.device_network_id] ~= nil)
or utils.is_edge_bridge(device) or utils.is_dth_light(device)
or (device.parent_assigned_child_key == nil)
end

--- Only checked during `added` callback, or as a later
--- fallback check in the chain of booleans used in `is_bridge`.
---
---@see hue.utils.is_bridge
---@param device HueDevice
---@return boolean
function utils.is_edge_bridge(device)
return device.device_network_id and #device.device_network_id == MAC_ADDRESS_STR_LEN and
not (device.data and device.data.username)
end

--- Only checked during `added` callback
--- Only checked during `added` callback, or as a later
--- fallback check in the chain of booleans used in `is_bridge`.
---
---@see hue.utils.is_bridge
---@param device HueDevice
---@return boolean
function utils.is_edge_light(device)
Expand Down

0 comments on commit 3979f46

Please sign in to comment.