Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rolling up main to beta #1219

Merged
merged 9 commits into from
Feb 13, 2024
20 changes: 12 additions & 8 deletions drivers/SmartThings/jbl/src/discovery.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ local st_utils = require "st.utils"
local discovery = {}

-- mapping from device DNI to info needed at discovery/init time
local device_discovery_cache = {}
local joined_device = {}

local function set_device_field(driver, device)
function discovery.set_device_field(driver, device)

log.info(string.format("set_device_field : %s", device.device_network_id))
local device_cache_value = device_discovery_cache[device.device_network_id]
local device_cache_value = driver.datastore.discovery_cache[device.device_network_id]

-- persistent fields
device:set_field(fields.DEVICE_IPV4, device_cache_value.ip, {persist = true})
device:set_field(fields.DEVICE_INFO, device_cache_value.device_info , {persist = true})
device:set_field(fields.CREDENTIAL, device_cache_value.credential , {persist = true})
device:set_field(fields.DEVICE_INFO, device_cache_value.device_info , {persist = true})
driver.datastore.discovery_cache[device.device_network_id] = nil
end

local function update_device_discovery_cache(driver, dni, ip, credential)
log.info(string.format("update_device_discovery_cache for device dni: %s, %s", dni, ip))
local device_info = driver.discovery_helper.get_device_info(driver, dni, ip)
device_discovery_cache[dni] = {
driver.datastore.discovery_cache[dni] = {
ip = ip,
device_info = device_info,
credential = credential,
Expand All @@ -39,6 +40,7 @@ local function try_add_device(driver, device_dni, device_ip)

if not credential then
log.error(string.format("failed to get credential. dni=%s, ip=%s", device_dni, device_ip))
joined_device[device_dni] = nil
return
end

Expand All @@ -49,8 +51,9 @@ end

function discovery.device_added(driver, device)
log.info("device_added : dni = " .. tostring(device.device_network_id))
set_device_field(driver, device)
device_discovery_cache[device.device_network_id] = nil

discovery.set_device_field(driver, device)
joined_device[device.device_network_id] = nil
driver.lifecycle_handlers.init(driver, device)
end

Expand All @@ -75,8 +78,9 @@ local function discovery_device(driver)
log.info(string.format("discovery_device dni, ip = %s, %s", dni, ip))
if not known_devices or not known_devices[dni] then
log.trace(string.format("unknown dni= %s, ip= %s", dni, ip))
if not device_discovery_cache[dni] then
if not joined_device[dni] then
try_add_device(driver, dni, ip)
joined_device[dni] = true
end
else
log.trace(string.format("known dni= %s, ip= %s", dni, ip))
Expand Down
9 changes: 9 additions & 0 deletions drivers/SmartThings/jbl/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ local function device_init(driver, device)

driver.controlled_devices[device_dni] = device

if driver.datastore.discovery_cache[device_dni] then
log.warn("set unsaved device field")
discovery.set_device_field(driver, device)
end

local device_ip = device:get_field(fields.DEVICE_IPV4)
local device_info = device:get_field(fields.DEVICE_INFO)
local credential = device:get_field(fields.CREDENTIAL)
Expand Down Expand Up @@ -214,6 +219,10 @@ local lan_driver = Driver("jbl",
}
)

if lan_driver.datastore.discovery_cache == nil then
lan_driver.datastore.discovery_cache = {}
end

lan_driver:call_on_schedule(CONNECTION_MONITORING_INTERVAL, connection_monitoring, "JBL Connection monitoring thread")

log.info("Starting lan driver")
Expand Down
17 changes: 16 additions & 1 deletion drivers/SmartThings/jbl/src/jbl/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,22 @@ function jbl_api.get_credential(bridge_ip, socket_builder)
end

function jbl_api.get_info(device_ip, socket_builder)
return process_rest_response(RestClient.one_shot_get(get_base_url(device_ip) .. "/info", ADDITIONAL_HEADERS, socket_builder))
local raw_device_info = process_rest_response(RestClient.one_shot_get(get_base_url(device_ip) .. "/info", ADDITIONAL_HEADERS, socket_builder))
if raw_device_info == nil then
log.error("failed to get device info")
return nil
end

local device_info = {
deviceType = raw_device_info.deviceType or "",
firmwareVersion = raw_device_info.firmwareVersion or "",
label = raw_device_info.label or "",
manufacturerName = raw_device_info.manufacturerName or "",
modelName = raw_device_info.modelName or "",
serialNumber = raw_device_info.serialNumber or "",
}

return device_info
end

function jbl_api:get_status()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ components:
- id: refresh
version: 1
categories:
- name: RemoteController
- name: Button
2 changes: 1 addition & 1 deletion drivers/SmartThings/matter-button/profiles/button.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ components:
- id: refresh
version: 1
categories:
- name: RemoteController
- name: Button
7 changes: 6 additions & 1 deletion drivers/SmartThings/matter-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,12 @@ matterManufacturer:
vendorId: 0x100b
productId: 0x228F
deviceProfileName: light-color-level-2200K-6500K

#Zemismart
- id: "5020/61154"
deviceLabel: Zemismart Inline Module
vendorId: 0x139C
productId: 0xEEE2
deviceProfileName: switch-binary

#Bridge devices need manufacturer specific fingerprints until
#bridge support is released to all hubs. This is because of the way generic
Expand Down
4 changes: 2 additions & 2 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ local function initialize_switch(driver, device)
end

device:set_field(SWITCH_INITIALIZED, true)
-- The case where num_server_eps == 1 is a workaround for devices that have the On/Off
-- The case where num_server_eps > 0 is a workaround for devices that have the On/Off
-- Light Switch device type but implement the On Off cluster as server (which is against the spec
-- for this device type). By default, we do not support On/Off Light Switch because by spec these
-- devices need bindings to work correctly (On/Off cluster is client in this case), so this device type
-- does not have a generic fingerprint and will join as a matter-thing. However, we have
-- seen some devices claim to be On/Off Light Switch device type and still implement On/Off server, so this
-- is a workaround for those devices.
if num_server_eps == 1 and detect_matter_thing(device) == true then
if num_server_eps > 0 and detect_matter_thing(device) == true then
device:try_update_metadata({profile = "switch-binary"})
end
end
Expand Down
9 changes: 8 additions & 1 deletion drivers/SmartThings/philips-hue/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ 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 @@ -712,7 +714,12 @@ 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()
Discovery.scan_bridge_and_update_devices(driver, bridge_device:get_field(Fields.BRIDGE_ID))
-- 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
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
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "|")
build_motion_status_message(mock_device, "\x7C")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.battery.battery(100)))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.inactive()))
Expand All @@ -85,7 +85,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "~")
build_motion_status_message(mock_device, "\x7E")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.battery.battery(100)))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.active()))
Expand All @@ -99,7 +99,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "X")
build_motion_status_message(mock_device, "\x58")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.battery.battery(70)))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.inactive()))
Expand All @@ -113,7 +113,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "Z")
build_motion_status_message(mock_device, "\x5A")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.battery.battery(70)))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.active()))
Expand All @@ -127,7 +127,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "½")
build_motion_status_message(mock_device, "\xBD")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.inactive()))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.signalStrength.lqi(50)))
Expand All @@ -140,7 +140,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "¿")
build_motion_status_message(mock_device, "\xBF")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.active()))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.signalStrength.lqi(50)))
Expand All @@ -153,7 +153,7 @@ test.register_coroutine_test(
function()
test.socket.zigbee:__queue_receive({
mock_device.id,
build_motion_status_message(mock_device, "0")
build_motion_status_message(mock_device, "\x30")
})
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.battery.battery(0)))
test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.motionSensor.motion.inactive()))
Expand All @@ -172,4 +172,4 @@ test.register_coroutine_test(
end
)

test.run_registered_tests()
test.run_registered_tests()
Loading