From 1f3d8bbbe90ac21686de68faf161e38d746c9d86 Mon Sep 17 00:00:00 2001 From: wzh <1090741189@qq.com> Date: Tue, 25 Aug 2026 16:41:41 +0800 Subject: [PATCH 1/5] Add the pressure display function to SNZB-02M --- .../zigbee-humidity-sensor/fingerprints.yml | 5 + .../sonoff-humidity-temp-press-battery.yml | 18 ++ .../src/sonoff/SNZB-02M/init.lua | 60 ++++ .../src/sonoff/init.lua | 256 ++++++++++++++++++ .../src/sonoff/sonoff_utils.lua | 135 +++++++++ 5 files changed, 474 insertions(+) create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/profiles/sonoff-humidity-temp-press-battery.yml create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua diff --git a/drivers/SmartThings/zigbee-humidity-sensor/fingerprints.yml b/drivers/SmartThings/zigbee-humidity-sensor/fingerprints.yml index ee36659670..7f46daba6a 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/fingerprints.yml +++ b/drivers/SmartThings/zigbee-humidity-sensor/fingerprints.yml @@ -83,6 +83,11 @@ zigbeeManufacturer: manufacturer: eWeLink model: SNZB-02P deviceProfileName: humidity-temp-battery + - id: "SONOFF/SNZB-02M" + deviceLabel: "SONOFF SNZB-02M" + manufacturer: SONOFF + model: SNZB-02M + deviceProfileName: sonoff-humidity-temp-press-battery - id: "SONOFF/SNZB-02DR2" deviceLabel: "SONOFF SNZB-02DR2" manufacturer: SONOFF diff --git a/drivers/SmartThings/zigbee-humidity-sensor/profiles/sonoff-humidity-temp-press-battery.yml b/drivers/SmartThings/zigbee-humidity-sensor/profiles/sonoff-humidity-temp-press-battery.yml new file mode 100644 index 0000000000..b6f48ef8e5 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/profiles/sonoff-humidity-temp-press-battery.yml @@ -0,0 +1,18 @@ +name: sonoff-humidity-temp-press-battery +components: +- id: main + capabilities: + - id: temperatureMeasurement + version: 1 + - id: relativeHumidityMeasurement + version: 1 + - id: atmosphericPressureMeasurement + version: 1 + - id: battery + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: MultiFunctionalSensor diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua new file mode 100644 index 0000000000..8939b61298 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua @@ -0,0 +1,60 @@ +--[[ +Description: SNZB-02M pressure/humidity/temperature sensor driver +Version: 1.0 +Author: GitHub Copilot +--]] + +local capabilities = require "st.capabilities" +local clusters = require "st.zigbee.zcl.clusters" +local log = require "log" + +local function convert_pressure_value(raw_value) + if raw_value == nil then + return nil + end + + if raw_value > 2000 then + return raw_value / 1000.0 + end + + return raw_value / 10.0 +end + +local function pressure_report_handler(driver, device, value, zb_rx) + local pressure_value = convert_pressure_value(value.value) + if pressure_value == nil then + log.warn(string.format("SNZB-02M pressure report has no value: %s", tostring(value))) + return + end + + log.debug(string.format("SNZB-02M pressure raw: %s, converted: %s kPa", tostring(value.value), tostring(pressure_value))) + device:emit_event(capabilities.atmosphericPressureMeasurement.atmosphericPressure({value = pressure_value, unit = "kPa"})) +end + +local function refresh_handler(driver, device, command) + device:send(clusters.TemperatureMeasurement.attributes.MeasuredValue:read(device)) + device:send(clusters.RelativeHumidity.attributes.MeasuredValue:read(device)) + device:send(clusters.PressureMeasurement.attributes.MeasuredValue:read(device)) + device:send(clusters.PowerConfiguration.attributes.BatteryPercentageRemaining:read(device)) +end + +local function can_handle(opts, driver, device) + return device:get_model() == "SNZB-02M" +end + +return { + NAME = "Sonoff SNZB-02M Sensor", + zigbee_handlers = { + attr = { + [clusters.PressureMeasurement.ID] = { + [clusters.PressureMeasurement.attributes.MeasuredValue.ID] = pressure_report_handler + } + } + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = refresh_handler + } + }, + can_handle = can_handle +} diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua new file mode 100644 index 0000000000..f89cc6ff27 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua @@ -0,0 +1,256 @@ +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-04-25 13:38:25 +LastEditors: liangjia +LastEditTime: 2024-04-25 13:53:04 +--]] +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-04-25 13:38:25 +LastEditors: liangjia +LastEditTime: 2024-04-25 13:47:42 +--]] +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-01-19 18:05:31 +LastEditors: liangjia +LastEditTime: 2024-01-20 10:41:41 +--]] +local capabilities = require "st.capabilities" +local zcl_commands = require "st.zigbee.zcl.global_commands" +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local sonoff_utils = require "sonoff/sonoff_utils" +local zcl_clusters = require "st.zigbee.zcl.clusters" +local battery_defaults = require "st.zigbee.defaults.battery_defaults" +local zb_const = require "st.zigbee.constants" +local write_attr_response = require "st.zigbee.zcl.global_commands.write_attribute_response" +local data_types = require "st.zigbee.data_types" +local Status = (require "st.zigbee.zcl.types").ZclStatus +local log = require "log" + +local PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS = 0 +local PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT = 1 + + +local capability_screenTemperatureDisplayUnit = capabilities["samplereturn62595.screenTemperatureDisplayUnit"] +local command_setScreenTemperatureDisplayUnit = "setScreenTemperatureDisplayUnit" + +local capability_temperatureCompensation = capabilities["samplereturn62595.temperatureCompensation"] +local command_setTemperatureCompensation = "setTemperatureCompensation" + +local capability_humidityCompensation = capabilities["samplereturn62595.humidityCompensation"] +local command_setHumidityCompensation = "setHumidityCompensation" + +local FINGERPRINTS = { + { mfr = "SONOFF", model = "SNZB-02LD" }, + { mfr = "SONOFF", model = "SNZB-02WD" } +} + + + + + +local function added_handler(self, device) + --update UI + log.debug("TH sensor added_handler >>>>>>") + device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) + device:emit_event(capability_temperatureCompensation.temperatureCompensation(sonoff_utils.PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT)) + device:emit_event(capability_humidityCompensation.humidityCompensation(sonoff_utils.PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT)) + log.debug("TH sensor added_handler end!") +end + + +local function device_init(driver, device) + --do notthing +end + + +local function send_screen_temperature_display_unit_value(device, value) + -- Store key + sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY, value) + log.debug("---->send_screen_temperature_display_unit_value:", sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID) + -- Write Attribute + device:send(sonoff_utils.custom_write_attribute(device, + sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, + sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID, + nil, + data_types.Uint16, + value)) +end + + +local function send_temperature_compensation_value(device, value) + -- Store key + sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY, value) + log.debug("---->send_temperature_compensation_value:", sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID) + -- Write Attribute + device:send(sonoff_utils.custom_write_attribute(device, + sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, + sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID, + nil, + data_types.Int16, + value * 100)) +end + + +local function send_humidity_compensation_value(device, value) + -- Store key + sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY, value) + log.debug("---->send_humidity_compensation_value:", sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID) + -- Write Attribute + device:send(sonoff_utils.custom_write_attribute(device, + sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, + sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID, + nil, + data_types.Int16, + value * 100)) +end + + +local function screen_temperature_display_unit_capability_handler(driver, device, command) + log.debug("screen_temperature_display_unit_capability_handler enter") + local display_unit = command.args.screenTemperatureDisplayUnit + log.debug("---->screen temperature display unit:", display_unit) + -- Store key + -- Update UI + if display_unit == 'Celsius' then + send_screen_temperature_display_unit_value(device, PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS) + elseif display_unit == 'Fahrenheit' then + send_screen_temperature_display_unit_value(device, PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT) + end +end + + +local function temperature_compensation_capability_handler(driver, device, command) + log.debug("temperature_compensation_capability_handler enter") + local temp_compensation = command.args.temperatureCompensation + log.debug("---->temperature compensation:", temp_compensation) + -- Store key + -- Update UI + send_temperature_compensation_value(device, temp_compensation) +end + + +local function humidity_compensation_capability_handler(driver, device, command) + log.debug("humidity_compensation_capability_handler enter") + local humidity_compensation = command.args.humidityCompensation + log.debug("---->humidity compensation:", humidity_compensation) + -- Store key + -- Update UI + send_humidity_compensation_value(device, humidity_compensation) +end + + +local function screen_temperature_display_unit_attr_handler(driver, device, value, zb_rx) + log.debug("---->ZB Rx screen temperature display unit Value", value.value) + local raw_value = value.value + if raw_value == PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS then + device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) + elseif raw_value == PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT then + device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Fahrenheit()) + end +end + + +local function write_attr_response_handler(driver, device, zb_rx) + log.debug("write_attr_response_handler enter") + --judge write resp success ? + log.debug("debug", write_attr_response.WriteAttributeResponse.ID) + log.debug(string.format("received Zigbee message: %s", zb_rx:pretty_print())) + log.debug(string.format("received Zigbee message: %s", zb_rx.body.zcl_body:pretty_print())) + log.debug("received Zigbee message:", zb_rx.body.zcl_body.global_status.value) + + local war = zb_rx.body.zcl_body + if war.global_status ~= nil and war.global_status.value == Status.SUCCESS then + log.debug("Write was successful") + local key, value = sonoff_utils.get_pref_changed_field(device) + if key == sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY then + -- Reset key + sonoff_utils.set_pref_changed_field(device, '', 0) + -- Update UI + log.debug("screenTemperatureDisplayUnit:", value) + if value == PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS then + device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) + elseif value == PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT then + device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Fahrenheit()) + end + end + + if key == sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY then + local real_tc_value = value + -- reset key + sonoff_utils.set_pref_changed_field(device, '', 0) + -- update ui + log.debug("temperature compensation:", real_tc_value) + device:emit_event(capability_temperatureCompensation.temperatureCompensation(real_tc_value)) + end + + if key == sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY then + local real_hc_value = value + -- reset key + sonoff_utils.set_pref_changed_field(device, '', 0) + -- update ui + log.debug("humidity compensation:", real_hc_value) + device:emit_event(capability_humidityCompensation.humidityCompensation(real_hc_value)) + end + end +end + + + +local is_sonoff_products = function(opts, driver, device) + for _, fingerprint in ipairs(FINGERPRINTS) do + if device:get_model() == fingerprint.model then + return true + end + end + return false +end + + +local sonoff_temp_humidity_sensor_handler = { + NAME = "Sonoff temperature and humidity sensor Handler", + lifecycle_handlers = { + init = device_init, + added = added_handler + }, + -- 能力点处理程序 + capability_handlers = { + [capability_screenTemperatureDisplayUnit.ID] = { + [command_setScreenTemperatureDisplayUnit] = screen_temperature_display_unit_capability_handler + }, + [capability_temperatureCompensation.ID] = { + [command_setTemperatureCompensation] = temperature_compensation_capability_handler + }, + [capability_humidityCompensation.ID] = { + [command_setHumidityCompensation] = humidity_compensation_capability_handler + } + }, + zigbee_handlers = { + -- 属性处理 + attr = { + [sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID] = { + [sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID] = screen_temperature_display_unit_attr_handler + } + }, + -- 全局处理 + global = { + [sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID] = { + [zcl_commands.WriteAttributeResponse.ID] = write_attr_response_handler + } + } + }, + sub_drivers = { + require("sonoff/SNZB-02LD") + }, + can_handle = is_sonoff_products +} + +return sonoff_temp_humidity_sensor_handler diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua new file mode 100644 index 0000000000..5124052d72 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua @@ -0,0 +1,135 @@ +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-01-24 12:00:32 +LastEditors: liangjia +LastEditTime: 2024-02-02 15:20:58 +--]] +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-01-19 18:05:31 +LastEditors: liangjia +LastEditTime: 2024-01-20 13:51:20 +--]] +--[[ +Description: +Version: 2.0 +Autor: liangjia +Date: 2024-01-19 15:39:47 +LastEditors: liangjia +LastEditTime: 2024-01-19 16:18:46 +--]] +local capabilities = require "st.capabilities" +local zb_const = require "st.zigbee.constants" +local cluster_base = require "st.zigbee.cluster_base" +local data_types = require "st.zigbee.data_types" +local log = require "log" + +-- Zigbee Manufacturer Code +local MFG_CODE_NULL = 0x0000 +local MFG_CODE_EWELINK = 0x1286 + +-- Zigbee cluster IDs -- sonoff private cluster +local ZCL_SONOFF_PRIVITE_CLUSTER_ID = 0xFC11 +-- Zigbee attribute IDs +local ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID = 0x0007 +local ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID = 0x2003 +local ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID= 0x2004 + +local PREF_CHANGED_KEY = "prefChangedKey" +local PREF_CHANGED_VALUE = "prefChangedValue" + +local PREF_TEMPERATRUE_UNIT_KEY = "screenTemperatureDisplayUnit" +local PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT = 0 + +local PREF_TEMPERATURE_COMPENSATION_KEY = "temperatureCompensation" +local PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT = 0.0 + +local PREF_HUMIDITY_COMPENSATION_KEY = "humidityCompensation" +local PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT = 0.0 + + +local function get_pref_changed_field(device) + local key = device:get_field(PREF_CHANGED_KEY) or '' + local value = device:get_field(PREF_CHANGED_VALUE) or 0 + return key, value +end + +local function set_pref_changed_field(device, key, value) + log.debug("set_pref_changed_field---->value:",value) + device:set_field(PREF_CHANGED_KEY, key) + device:set_field(PREF_CHANGED_VALUE, value) +end + +local custom_read_attribute = function(device, cluster, attribute, mfg_code) + local message = cluster_base.read_attribute(device, data_types.ClusterId(cluster), attribute) + if mfg_code ~= nil then + message.body.zcl_header.frame_ctrl:set_mfg_specific() + message.body.zcl_header.mfg_code = data_types.validate_or_build_type(mfg_code, data_types.Uint16, "mfg_code") + end + return message +end + +local function custom_sign(number) + if _VERSION and _VERSION:match("^5%.3") then + -- Lua 5.3及以上版本,直接使用math.sign + return math.sign(number) + else + -- Lua 5.2及以下版本,实现一个替代的sign函数 + if number > 0 then + return 1 + elseif number < 0 then + return -1 + else + -- 处理数字为零的情况 + return 0 + end + end +end + +local custom_write_attribute = function(device, cluster, attribute, mfg_code, data_type, value) + local sign = custom_sign(value) -- 获取数字的符号(正1或负-1) + local abs_number = math.abs(value) -- 获取数字的绝对值 + local integer_part = math.floor(abs_number) -- 对绝对值进行向下取整 + local real_value =sign * integer_part -- 根据原始数字的符号恢复截断后的整数 + + log.debug("---->custom_write_attribute real_value:", real_value) + + local data = data_types.validate_or_build_type(real_value, data_type) + local message = cluster_base.write_attribute(device, data_types.ClusterId(cluster), attribute, data) + if mfg_code ~= nil then + message.body.zcl_header.frame_ctrl:set_mfg_specific() + message.body.zcl_header.mfg_code = data_types.validate_or_build_type(mfg_code, data_types.Uint16, "mfg_code") + end + return message +end + +local sonoff_utils = {} + +sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY = PREF_TEMPERATRUE_UNIT_KEY +sonoff_utils.PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT = PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT + +sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY = PREF_TEMPERATURE_COMPENSATION_KEY +sonoff_utils.PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT = PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT + +sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY = PREF_HUMIDITY_COMPENSATION_KEY +sonoff_utils.PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT = PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT + +sonoff_utils.MFG_CODE_NULL = MFG_CODE_NULL +sonoff_utils.MFG_CODE_EWELINK = MFG_CODE_EWELINK + +sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID = ZCL_SONOFF_PRIVITE_CLUSTER_ID +sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID = ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID +sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID = ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID +sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID = ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID + +sonoff_utils.get_pref_changed_field = get_pref_changed_field +sonoff_utils.set_pref_changed_field = set_pref_changed_field + +sonoff_utils.custom_read_attribute = custom_read_attribute +sonoff_utils.custom_write_attribute = custom_write_attribute + +return sonoff_utils From b5e366548528dd8688588359055bcfa56a1ad6dc Mon Sep 17 00:00:00 2001 From: "guoxin.yang" Date: Tue, 25 Aug 2026 18:04:27 +0800 Subject: [PATCH 2/5] Wire SNZB-02M sub-driver and add pressure tests The SNZB-02M sub-driver was added but never registered, so the pressure display feature was dead code on the device. Register it via sub_drivers.lua, drop the unrelated SNZB-02LD/WD handler and utils (not in this driver, and referencing a nonexistent sub-driver), and add unit tests for pressure conversion and refresh. Co-Authored-By: Claude --- .../src/sonoff/init.lua | 256 ------------------ .../src/sonoff/sonoff_utils.lua | 135 --------- .../src/sub_drivers.lua | 1 + .../src/test/test_sonoff_snzb02m.lua | 117 ++++++++ 4 files changed, 118 insertions(+), 391 deletions(-) delete mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua delete mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua deleted file mode 100644 index f89cc6ff27..0000000000 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/init.lua +++ /dev/null @@ -1,256 +0,0 @@ ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-04-25 13:38:25 -LastEditors: liangjia -LastEditTime: 2024-04-25 13:53:04 ---]] ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-04-25 13:38:25 -LastEditors: liangjia -LastEditTime: 2024-04-25 13:47:42 ---]] ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-01-19 18:05:31 -LastEditors: liangjia -LastEditTime: 2024-01-20 10:41:41 ---]] -local capabilities = require "st.capabilities" -local zcl_commands = require "st.zigbee.zcl.global_commands" -local cluster_base = require "st.zigbee.cluster_base" -local data_types = require "st.zigbee.data_types" -local sonoff_utils = require "sonoff/sonoff_utils" -local zcl_clusters = require "st.zigbee.zcl.clusters" -local battery_defaults = require "st.zigbee.defaults.battery_defaults" -local zb_const = require "st.zigbee.constants" -local write_attr_response = require "st.zigbee.zcl.global_commands.write_attribute_response" -local data_types = require "st.zigbee.data_types" -local Status = (require "st.zigbee.zcl.types").ZclStatus -local log = require "log" - -local PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS = 0 -local PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT = 1 - - -local capability_screenTemperatureDisplayUnit = capabilities["samplereturn62595.screenTemperatureDisplayUnit"] -local command_setScreenTemperatureDisplayUnit = "setScreenTemperatureDisplayUnit" - -local capability_temperatureCompensation = capabilities["samplereturn62595.temperatureCompensation"] -local command_setTemperatureCompensation = "setTemperatureCompensation" - -local capability_humidityCompensation = capabilities["samplereturn62595.humidityCompensation"] -local command_setHumidityCompensation = "setHumidityCompensation" - -local FINGERPRINTS = { - { mfr = "SONOFF", model = "SNZB-02LD" }, - { mfr = "SONOFF", model = "SNZB-02WD" } -} - - - - - -local function added_handler(self, device) - --update UI - log.debug("TH sensor added_handler >>>>>>") - device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) - device:emit_event(capability_temperatureCompensation.temperatureCompensation(sonoff_utils.PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT)) - device:emit_event(capability_humidityCompensation.humidityCompensation(sonoff_utils.PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT)) - log.debug("TH sensor added_handler end!") -end - - -local function device_init(driver, device) - --do notthing -end - - -local function send_screen_temperature_display_unit_value(device, value) - -- Store key - sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY, value) - log.debug("---->send_screen_temperature_display_unit_value:", sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID) - -- Write Attribute - device:send(sonoff_utils.custom_write_attribute(device, - sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, - sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID, - nil, - data_types.Uint16, - value)) -end - - -local function send_temperature_compensation_value(device, value) - -- Store key - sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY, value) - log.debug("---->send_temperature_compensation_value:", sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID) - -- Write Attribute - device:send(sonoff_utils.custom_write_attribute(device, - sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, - sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID, - nil, - data_types.Int16, - value * 100)) -end - - -local function send_humidity_compensation_value(device, value) - -- Store key - sonoff_utils.set_pref_changed_field(device, sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY, value) - log.debug("---->send_humidity_compensation_value:", sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID) - -- Write Attribute - device:send(sonoff_utils.custom_write_attribute(device, - sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID, - sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID, - nil, - data_types.Int16, - value * 100)) -end - - -local function screen_temperature_display_unit_capability_handler(driver, device, command) - log.debug("screen_temperature_display_unit_capability_handler enter") - local display_unit = command.args.screenTemperatureDisplayUnit - log.debug("---->screen temperature display unit:", display_unit) - -- Store key - -- Update UI - if display_unit == 'Celsius' then - send_screen_temperature_display_unit_value(device, PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS) - elseif display_unit == 'Fahrenheit' then - send_screen_temperature_display_unit_value(device, PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT) - end -end - - -local function temperature_compensation_capability_handler(driver, device, command) - log.debug("temperature_compensation_capability_handler enter") - local temp_compensation = command.args.temperatureCompensation - log.debug("---->temperature compensation:", temp_compensation) - -- Store key - -- Update UI - send_temperature_compensation_value(device, temp_compensation) -end - - -local function humidity_compensation_capability_handler(driver, device, command) - log.debug("humidity_compensation_capability_handler enter") - local humidity_compensation = command.args.humidityCompensation - log.debug("---->humidity compensation:", humidity_compensation) - -- Store key - -- Update UI - send_humidity_compensation_value(device, humidity_compensation) -end - - -local function screen_temperature_display_unit_attr_handler(driver, device, value, zb_rx) - log.debug("---->ZB Rx screen temperature display unit Value", value.value) - local raw_value = value.value - if raw_value == PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS then - device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) - elseif raw_value == PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT then - device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Fahrenheit()) - end -end - - -local function write_attr_response_handler(driver, device, zb_rx) - log.debug("write_attr_response_handler enter") - --judge write resp success ? - log.debug("debug", write_attr_response.WriteAttributeResponse.ID) - log.debug(string.format("received Zigbee message: %s", zb_rx:pretty_print())) - log.debug(string.format("received Zigbee message: %s", zb_rx.body.zcl_body:pretty_print())) - log.debug("received Zigbee message:", zb_rx.body.zcl_body.global_status.value) - - local war = zb_rx.body.zcl_body - if war.global_status ~= nil and war.global_status.value == Status.SUCCESS then - log.debug("Write was successful") - local key, value = sonoff_utils.get_pref_changed_field(device) - if key == sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY then - -- Reset key - sonoff_utils.set_pref_changed_field(device, '', 0) - -- Update UI - log.debug("screenTemperatureDisplayUnit:", value) - if value == PREF_TEMPERATRUE_UNIT_VALUE_CELSIUS then - device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Celsius()) - elseif value == PREF_TEMPERATRUE_UNIT_VALUE_FAHRENHEIT then - device:emit_event(capability_screenTemperatureDisplayUnit.screenTemperatureDisplayUnit.Fahrenheit()) - end - end - - if key == sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY then - local real_tc_value = value - -- reset key - sonoff_utils.set_pref_changed_field(device, '', 0) - -- update ui - log.debug("temperature compensation:", real_tc_value) - device:emit_event(capability_temperatureCompensation.temperatureCompensation(real_tc_value)) - end - - if key == sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY then - local real_hc_value = value - -- reset key - sonoff_utils.set_pref_changed_field(device, '', 0) - -- update ui - log.debug("humidity compensation:", real_hc_value) - device:emit_event(capability_humidityCompensation.humidityCompensation(real_hc_value)) - end - end -end - - - -local is_sonoff_products = function(opts, driver, device) - for _, fingerprint in ipairs(FINGERPRINTS) do - if device:get_model() == fingerprint.model then - return true - end - end - return false -end - - -local sonoff_temp_humidity_sensor_handler = { - NAME = "Sonoff temperature and humidity sensor Handler", - lifecycle_handlers = { - init = device_init, - added = added_handler - }, - -- 能力点处理程序 - capability_handlers = { - [capability_screenTemperatureDisplayUnit.ID] = { - [command_setScreenTemperatureDisplayUnit] = screen_temperature_display_unit_capability_handler - }, - [capability_temperatureCompensation.ID] = { - [command_setTemperatureCompensation] = temperature_compensation_capability_handler - }, - [capability_humidityCompensation.ID] = { - [command_setHumidityCompensation] = humidity_compensation_capability_handler - } - }, - zigbee_handlers = { - -- 属性处理 - attr = { - [sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID] = { - [sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID] = screen_temperature_display_unit_attr_handler - } - }, - -- 全局处理 - global = { - [sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID] = { - [zcl_commands.WriteAttributeResponse.ID] = write_attr_response_handler - } - } - }, - sub_drivers = { - require("sonoff/SNZB-02LD") - }, - can_handle = is_sonoff_products -} - -return sonoff_temp_humidity_sensor_handler diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua deleted file mode 100644 index 5124052d72..0000000000 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/sonoff_utils.lua +++ /dev/null @@ -1,135 +0,0 @@ ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-01-24 12:00:32 -LastEditors: liangjia -LastEditTime: 2024-02-02 15:20:58 ---]] ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-01-19 18:05:31 -LastEditors: liangjia -LastEditTime: 2024-01-20 13:51:20 ---]] ---[[ -Description: -Version: 2.0 -Autor: liangjia -Date: 2024-01-19 15:39:47 -LastEditors: liangjia -LastEditTime: 2024-01-19 16:18:46 ---]] -local capabilities = require "st.capabilities" -local zb_const = require "st.zigbee.constants" -local cluster_base = require "st.zigbee.cluster_base" -local data_types = require "st.zigbee.data_types" -local log = require "log" - --- Zigbee Manufacturer Code -local MFG_CODE_NULL = 0x0000 -local MFG_CODE_EWELINK = 0x1286 - --- Zigbee cluster IDs -- sonoff private cluster -local ZCL_SONOFF_PRIVITE_CLUSTER_ID = 0xFC11 --- Zigbee attribute IDs -local ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID = 0x0007 -local ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID = 0x2003 -local ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID= 0x2004 - -local PREF_CHANGED_KEY = "prefChangedKey" -local PREF_CHANGED_VALUE = "prefChangedValue" - -local PREF_TEMPERATRUE_UNIT_KEY = "screenTemperatureDisplayUnit" -local PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT = 0 - -local PREF_TEMPERATURE_COMPENSATION_KEY = "temperatureCompensation" -local PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT = 0.0 - -local PREF_HUMIDITY_COMPENSATION_KEY = "humidityCompensation" -local PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT = 0.0 - - -local function get_pref_changed_field(device) - local key = device:get_field(PREF_CHANGED_KEY) or '' - local value = device:get_field(PREF_CHANGED_VALUE) or 0 - return key, value -end - -local function set_pref_changed_field(device, key, value) - log.debug("set_pref_changed_field---->value:",value) - device:set_field(PREF_CHANGED_KEY, key) - device:set_field(PREF_CHANGED_VALUE, value) -end - -local custom_read_attribute = function(device, cluster, attribute, mfg_code) - local message = cluster_base.read_attribute(device, data_types.ClusterId(cluster), attribute) - if mfg_code ~= nil then - message.body.zcl_header.frame_ctrl:set_mfg_specific() - message.body.zcl_header.mfg_code = data_types.validate_or_build_type(mfg_code, data_types.Uint16, "mfg_code") - end - return message -end - -local function custom_sign(number) - if _VERSION and _VERSION:match("^5%.3") then - -- Lua 5.3及以上版本,直接使用math.sign - return math.sign(number) - else - -- Lua 5.2及以下版本,实现一个替代的sign函数 - if number > 0 then - return 1 - elseif number < 0 then - return -1 - else - -- 处理数字为零的情况 - return 0 - end - end -end - -local custom_write_attribute = function(device, cluster, attribute, mfg_code, data_type, value) - local sign = custom_sign(value) -- 获取数字的符号(正1或负-1) - local abs_number = math.abs(value) -- 获取数字的绝对值 - local integer_part = math.floor(abs_number) -- 对绝对值进行向下取整 - local real_value =sign * integer_part -- 根据原始数字的符号恢复截断后的整数 - - log.debug("---->custom_write_attribute real_value:", real_value) - - local data = data_types.validate_or_build_type(real_value, data_type) - local message = cluster_base.write_attribute(device, data_types.ClusterId(cluster), attribute, data) - if mfg_code ~= nil then - message.body.zcl_header.frame_ctrl:set_mfg_specific() - message.body.zcl_header.mfg_code = data_types.validate_or_build_type(mfg_code, data_types.Uint16, "mfg_code") - end - return message -end - -local sonoff_utils = {} - -sonoff_utils.PREF_TEMPERATRUE_UNIT_KEY = PREF_TEMPERATRUE_UNIT_KEY -sonoff_utils.PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT = PREF_TEMPERATRUE_UNIT_VALUE_DEFAULT - -sonoff_utils.PREF_TEMPERATURE_COMPENSATION_KEY = PREF_TEMPERATURE_COMPENSATION_KEY -sonoff_utils.PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT = PREF_TEMPERATURE_COMPENSATION_VALUE_DEFAULT - -sonoff_utils.PREF_HUMIDITY_COMPENSATION_KEY = PREF_HUMIDITY_COMPENSATION_KEY -sonoff_utils.PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT = PREF_HUMIDITY_COMPENSATION_VALUE_DEFAULT - -sonoff_utils.MFG_CODE_NULL = MFG_CODE_NULL -sonoff_utils.MFG_CODE_EWELINK = MFG_CODE_EWELINK - -sonoff_utils.ZCL_SONOFF_PRIVITE_CLUSTER_ID = ZCL_SONOFF_PRIVITE_CLUSTER_ID -sonoff_utils.ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID = ZCL_TEMPERATRUE_UNIT_ATTRIBUTE_ID -sonoff_utils.ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID = ZCL_TEMPERATURE_COMPENSATION_ATTRIBUTE_ID -sonoff_utils.ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID = ZCL_HUMIDITY_COMPENSATION_ATTRIBUTE_ID - -sonoff_utils.get_pref_changed_field = get_pref_changed_field -sonoff_utils.set_pref_changed_field = set_pref_changed_field - -sonoff_utils.custom_read_attribute = custom_read_attribute -sonoff_utils.custom_write_attribute = custom_write_attribute - -return sonoff_utils diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sub_drivers.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sub_drivers.lua index 6f49a5f18c..4ec183d6cb 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/sub_drivers.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sub_drivers.lua @@ -9,5 +9,6 @@ local sub_drivers = { lazy_load_if_possible("centralite-sensor"), lazy_load_if_possible("heiman-sensor"), lazy_load_if_possible("frient-sensor"), + lazy_load_if_possible("sonoff.SNZB-02M"), } return sub_drivers diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua new file mode 100644 index 0000000000..8881b1d639 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua @@ -0,0 +1,117 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local test = require "integration_test" +local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" +local clusters = require "st.zigbee.zcl.clusters" +local capabilities = require "st.capabilities" + +local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement +local RelativeHumidity = clusters.RelativeHumidity +local PressureMeasurement = clusters.PressureMeasurement + +local mock_device = test.mock_device.build_test_zigbee_device( + { + profile = t_utils.get_profile_definition("sonoff-humidity-temp-press-battery.yml"), + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "SONOFF", + model = "SNZB-02M", + server_clusters = { 0x0001, 0x0402, 0x0405, 0x0403 } + } + } + } +) + +zigbee_test_utils.prepare_zigbee_env_info() +local function test_init() + test.mock_device.add_test_device(mock_device) +end + +test.set_test_init_function(test_init) + +test.register_message_test( + "Pressure report above 2000 should be divided by 1000", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + PressureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 100000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.atmosphericPressureMeasurement.atmosphericPressure({ value = 100.0, unit = "kPa" })) + } + }, + { + min_api_version = 14 + } +) + +test.register_message_test( + "Pressure report at or below 2000 should be divided by 10", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + PressureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 960) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.atmosphericPressureMeasurement.atmosphericPressure({ value = 96.0, unit = "kPa" })) + } + }, + { + min_api_version = 14 + } +) + +test.register_message_test( + "Refresh should read temperature, humidity, pressure and battery", + { + { + channel = "capability", + direction = "receive", + message = { mock_device.id, { capability = "refresh", component = "main", command = "refresh", args = {} } } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, RelativeHumidity.attributes.MeasuredValue:read(mock_device) } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, PressureMeasurement.attributes.MeasuredValue:read(mock_device) } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) } + } + }, + { + inner_block_ordering = "relaxed", + min_api_version = 14 + } +) + +test.run_registered_tests() From 46e746d117450c5dc201aeda4f74367e94dd36e2 Mon Sep 17 00:00:00 2001 From: wzh <1090741189@qq.com> Date: Tue, 25 Aug 2026 20:20:42 +0800 Subject: [PATCH 3/5] Fix SNZB-02M lazy-load and pressure test --- .../src/sonoff/SNZB-02M/can_handle.lua | 8 ++++++++ .../zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua | 4 +--- .../src/test/test_sonoff_snzb02m.lua | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua new file mode 100644 index 0000000000..6c2c0c38f8 --- /dev/null +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua @@ -0,0 +1,8 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local function can_handle(opts, driver, device, ...) + return device:get_model() == "SNZB-02M" +end + +return can_handle diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua index 8939b61298..194f9b2aa0 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/init.lua @@ -38,9 +38,7 @@ local function refresh_handler(driver, device, command) device:send(clusters.PowerConfiguration.attributes.BatteryPercentageRemaining:read(device)) end -local function can_handle(opts, driver, device) - return device:get_model() == "SNZB-02M" -end +local can_handle = require "sonoff.SNZB-02M.can_handle" return { NAME = "Sonoff SNZB-02M Sensor", diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua index 8881b1d639..c48b01f3ae 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_sonoff_snzb02m.lua @@ -41,14 +41,14 @@ test.register_message_test( direction = "receive", message = { mock_device.id, - PressureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 100000) + PressureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 10000) } }, { channel = "capability", direction = "send", message = mock_device:generate_test_message("main", - capabilities.atmosphericPressureMeasurement.atmosphericPressure({ value = 100.0, unit = "kPa" })) + capabilities.atmosphericPressureMeasurement.atmosphericPressure({ value = 10.0, unit = "kPa" })) } }, { From 0909220cb671b6e6ef6e1681457c28307c1eccd2 Mon Sep 17 00:00:00 2001 From: wzh <1090741189@qq.com> Date: Wed, 26 Aug 2026 10:45:59 +0800 Subject: [PATCH 4/5] Load-SNZB-02M-handlers-during-lazy-load --- .../src/sonoff/SNZB-02M/can_handle.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua index 6c2c0c38f8..3989d7bc96 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/sonoff/SNZB-02M/can_handle.lua @@ -2,7 +2,11 @@ -- Licensed under the Apache License, Version 2.0 local function can_handle(opts, driver, device, ...) - return device:get_model() == "SNZB-02M" + if device:get_model() == "SNZB-02M" then + return true, require("sonoff.SNZB-02M") + end + + return false end return can_handle From 1ca26b18332979b2d7c720901e5796e3ffe9874f Mon Sep 17 00:00:00 2001 From: wzh <1090741189@qq.com> Date: Wed, 26 Aug 2026 13:35:30 +0800 Subject: [PATCH 5/5] Limit-parallel-driver-tests-to-changed-drivers --- tools/run_driver_tests_p.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/run_driver_tests_p.py b/tools/run_driver_tests_p.py index c8387dcb1c..dac1721e86 100644 --- a/tools/run_driver_tests_p.py +++ b/tools/run_driver_tests_p.py @@ -10,6 +10,8 @@ DRIVER_DIRS = Path(os.path.abspath(__file__)).parents[1].joinpath("drivers") DRIVERS = [driver for driver in DRIVER_DIRS.glob("*/*") if driver.is_dir()] # this gets all the children of the children of the drivers directory CHANGED_DRIVERS = [Path(driver).name for driver in sys.argv[1:]] +if CHANGED_DRIVERS: + DRIVERS = [driver for driver in DRIVERS if driver.name in CHANGED_DRIVERS] def per_driver_task(driver_dir): os.chdir(driver_dir.joinpath('src'))