diff --git a/drivers/SmartThings/zigbee-button/src/init.lua b/drivers/SmartThings/zigbee-button/src/init.lua index a0e4dec66e..d20bf31870 100644 --- a/drivers/SmartThings/zigbee-button/src/init.lua +++ b/drivers/SmartThings/zigbee-button/src/init.lua @@ -17,6 +17,12 @@ local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" local constants = require "st.zigbee.constants" local IASZone = (require "st.zigbee.zcl.clusters").IASZone +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement + +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} local generate_event_from_zone_status = function(driver, device, zone_status, zb_rx) local event @@ -65,10 +71,47 @@ local ias_zone_status_change_handler = function(driver, device, zb_rx) generate_event_from_zone_status(driver, device, zb_rx.body.zcl_body.zone_status, zb_rx) end +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function added_handler(self, device) device:emit_event(capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }})) device:emit_event(capabilities.button.numberOfButtons({value = 1}, {visibility = { displayed = false }})) device:emit_event(capabilities.button.button.pushed({state_change = false})) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) end local zigbee_button_driver_template = { @@ -81,6 +124,10 @@ local zigbee_button_driver_template = { attr = { [IASZone.ID] = { [IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } }, cluster = { diff --git a/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua index e9fe8c8724..894a579ea7 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua @@ -20,6 +20,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local OnOff = clusters.OnOff local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local button = capabilities.button @@ -64,6 +65,14 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", button.button.pushed({ state_change = false })) ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) end ) diff --git a/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua index 9e986f097f..d6b8e744c3 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua @@ -128,6 +128,14 @@ test.register_coroutine_test( attribute_id = "button", state = { value = "pushed" } } }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) -- test.socket.zigbee:__expect_send({ -- mock_device.id, -- PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) diff --git a/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua index 747e17241a..58cc4b83e6 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IasEnrollResponseCode = require "st.zigbee.generated.zcl_clusters.IASZone.types.EnrollResponseCode" @@ -26,7 +27,7 @@ local ZoneStatusAttribute = IASZone.attributes.ZoneStatus local button_attr = capabilities.button.button local mock_device = test.mock_device.build_test_zigbee_device( - { profile = t_utils.get_profile_definition("button-profile.yml") } + { profile = t_utils.get_profile_definition("one-button-temp-battery.yml") } ) zigbee_test_utils.prepare_zigbee_env_info() local function test_init() @@ -159,6 +160,46 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_coroutine_test( "Health check should check all relevant attributes", function() @@ -182,6 +223,14 @@ test.register_coroutine_test( attribute_id = "button", state = { value = "pushed" } } }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- Battery has a max reporting interval of 21600 @@ -192,6 +241,10 @@ test.register_coroutine_test( PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) } ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + }) end, { test_init = function() @@ -218,6 +271,12 @@ test.register_coroutine_test( IASZone.attributes.ZoneStatus:read(mock_device) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + ) end ) @@ -237,6 +296,14 @@ test.register_coroutine_test( 1) } ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:configure_reporting(mock_device, + 30, + 600, + 100) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, @@ -245,6 +312,14 @@ test.register_coroutine_test( PowerConfiguration.ID) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + TemperatureMeasurement.ID) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, @@ -263,6 +338,12 @@ test.register_coroutine_test( PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, diff --git a/drivers/SmartThings/zigbee-contact/src/init.lua b/drivers/SmartThings/zigbee-contact/src/init.lua index 7a1dc6b237..6dbd542f41 100644 --- a/drivers/SmartThings/zigbee-contact/src/init.lua +++ b/drivers/SmartThings/zigbee-contact/src/init.lua @@ -16,9 +16,50 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local constants = require "st.zigbee.constants" local defaults = require "st.zigbee.defaults" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement local configurationMap = require "configurations" local SMARTSENSE_MULTI_SENSOR_CUSTOM_PROFILE = 0xFC01 +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) if configuration ~= nil then @@ -29,6 +70,11 @@ local function device_init(driver, device) end end +local function added_handler(driver, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_contact_driver_template = { supported_capabilities = { capabilities.contactSensor, @@ -37,11 +83,20 @@ local zigbee_contact_driver_template = { capabilities.threeAxis, capabilities.accelerationSensor }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, additional_zcl_profiles = { [SMARTSENSE_MULTI_SENSOR_CUSTOM_PROFILE] = true }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler, }, sub_drivers = { require("aqara"), diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua index 41e9ebce57..fa9667cd1d 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua @@ -21,6 +21,7 @@ local data_types = require "st.zigbee.data_types" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -50,6 +51,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua index 1f36536d4e..40cc2c47be 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua index bc139a0904..e05233ad48 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua @@ -62,6 +62,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua index f254c108f9..a05f420166 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua index 3032ff3fc4..58c2c8d6b2 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -60,6 +61,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua index db72c3a5c2..05c82b60b6 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua @@ -62,6 +62,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua index dbf30b3d13..458af19546 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua index 623d55cce6..1950a22649 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua index d0ddd9c6d9..07beb7c0dd 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua index 0c89cbb6aa..df1becb201 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua @@ -121,6 +121,29 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Battery percentage report should be handled", { @@ -142,6 +165,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) @@ -176,6 +207,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua index 0e19b78d02..cf1bb61b7c 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua @@ -15,8 +15,37 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement local configurationMap = require "configurations" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) if configuration ~= nil then @@ -27,14 +56,28 @@ local function device_init(driver, device) end end +local function added_handler(driver, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_humidity_driver = { supported_capabilities = { capabilities.battery, capabilities.relativeHumidityMeasurement, capabilities.temperatureMeasurement }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler, }, sub_drivers = { require("aqara"), diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua index 3fa1b5719b..ca121baa9b 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua @@ -52,6 +52,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua index 1defdb1b71..7da190b523 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua @@ -59,6 +59,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/init.lua b/drivers/SmartThings/zigbee-motion-sensor/src/init.lua index 88e06eae68..5cc838177c 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/init.lua @@ -18,8 +18,48 @@ local defaults = require "st.zigbee.defaults" local constants = require "st.zigbee.constants" local zcl_clusters = require "st.zigbee.zcl.clusters" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local HAS_RECONFIGURED = "_has_reconfigured" +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + -- TODO: Remove when available in lua libs -- This is a temporary method to lower battery consumption in several devices. -- Disparities were noted between DTH implementations and driver defaults. -sg @@ -38,6 +78,11 @@ local do_refresh = function(driver, device, command) end end +local added_handler = function(self, device) + device:send(zcl_clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(zcl_clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) +end + local zigbee_motion_driver = { supported_capabilities = { capabilities.motionSensor, @@ -47,11 +92,22 @@ local zigbee_motion_driver = { capabilities.presenceSensor, capabilities.contactSensor }, + zigbee_handlers = { + attr = { + [zcl_clusters.TemperatureMeasurement.ID] = { + [zcl_clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [zcl_clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, capability_handlers = { [capabilities.refresh.ID] = { [capabilities.refresh.commands.refresh.NAME] = do_refresh, } }, + lifecycle_handlers = { + added = added_handler + }, sub_drivers = { require("aqara"), require("aurora"), diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua index c68eb33ef9..520906cd8c 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua @@ -117,6 +117,29 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { @@ -153,6 +176,8 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) }) + test.socket.zigbee:__expect_send({ mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) }) test.wait_for_events() test.mock_time.advance_time(50000) -- 21600 is the battery max interval @@ -175,6 +200,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -253,6 +286,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua index 1b9676c9b6..da645dcc9f 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -60,6 +61,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua index 922bc663c9..c0da6f813e 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua @@ -77,6 +77,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua index 4f063159be..c971d7d239 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" --- @type st.zigbee.zcl.clusters.OccupancySensing local OccupancySensing = clusters.OccupancySensing +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local t_utils = require "integration_test.utils" @@ -86,6 +87,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-sound-sensor/src/init.lua b/drivers/SmartThings/zigbee-sound-sensor/src/init.lua index cf305ef133..fb972bd5b5 100644 --- a/drivers/SmartThings/zigbee-sound-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-sound-sensor/src/init.lua @@ -21,8 +21,14 @@ local zcl_clusters = require "st.zigbee.zcl.clusters" local PollControl = zcl_clusters.PollControl local IASZone = zcl_clusters.IASZone local PowerConfiguration = zcl_clusters.PowerConfiguration +local TemperatureMeasurement = zcl_clusters.TemperatureMeasurement local battery_defaults = require "st.zigbee.defaults.battery_defaults" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local CHECK_IN_INTERVAL = 6480 local LONG_POLL_INTERVAL = 1200 local SHORT_POLL_INTERVAL = 2 @@ -52,6 +58,29 @@ local ias_zone_status_change_handler = function(driver, device, zb_rx) generate_event_from_zone_status(driver, device, zb_rx.body.zcl_body.zone_status, zb_rx) end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local do_configure = function(self, device) device_management.write_ias_cie_address(device, self.environment_info.hub_zigbee_eui) device:send(IASZone.server.commands.ZoneEnrollResponse(device, 0x00, 0x00)) -- ZoneEnroll Response should be called first in case of this device. @@ -67,6 +96,8 @@ end local added_handler = function(self, device) device:emit_event(capabilities.soundSensor.sound.not_detected()) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) end local zigbee_sound_sensor_driver_template = { @@ -79,6 +110,10 @@ local zigbee_sound_sensor_driver_template = { attr = { [IASZone.ID] = { [IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } }, cluster = { diff --git a/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua b/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua index 90249669ba..673877b67c 100644 --- a/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua +++ b/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua @@ -139,6 +139,22 @@ test.register_message_test( direction = "send", message = mock_device:generate_test_message("main", capabilities.soundSensor.sound.not_detected()) }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", @@ -241,4 +257,41 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-thermostat/src/init.lua b/drivers/SmartThings/zigbee-thermostat/src/init.lua index 6602c1c3db..da31da57d0 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/init.lua @@ -13,16 +13,17 @@ -- limitations under the License. -- Zigbee Driver utilities -local ZigbeeDriver = require "st.zigbee" -local device_management = require "st.zigbee.device_management" -local defaults = require "st.zigbee.defaults" -local utils = require "st.utils" +local ZigbeeDriver = require "st.zigbee" +local device_management = require "st.zigbee.device_management" +local defaults = require "st.zigbee.defaults" +local utils = require "st.utils" -- Zigbee Spec Utils local clusters = require "st.zigbee.zcl.clusters" local PowerConfiguration = clusters.PowerConfiguration local Thermostat = clusters.Thermostat local FanControl = clusters.FanControl +local TemperatureMeasurement = clusters.TemperatureMeasurement local FanMode = FanControl.attributes.FanMode local FanModeSequence = FanControl.attributes.FanModeSequence @@ -31,7 +32,7 @@ local ThermostatControlSequence = Thermostat.attributes.ControlSequenceOfOperati -- Capabilities local capabilities = require "st.capabilities" -local TemperatureMeasurement = capabilities.temperatureMeasurement +local Temperature = capabilities.temperatureMeasurement local ThermostatCoolingSetpoint = capabilities.thermostatCoolingSetpoint local ThermostatHeatingSetpoint = capabilities.thermostatHeatingSetpoint local ThermostatMode = capabilities.thermostatMode @@ -91,6 +92,12 @@ local SUPPORTED_THERMOSTAT_MODES = { ThermostatMode.thermostatMode.emergency_heat.NAME} } +-- TemperatureMeasurement cluster defaults +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local battery_voltage_handler = function(driver, device, battery_voltage) if (battery_voltage.value == 0) then -- this means we're plugged in device:emit_event(PowerSource.powerSource.mains()) @@ -197,6 +204,29 @@ local set_setpoint_factory = function(setpoint_attribute) end end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local do_refresh = function(self, device) local attributes = { Thermostat.attributes.OccupiedCoolingSetpoint, @@ -223,12 +253,14 @@ local do_configure = function(self, device) end local device_added = function(self, device) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) do_refresh(self, device) end local zigbee_thermostat_driver = { supported_capabilities = { - TemperatureMeasurement, + Temperature, ThermostatCoolingSetpoint, ThermostatHeatingSetpoint, ThermostatMode, @@ -253,6 +285,10 @@ local zigbee_thermostat_driver = { [FanControl.ID] = { [FanControl.attributes.FanModeSequence.ID] = supported_fan_modes_handler, [FanControl.attributes.FanMode.ID] = thermostat_fan_mode_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } } }, diff --git a/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua b/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua index a02045a1a9..d80731888d 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua @@ -18,6 +18,7 @@ local clusters = require "st.zigbee.zcl.clusters" local PowerConfiguration = clusters.PowerConfiguration local Thermostat = clusters.Thermostat local FanControl = clusters.FanControl +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local t_utils = require "integration_test.utils" @@ -109,6 +110,43 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C) for the temperature cluster", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C) for the temperature cluster", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Heating setpoint reports are handled", { @@ -505,6 +543,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "zigbee", direction = "send", diff --git a/drivers/SmartThings/zigbee-vent/src/init.lua b/drivers/SmartThings/zigbee-vent/src/init.lua index bdd643d06f..0a5b7fb506 100644 --- a/drivers/SmartThings/zigbee-vent/src/init.lua +++ b/drivers/SmartThings/zigbee-vent/src/init.lua @@ -19,6 +19,11 @@ local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local KEEN_PRESSURE_ATTRIBUTE = 0x0020 local KEEN_MFG_CODE = 0x115B @@ -58,10 +63,35 @@ local function switch_on_handler(driver, device, command) device:send(clusters.Level.commands.MoveToLevelWithOnOff(device, last_level, 0xFFFF)) end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function refresh_handler(driver, device, command) device:send(clusters.Level.attributes.CurrentLevel:read(device)) device:send(clusters.OnOff.attributes.OnOff:read(device)) device:send(clusters.TemperatureMeasurement.attributes.MeasuredValue:read(device)) + device:send(clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) device:send(clusters.PowerConfiguration.attributes.BatteryPercentageRemaining:read(device)) local pressure_read = cluster_base.read_manufacturer_specific_attribute(device, clusters.PressureMeasurement.ID, KEEN_PRESSURE_ATTRIBUTE, KEEN_MFG_CODE) @@ -102,6 +132,10 @@ local zigbee_vent_driver = { }, [clusters.Level.ID] = { [clusters.Level.attributes.CurrentLevel.ID] = level_report_handler + }, + [clusters.TemperatureMeasurement.ID] = { + [clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } } }, diff --git a/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua b/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua index dcb1efcb7c..cedc74b9ec 100644 --- a/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua +++ b/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" local OnOff = clusters.OnOff local Level = clusters.Level +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local base64 = require "st.base64" @@ -112,6 +113,43 @@ test.register_coroutine_test( end ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "added lifecycle event should get initial state for device", { @@ -144,6 +182,22 @@ test.register_message_test( clusters.TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) } }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "zigbee", direction = "send", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua index d7969a8e98..6ff290c337 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua @@ -18,6 +18,35 @@ local defaults = require "st.zigbee.defaults" local battery_defaults = require "st.zigbee.defaults.battery_defaults" local constants = require "st.zigbee.constants" local configurationMap = require "configurations" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement + +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) @@ -36,6 +65,11 @@ local function device_init(driver, device) end end +local function added_handler(self, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_water_driver_template = { supported_capabilities = { capabilities.waterSensor, @@ -43,8 +77,17 @@ local zigbee_water_driver_template = { capabilities.temperatureMeasurement, capabilities.battery, }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler }, ias_zone_configuration_method = constants.IAS_ZONE_CONFIGURE_TYPE.AUTO_ENROLL_RESPONSE, sub_drivers = { diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua index 30258012d4..dec30eed40 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua index 4cae9883ca..a2fc7c3b45 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua index 352841bdd4..05224a53fc 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua index e1e57db4fc..d4ad7bccff 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua index 33f6c28f24..3309db23f5 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua @@ -161,6 +161,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval @@ -197,6 +205,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -289,6 +305,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua index 5cf7801637..d3e624c29b 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua index b202dd450c..c5f93506cf 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua @@ -115,6 +115,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Battery percentage report should be handled", { @@ -135,6 +162,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval @@ -171,6 +206,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -263,6 +306,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua index ed03d10974..73f97cfcd4 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua @@ -88,11 +88,40 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_coroutine_test( "Configure should configure all necessary attributes", function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -209,6 +238,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive",