From e914f256a9100c24d9a36916b490ce757e40b577 Mon Sep 17 00:00:00 2001 From: hiconkong Date: Mon, 19 Oct 2026 14:04:29 +0800 Subject: [PATCH 1/3] Add SONOFF Dongle-LMG21 range extender fingerprint --- drivers/SmartThings/zigbee-range-extender/fingerprints.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-range-extender/fingerprints.yml b/drivers/SmartThings/zigbee-range-extender/fingerprints.yml index d8d4bcd5cf..9d87b1e707 100644 --- a/drivers/SmartThings/zigbee-range-extender/fingerprints.yml +++ b/drivers/SmartThings/zigbee-range-extender/fingerprints.yml @@ -33,4 +33,9 @@ zigbeeManufacturer: deviceLabel: frient Zigbee Range Extender manufacturer: frient A/S model: REXZB-111 - deviceProfileName: range-extender-battery-source \ No newline at end of file + deviceProfileName: range-extender-battery-source + - id: "SONOFF/Router" + deviceLabel: "SONOFF Zigbee Range Extender" + manufacturer: "SONOFF" + model: "Dongle-LMG21" + deviceProfileName: range-extender \ No newline at end of file From 9592ea42b88de685e72dccf27bc5f3319553a95b Mon Sep 17 00:00:00 2001 From: hiconkong Date: Mon, 2 Nov 2026 11:12:25 +0800 Subject: [PATCH 2/3] Add signal strength support for Zigbee range extenders - Add a reusable range-extender-signal profile with signalStrength and refresh - Report RSSI and LQI from Basic cluster responses - Reuse manual refresh and existing five-minute polling for signal sampling - Select the sub-driver by capability rather than manufacturer or model - Update the Dongle-LMG21 fingerprint to use the new profile - Add integration tests for sampling, profile changes, and device matching Validation: all 22 integration tests pass; luacheck reports no warnings or errors. --- .../zigbee-range-extender/README.md | 45 ++++ .../zigbee-range-extender/fingerprints.yml | 2 +- .../profiles/range-extender-signal.yml | 10 + .../zigbee-range-extender/src/init.lua | 3 +- .../src/range-extender-signal/can_handle.lua | 13 ++ .../src/range-extender-signal/init.lua | 45 ++++ .../zigbee-range-extender/src/sub_drivers.lua | 1 + .../src/test/test_range_extender_signal.lua | 200 ++++++++++++++++++ 8 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 drivers/SmartThings/zigbee-range-extender/README.md create mode 100644 drivers/SmartThings/zigbee-range-extender/profiles/range-extender-signal.yml create mode 100644 drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua create mode 100644 drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/init.lua create mode 100644 drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua diff --git a/drivers/SmartThings/zigbee-range-extender/README.md b/drivers/SmartThings/zigbee-range-extender/README.md new file mode 100644 index 0000000000..a8c77e246d --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/README.md @@ -0,0 +1,45 @@ +# Zigbee Range Extender + +## Signal strength + +The reusable `range-extender-signal` profile exposes the standard +`signalStrength` capability alongside `refresh`. +Assign it to a device's fingerprint to enable signal strength support. + +The `range-extender-signal` sub-driver handles devices whose `main` component +includes `signalStrength`, independently of manufacturer and model. The driver's +existing refresh handler reads the Basic cluster's `ZCLVersion` attribute during +default configuration and manual refresh. The 300-second health poll also reads +this attribute. Each successful response supplies the received-message +metadata used to emit: + +- `signalStrength.lqi`: LQI, from 0 to 255. +- `signalStrength.rssi`: RSSI, in dBm. + +The driver publishes measured values only after receiving a response; it does +not initialize signal strength with placeholder values. These values describe +reception at the hub. In a routed network they can reflect the last received hop, +and do not measure overall mesh coverage or repeater throughput. + +Existing devices retain their profile when a driver is updated. Devices using +the original `range-extender` profile need their profile updated or must rejoin +to receive the new fingerprint's profile. A profile change triggers a fresh +read. Profiles without `signalStrength` retain their existing behavior. + +## Hardware verification + +1. Use router/range-extender firmware and verify the joined device matches a + fingerprint assigned to `range-extender-signal`. +2. Verify a newly joined device exposes `signalStrength` and `refresh`, and + receives an initial RSSI/LQI sample. +3. Pull to refresh and confirm a Basic `ZCLVersion` response produces new + RSSI/LQI events. Check that sampling repeats after five minutes. +4. Update an existing device's profile to `range-extender-signal` or rejoin the + device, and confirm signal strength becomes available. +5. Check power cycling/rejoining and confirm an unavailable device does not + produce fabricated signal measurements. + +Integration tests cover the command/response paths, polling, profile changes, +metadata values, and capability-based device matching. Certification still +requires physical sample evaluation as requested by SmartThings; local tests +do not replace it. diff --git a/drivers/SmartThings/zigbee-range-extender/fingerprints.yml b/drivers/SmartThings/zigbee-range-extender/fingerprints.yml index 9d87b1e707..a5a4077fed 100644 --- a/drivers/SmartThings/zigbee-range-extender/fingerprints.yml +++ b/drivers/SmartThings/zigbee-range-extender/fingerprints.yml @@ -38,4 +38,4 @@ zigbeeManufacturer: deviceLabel: "SONOFF Zigbee Range Extender" manufacturer: "SONOFF" model: "Dongle-LMG21" - deviceProfileName: range-extender \ No newline at end of file + deviceProfileName: range-extender-signal diff --git a/drivers/SmartThings/zigbee-range-extender/profiles/range-extender-signal.yml b/drivers/SmartThings/zigbee-range-extender/profiles/range-extender-signal.yml new file mode 100644 index 0000000000..f32a15e37f --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/profiles/range-extender-signal.yml @@ -0,0 +1,10 @@ +name: range-extender-signal +components: +- id: main + capabilities: + - id: signalStrength + version: 1 + - id: refresh + version: 1 + categories: + - name: Networking diff --git a/drivers/SmartThings/zigbee-range-extender/src/init.lua b/drivers/SmartThings/zigbee-range-extender/src/init.lua index f06988f5cf..74a834ec56 100644 --- a/drivers/SmartThings/zigbee-range-extender/src/init.lua +++ b/drivers/SmartThings/zigbee-range-extender/src/init.lua @@ -15,7 +15,8 @@ end local zigbee_range_driver_template = { supported_capabilities = { capabilities.refresh, - capabilities.battery + capabilities.battery, + capabilities.signalStrength }, capability_handlers = { [capabilities.refresh.ID] = { diff --git a/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua new file mode 100644 index 0000000000..04aa7ff1d9 --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua @@ -0,0 +1,13 @@ +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local capabilities = require "st.capabilities" + +local function can_handle(opts, driver, device, ...) + if device:supports_capability(capabilities.signalStrength, "main") then + return true, require("range-extender-signal") + end + return false +end + +return can_handle diff --git a/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/init.lua b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/init.lua new file mode 100644 index 0000000000..1e2707e237 --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/init.lua @@ -0,0 +1,45 @@ +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local capabilities = require "st.capabilities" +local Basic = (require "st.zigbee.zcl.clusters").Basic + +local function refresh_signal_strength(driver, device) + -- The reply carries the hub's received-message RSSI and LQI. + device:send(Basic.attributes.ZCLVersion:read(device)) +end + +local function info_changed(driver, device, event, args) + if device.profile.id ~= args.old_st_store.profile.id then + refresh_signal_strength(driver, device) + end +end + +local function signal_strength_handler(driver, device, value, zb_rx) + -- A device can change profiles while this sub-driver is loaded. + if not device:supports_capability(capabilities.signalStrength, "main") then + return + end + + if zb_rx.lqi ~= nil and zb_rx.lqi.value ~= nil then + device:emit_event(capabilities.signalStrength.lqi(zb_rx.lqi.value)) + end + if zb_rx.rssi ~= nil and zb_rx.rssi.value ~= nil then + device:emit_event(capabilities.signalStrength.rssi({ value = zb_rx.rssi.value, unit = "dBm" })) + end +end + +return { + NAME = "Range Extender Signal Strength", + lifecycle_handlers = { + infoChanged = info_changed, + }, + zigbee_handlers = { + attr = { + [Basic.ID] = { + [Basic.attributes.ZCLVersion.ID] = signal_strength_handler, + }, + }, + }, + can_handle = require("range-extender-signal.can_handle"), +} diff --git a/drivers/SmartThings/zigbee-range-extender/src/sub_drivers.lua b/drivers/SmartThings/zigbee-range-extender/src/sub_drivers.lua index 2f30e461ee..1bf3e7d3e5 100644 --- a/drivers/SmartThings/zigbee-range-extender/src/sub_drivers.lua +++ b/drivers/SmartThings/zigbee-range-extender/src/sub_drivers.lua @@ -4,5 +4,6 @@ local lazy_load_if_possible = require "lazy_load_subdriver" local sub_drivers = { lazy_load_if_possible("frient"), + lazy_load_if_possible("range-extender-signal"), } return sub_drivers diff --git a/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua b/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua new file mode 100644 index 0000000000..04c849018c --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua @@ -0,0 +1,200 @@ +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local clusters = require "st.zigbee.zcl.clusters" +local data_types = require "st.zigbee.data_types" +local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" + +local Basic = clusters.Basic + +local function build_device(profile, manufacturer, model) + return test.mock_device.build_test_zigbee_device({ + profile = t_utils.get_profile_definition(profile), + zigbee_endpoints = { + [0x01] = { + id = 0x01, + manufacturer = manufacturer or "Generic manufacturer", + model = model or "Range Extender", + server_clusters = { Basic.ID }, + }, + }, + }) +end + +local mock_device = build_device("range-extender-signal.yml") +local base_device = build_device("range-extender.yml") +local other_manufacturer = build_device("range-extender-signal.yml", "Other manufacturer") +local other_model = build_device("range-extender-signal.yml", "Another manufacturer", "Other model") + +local function read_response(device, lqi, rssi) + local message = Basic.attributes.ZCLVersion:build_test_read_attr_response(device, 3) + message.lqi = data_types.Uint8(lqi) + message.rssi = data_types.Int8(rssi) + return message +end + +local function expect_signal_strength(device, lqi, rssi) + test.socket.capability:__expect_send(device:generate_test_message( + "main", capabilities.signalStrength.lqi(lqi))) + test.socket.capability:__expect_send(device:generate_test_message( + "main", capabilities.signalStrength.rssi({ value = rssi, unit = "dBm" }))) +end + +local function base_test_init() + test.mock_device.add_test_device(base_device) +end + +zigbee_test_utils.prepare_zigbee_env_info() +test.set_test_init_function(function() + test.mock_device.add_test_device(mock_device) +end) + +test.register_coroutine_test( + "Refresh reads the device and publishes received signal strength", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { capability = "refresh", component = "main", command = "refresh", args = {} }, + }) + test.socket.zigbee:__expect_send({ mock_device.id, Basic.attributes.ZCLVersion:read(mock_device) }) + test.wait_for_events() + + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 203, -67) }) + expect_signal_strength(mock_device, 203, -67) + end +) + +test.register_coroutine_test( + "Configuration obtains an initial signal sample without configuring reporting", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) + test.socket.zigbee:__expect_send({ mock_device.id, Basic.attributes.ZCLVersion:read(mock_device) }) + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + test.wait_for_events() + + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 169, -74) }) + expect_signal_strength(mock_device, 169, -74) + end +) + +test.register_coroutine_test( + "Health polling obtains new signal samples every five minutes", + function() + test.wait_for_events() + test.mock_time.advance_time(300) + test.socket.zigbee:__expect_send({ mock_device.id, Basic.attributes.ZCLVersion:read(mock_device) }) + test.wait_for_events() + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 211, -61) }) + expect_signal_strength(mock_device, 211, -61) + test.wait_for_events() + + test.mock_time.advance_time(300) + test.socket.zigbee:__expect_send({ mock_device.id, Basic.attributes.ZCLVersion:read(mock_device) }) + test.wait_for_events() + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 83, -91) }) + expect_signal_strength(mock_device, 83, -91) + end, + { + test_init = function() + test.mock_device.add_test_device(mock_device) + test.timer.__create_and_queue_test_time_advance_timer(300, "interval", 2) + end, + } +) + +test.register_coroutine_test( + "Zero LQI and zero dBm are preserved in received samples", + function() + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 0, 0) }) + expect_signal_strength(mock_device, 0, 0) + end +) + +test.register_coroutine_test( + "Signal strength preserves Zigbee metadata boundary values", + function() + test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 255, -128) }) + expect_signal_strength(mock_device, 255, -128) + end +) + +test.register_coroutine_test( + "Unsolicited Basic reports also update signal strength", + function() + local report = Basic.attributes.ZCLVersion:build_test_attr_report(mock_device, 3) + report.lqi = data_types.Uint8(127) + report.rssi = data_types.Int8(-82) + test.socket.zigbee:__queue_receive({ mock_device.id, report }) + expect_signal_strength(mock_device, 127, -82) + end +) + +test.register_coroutine_test( + "Initializing a base profile does not automatically add signal strength capabilities", + function() + test.wait_for_events() + end, + { + test_init = base_test_init, + } +) + +test.register_coroutine_test( + "Samples are not published for a base profile without signal strength", + function() + test.socket.zigbee:__queue_receive({ base_device.id, read_response(base_device, 196, -70) }) + end, + { + test_init = base_test_init, + } +) + +test.register_coroutine_test( + "Changing to the signal strength profile obtains and publishes an initial sample", + function() + test.socket.device_lifecycle:__queue_receive(base_device:generate_info_changed({ + profile = t_utils.get_profile_definition("range-extender-signal.yml"), + })) + test.socket.zigbee:__expect_send({ base_device.id, Basic.attributes.ZCLVersion:read(base_device) }) + test.wait_for_events() + + test.socket.zigbee:__queue_receive({ base_device.id, read_response(base_device, 184, -72) }) + expect_signal_strength(base_device, 184, -72) + end, + { + test_init = base_test_init, + } +) + +test.register_coroutine_test( + "Initializing or changing preferences does not request another signal sample", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "init" }) + test.wait_for_events() + test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = {} })) + end +) + +for _, case in ipairs({ + { name = "another manufacturer", device = other_manufacturer }, + { name = "another model", device = other_model }, +}) do + local device = case.device + test.register_coroutine_test( + "Signal strength capability is supported for " .. case.name, + function() + test.socket.zigbee:__queue_receive({ device.id, read_response(device, 196, -70) }) + expect_signal_strength(device, 196, -70) + end, + { + test_init = function() + test.mock_device.add_test_device(device) + end, + } + ) +end + +test.run_registered_tests() From 7018d889d9bf06626820c0802c32cf1d0b87ca61 Mon Sep 17 00:00:00 2001 From: hiconkong Date: Tue, 3 Nov 2026 20:18:03 +0800 Subject: [PATCH 3/3] Address review feedback for range extender signal support - Set min_api_version to 17 for all new tests - Match the sub-driver using manufacturer and model fingerprints - Add an extensible fingerprint list for supported range extenders - Verify that unmatched manufacturers and models are rejected Validation: all 22 tests pass; luacheck reports no warnings or errors. --- .../zigbee-range-extender/README.md | 45 ----------------- .../src/range-extender-signal/can_handle.lua | 11 +++-- .../range-extender-signal/fingerprints.lua | 8 ++++ .../src/test/test_range_extender_signal.lua | 48 ++++++++++++++----- 4 files changed, 49 insertions(+), 63 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-range-extender/README.md create mode 100644 drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/fingerprints.lua diff --git a/drivers/SmartThings/zigbee-range-extender/README.md b/drivers/SmartThings/zigbee-range-extender/README.md deleted file mode 100644 index a8c77e246d..0000000000 --- a/drivers/SmartThings/zigbee-range-extender/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Zigbee Range Extender - -## Signal strength - -The reusable `range-extender-signal` profile exposes the standard -`signalStrength` capability alongside `refresh`. -Assign it to a device's fingerprint to enable signal strength support. - -The `range-extender-signal` sub-driver handles devices whose `main` component -includes `signalStrength`, independently of manufacturer and model. The driver's -existing refresh handler reads the Basic cluster's `ZCLVersion` attribute during -default configuration and manual refresh. The 300-second health poll also reads -this attribute. Each successful response supplies the received-message -metadata used to emit: - -- `signalStrength.lqi`: LQI, from 0 to 255. -- `signalStrength.rssi`: RSSI, in dBm. - -The driver publishes measured values only after receiving a response; it does -not initialize signal strength with placeholder values. These values describe -reception at the hub. In a routed network they can reflect the last received hop, -and do not measure overall mesh coverage or repeater throughput. - -Existing devices retain their profile when a driver is updated. Devices using -the original `range-extender` profile need their profile updated or must rejoin -to receive the new fingerprint's profile. A profile change triggers a fresh -read. Profiles without `signalStrength` retain their existing behavior. - -## Hardware verification - -1. Use router/range-extender firmware and verify the joined device matches a - fingerprint assigned to `range-extender-signal`. -2. Verify a newly joined device exposes `signalStrength` and `refresh`, and - receives an initial RSSI/LQI sample. -3. Pull to refresh and confirm a Basic `ZCLVersion` response produces new - RSSI/LQI events. Check that sampling repeats after five minutes. -4. Update an existing device's profile to `range-extender-signal` or rejoin the - device, and confirm signal strength becomes available. -5. Check power cycling/rejoining and confirm an unavailable device does not - produce fabricated signal measurements. - -Integration tests cover the command/response paths, polling, profile changes, -metadata values, and capability-based device matching. Certification still -requires physical sample evaluation as requested by SmartThings; local tests -do not replace it. diff --git a/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua index 04aa7ff1d9..65c1682432 100644 --- a/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua +++ b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/can_handle.lua @@ -1,11 +1,12 @@ -- Copyright 2026 SmartThings, Inc. -- Licensed under the Apache License, Version 2.0 -local capabilities = require "st.capabilities" - -local function can_handle(opts, driver, device, ...) - if device:supports_capability(capabilities.signalStrength, "main") then - return true, require("range-extender-signal") +local function can_handle(opts, driver, device) + local FINGERPRINTS = require("range-extender-signal.fingerprints") + for _, fingerprint in ipairs(FINGERPRINTS) do + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true, require("range-extender-signal") + end end return false end diff --git a/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/fingerprints.lua b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/fingerprints.lua new file mode 100644 index 0000000000..bd95802086 --- /dev/null +++ b/drivers/SmartThings/zigbee-range-extender/src/range-extender-signal/fingerprints.lua @@ -0,0 +1,8 @@ +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local RANGE_EXTENDER_SIGNAL_FINGERPRINTS = { + { mfr = "SONOFF", model = "Dongle-LMG21" }, +} + +return RANGE_EXTENDER_SIGNAL_FINGERPRINTS diff --git a/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua b/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua index 04c849018c..6b8116519d 100644 --- a/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua +++ b/drivers/SmartThings/zigbee-range-extender/src/test/test_range_extender_signal.lua @@ -16,8 +16,8 @@ local function build_device(profile, manufacturer, model) zigbee_endpoints = { [0x01] = { id = 0x01, - manufacturer = manufacturer or "Generic manufacturer", - model = model or "Range Extender", + manufacturer = manufacturer or "SONOFF", + model = model or "Dongle-LMG21", server_clusters = { Basic.ID }, }, }, @@ -27,7 +27,7 @@ end local mock_device = build_device("range-extender-signal.yml") local base_device = build_device("range-extender.yml") local other_manufacturer = build_device("range-extender-signal.yml", "Other manufacturer") -local other_model = build_device("range-extender-signal.yml", "Another manufacturer", "Other model") +local other_model = build_device("range-extender-signal.yml", "SONOFF", "Other model") local function read_response(device, lqi, rssi) local message = Basic.attributes.ZCLVersion:build_test_read_attr_response(device, 3) @@ -64,7 +64,10 @@ test.register_coroutine_test( test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 203, -67) }) expect_signal_strength(mock_device, 203, -67) - end + end, + { + min_api_version = 17, + } ) test.register_coroutine_test( @@ -77,7 +80,10 @@ test.register_coroutine_test( test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 169, -74) }) expect_signal_strength(mock_device, 169, -74) - end + end, + { + min_api_version = 17, + } ) test.register_coroutine_test( @@ -98,6 +104,7 @@ test.register_coroutine_test( expect_signal_strength(mock_device, 83, -91) end, { + min_api_version = 17, test_init = function() test.mock_device.add_test_device(mock_device) test.timer.__create_and_queue_test_time_advance_timer(300, "interval", 2) @@ -110,7 +117,10 @@ test.register_coroutine_test( function() test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 0, 0) }) expect_signal_strength(mock_device, 0, 0) - end + end, + { + min_api_version = 17, + } ) test.register_coroutine_test( @@ -118,7 +128,10 @@ test.register_coroutine_test( function() test.socket.zigbee:__queue_receive({ mock_device.id, read_response(mock_device, 255, -128) }) expect_signal_strength(mock_device, 255, -128) - end + end, + { + min_api_version = 17, + } ) test.register_coroutine_test( @@ -129,7 +142,10 @@ test.register_coroutine_test( report.rssi = data_types.Int8(-82) test.socket.zigbee:__queue_receive({ mock_device.id, report }) expect_signal_strength(mock_device, 127, -82) - end + end, + { + min_api_version = 17, + } ) test.register_coroutine_test( @@ -138,6 +154,7 @@ test.register_coroutine_test( test.wait_for_events() end, { + min_api_version = 17, test_init = base_test_init, } ) @@ -148,6 +165,7 @@ test.register_coroutine_test( test.socket.zigbee:__queue_receive({ base_device.id, read_response(base_device, 196, -70) }) end, { + min_api_version = 17, test_init = base_test_init, } ) @@ -165,6 +183,7 @@ test.register_coroutine_test( expect_signal_strength(base_device, 184, -72) end, { + min_api_version = 17, test_init = base_test_init, } ) @@ -175,21 +194,24 @@ test.register_coroutine_test( test.socket.device_lifecycle:__queue_receive({ mock_device.id, "init" }) test.wait_for_events() test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed({ preferences = {} })) - end + end, + { + min_api_version = 17, + } ) for _, case in ipairs({ - { name = "another manufacturer", device = other_manufacturer }, - { name = "another model", device = other_model }, + { name = "a different manufacturer with the supported model", device = other_manufacturer }, + { name = "a different model with the supported manufacturer", device = other_model }, }) do local device = case.device test.register_coroutine_test( - "Signal strength capability is supported for " .. case.name, + "Signal strength subdriver rejects " .. case.name, function() test.socket.zigbee:__queue_receive({ device.id, read_response(device, 196, -70) }) - expect_signal_strength(device, 196, -70) end, { + min_api_version = 17, test_init = function() test.mock_device.add_test_device(device) end,