diff --git a/drivers/SmartThings/zigbee-smoke-detector/fingerprints.yml b/drivers/SmartThings/zigbee-smoke-detector/fingerprints.yml index a8384b886c..76b105fdb8 100644 --- a/drivers/SmartThings/zigbee-smoke-detector/fingerprints.yml +++ b/drivers/SmartThings/zigbee-smoke-detector/fingerprints.yml @@ -33,7 +33,7 @@ zigbeeManufacturer: deviceLabel: frient Smoke Detector manufacturer: frient A/S model: SMSZB-120 - deviceProfileName: smoke-battery + deviceProfileName: smoke-temp-battery-alarm - id: "Heiman/Orvibo/Gas3" deviceLabel: Orvibo Gas Detector manufacturer: Heiman diff --git a/drivers/SmartThings/zigbee-smoke-detector/profiles/smoke-temp-battery-alarm.yml b/drivers/SmartThings/zigbee-smoke-detector/profiles/smoke-temp-battery-alarm.yml new file mode 100644 index 0000000000..c1134baa02 --- /dev/null +++ b/drivers/SmartThings/zigbee-smoke-detector/profiles/smoke-temp-battery-alarm.yml @@ -0,0 +1,50 @@ +name: smoke-temp-battery-alarm +components: +- id: main + capabilities: + - id: smokeDetector + version: 1 + - id: temperatureMeasurement + version: 1 + - id: battery + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + - id: alarm + version: 1 + config: + values: + - key: "alarm.value" + enabledValues: + - off + - siren + - key: "{{enumCommands}}" + enabledValues: + - off + - siren + categories: + - name: SmokeDetector +preferences: + - preferenceId: tempOffset + explicit: true + - name: "tempSensitivity" + title: "Temperature Sensitivity (18.0°)" + description: "Minimum change in temperature to report" + required: false + preferenceType: number + definition: + minimum: 0.1 + maximum: 2.0 + default: 1.0 + - name: "warningDuration" + title: "Alarm duration (s)" + description: "After how many seconds should the alarm turn off" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 65534 + default: 240 + \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-smoke-detector/src/frient/init.lua b/drivers/SmartThings/zigbee-smoke-detector/src/frient/init.lua index 0f1dee8e23..16008ecf52 100644 --- a/drivers/SmartThings/zigbee-smoke-detector/src/frient/init.lua +++ b/drivers/SmartThings/zigbee-smoke-detector/src/frient/init.lua @@ -13,20 +13,201 @@ -- limitations under the License. local battery_defaults = require "st.zigbee.defaults.battery_defaults" +local capabilities = require "st.capabilities" +local zcl_clusters = require "st.zigbee.zcl.clusters" +local zcl_global_commands = require "st.zigbee.zcl.global_commands" +local data_types = require "st.zigbee.data_types" +local alarm = capabilities.alarm +local smokeDetector = capabilities.smokeDetector -local is_frient_smoke_detector = function(opts, driver, device) - if device:get_manufacturer() == "frient A/S" then - return true +local IASWD = zcl_clusters.IASWD +local IASZone = zcl_clusters.IASZone +local TemperatureMeasurement = zcl_clusters.TemperatureMeasurement + +local ALARM_COMMAND = "alarmCommand" +local ALARM_LAST_DURATION = "Custom_Alarm_Duration" +local ALARM_DEFAULT_MAX_DURATION = 0x00F0 +local DEFAULT_WARNING_DURATION = 240 +local BATTERY_MIN_VOLTAGE = 2.3 +local BATTERY_MAX_VOLTAGE = 3.0 + +local TEMPERATURE_MEASUREMENT_ENDPOINT = 0x26 + +local alarm_command = { + OFF = 0, + SIREN = 1 +} + +local CONFIGURATIONS = { + { + cluster = IASZone.ID, + attribute = IASZone.attributes.ZoneStatus.ID, + minimum_interval = 30, + maximum_interval = 300, + data_type = IASZone.attributes.ZoneStatus.base_type, + reportable_change = 1 + }, + { + cluster = TemperatureMeasurement.ID, + attribute = TemperatureMeasurement.attributes.MeasuredValue.ID, + minimum_interval = 60, + maximum_interval = 600, + data_type = TemperatureMeasurement.attributes.MeasuredValue.base_type, + reportable_change = 100 + } +} + +local function device_added(driver, device) + device:emit_event(alarm.alarm.off()) + device:emit_event(smokeDetector.smoke.clear()) +end + +local function device_init(driver, device) + battery_defaults.build_linear_voltage_init(BATTERY_MIN_VOLTAGE, BATTERY_MAX_VOLTAGE)(driver, device) + if CONFIGURATIONS ~= nil then + for _, attribute in ipairs(CONFIGURATIONS) do + device:add_configured_attribute(attribute) + device:add_monitored_attribute(attribute) + end + end +end + +local function do_configure(self, device) + device:configure() + device:send(IASWD.attributes.MaxDuration:write(device, ALARM_DEFAULT_MAX_DURATION)) +end + +local info_changed = function (driver, device, event, args) + for name, info in pairs(device.preferences) do + if (device.preferences[name] ~= nil and args.old_st_store.preferences[name] ~= device.preferences[name]) then + local input = device.preferences[name] + if (name == "tempSensitivity") then + local sensitivity = math.floor((device.preferences.tempSensitivity or 0.1)*100 + 0.5) + device:send(TemperatureMeasurement.attributes.MeasuredValue:configure_reporting(device, 60, 600, sensitivity):to_endpoint(TEMPERATURE_MEASUREMENT_ENDPOINT)) + elseif (name == "warningDuration") then + device:set_field(ALARM_LAST_DURATION, input, {persist = true}) + device:send(IASWD.attributes.MaxDuration:write(device, tonumber(input))) + end + end end - return false end -local frient_smoke_detector = { - NAME = "Freint Smoke Detector", +local function generate_event_from_zone_status(driver, device, zone_status, zigbee_message) + + if zone_status:is_test_set() then + device:emit_event(smokeDetector.smoke.tested()) + elseif zone_status:is_alarm1_set() then + device:emit_event(smokeDetector.smoke.detected()) + else + device.thread:call_with_delay(6, function () + device:emit_event(smokeDetector.smoke.clear()) + end) + end +end + +local function ias_zone_status_attr_handler(driver, device, zone_status, zb_rx) + generate_event_from_zone_status(driver, device, zone_status, zb_rx) +end + +local function ias_zone_status_change_handler(driver, device, zb_rx) + local zone_status = zb_rx.body.zcl_body.zone_status + generate_event_from_zone_status(driver, device, zone_status, zb_rx) +end + +local function send_siren_command(device) + local warning_duration = device:get_field(ALARM_LAST_DURATION) or DEFAULT_WARNING_DURATION + local sirenConfiguration = IASWD.types.SirenConfiguration(0x00) + + sirenConfiguration:set_warning_mode(0x01) + + device:send( + IASWD.server.commands.StartWarning( + device, + sirenConfiguration, + data_types.Uint16(warning_duration) + ) + ) + +end + +local emit_alarm_event = function(device, cmd) + if cmd == alarm_command.OFF then + device:emit_event(alarm.alarm.off()) + else + if cmd == alarm_command.SIREN then + device:emit_event(alarm.alarm.siren()) + end + end +end + +local default_response_handler = function(driver, device, zigbee_message) + local command = zigbee_message.body.zcl_body.cmd.value + local alarm_ev = device:get_field(ALARM_COMMAND) + if command == IASWD.server.commands.StartWarning.ID then + if alarm_ev ~= alarm_command.OFF then + emit_alarm_event(device, alarm_ev) + local lastDuration = device:get_field(ALARM_LAST_DURATION) or ALARM_DEFAULT_MAX_DURATION + device.thread:call_with_delay(lastDuration, function(d) + device:emit_event(alarm.alarm.off()) + end) + else + emit_alarm_event(device,alarm_command.OFF) + end + end +end + +local siren_alarm_siren_handler = function(driver, device, command) + device:set_field(ALARM_COMMAND, alarm_command.SIREN, {persist = true}) + send_siren_command(device) +end + + +local siren_switch_off_handler = function(driver, device, command) + local sirenConfiguration = IASWD.types.SirenConfiguration(0x00) + sirenConfiguration:set_warning_mode(0x00) + device:set_field(ALARM_COMMAND, alarm_command.OFF, {persist = true}) + + device:send( + IASWD.server.commands.StartWarning( + device, + sirenConfiguration + ) + ) +end + +local frient_smoke_sensor = { + NAME = "frient smoke sensor", lifecycle_handlers = { - init = battery_defaults.build_linear_voltage_init(2.3, 3.0) + added = device_added, + doConfigure = do_configure, + init = device_init, + infoChanged = info_changed + }, + capability_handlers = { + [alarm.ID] = { + [alarm.commands.off.NAME] = siren_switch_off_handler, + [alarm.commands.siren.NAME] = siren_alarm_siren_handler, + }, + }, + zigbee_handlers = { + global = { + [IASWD.ID] = { + [zcl_global_commands.DEFAULT_RESPONSE_ID] = default_response_handler + }, + }, + cluster = { + [IASZone.ID] = { + [IASZone.client.commands.ZoneStatusChangeNotification.ID] = ias_zone_status_change_handler + } + }, + attr = { + [IASZone.ID] = { + [IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler + } + } }, - can_handle = is_frient_smoke_detector + can_handle = function(opts, driver, device, ...) + return device:get_manufacturer() == "frient A/S" and device:get_model() == "SMSZB-120" + end } - -return frient_smoke_detector +return frient_smoke_sensor diff --git a/drivers/SmartThings/zigbee-smoke-detector/src/init.lua b/drivers/SmartThings/zigbee-smoke-detector/src/init.lua index 2d46a5dc8c..6f4f44f492 100644 --- a/drivers/SmartThings/zigbee-smoke-detector/src/init.lua +++ b/drivers/SmartThings/zigbee-smoke-detector/src/init.lua @@ -20,17 +20,18 @@ local constants = require "st.zigbee.constants" local zigbee_smoke_driver_template = { supported_capabilities = { capabilities.smokeDetector, - capabilities.battery + capabilities.battery, + capabilities.alarm, + capabilities.temperatureMeasurement }, sub_drivers = { require("frient"), require("aqara-gas"), - require("aqara"), - require("frient") + require("aqara") }, ias_zone_configuration_method = constants.IAS_ZONE_CONFIGURE_TYPE.AUTO_ENROLL_RESPONSE, } defaults.register_for_default_handlers(zigbee_smoke_driver_template, zigbee_smoke_driver_template.supported_capabilities) local zigbee_smoke_driver = ZigbeeDriver("zigbee-smoke-detector", zigbee_smoke_driver_template) -zigbee_smoke_driver:run() +zigbee_smoke_driver:run() \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-smoke-detector/src/test/test_frient_smoke_detector.lua b/drivers/SmartThings/zigbee-smoke-detector/src/test/test_frient_smoke_detector.lua index fae04f8963..e8453260fa 100644 --- a/drivers/SmartThings/zigbee-smoke-detector/src/test/test_frient_smoke_detector.lua +++ b/drivers/SmartThings/zigbee-smoke-detector/src/test/test_frient_smoke_detector.lua @@ -15,182 +15,460 @@ -- Mock out globals local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" +local IASWD = clusters.IASWD local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" +local alarm = capabilities.alarm +local smokeDetector = capabilities.smokeDetector local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IasEnrollResponseCode = require "st.zigbee.generated.zcl_clusters.IASZone.types.EnrollResponseCode" local t_utils = require "integration_test.utils" +local data_types = require "st.zigbee.data_types" +local SirenConfiguration = require "st.zigbee.generated.zcl_clusters.IASWD.types.SirenConfiguration" +local ALARM_DEFAULT_MAX_DURATION = 0x00F0 +local POWER_CONFIGURATION_ENDPOINT = 0x23 +local IASZONE_ENDPOINT = 0x23 +local TEMPERATURE_MEASUREMENT_ENDPOINT = 0x26 +local base64 = require "base64" + local mock_device = test.mock_device.build_test_zigbee_device( - { profile = t_utils.get_profile_definition("smoke-battery.yml"), - zigbee_endpoints = { - [1] = { - id = 1, - manufacturer = "frient A/S", - model = "SMSZB-120", - server_clusters = {0x0000,0x0001,0x0003,0x000F,0x0020,0x0500,0x0502} - } - } - } + { profile = t_utils.get_profile_definition("smoke-temp-battery-alarm.yml"), + zigbee_endpoints = { + [0x01] = { + id = 0x01, + manufacturer = "frient A/S", + model = "SMSZB-120", + server_clusters = { 0x0003, 0x0005, 0x0006 } + }, + [0x23] = { + id = 0x23, + server_clusters = { 0x0000, 0x0001, 0x0003, 0x000f, 0x0020, 0x0500, 0x0502 } + }, + [0x26] = { + id = 0x26, + server_clusters = { 0x0000, 0x0003, 0x0402 } + } + } + } ) zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device) - zigbee_test_utils.init_noop_health_check_timer() + test.mock_device.add_test_device(mock_device) + zigbee_test_utils.init_noop_health_check_timer() end test.set_test_init_function(test_init) -test.register_message_test( - "Battery voltage report should be handled", - { - { - channel = "zigbee", - direction = "receive", - message = { mock_device.id, PowerConfiguration.attributes.BatteryVoltage:build_test_attr_report(mock_device, 24) } - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.battery.battery(14)) - } - } +test.register_coroutine_test( + "Clear alarm and smokeDetector states when the device is added", function() + test.socket.matter:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", alarm.alarm.off()) + ) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", smokeDetector.smoke.clear()) + ) + + test.wait_for_events() + end ) test.register_coroutine_test( - "Health check should check all relevant attributes", - function() - test.socket.device_lifecycle:__queue_receive({mock_device.id, "added"}) - test.wait_for_events() - - test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval - test.socket.zigbee:__set_channel_ordering("relaxed") - test.socket.zigbee:__expect_send( - { - mock_device.id, - PowerConfiguration.attributes.BatteryVoltage:read(mock_device) - } - ) - test.socket.zigbee:__expect_send( - { - mock_device.id, - IASZone.attributes.ZoneStatus:read(mock_device) - } - ) - end, - { - test_init = function() - test.mock_device.add_test_device(mock_device) - test.timer.__create_and_queue_test_time_advance_timer(30, "interval", "health_check") - end - } + "init and doConfigure lifecycles should be handled properly", + function() + test.socket.environment_update:__queue_receive({ "zigbee", { hub_zigbee_id = base64.encode(zigbee_test_utils.mock_hub_eui) } }) + test.socket.zigbee:__set_channel_ordering("relaxed") + + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "init" }) + + test.wait_for_events() + + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", alarm.alarm.off()) + ) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", smokeDetector.smoke.clear()) + ) + + test.wait_for_events() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request( + mock_device, + zigbee_test_utils.mock_hub_eui, + PowerConfiguration.ID, + POWER_CONFIGURATION_ENDPOINT + ):to_endpoint(POWER_CONFIGURATION_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + PowerConfiguration.attributes.BatteryVoltage:configure_reporting( + mock_device, + 30, + 21600, + 1 + ):to_endpoint(POWER_CONFIGURATION_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request( + mock_device, + zigbee_test_utils.mock_hub_eui, + TemperatureMeasurement.ID, + TEMPERATURE_MEASUREMENT_ENDPOINT + ):to_endpoint(TEMPERATURE_MEASUREMENT_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:configure_reporting( + mock_device, + 60, + 600, + 100 + ):to_endpoint(TEMPERATURE_MEASUREMENT_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + zigbee_test_utils.build_bind_request( + mock_device, + zigbee_test_utils.mock_hub_eui, + IASZone.ID, + IASZONE_ENDPOINT + ):to_endpoint(IASZONE_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + IASZone.attributes.ZoneStatus:configure_reporting( + mock_device, + 30, + 300, + 0 + ):to_endpoint(IASZONE_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + IASZone.attributes.IASCIEAddress:write( + mock_device, + zigbee_test_utils.mock_hub_eui + ):to_endpoint(IASZONE_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + IASZone.server.commands.ZoneEnrollResponse( + mock_device, + IasEnrollResponseCode.SUCCESS, + 0x00 + ) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + IASWD.attributes.MaxDuration:write(mock_device, ALARM_DEFAULT_MAX_DURATION) + }) + + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + +test.register_message_test( + "Battery voltage report should be handled", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, PowerConfiguration.attributes.BatteryVoltage:build_test_attr_report(mock_device, 24) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.battery.battery(14)) + } + } +) + +test.register_message_test( + "ZoneStatusChangeNotification should be handled: detected", + { + { + channel = "zigbee", + direction = "receive", + -- ZoneStatus | Bit0 Alarm1 set to 1 + message = { mock_device.id, IASZone.client.commands.ZoneStatusChangeNotification.build_test_rx(mock_device, 0x0001, 0x00) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.detected()) + } + } +) + +test.register_message_test( + "ZoneStatusChangeNotification should be handled: tested", + { + { + channel = "zigbee", + direction = "receive", + -- ZoneStatus | Bit8: Test set to 1 + message = { mock_device.id, IASZone.client.commands.ZoneStatusChangeNotification.build_test_rx(mock_device, 0x100, 0x01) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.smokeDetector.smoke.tested()) + } + } +) + +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_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.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) - test.socket.zigbee:__expect_send({ - mock_device.id, - PowerConfiguration.attributes.BatteryVoltage:read(mock_device) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - IASZone.attributes.ZoneStatus:read(mock_device) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - PowerConfiguration.attributes.BatteryVoltage:configure_reporting( - mock_device, - 30, - 21600, - 1 - ) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - zigbee_test_utils.build_bind_request( - mock_device, - zigbee_test_utils.mock_hub_eui, - PowerConfiguration.ID - ) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - IASZone.attributes.IASCIEAddress:write( - mock_device, - zigbee_test_utils.mock_hub_eui - ) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - IASZone.server.commands.ZoneEnrollResponse( - mock_device, - IasEnrollResponseCode.SUCCESS, - 0x00 - ) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - IASZone.attributes.ZoneStatus:configure_reporting( - mock_device, - 0, - 180, - 0 - ) - }) - test.socket.zigbee:__expect_send({ - mock_device.id, - zigbee_test_utils.build_bind_request( - mock_device, - zigbee_test_utils.mock_hub_eui, - IASZone.ID - ) - }) - - mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) - end + "Health check should check all relevant attributes", + function() + test.wait_for_events() + + test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval + test.socket.zigbee:__set_channel_ordering("relaxed") + + test.socket.zigbee:__expect_send( + { + mock_device.id, + PowerConfiguration.attributes.BatteryVoltage: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, + IASZone.attributes.ZoneStatus:read(mock_device) + } + ) + end, + { + test_init = function() + test.mock_device.add_test_device(mock_device) + test.timer.__create_and_queue_test_time_advance_timer(30, "interval", "health_check") + end + } +) + +test.register_message_test( + "Refresh should read all necessary attributes", + { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { capability = "refresh", component = "main", command = "refresh", args = {} } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + IASZone.attributes.ZoneStatus:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + PowerConfiguration.attributes.BatteryVoltage:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + } + }, + { + inner_block_ordering = "relaxed" + } ) test.register_message_test( - "Refresh should read all necessary attributes", - { - { - channel = "device_lifecycle", - direction = "receive", - message = {mock_device.id, "added"} - }, - { - channel = "capability", - direction = "receive", - message = { - mock_device.id, - { capability = "refresh", component = "main", command = "refresh", args = {} } + "Refresh should read all necessary attributes", + { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { capability = "refresh", component = "main", command = "refresh", args = {} } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + IASZone.attributes.ZoneStatus:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + PowerConfiguration.attributes.BatteryVoltage:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + } + }, + { + inner_block_ordering = "relaxed" } - }, - { - channel = "zigbee", - direction = "send", - message = { - mock_device.id, - PowerConfiguration.attributes.BatteryVoltage:read(mock_device) +) + +test.register_coroutine_test( + "infochanged to check for necessary preferences settings: tempSensitivity, warningDuration", + function() + local updates = { + preferences = { + tempSensitivity = 1.3, + warningDuration = 100 + } + } + + test.wait_for_events() + test.socket.device_lifecycle:__queue_receive(mock_device:generate_info_changed(updates)) + + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:configure_reporting( + mock_device, + 60, + 600, + 130 + )--:to_endpoint(TEMPERATURE_MEASUREMENT_ENDPOINT) + }) + + test.socket.zigbee:__expect_send({ + mock_device.id, + IASWD.attributes.MaxDuration:write(mock_device, 0x0064)--:to_endpoint(IASZONE_ENDPOINT) + }) + + + test.socket.zigbee:__set_channel_ordering("relaxed") + + end +) + +local sirenConfiguration = SirenConfiguration(0x00) +sirenConfiguration:set_warning_mode(0x01) +local defaultWarningDuration = 240 + +test.register_message_test( + "Capability command Alarm - siren should be handled", + { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { capability = "alarm", component = "main", command = "siren", args = {} } + } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, + IASWD.server.commands.StartWarning(mock_device, + sirenConfiguration, + data_types.Uint16(defaultWarningDuration), + data_types.Uint8(00), + data_types.Enum8(00)) + } + } + }, + { + inner_block_ordering = "relaxed" } - }, - { - channel = "zigbee", - direction = "send", - message = { - mock_device.id, - IASZone.attributes.ZoneStatus:read(mock_device) +) + +local sirenConfiguration = SirenConfiguration(0x00) +sirenConfiguration:set_warning_mode(0x00) + +test.register_message_test( + "Capability command Alarm - OFF should be handled", + { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { capability = "alarm", component = "main", command = "off", args = {} } + } + }, + { + channel = "zigbee", + direction = "send", + message = { mock_device.id, + IASWD.server.commands.StartWarning(mock_device, + sirenConfiguration, + data_types.Uint16(0x00), + data_types.Uint8(00), + data_types.Enum8(00)) + } + } + }, + { + inner_block_ordering = "relaxed" } - }, - }, - { - inner_block_ordering = "relaxed" - } ) + test.run_registered_tests()