From a51d69521ca57e25b98760d6fd7cf875cda79c41 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Mon, 13 Apr 2026 15:37:36 +0200 Subject: [PATCH 01/16] new pull request --- .../SmartThings/zwave-sensor/fingerprints.yml | 54 ++ .../zwave-sensor/profiles/aeotec-aerq-8.yml | 133 +++++ .../profiles/aeotec-door-window-sensor-8.yml | 197 +++++++ .../aeotec-water-sensor-8-co.yml\342\200\216" | 162 ++++++ ...aeotec-water-sensor-8-co2.yml\342\200\216" | 162 ++++++ .../aeotec-water-sensor-8-contact.yml | 162 ++++++ .../aeotec-water-sensor-8-glass-break.yml | 162 ++++++ .../profiles/aeotec-water-sensor-8-motion.yml | 162 ++++++ .../profiles/aeotec-water-sensor-8-panic.yml | 162 ++++++ .../profiles/aeotec-water-sensor-8-smoke.yml | 162 ++++++ .../profiles/aeotec-water-sensor-8.yml | 162 ++++++ .../zwave-sensor/src/aeotec-aerq-8/init.lua | 123 +++++ .../src/aeotec-door-window-sensor-8/init.lua | 199 +++++++ .../init.lua\342\200\216" | 259 +++++++++ drivers/SmartThings/zwave-sensor/src/init.lua | 3 + .../test/test_aeotec_aerq_8.lua\342\200\216" | 293 ++++++++++ .../test/test_aeotec_door_window_sesnor_8.lua | 430 +++++++++++++++ ...est_aeotec_water_sensor_8.lua\342\200\216" | 511 ++++++++++++++++++ .../src/timed-tamper-clear/init.lua | 53 +- 19 files changed, 3542 insertions(+), 9 deletions(-) create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml create mode 100644 "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" create mode 100644 "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml create mode 100644 drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml create mode 100644 drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua create mode 100644 drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua create mode 100644 "drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" create mode 100644 "drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" create mode 100644 drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua create mode 100644 "drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" diff --git a/drivers/SmartThings/zwave-sensor/fingerprints.yml b/drivers/SmartThings/zwave-sensor/fingerprints.yml index 0810b20a38..9c0217ff39 100644 --- a/drivers/SmartThings/zwave-sensor/fingerprints.yml +++ b/drivers/SmartThings/zwave-sensor/fingerprints.yml @@ -560,6 +560,60 @@ zwaveManufacturer: productType: 0x0100 productId: 0x0082 deviceProfileName: shelly-wave-motion + - id: "aeotec/contact/8/eu" + deviceLabel: Aeotec Door Window Sensor 8 + manufacturerId: 0x0371 + productType: 0x0002 + productId: 0x0037 + deviceProfileName: aeotec-door-window-sensor-8 + - id: "aeotec/contact/8/us" + deviceLabel: Aeotec Door Window Sensor 8 + manufacturerId: 0x0371 + productType: 0x0102 + productId: 0x0037 + deviceProfileName: aeotec-door-window-sensor-8 + - id: "aeotec/contact/8/au" + deviceLabel: Aeotec Door Window Sensor 8 + manufacturerId: 0x0371 + productType: 0x0202 + productId: 0x0037 + deviceProfileName: aeotec-door-window-sensor-8 + - id: aeotec/aerq/8/eu + deviceLabel: Aeotec aerQ 8 + manufacturerId: 0x0371 + productType: 0x0002 + productId: 0x0039 + deviceProfileName: aeotec-aerq-8 + - id: aeotec/aerq/8/us + deviceLabel: Aeotec aerQ 8 + manufacturerId: 0x0371 + productType: 0x0102 + productId: 0x0039 + deviceProfileName: aeotec-aerq-8 + - id: aeotec/aerq/8/au + deviceLabel: Aeotec aerQ 8 + manufacturerId: 0x0371 + productType: 0x0202 + productId: 0x0039 + deviceProfileName: aeotec-aerq-8 + - id: "aeotec/water/8/eu" + deviceLabel: Aeotec Water Sensor 8 + manufacturerId: 0x0371 + productType: 0x0002 + productId: 0x0038 + deviceProfileName: aeotec-water-sensor-8 + - id: "aeotec/water/8/us" + deviceLabel: Aeotec Water Sensor 8 + manufacturerId: 0x0371 + productType: 0x0102 + productId: 0x0038 + deviceProfileName: aeotec-water-sensor-8 + - id: "aeotec/water/8/au" + deviceLabel: Aeotec Water Sensor 8 + manufacturerId: 0x0371 + productType: 0x0202 + productId: 0x0038 + deviceProfileName: aeotec-water-sensor-8 zwaveGeneric: - id: "GenericSensorAlarm" deviceLabel: Z-Wave Sensor diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml new file mode 100644 index 0000000000..7055dd8300 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml @@ -0,0 +1,133 @@ +name: aeotec-aerq-8 +components: +- id: main + capabilities: + - id: temperatureMeasurement + config: + values: + - key: "temperature.value" + range: [-10, 60] + version: 1 + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + version: 1 + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: TempHumiditySensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + desccription: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml new file mode 100644 index 0000000000..6b7206293c --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -0,0 +1,197 @@ +name: aeotec-door-window-sensor-8 +components: +- id: main + capabilities: + - id: contactSensor + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: threeAxis + version: 1 + - id: battery + version: 1 + - id: refresh + version: 1 +categories: + - name: ContactSensor +metadata: + deviceType: ContactSensor + ocfDeviceType: x.com.st.d.sensor.contact + deviceTypeId: ContactSensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter5" + title: "5 State when the magnet is close" + description: "This parameter allows to set the states of door/window when the magnet closes to the sensor." + required: false + preferenceType: enumeration + definition: + options: + 0: "Open=magnet far, Closed=magnet near" + 1: "Closed=magnet far, Open=magnet near" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + desccription: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter27" + title: "27 Set tilt sensor mode" + description: "Set tilt sensor mode." + required: false + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enabled. Needs magnet" + 2: "Enabled. It can used without magnet." + default: 1 + - name: "parameter28" + title: "28 State of tilt in Mode 2" + description: "This parameter allows setting the state of door/window when the sensor is tilted." + required: false + preferenceType: enumeration + definition: + options: + 0: "Opened = tilted, closed = not tilted" + 1: "Closed = tilted, opened = not tilted" + default: 0 + - name: "parameter33" + title: "33 Tilt triggered angle" + description: "With this parameter, you can adjust the tilt triggered angle if the tilt is too low or too strong." + required: false + preferenceType: integer + definition: + minimum: 1 + maximum: 90 + default: 5 + - name: "parameter34" + title: "34 Timeout tilt detection Mode 1" + description: "Set the timeout of tilt detection Mode 1." + required: false + preferenceType: integer + definition: + minimum: 5 + maximum: 60 + default: 5 + - name: "parameter35" + title: "35 Timeout tilt detection Mode 2" + description: "Set the timeout of tilt detection Mode 2." + required: false + preferenceType: integer + definition: + minimum: 5 + maximum: 60 + default: 8 + - name: "parameter36" + title: "36 Min. acc. change to report" + description: "Minimum acceleration change to trigger report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" \ No newline at end of file diff --git "a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" "b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" new file mode 100644 index 0000000000..c13d2254fa --- /dev/null +++ "b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-co +components: +- id: main + capabilities: + - id: carbonMonoxideDetector + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: AirQualityDetector +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git "a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" "b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" new file mode 100644 index 0000000000..36367534a6 --- /dev/null +++ "b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-co2 +components: +- id: main + capabilities: + - id: carbonDioxideHealthConcern + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: AirQualityDetector +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml new file mode 100644 index 0000000000..994cc7b4bd --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-contact +components: +- id: main + capabilities: + - id: contactSensor + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: ContactSensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml new file mode 100644 index 0000000000..759d0d0f94 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-glass-break +components: +- id: main + capabilities: + - id: soundDetection + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: SoundSensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml new file mode 100644 index 0000000000..576253e2cb --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-motion +components: +- id: main + capabilities: + - id: motionSensor + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: MotionSensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml new file mode 100644 index 0000000000..3aa63e911c --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-panic +components: +- id: main + capabilities: + - id: panicAlarm + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: PanicButton +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml new file mode 100644 index 0000000000..a6686b6b57 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8-smoke +components: +- id: main + capabilities: + - id: smokeDetector + version: 1 + - id: temperatureMeasurement + config: + values: + - key: "temperature.value" + range: [-10, 60] + version: 1 + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: SmokeDetector +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml new file mode 100644 index 0000000000..717b2c8ce0 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml @@ -0,0 +1,162 @@ +name: aeotec-water-sensor-8 +components: +- id: main + capabilities: + - id: waterSensor + version: 1 + - id: temperatureMeasurement + version: 1 + config: + values: + - key: "temperature.value" + range: [-10, 60] + - id: relativeHumidityMeasurement + version: 1 + - id: dewPoint + version: 1 + config: + values: + - key: "dewpoint.value" + range: [-10, 60] + - id: moldHealthConcern + version: 1 + config: + values: + - key: "moldHealthConcern.value" + enabledValues: + - good + - moderate + - id: tamperAlert + version: 1 + - id: powerSource + version: 1 + config: + values: + - key: "powerSource.value" + enabledValues: + - battery + - dc + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: LeakSensor +preferences: + - name: "parameter1" + title: "1 Set threshold Check Time" + description: "When using battery power, follow this configuration, the minimum time is 30 seconds. When using USB power supply, for real-time detection." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 900 + - name: "parameter2" + title: "2 Min. temperature change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 20 + - name: "parameter3" + title: "3 Min. humidity change to report" + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 255 + default: 50 + - name: "parameter4" + title: "4 Enable led indication" + description: "This parameter defines when the green or red LED will indicate events. Disabling all indications may extend battery life. Off means no indications." + required: false + preferenceType: enumeration + definition: + options: + 0: "Off" + 1: "On" + default: 0 + - name: "parameter5" + title: "5 Dry contact sensor polarity" + description: "This parameter allows to set the states of alarm when the dry contact is closed" + required: false + preferenceType: enumeration + definition: + options: + 0: "Closed = Alarm, Open = Idle" + 1: "Open = Alarm, Closed = Idle" + default: 0 + - name: "parameter10" + title: "Notification Type" + description: "Set the notification type." + required: false + preferenceType: enumeration + definition: + options: + 0: "Water Alarm" + 1: "Smoke Alarm" + 2: "CO Alarm" + 3: "CO2 Alarm" + 4: "Door/Window Alarm" + 5: "Tilt Alarm" + 6: "Motion Alarm" + 7: "Glass Break Alarm" + 8: "Panic Alarm" + default: 0 + - name: "parameter13" + title: "13 Mold alarm offset" + description: "Increase the humidity threshold." + required: false + preferenceType: integer + definition: + minimum: -10 + maximum: 10 + default: 0 + - name: "parameter23" + title: "23 Low battery threshold" + description: "Report low battery report when level goes under threshold setting." + required: false + preferenceType: integer + definition: + minimum: 10 + maximum: 50 + default: 20 + - name: "parameter24" + title: "24 Periodic Reports" + description: "The period of battery, temperature and humidity report, the minimum time is 30 seconds." + required: false + preferenceType: integer + definition: + minimum: 0 + maximum: 2678400 + default: 43200 + - name: "parameter25" + title: "25 Offset value for temperature" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter26" + title: "26 Offset value for Humidity" + description: "Calibrate humidity." + required: false + preferenceType: integer + definition: + minimum: -200 + maximum: 200 + default: 0 + - name: "parameter64" + title: "64 Temperature Scale" + description: "Scale for auto reports and settings." + required: false + preferenceType: enumeration + definition: + options: + 0: "Celsius" + 1: "Fahrenheit" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua new file mode 100644 index 0000000000..b523b01c97 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua @@ -0,0 +1,123 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) + +local MoldHealthConcern = capabilities.moldHealthConcern +local PowerSource = capabilities.powerSource +local TamperAlert = capabilities.tamperAlert + +local AEOTEC_AERQ_FINGERPRINTS = { + { manufacturerId = 0x0371, productId = 0x0039 } -- Aeotec aerQ 8 EU/US/AU +} + +local function can_handle_aeotec_aerq(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_AERQ_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + local subdriver = require("aeotec-aerq-8") + return true, subdriver + end + end + return false +end + +local function added_handler(driver, device) + device:send(Configuration:Get({ parameter_number = 10 })) + + device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) + + -- Default value + device:emit_event(MoldHealthConcern.moldHealthConcern.good()) + + -- Default value + device:emit_event(PowerSource.powerSource.battery()) + + device:send(Battery:Get({})) + + device:register_native_capability_attr_handler("temperatureMeasurement", "temperature") + -- device:register_native_capability_attr_handler("colorControl", "hue") + +end + +local function do_refresh(driver, device) + device:send(Battery:Get({})) +end + +local function notification_report_handler(self, device, cmd) + local event + + -- POWER + if cmd.args.notification_type == Notification.notification_type.POWER_MANAGEMENT then + if cmd.args.event == Notification.event.power_management.AC_MAINS_DISCONNECTED then + event = capabilities.powerSource.powerSource.battery() + elseif cmd.args.event == Notification.event.power_management.AC_MAINS_RE_CONNECTED then + event = capabilities.powerSource.powerSource.dc() + elseif cmd.args.event == Notification.event.power_management.POWER_HAS_BEEN_APPLIED then + device:send(Battery:Get({})) + end + end + + -- MOLD + if cmd.args.notification_type == Notification.notification_type.WEATHER_ALARM then + if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then + event = MoldHealthConcern.moldHealthConcern.good() + elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then + event = MoldHealthConcern.moldHealthConcern.moderate() + end + end + + -- TAMPER + if cmd.args.notification_type == Notification.notification_type.HOME_SECURITY then + if cmd.args.event == Notification.event.home_security.STATE_IDLE then + event = TamperAlert.tamper.clear() + elseif cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED then + event = TamperAlert.tamper.detected() + end + end + + if (event ~= nil) then + device:emit_event(event) + end +end + +local aeotec_aerq_8 = { + supported_capabilities = { + capabilities.powerSource + }, + zwave_handlers = { + [cc.NOTIFICATION] = { + [Notification.REPORT] = notification_report_handler + }, + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + lifecycle_handlers = { + added = added_handler, + }, + NAME = "Aeotec aerQ 8", + can_handle = can_handle_aeotec_aerq +} + +return aeotec_aerq_8 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua new file mode 100644 index 0000000000..9ca600d55f --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -0,0 +1,199 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.SensorMultilevel +local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) + +local MoldHealthConcern = capabilities.moldHealthConcern +local ContactSensor = capabilities.contactSensor +local PowerSource = capabilities.powerSource +local ThreeAxis = capabilities.threeAxis +local TamperAlert = capabilities.tamperAlert +local TemperatureMeasurement = capabilities.temperatureMeasurement +local RelativeHumidityMeasurement = capabilities.relativeHumidityMeasurement +local DewPoint = capabilities.dewPoint + +local AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS = { + { manufacturerId = 0x0371, productId = 0x0037 } -- Aeotec Door Window Sensor 8 EU/US/AU +} + +local function can_handle_aeotec_door_window_sensor_8(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + local subdriver = require("aeotec-door-window-sensor-8") + return true, subdriver + end + end + return false +end + +local function added_handler(driver, device) + device:send(Configuration:Get({ parameter_number = 10 })) + + device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) + + -- Default value + device:emit_event(MoldHealthConcern.moldHealthConcern.good()) + + -- Default value + device:emit_event(PowerSource.powerSource.battery()) + + device:send(Battery:Get({})) +end + +local function device_init(driver, device) + device:set_field("three_axis_x", 0) + device:set_field("three_axis_y", 0) + device:set_field("three_axis_z", 0) +end + +local function do_refresh(driver, device) + device:send(Battery:Get({})) +end + +local function notification_report_handler(self, device, cmd) + local event + + -- DOOR_WINDOW + if cmd.args.notification_type == Notification.notification_type.ACCESS_CONTROL then + if cmd.args.event == Notification.event.access_control.WINDOW_DOOR_IS_CLOSED then + event = ContactSensor.contact.closed() + elseif cmd.args.event == Notification.event.access_control.WINDOW_DOOR_IS_OPEN then + event = ContactSensor.contact.open() + end + end + + -- POWER + if cmd.args.notification_type == Notification.notification_type.POWER_MANAGEMENT then + if cmd.args.event == Notification.event.power_management.AC_MAINS_DISCONNECTED then + event = PowerSource.powerSource.battery() + elseif cmd.args.event == Notification.event.power_management.AC_MAINS_RE_CONNECTED then + event = PowerSource.powerSource.dc() + elseif cmd.args.event == Notification.event.power_management.POWER_HAS_BEEN_APPLIED then + device:send(Battery:Get({})) + end + end + + -- MOLD + if cmd.args.notification_type == Notification.notification_type.WEATHER_ALARM then + if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then + event = MoldHealthConcern.moldHealthConcern.good() + elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then + event = MoldHealthConcern.moldHealthConcern.moderate() + end + end + + -- TAMPER + if cmd.args.notification_type == Notification.notification_type.HOME_SECURITY then + if cmd.args.event == Notification.event.home_security.STATE_IDLE then + event = TamperAlert.tamper.clear() + elseif cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED then + event = TamperAlert.tamper.detected() + end + end + + if (event ~= nil) then + device:emit_event(event) + end +end + +local function sensor_multilevel_report_handler(self, device, cmd) + local event + local sensor_type = cmd.args.sensor_type + local value = cmd.args.sensor_value + + local x = device:get_field("three_axis_x") or 0 + local y = device:get_field("three_axis_y") or 0 + local z = device:get_field("three_axis_z") or 0 + + local MIN_VAL = -10000 + local MAX_VAL = 10000 + value = math.max(MIN_VAL, math.min(MAX_VAL, value)) + + if (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_X_AXIS) then + x = value + device:set_field("three_axis_x", x) + event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) + elseif (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS) then + y = value + device:set_field("three_axis_y", y) + event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) + elseif (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS) then + z = value + device:set_field("three_axis_z", z) + event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) + end + + if (sensor_type == SensorMultilevel.sensor_type.TEMPERATURE) then + local scale = 'C' + if (SensorMultilevel.scale.temperature.FAHRENHEIT == cmd.args.scale) then + scale = 'F' + end + event = TemperatureMeasurement.temperature({value = value, unit = scale}) + end + + if (sensor_type == SensorMultilevel.sensor_type.RELATIVE_HUMIDITY) then + event = RelativeHumidityMeasurement.humidity({value = value, unit = "%"}) + end + + if (sensor_type == SensorMultilevel.sensor_type.DEW_POINT) then + local scale = 'C' + if (SensorMultilevel.scale.dew_point.FAHRENHEIT == cmd.args.scale) then + scale = 'F' + end + event = DewPoint.dewpoint({value = value, unit = scale}) + end + + if (event ~= nil) then + device:emit_event(event) + return; + end +end + +local aeotec_door_window_sensor_8 = { + supported_capabilities = { + capabilities.powerSource, + capabilities.threeAxis, + }, + zwave_handlers = { + [cc.NOTIFICATION] = { + [Notification.REPORT] = notification_report_handler + }, + [cc.SENSOR_MULTILEVEL] = { + [SensorMultilevel.REPORT] = sensor_multilevel_report_handler + } + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + lifecycle_handlers = { + init = device_init, + added = added_handler + }, + NAME = "Aeotec Door Window Sensor 8", + can_handle = can_handle_aeotec_door_window_sensor_8 +} + +return aeotec_door_window_sensor_8 \ No newline at end of file diff --git "a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" new file mode 100644 index 0000000000..6fa0d3b637 --- /dev/null +++ "b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" @@ -0,0 +1,259 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) + +local MoldHealthConcern = capabilities.moldHealthConcern +local CarbonDioxideHealthConcern = capabilities.carbonDioxideHealthConcern +local SoundDetection = capabilities.soundDetection +local SmokeDetector = capabilities.smokeDetector +local WaterSensor = capabilities.waterSensor +local CarbonMonoxideDetector = capabilities.carbonMonoxideDetector +local TamperAlert = capabilities.tamperAlert +local MotionSensor = capabilities.motionSensor +local PowerSource = capabilities.powerSource +local ContactSensor = capabilities.contactSensor +local PanicAlarm = capabilities.panicAlarm + +local AEOTEC_WATER_SENSOR_8_FINGERPRINTS = { + { manufacturerId = 0x0371, productId = 0x0038 } -- Aeotec Water Sensor 8 EU/US/AU +} + +local DEVICE_PROFILES = { + [0] = { profile = "aeotec-water-sensor-8"}, + [1] = { profile = "aeotec-water-sensor-8-smoke"}, + [2] = { profile = "aeotec-water-sensor-8-co"}, + [3] = { profile = "aeotec-water-sensor-8-co2"}, + [4] = { profile = "aeotec-water-sensor-8-contact"}, + [5] = { profile = "aeotec-water-sensor-8-contact"}, + [6] = { profile = "aeotec-water-sensor-8-motion"}, + [7] = { profile = "aeotec-water-sensor-8-glass-break"}, + [8] = { profile = "aeotec-water-sensor-8-panic"} +} + +local function can_handle_aeotec_water_sensor_8(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_WATER_SENSOR_8_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + local subdriver = require("aeotec-water-sensor-8") + return true, subdriver + end + end + return false +end + +local function set_profile(device, profile) + local current = device:get_field("active_profile") + if current ~= profile.profile then + device:try_update_metadata({ profile = profile.profile }) + device:set_field("active_profile", profile.profile) + + -- Set supported modes and default value based on profile + if profile.profile == "aeotec-water-sensor-8" then + device:emit_event(WaterSensor.water.dry()) + elseif profile.profile == "aeotec-water-sensor-8-glass-break" then + device:emit_event(SoundDetection.supportedSoundTypes({"noSound", "glassBreaking"})) + device:emit_event(SoundDetection.soundDetected.noSound()) + elseif profile.profile == "aeotec-water-sensor-8-co2" then + device:emit_event(CarbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "moderate"})) + device:emit_event(CarbonDioxideHealthConcern.carbonDioxideHealthConcern.good()) + elseif profile.profile == "aeotec-water-sensor-8-co" then + device:emit_event(CarbonMonoxideDetector.carbonMonoxide.clear()) + elseif profile.profile == "aeotec-water-sensor-8-contact" then + device:emit_event(ContactSensor.contact.closed()) + elseif profile.profile == "aeotec-water-sensor-8-motion" then + device:emit_event(MotionSensor.motion.inactive()) + elseif profile.profile == "aeotec-water-sensor-8-panic" then + device:emit_event(PanicAlarm.panicAlarm.clear()) + elseif profile.profile == "aeotec-water-sensor-8-smoke" then + device:emit_event(SmokeDetector.smoke.clear()) + end + end +end + +local function added_handler(driver, device) + -- Get parameter 10 to switch device profile bsaed on the parameter value + device:send(Configuration:Get({ parameter_number = 10 })) + + device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) + -- Default value + device:emit_event(MoldHealthConcern.moldHealthConcern.good()) + + -- Default value + device:emit_event(PowerSource.powerSource.battery()) + + device:send(Battery:Get({})) +end + +local function do_refresh(driver, device) + device:send(Battery:Get({})) +end + +local function notification_report_handler(self, device, cmd) + local active_profile = device:get_field("active_profile") + local event + local event_parameter + + if (0 ~= string.len(cmd.args.event_parameter)) then + event_parameter = string.byte(cmd.args.event_parameter) + end + + -- MOTION, GLASS_BREAK, TAMPER + if cmd.args.notification_type == Notification.notification_type.HOME_SECURITY then + -- TAMPER + if cmd.args.event == Notification.event.home_security.STATE_IDLE and event_parameter == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED then + event = TamperAlert.tamper.clear() + elseif cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED and event_parameter == Notification.event.home_security.STATE_IDLE then + event = TamperAlert.tamper.detected() + elseif active_profile == 'aeotec-water-sensor-8-motion' then -- MOTION + if cmd.args.event == Notification.event.home_security.STATE_IDLE and event_parameter == Notification.event.home_security.MOTION_DETECTION then + event = MotionSensor.motion.inactive() + elseif cmd.args.event == Notification.event.home_security.MOTION_DETECTION then + event = MotionSensor.motion.active() + end + elseif active_profile == 'aeotec-water-sensor-8-glass-break' then -- GLASS_BREAK + if cmd.args.event == Notification.event.home_security.STATE_IDLE and event_parameter == Notification.event.home_security.GLASS_BREAKAGE then + event = SoundDetection.soundDetected.noSound() + elseif cmd.args.event == Notification.event.home_security.GLASS_BREAKAGE then + event = SoundDetection.soundDetected.glassBreaking() + end + end + end + + if cmd.args.notification_type == Notification.notification_type.POWER_MANAGEMENT then + if cmd.args.event == Notification.event.power_management.AC_MAINS_DISCONNECTED then + event = PowerSource.powerSource.battery() + elseif cmd.args.event == Notification.event.power_management.AC_MAINS_RE_CONNECTED then + event = PowerSource.powerSource.dc() + elseif cmd.args.event == Notification.event.power_management.POWER_HAS_BEEN_APPLIED then + device:send(Battery:Get({})) + end + end + + -- WATER + if cmd.args.notification_type == Notification.notification_type.WATER then + if cmd.args.event == Notification.event.water.STATE_IDLE then + event = WaterSensor.water.dry() + elseif cmd.args.event == Notification.event.water.LEAK_DETECTED then + event = WaterSensor.water.wet() + end + end + + -- MOLD + if cmd.args.notification_type == Notification.notification_type.WEATHER_ALARM then + if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then + event = MoldHealthConcern.moldHealthConcern.good() + elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then + event = MoldHealthConcern.moldHealthConcern.moderate() + end + end + + -- SMOKE + if cmd.args.notification_type == Notification.notification_type.SMOKE then + if cmd.args.event == Notification.event.smoke.STATE_IDLE then + event = SmokeDetector.smoke.clear() + elseif cmd.args.event == Notification.event.smoke.DETECTED then + event = SmokeDetector.smoke.detected() + end + end + + -- CO + if cmd.args.notification_type == Notification.notification_type.CO then + if cmd.args.event == Notification.event.co.STATE_IDLE then + event = CarbonMonoxideDetector.carbonMonoxide.clear() + elseif cmd.args.event == Notification.event.co.CARBON_MONOXIDE_DETECTED then + event = CarbonMonoxideDetector.carbonMonoxide.detected() + end + end + + -- CO2 + if cmd.args.notification_type == Notification.notification_type.CO2 then + if cmd.args.event == Notification.event.co2.STATE_IDLE then + event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.good() + elseif cmd.args.event == Notification.event.co2.CARBON_DIOXIDE_DETECTED then + event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.moderate() + end + end + + -- DOOR_WINDOW/TILT + if cmd.args.notification_type == Notification.notification_type.ACCESS_CONTROL then + if cmd.args.event == Notification.event.access_control.WINDOW_DOOR_IS_CLOSED then + event = ContactSensor.contact.closed() + elseif cmd.args.event == Notification.event.access_control.WINDOW_DOOR_IS_OPEN then + event = ContactSensor.contact.open() + end + end + + -- PANIC + if cmd.args.notification_type == Notification.notification_type.EMERGENCY then + if cmd.args.event == Notification.event.emergency.STATE_IDLE then + event = PanicAlarm.panicAlarm.clear() + elseif cmd.args.event == Notification.event.emergency.PANIC_ALERT then + event = PanicAlarm.panicAlarm.panic() + end + end + + if (event ~= nil) then + device:emit_event(event) + end +end + +local function configuration_report_handler(self, device, cmd) + local param_number = cmd.args.parameter_number + local value = cmd.args.configuration_value + + if param_number == 10 then + local mapping = DEVICE_PROFILES[value] + if mapping then + set_profile(device, mapping) + end + end +end + +local aeotec_water_sensor_8 = { + supported_capabilities = { + capabilities.powerSource, + capabilities.carbonMonoxideDetector, + capabilities.carbonDioxideHealthConcern, + capabilities.soundDetection, + capabilities.panicAlarm + }, + zwave_handlers = { + [cc.CONFIGURATION] = { + [Configuration.REPORT] = configuration_report_handler + }, + [cc.NOTIFICATION] = { + [Notification.REPORT] = notification_report_handler + }, + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + lifecycle_handlers = { + added = added_handler, + }, + NAME = "Aeotec Water Sensor 8", + can_handle = can_handle_aeotec_water_sensor_8 +} + +return aeotec_water_sensor_8 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/init.lua b/drivers/SmartThings/zwave-sensor/src/init.lua index 213aa8c389..feb03115c2 100644 --- a/drivers/SmartThings/zwave-sensor/src/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/init.lua @@ -154,6 +154,9 @@ local driver_template = { lazy_load_if_possible("wakeup-no-poll"), lazy_load_if_possible("firmware-version"), lazy_load_if_possible("apiv6_bugfix"), + lazy_load_if_possible("aeotec-door-window-sensor-8"), + lazy_load_if_possible("aeotec-aerq-8"), + lazy_load_if_possible("aeotec-water-sensor-8") }, lifecycle_handlers = { added = added_handler, diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" new file mode 100644 index 0000000000..2529cb290b --- /dev/null +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" @@ -0,0 +1,293 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.SensorMultilevel +local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) +local t_utils = require "integration_test.utils" + +local sensor_endpoints = { + { + command_classes = { + {value = zw.BATTERY}, + {value = zw.NOTIFICATION}, + {value = zw.SENSOR_MULTILEVEL}, + {value = zw.CONFIGURATION} + } + } +} + +local mock_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-aerq-8.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_id = 0x0039, +}) + +local function test_init() + test.mock_device.add_test_device(mock_sensor) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "Device added lifecycle event for profile", + function() + test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "added" }) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Configuration:Get({ + parameter_number = 10 + }) + ) + ) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) + ) + + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) + ) + + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + ) + + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + ) + end +) + +test.register_message_test( + "Refresh should generate the correct commands", + { + { + channel = "capability", + direction = "receive", + message = { + mock_sensor.id, + { capability = "refresh", command = "refresh", args = {} } + } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + }, + }, + { + inner_block_ordering = "relaxed" + } +) + +test.register_message_test( + "Battery report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.battery.battery(99)) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_DISCONNECTED event should be handled power source state battery", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_DISCONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_RE_CONNECTED event should be handled power source state dc", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_RE_CONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) + } + } +) + +test.register_message_test( + "Notification report POWER_HAS_BEEN_APPLIED event should be send battery get", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.POWER_HAS_BEEN_APPLIED, + })) } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + } + } +) + +test.register_message_test( + "Temperature reports should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.TEMPERATURE, + scale = SensorMultilevel.scale.temperature.CELSIUS, + sensor_value = 21.5 })) + } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 21.5, unit = 'C' })) + }, + { + channel = "devices", + direction = "send", + message = { + "register_native_capability_attr_handler", + { device_uuid = mock_sensor.id, capability_id = "temperatureMeasurement", capability_attr_id = "temperature" } + } + } + } +) + +test.register_message_test( + "Humidity reports should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.RELATIVE_HUMIDITY, + sensor_value = 70 })) + } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70, })) + }, + } +) + +test.register_message_test( + "Sensor multilevel reports dew_point type command should be handled as dew point measurement", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.DEW_POINT, + sensor_value = 8, + scale = 0 + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.dewPoint.dewpoint({value = 8, unit = "C"})) + } + } +) + +test.register_message_test( + "Notification report type WEATHER_ALARM event STATE_IDLE should be handled mold healt concern state good", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.STATE_IDLE, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) + } + } +) + +test.register_message_test( + "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.MOISTURE_ALARM, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) + } + } +) + +test.run_registered_tests() \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua new file mode 100644 index 0000000000..44ae9f52ae --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua @@ -0,0 +1,430 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.SensorMultilevel +local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) +local t_utils = require "integration_test.utils" + +local sensor_endpoints = { + { + command_classes = { + {value = zw.BATTERY}, + {value = zw.NOTIFICATION}, + {value = zw.SENSOR_MULTILEVEL}, + {value = zw.CONFIGURATION} + } + } +} + +local mock_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-door-window-sensor-8.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_id = 0x0037, +}) + +local function test_init() + test.mock_device.add_test_device(mock_sensor) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "Device added lifecycle event for profile", + function() + test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "added" }) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Configuration:Get({ + parameter_number = 10 + }) + ) + ) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) + ) + + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) + ) + + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + ) + + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + ) + end +) + +test.register_coroutine_test( + "Device init lifecycle event", + function() + test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "init" }) + + mock_sensor:set_field("three_axis_x", 0) + mock_sensor:set_field("three_axis_y", 0) + mock_sensor:set_field("three_axis_z", 0) + end +) + +test.register_message_test( + "Refresh should generate the correct commands", + { + { + channel = "capability", + direction = "receive", + message = { + mock_sensor.id, + { capability = "refresh", command = "refresh", args = {} } + } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + }, + }, + { + inner_block_ordering = "relaxed" + } +) + +test.register_message_test( + "Notification report STATE_IDLE event should be handled as tamperAlert clear", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.STATE_IDLE, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) + } + } +) + +test.register_message_test( + "Notification report TAMPERING_PRODUCT_COVER_REMOVED event should be handled as tamperAlert detected", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.detected()) + } + } +) + +test.register_message_test( + "Battery report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.battery.battery(99)) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_DISCONNECTED event should be handled power source state battery", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_DISCONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_RE_CONNECTED event should be handled power source state dc", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_RE_CONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) + } + } +) + +test.register_message_test( + "Notification report POWER_HAS_BEEN_APPLIED event should be send battery get", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.POWER_HAS_BEEN_APPLIED, + })) } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_sensor, + Battery:Get({}) + ) + } + } +) + +test.register_message_test( + "Notification report WINDOW_DOOR_IS_OPEN event should be handled contact sensor state open", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.ACCESS_CONTROL, + event = Notification.event.access_control.WINDOW_DOOR_IS_OPEN, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.open()) + } + } +) + +test.register_message_test( + "Notification report WINDOW_DOOR_IS_CLOSED event should be handled contact sensor state closed", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.ACCESS_CONTROL, + event = Notification.event.access_control.WINDOW_DOOR_IS_CLOSED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.closed()) + } + } +) + +test.register_message_test( + "Temperature reports should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.TEMPERATURE, + scale = SensorMultilevel.scale.temperature.CELSIUS, + sensor_value = 21.5 })) + } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 21.5, unit = 'C' })) + }, + } +) + +test.register_message_test( + "Humidity reports should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.RELATIVE_HUMIDITY, + scale = SensorMultilevel.scale.relative_humidity.PERCENTAGE, + sensor_value = 70 })) + } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70, unit= '%' })) + }, + } +) + +test.register_message_test( + "Sensor multilevel reports dew_point type command should be handled as dew point measurement", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.DEW_POINT, + sensor_value = 8, + scale = 0 + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.dewPoint.dewpoint({value = 8, unit = "C"})) + } + } +) + +test.register_coroutine_test( + "Three Axis x reports should be correctly handled", + function() + test.socket.zwave:__queue_receive({ + mock_sensor.id, + SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.ACCELERATION_X_AXIS, + sensor_value = 200, + scale = SensorMultilevel.scale.acceleration_x_axis.METERS_PER_SQUARE_SECOND } + ) + }) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", + capabilities.threeAxis.threeAxis({value = {200, 0, 0}, unit = 'mG'}) + ) + ) + end +) + +test.register_coroutine_test( + "Three Axis y reports should be correctly handled", + function() + test.socket.zwave:__queue_receive({ + mock_sensor.id, + SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS, + sensor_value = 200, + scale = SensorMultilevel.scale.acceleration_y_axis.METERS_PER_SQUARE_SECOND } + ) + }) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", + capabilities.threeAxis.threeAxis({value = {0, 200, 0}, unit = 'mG'}) + ) + ) + end +) + +test.register_coroutine_test( + "Three Axis z reports should be correctly handled", + function() + test.socket.zwave:__queue_receive({ + mock_sensor.id, + SensorMultilevel:Report({ + sensor_type = SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS, + sensor_value = 400, + scale = SensorMultilevel.scale.acceleration_z_axis.METERS_PER_SQUARE_SECOND } + ) + }) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message("main", + capabilities.threeAxis.threeAxis({value = {0, 0, 400}, unit = 'mG'}) + ) + ) + end +) + +test.register_message_test( + "Notification report type WEATHER_ALARM event STATE_IDLE should be handled mold healt concern state good", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.STATE_IDLE, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) + } + } +) + +test.register_message_test( + "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", + { + { + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.MOISTURE_ALARM, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) + } + } +) + +test.run_registered_tests() \ No newline at end of file diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" new file mode 100644 index 0000000000..ca6aeb8169 --- /dev/null +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" @@ -0,0 +1,511 @@ +-- Copyright 2025 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) +--- @type st.zwave.CommandClass.Battery +local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) +local t_utils = require "integration_test.utils" + +local sensor_endpoints = { + { + command_classes = { + {value = zw.BATTERY}, + {value = zw.NOTIFICATION}, + {value = zw.SENSOR_MULTILEVEL}, + {value = zw.CONFIGURATION} + } + } +} + +local mock_water_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_co_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-co.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_co2_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-co2.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_contact_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-contact.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_glass_break_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-glass-break.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_motion_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-motion.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_panic_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-panic.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local mock_smoke_sensor = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-water-sensor-8-smoke.yml"), + zwave_endpoints = sensor_endpoints, + zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, + zwave_product_id = 0x0038, +}) + +local DEVICE_PROFILES = { + [0] = { + profile = "aeotec-water-sensor-8", + mock_device = mock_water_sensor, + default_cap = capabilities.waterSensor.water.dry(), + active_cap = capabilities.waterSensor.water.wet(), + default_cap_str = "dry", + active_cap_str = "wet", + notification_typ = Notification.notification_type.WATER, + on_event = Notification.event.water.LEAK_DETECTED, + off_event = Notification.event.water.STATE_IDLE + }, + [1] = { + profile = "aeotec-water-sensor-8-smoke", + mock_device = mock_smoke_sensor, + default_cap = capabilities.smokeDetector.smoke.clear(), + active_cap = capabilities.smokeDetector.smoke.detected(), + default_cap_str = "clear", + active_cap_str = "detected", + notification_typ = Notification.notification_type.SMOKE, + on_event = Notification.event.smoke.DETECTED, + off_event = Notification.event.smoke.STATE_IDLE + }, + [2] = { + profile = "aeotec-water-sensor-8-co", + mock_device = mock_co_sensor, + default_cap = capabilities.carbonMonoxideDetector.carbonMonoxide.clear(), + active_cap = capabilities.carbonMonoxideDetector.carbonMonoxide.detected(), + default_cap_str = "clear", + active_cap_str = "detected", + notification_typ = Notification.notification_type.CO, + on_event = Notification.event.co.CARBON_MONOXIDE_DETECTED, + off_event = Notification.event.co.STATE_IDLE + }, + [3] = { + profile = "aeotec-water-sensor-8-co2", + mock_device = mock_co2_sensor, + default_cap = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.good(), + active_cap = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.moderate(), + default_cap_str = "good", + active_cap_str = "moderate", + notification_typ = Notification.notification_type.CO2, + on_event = Notification.event.co2.CARBON_DIOXIDE_DETECTED, + off_event = Notification.event.co2.STATE_IDLE + }, + [4] = { + profile = "aeotec-water-sensor-8-contact", + mock_device = mock_contact_sensor, + default_cap = capabilities.contactSensor.contact.closed(), + active_cap = capabilities.contactSensor.contact.open(), + default_cap_str = "closed", + active_cap_str = "open", + notification_typ = Notification.notification_type.ACCESS_CONTROL, + on_event = Notification.event.access_control.WINDOW_DOOR_IS_OPEN, + off_event = Notification.event.access_control.WINDOW_DOOR_IS_CLOSED + }, + [5] = { + profile = "aeotec-water-sensor-8-contact", + mock_device = mock_contact_sensor, + default_cap = capabilities.contactSensor.contact.closed(), + active_cap = capabilities.contactSensor.contact.open(), + default_cap_str = "closed", + active_cap_str = "open", + notification_typ = Notification.notification_type.ACCESS_CONTROL, + on_event = Notification.event.access_control.WINDOW_DOOR_IS_OPEN, + off_event = Notification.event.access_control.WINDOW_DOOR_IS_CLOSED + }, + [6] = { + profile = "aeotec-water-sensor-8-motion", + mock_device = mock_motion_sensor, + default_cap = capabilities.motionSensor.motion.inactive(), + active_cap = capabilities.motionSensor.motion.active(), + default_cap_str = "inactive", + active_cap_str = "active", + notification_typ = Notification.notification_type.HOME_SECURITY, + on_event = Notification.event.home_security.MOTION_DETECTION, + off_event = Notification.event.home_security.STATE_IDLE + }, + [7] = { + profile = "aeotec-water-sensor-8-glass-break", + mock_device = mock_glass_break_sensor, + default_cap = capabilities.soundDetection.soundDetected.noSound(), + active_cap = capabilities.soundDetection.soundDetected.glassBreaking(), + default_cap_str = "noSound", + active_cap_str = "glassBreaking", + notification_typ = Notification.notification_type.HOME_SECURITY, + on_event = Notification.event.home_security.GLASS_BREAKAGE, + off_event = Notification.event.home_security.STATE_IDLE + }, + [8] = { + profile = "aeotec-water-sensor-8-panic", + mock_device = mock_panic_sensor, + default_cap = capabilities.panicAlarm.panicAlarm.clear(), + active_cap = capabilities.panicAlarm.panicAlarm.panic(), + default_cap_str = "clear", + active_cap_str = "panic", + notification_typ = Notification.notification_type.EMERGENCY, + on_event = Notification.event.emergency.PANIC_ALERT, + off_event = Notification.event.emergency.STATE_IDLE + } +} + +local function test_init() + test.mock_device.add_test_device(mock_water_sensor) + test.mock_device.add_test_device(mock_smoke_sensor) + test.mock_device.add_test_device(mock_co_sensor) + test.mock_device.add_test_device(mock_co2_sensor) + test.mock_device.add_test_device(mock_contact_sensor) + test.mock_device.add_test_device(mock_contact_sensor) + test.mock_device.add_test_device(mock_motion_sensor) + test.mock_device.add_test_device(mock_glass_break_sensor) + test.mock_device.add_test_device(mock_panic_sensor) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "Device added lifecycle event for profile", + function() + test.socket.device_lifecycle:__queue_receive({ mock_water_sensor.id, "added" }) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_water_sensor, + Configuration:Get({ + parameter_number = 10 + }) + ) + ) + test.socket.capability:__expect_send( + mock_water_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) + ) + test.socket.capability:__expect_send( + mock_water_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) + ) + test.socket.capability:__expect_send( + mock_water_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_water_sensor, + Battery:Get({}) + ) + ) + end +) + +test.register_message_test( + "Refresh should generate the correct commands", + { + { + channel = "capability", + direction = "receive", + message = { + mock_water_sensor.id, + { capability = "refresh", command = "refresh", args = {} } + } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_water_sensor, + Battery:Get({}) + ) + }, + }, + { + inner_block_ordering = "relaxed" + } +) + +test.register_message_test( + "Notification report STATE_IDLE event should be handled tamper alert state clear", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.STATE_IDLE, + event_parameter = string.char(Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED) + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) + } + } +) + +test.register_message_test( + "Notification report STATE_IDLE event should be handled tamper alert state clear", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED, + event_parameter = string.char(Notification.event.home_security.STATE_IDLE) + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.detected()) + } + } +) + +test.register_message_test( + "Battery report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.battery.battery(99)) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_DISCONNECTED event should be handled power source state battery", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_DISCONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) + } + } +) + +test.register_message_test( + "Notification report AC_MAINS_RE_CONNECTED event should be handled power source state dc", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.AC_MAINS_RE_CONNECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) + } + } +) + +test.register_message_test( + "Notification report POWER_HAS_BEEN_APPLIED event should be send battery get", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.POWER_MANAGEMENT, + event = Notification.event.power_management.POWER_HAS_BEEN_APPLIED, + })) } + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_water_sensor, + Battery:Get({}) + ) + } + } +) + +test.register_message_test( + "Notification report LEAK_DETECTED event should be handled water sensor state wet", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WATER, + event = Notification.event.water.LEAK_DETECTED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.wet()) + } + } +) + +test.register_message_test( + "Notification report STATE_IDLE event should be handled water sensor state dry", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WATER, + event = Notification.event.water.STATE_IDLE, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.dry()) + } + } +) + +for param_value, data in pairs(DEVICE_PROFILES) do + local value = param_value + local profile = data.profile + local mock_device = data.mock_device + local default_cap = data.default_cap + local active_cap = data.active_cap + local notification_type = data.notification_typ + local on_event = data.on_event + local off_event = data.off_event + + + test.register_coroutine_test( + "Profile should update when Configuration Report parameter 10 = " .. value, + function() + test.socket.zwave:__queue_receive({ + mock_device.id, + Configuration:Report({ + parameter_number = 10, + configuration_value = value + }) + }) + + test.socket.device_lifecycle:__expect_send( + mock_device:expect_metadata_update({ + profile = profile + }) + ) + + if profile == "aeotec-water-sensor-8-glass-break" then + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.soundDetection.supportedSoundTypes({"noSound", "glassBreaking"})) + ) + elseif profile == "aeotec-water-sensor-8-co2" then + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.carbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "moderate"})) + ) + end + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", default_cap) + ) + end + ) + + test.register_coroutine_test( + "Notification report type " .. notification_type .. " event ".. off_event .. " should be handled " .. data.default_cap_str, + function() + mock_device:set_field("active_profile", profile) + + test.socket.zwave:__queue_receive({ + mock_device.id, + Notification:Report({ + notification_type = notification_type, + event = off_event, + event_parameter = string.char(on_event) + }) + }) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", default_cap) + ) + end + ) + + test.register_coroutine_test( + "Notification report type " .. notification_type .. " event ".. on_event .. " should be handled " .. data.active_cap_str, + function() + mock_device:set_field("active_profile", profile) + + test.socket.zwave:__queue_receive({ + mock_device.id, + Notification:Report({ + notification_type = notification_type, + event = on_event, + }) + }) + + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", active_cap) + ) + end + ) +end + +test.run_registered_tests() \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua index 2007bedb0d..6551c773d7 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua @@ -20,22 +20,57 @@ local capabilities = require "st.capabilities" local TAMPER_TIMER = "_tamper_timer" local TAMPER_CLEAR = 10 -local FIBARO_DOOR_WINDOW_MFR_ID = 0x010F -local function can_handle_tamper_event(opts, driver, device, cmd, ...) - if device.zwave_manufacturer_id ~= FIBARO_DOOR_WINDOW_MFR_ID and - opts.dispatcher_class == "ZwaveDispatcher" and +local excluded_devices = { + FIBARO_DOOR_WINDOW = { + mfrs = 0x010F + }, + AEOTEC_AERQ_8 = { + mfrs = 0x0371, + product_ids = 0x0018 + }, + AEOTEC_DOOR_WINDOW_SENSOR_8 = { + mfrs = 0x0371, + product_ids = 0x0037 + }, + AEOTEC_WATER_SENSOR_8 = { + mfrs = 0x0371, + product_ids = 0x0038 + }, +} + +local function can_handle_tamper_event(opts, driver, zw_device, cmd, ...) + -- check only for relevant tamper event first + if not(opts.dispatcher_class == "ZwaveDispatcher" and cmd ~= nil and cmd.cmd_class ~= nil and cmd.cmd_class == cc.NOTIFICATION and cmd.cmd_id == Notification.REPORT and cmd.args.notification_type == Notification.notification_type.HOME_SECURITY and (cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED or - cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_MOVED) then - local subdriver = require("timed-tamper-clear") - return true, subdriver - else return false + cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_MOVED)) then + return false + end + + -- check exclusion list: if device matches any entry, skip auto-clear + for _, excluded_device in pairs(excluded_devices) do + local mfrs = excluded_device.mfrs + local product_types = excluded_device.product_types or nil + local product_ids = excluded_device.product_ids or nil + + if mfrs ~= nil then + if zw_device:id_match( + mfrs, + product_types, + product_ids + ) then + return false + end end + end + + local subdriver = require("timed-tamper-clear") + return true, subdriver end -- This behavior is from zwave-door-window-sensor.groovy. We've seen this behavior @@ -63,4 +98,4 @@ local timed_tamper_clear = { can_handle = can_handle_tamper_event } -return timed_tamper_clear +return timed_tamper_clear \ No newline at end of file From a59dd3e9df1903d3205a85f382a6270ca1a02a1f Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Tue, 14 Apr 2026 09:59:42 +0200 Subject: [PATCH 02/16] Update preferences.lua --- .../zwave-sensor/src/preferences.lua | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/drivers/SmartThings/zwave-sensor/src/preferences.lua b/drivers/SmartThings/zwave-sensor/src/preferences.lua index 9585b6ffe9..837cbb0d38 100644 --- a/drivers/SmartThings/zwave-sensor/src/preferences.lua +++ b/drivers/SmartThings/zwave-sensor/src/preferences.lua @@ -175,6 +175,71 @@ local devices = { lowBatteryAlert = { parameter_number = 4, size = 1 }, }, }, + AEOTEC_AERQ_8 = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = {0x0002, 0x0102, 0x0202}, + product_ids = 0x0018 + }, + PARAMETERS = { + parameter1 = {parameter_number = 1, size = 1}, + parameter2 = {parameter_number = 2, size = 1}, + parameter3 = {parameter_number = 3, size = 1}, + parameter4 = {parameter_number = 4, size = 1}, + parameter13 = {parameter_number = 13, size = 1}, + parameter23 = {parameter_number = 23, size = 1}, + parameter24 = {parameter_number = 24, size = 4}, + parameter25 = {parameter_number = 25, size = 2}, + parameter26 = {parameter_number = 26, size = 2}, + parameter64 = {parameter_number = 64, size = 1}, + } + }, + AEOTEC_DOOR_WINDOW_SENSOR_8 = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = {0x0002, 0x0102, 0x0202}, + product_ids = {0x0037} + }, + PARAMETERS = { + parameter1 = {parameter_number = 1, size = 4}, + parameter2 = {parameter_number = 2, size = 1}, + parameter3 = {parameter_number = 3, size = 1}, + parameter5 = {parameter_number = 5, size = 1}, + parameter13 = {parameter_number = 13, size = 1}, + parameter23 = {parameter_number = 23, size = 1}, + parameter24 = {parameter_number = 24, size = 4}, + parameter25 = {parameter_number = 25, size = 2}, + parameter26 = {parameter_number = 26, size = 2}, + parameter27 = {parameter_number = 27, size = 1}, + parameter28 = {parameter_number = 28, size = 1}, + parameter33 = {parameter_number = 33, size = 1}, + parameter34 = {parameter_number = 34, size = 1}, + parameter35 = {parameter_number = 35, size = 1}, + parameter36 = {parameter_number = 36, size = 1}, + parameter64 = {parameter_number = 64, size = 1}, + }, + }, + AEOTEC_WATER_SENSOR_8 = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = {0x0002, 0x0102, 0x0202}, + product_ids = {0x0038} + }, + PARAMETERS = { + parameter1 = {parameter_number = 1, size = 1}, + parameter2 = {parameter_number = 2, size = 1}, + parameter3 = {parameter_number = 3, size = 1}, + parameter4 = {parameter_number = 4, size = 1}, + parameter5 = {parameter_number = 5, size = 1}, + parameter10 = {parameter_number = 10, size = 1}, + parameter13 = {parameter_number = 13, size = 1}, + parameter23 = {parameter_number = 23, size = 1}, + parameter24 = {parameter_number = 24, size = 4}, + parameter25 = {parameter_number = 25, size = 2}, + parameter26 = {parameter_number = 26, size = 2}, + parameter64 = {parameter_number = 64, size = 1}, + }, + }, } local preferences = {} From 6645186cd1f276ecee27e85293f4f615767244b0 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 16 Apr 2026 11:26:01 +0200 Subject: [PATCH 03/16] update --- .../zwave-sensor/profiles/aeotec-aerq-8.yml | 2 +- .../profiles/aeotec-door-window-sensor-8.yml | 2 +- .../profiles/aeotec-water-sensor-8-co.yml | 0 .../profiles/aeotec-water-sensor-8-co2.yml | 0 .../zwave-sensor/src/aeotec-aerq-8/init.lua | 28 ++----------- .../src/aeotec-door-window-sensor-8/init.lua | 26 ++---------- .../src/aeotec-water-sensor-8/init.lua | 26 ++---------- .../zwave-sensor/src/preferences.lua | 21 +++------- .../test/test_aeotec_aerq_8.lua\342\200\216" | 2 +- .../test/test_aeotec_door_window_sesnor_8.lua | 42 ++----------------- ...est_aeotec_water_sensor_8.lua\342\200\216" | 42 ++----------------- 11 files changed, 23 insertions(+), 168 deletions(-) rename "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" => drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml (100%) rename "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" => drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml (100%) rename "drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" => drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua (92%) diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml index 7055dd8300..10c57a9880 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml @@ -78,7 +78,7 @@ preferences: default: 0 - name: "parameter13" title: "13 Mold alarm offset" - desccription: "Increase the humidity threshold." + description: "Increase the humidity threshold." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml index 6b7206293c..4a138d3691 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -86,7 +86,7 @@ preferences: default: 0 - name: "parameter13" title: "13 Mold alarm offset" - desccription: "Increase the humidity threshold." + description: "Increase the humidity threshold." required: false preferenceType: integer definition: diff --git "a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml similarity index 100% rename from "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml\342\200\216" rename to drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml diff --git "a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml similarity index 100% rename from "drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml\342\200\216" rename to drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua index b523b01c97..39178551e6 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass @@ -54,12 +43,6 @@ local function added_handler(driver, device) device:send(Battery:Get({})) device:register_native_capability_attr_handler("temperatureMeasurement", "temperature") - -- device:register_native_capability_attr_handler("colorControl", "hue") - -end - -local function do_refresh(driver, device) - device:send(Battery:Get({})) end local function notification_report_handler(self, device, cmd) @@ -108,11 +91,6 @@ local aeotec_aerq_8 = { [Notification.REPORT] = notification_report_handler }, }, - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh - } - }, lifecycle_handlers = { added = added_handler, }, @@ -120,4 +98,4 @@ local aeotec_aerq_8 = { can_handle = can_handle_aeotec_aerq } -return aeotec_aerq_8 \ No newline at end of file +return aeotec_aerq_8 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index 9ca600d55f..e208e26d42 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass @@ -67,10 +56,6 @@ local function device_init(driver, device) device:set_field("three_axis_z", 0) end -local function do_refresh(driver, device) - device:send(Battery:Get({})) -end - local function notification_report_handler(self, device, cmd) local event @@ -183,11 +168,6 @@ local aeotec_door_window_sensor_8 = { [SensorMultilevel.REPORT] = sensor_multilevel_report_handler } }, - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh - } - }, lifecycle_handlers = { init = device_init, added = added_handler @@ -196,4 +176,4 @@ local aeotec_door_window_sensor_8 = { can_handle = can_handle_aeotec_door_window_sensor_8 } -return aeotec_door_window_sensor_8 \ No newline at end of file +return aeotec_door_window_sensor_8 diff --git "a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua similarity index 92% rename from "drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" rename to drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua index 6fa0d3b637..eeb1c3b0bc 100644 --- "a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua\342\200\216" +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass @@ -103,10 +92,6 @@ local function added_handler(driver, device) device:send(Battery:Get({})) end -local function do_refresh(driver, device) - device:send(Battery:Get({})) -end - local function notification_report_handler(self, device, cmd) local active_profile = device:get_field("active_profile") local event @@ -244,11 +229,6 @@ local aeotec_water_sensor_8 = { [Notification.REPORT] = notification_report_handler }, }, - capability_handlers = { - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh - } - }, lifecycle_handlers = { added = added_handler, }, @@ -256,4 +236,4 @@ local aeotec_water_sensor_8 = { can_handle = can_handle_aeotec_water_sensor_8 } -return aeotec_water_sensor_8 \ No newline at end of file +return aeotec_water_sensor_8 diff --git a/drivers/SmartThings/zwave-sensor/src/preferences.lua b/drivers/SmartThings/zwave-sensor/src/preferences.lua index 837cbb0d38..7856f66be9 100644 --- a/drivers/SmartThings/zwave-sensor/src/preferences.lua +++ b/drivers/SmartThings/zwave-sensor/src/preferences.lua @@ -1,16 +1,5 @@ --- Copyright 2022 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 --- @type st.zwave.CommandClass.Configuration local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) @@ -179,10 +168,10 @@ local devices = { MATCHING_MATRIX = { mfrs = 0x0371, product_types = {0x0002, 0x0102, 0x0202}, - product_ids = 0x0018 + product_ids = 0x0039 }, PARAMETERS = { - parameter1 = {parameter_number = 1, size = 1}, + parameter1 = {parameter_number = 1, size = 4}, parameter2 = {parameter_number = 2, size = 1}, parameter3 = {parameter_number = 3, size = 1}, parameter4 = {parameter_number = 4, size = 1}, @@ -226,7 +215,7 @@ local devices = { product_ids = {0x0038} }, PARAMETERS = { - parameter1 = {parameter_number = 1, size = 1}, + parameter1 = {parameter_number = 1, size = 4}, parameter2 = {parameter_number = 2, size = 1}, parameter3 = {parameter_number = 3, size = 1}, parameter4 = {parameter_number = 4, size = 1}, diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" index 2529cb290b..21bd9ef1b0 100644 --- "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" @@ -290,4 +290,4 @@ test.register_message_test( } ) -test.run_registered_tests() \ No newline at end of file +test.run_registered_tests() diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua index 44ae9f52ae..52cb6fd9c6 100644 --- a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local test = require "integration_test" local capabilities = require "st.capabilities" @@ -95,31 +84,6 @@ test.register_coroutine_test( end ) -test.register_message_test( - "Refresh should generate the correct commands", - { - { - channel = "capability", - direction = "receive", - message = { - mock_sensor.id, - { capability = "refresh", command = "refresh", args = {} } - } - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Battery:Get({}) - ) - }, - }, - { - inner_block_ordering = "relaxed" - } -) - test.register_message_test( "Notification report STATE_IDLE event should be handled as tamperAlert clear", { @@ -427,4 +391,4 @@ test.register_message_test( } ) -test.run_registered_tests() \ No newline at end of file +test.run_registered_tests() diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" index ca6aeb8169..963e35193f 100644 --- "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local test = require "integration_test" local capabilities = require "st.capabilities" @@ -245,31 +234,6 @@ test.register_coroutine_test( end ) -test.register_message_test( - "Refresh should generate the correct commands", - { - { - channel = "capability", - direction = "receive", - message = { - mock_water_sensor.id, - { capability = "refresh", command = "refresh", args = {} } - } - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_water_sensor, - Battery:Get({}) - ) - }, - }, - { - inner_block_ordering = "relaxed" - } -) - test.register_message_test( "Notification report STATE_IDLE event should be handled tamper alert state clear", { @@ -508,4 +472,4 @@ for param_value, data in pairs(DEVICE_PROFILES) do ) end -test.run_registered_tests() \ No newline at end of file +test.run_registered_tests() From e89ca6486dcc22f0f4d06e77c0db76083bdfc28f Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 16 Apr 2026 14:07:23 +0200 Subject: [PATCH 04/16] =?UTF-8?q?Update=20test=5Faeotec=5Faerq=5F8.lua?= =?UTF-8?q?=E2=80=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/test_aeotec_aerq_8.lua\342\200\216" | 40 +------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" index 21bd9ef1b0..fcf6098ff2 100644 --- "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" @@ -1,16 +1,5 @@ --- Copyright 2025 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local test = require "integration_test" local capabilities = require "st.capabilities" @@ -84,31 +73,6 @@ test.register_coroutine_test( end ) -test.register_message_test( - "Refresh should generate the correct commands", - { - { - channel = "capability", - direction = "receive", - message = { - mock_sensor.id, - { capability = "refresh", command = "refresh", args = {} } - } - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Battery:Get({}) - ) - }, - }, - { - inner_block_ordering = "relaxed" - } -) - test.register_message_test( "Battery report should be handled", { From 7af6533ee912f183569ba710d4ff590c273f46c4 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Tue, 21 Apr 2026 10:26:14 +0200 Subject: [PATCH 05/16] fix wrong product_id for aerq 8 --- .../SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua index 6551c773d7..ed6bd0fcb8 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua @@ -27,7 +27,7 @@ local excluded_devices = { }, AEOTEC_AERQ_8 = { mfrs = 0x0371, - product_ids = 0x0018 + product_ids = 0x0039 }, AEOTEC_DOOR_WINDOW_SENSOR_8 = { mfrs = 0x0371, From d1a82adb09401b594552ddc09a967beea34baa18 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 13 May 2026 12:00:33 +0200 Subject: [PATCH 06/16] Update sub_drivers.lua --- drivers/SmartThings/zwave-sensor/src/sub_drivers.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua b/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua index 9504479304..c553c2243b 100644 --- a/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua +++ b/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua @@ -23,4 +23,7 @@ return { lazy_load_if_possible("wakeup-no-poll"), lazy_load_if_possible("firmware-version"), lazy_load_if_possible("apiv6_bugfix"), + lazy_load_if_possible("aeotec-door-window-sensor-8"), + lazy_load_if_possible("aeotec-aerq-8"), + lazy_load_if_possible("aeotec-water-sensor-8") } From d39d086f9600c32c255d37a00b94367d816cec0b Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 13 May 2026 13:22:46 +0200 Subject: [PATCH 07/16] update timed-tamper-clear --- .../src/timed-tamper-clear/can_handle.lua | 50 ++++++++++++++---- .../src/timed-tamper-clear/init.lua | 52 ------------------- 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua index c05cbdcf7d..09a2bbf9e8 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua @@ -1,23 +1,53 @@ -- Copyright 2025 SmartThings, Inc. -- Licensed under the Apache License, Version 2.0 -local function can_handle_tamper_event(opts, driver, device, cmd, ...) - local cc = require "st.zwave.CommandClass" - local Notification = (require "st.zwave.CommandClass.Notification")({ version = 4 }) - local FIBARO_DOOR_WINDOW_MFR_ID = 0x010F +local excluded_devices = { + FIBARO_DOOR_WINDOW = { + mfrs = 0x010F + }, + AEOTEC_AERQ_8 = { + mfrs = 0x0371, + product_ids = 0x0039 + }, + AEOTEC_DOOR_WINDOW_SENSOR_8 = { + mfrs = 0x0371, + product_ids = 0x0037 + }, + AEOTEC_WATER_SENSOR_8 = { + mfrs = 0x0371, + product_ids = 0x0038 + }, +} - if device.zwave_manufacturer_id ~= FIBARO_DOOR_WINDOW_MFR_ID and - opts.dispatcher_class == "ZwaveDispatcher" and +local function can_handle_tamper_event(opts, driver, zw_device, cmd, ...) + -- check only for relevant tamper event first + if not(opts.dispatcher_class == "ZwaveDispatcher" and cmd ~= nil and cmd.cmd_class ~= nil and cmd.cmd_class == cc.NOTIFICATION and cmd.cmd_id == Notification.REPORT and cmd.args.notification_type == Notification.notification_type.HOME_SECURITY and (cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED or - cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_MOVED) then - return true, require("timed-tamper-clear") - end + cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_MOVED)) then return false + end + + -- check exclusion list: if device matches any entry, skip auto-clear + for _, excluded_device in pairs(excluded_devices) do + local mfrs = excluded_device.mfrs + local product_types = excluded_device.product_types or nil + local product_ids = excluded_device.product_ids or nil + + if mfrs ~= nil then + if zw_device:id_match( + mfrs, + product_types, + product_ids + ) then + return false + end + end + end end -return can_handle_tamper_event +return can_handle_tamper_event \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua index 7eaca74f30..0af76c8593 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/init.lua @@ -12,58 +12,6 @@ local capabilities = require "st.capabilities" local TAMPER_TIMER = "_tamper_timer" local TAMPER_CLEAR = 10 -local excluded_devices = { - FIBARO_DOOR_WINDOW = { - mfrs = 0x010F - }, - AEOTEC_AERQ_8 = { - mfrs = 0x0371, - product_ids = 0x0039 - }, - AEOTEC_DOOR_WINDOW_SENSOR_8 = { - mfrs = 0x0371, - product_ids = 0x0037 - }, - AEOTEC_WATER_SENSOR_8 = { - mfrs = 0x0371, - product_ids = 0x0038 - }, -} - -local function can_handle_tamper_event(opts, driver, zw_device, cmd, ...) - -- check only for relevant tamper event first - if not(opts.dispatcher_class == "ZwaveDispatcher" and - cmd ~= nil and - cmd.cmd_class ~= nil and - cmd.cmd_class == cc.NOTIFICATION and - cmd.cmd_id == Notification.REPORT and - cmd.args.notification_type == Notification.notification_type.HOME_SECURITY and - (cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED or - cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_MOVED)) then - return false - end - - -- check exclusion list: if device matches any entry, skip auto-clear - for _, excluded_device in pairs(excluded_devices) do - local mfrs = excluded_device.mfrs - local product_types = excluded_device.product_types or nil - local product_ids = excluded_device.product_ids or nil - - if mfrs ~= nil then - if zw_device:id_match( - mfrs, - product_types, - product_ids - ) then - return false - end - end - end - - local subdriver = require("timed-tamper-clear") - return true, subdriver -end - -- This behavior is from zwave-door-window-sensor.groovy. We've seen this behavior -- in Ecolink and several other z-wave sensors that do not send tamper clear events local function handle_tamper_event(driver, device, cmd) From f8695ca028374a12b64fae17609eda3f47ffdefd Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 13 May 2026 13:26:22 +0200 Subject: [PATCH 08/16] Update can_handle.lua --- .../zwave-sensor/src/timed-tamper-clear/can_handle.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua index 09a2bbf9e8..2b7ab951a0 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua @@ -1,6 +1,11 @@ -- Copyright 2025 SmartThings, Inc. -- Licensed under the Apache License, Version 2.0 +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" +--- @type st.zwave.CommandClass.Notification +local Notification = (require "st.zwave.CommandClass.Notification")({ version = 4 }) + local excluded_devices = { FIBARO_DOOR_WINDOW = { mfrs = 0x010F From 7c9e20d894d70584a9b290b6dcbbcec51ccba465 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 29 Jul 2026 11:58:41 +0200 Subject: [PATCH 09/16] update --- .../zwave-sensor/profiles/aeotec-aerq-8.yml | 2 +- .../profiles/aeotec-door-window-sensor-8.yml | 4 +- .../profiles/aeotec-water-sensor-8-co.yml | 4 +- .../profiles/aeotec-water-sensor-8-co2.yml | 4 +- .../aeotec-water-sensor-8-contact.yml | 4 +- .../aeotec-water-sensor-8-glass-break.yml | 4 +- .../profiles/aeotec-water-sensor-8-motion.yml | 4 +- .../profiles/aeotec-water-sensor-8-panic.yml | 4 +- .../profiles/aeotec-water-sensor-8-smoke.yml | 4 +- .../profiles/aeotec-water-sensor-8.yml | 4 +- .../zwave-sensor/src/aeotec-aerq-8/init.lua | 101 ------- .../can_handle.lua | 19 ++ .../src/aeotec-door-window-sensor-8/init.lua | 16 +- .../src/aeotec-water-sensor-8/can_handle.lua | 18 ++ .../zwave-sensor/src/sub_drivers.lua | 2 - .../test/test_aeotec_aerq_8.lua\342\200\216" | 257 ------------------ .../test/test_aeotec_door_window_sesnor_8.lua | 254 ++++++++++------- ...est_aeotec_water_sensor_8.lua\342\200\216" | 152 +++++++---- .../src/timed-tamper-clear/can_handle.lua | 2 + 19 files changed, 307 insertions(+), 552 deletions(-) delete mode 100644 drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua create mode 100644 drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua create mode 100644 drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua delete mode 100644 "drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml index 10c57a9880..01559b6453 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml @@ -48,7 +48,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml index 4a138d3691..fc8fe97af5 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -56,7 +56,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -109,7 +109,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml index c13d2254fa..302e300996 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml index 36367534a6..467715a161 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml index 994cc7b4bd..f03f1b9fae 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml index 759d0d0f94..6da7037341 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml index 576253e2cb..22eeb3be2a 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml index 3aa63e911c..46ff2c8675 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml index a6686b6b57..a0ab1d01df 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml index 717b2c8ce0..a1f8a54f23 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml @@ -50,7 +50,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 900 - name: "parameter2" title: "2 Min. temperature change to report" @@ -130,7 +130,7 @@ preferences: preferenceType: integer definition: minimum: 0 - maximum: 2678400 + maximum: 65535 default: 43200 - name: "parameter25" title: "25 Offset value for temperature" diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua deleted file mode 100644 index 39178551e6..0000000000 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-aerq-8/init.lua +++ /dev/null @@ -1,101 +0,0 @@ --- Copyright 2025 SmartThings, Inc. --- Licensed under the Apache License, Version 2.0 - -local capabilities = require "st.capabilities" ---- @type st.zwave.CommandClass -local cc = require "st.zwave.CommandClass" ---- @type st.zwave.CommandClass.Notification -local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) ---- @type st.zwave.CommandClass.Battery -local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) ---- @type st.zwave.CommandClass.Configuration -local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) - -local MoldHealthConcern = capabilities.moldHealthConcern -local PowerSource = capabilities.powerSource -local TamperAlert = capabilities.tamperAlert - -local AEOTEC_AERQ_FINGERPRINTS = { - { manufacturerId = 0x0371, productId = 0x0039 } -- Aeotec aerQ 8 EU/US/AU -} - -local function can_handle_aeotec_aerq(opts, driver, device, ...) - for _, fingerprint in ipairs(AEOTEC_AERQ_FINGERPRINTS) do - if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then - local subdriver = require("aeotec-aerq-8") - return true, subdriver - end - end - return false -end - -local function added_handler(driver, device) - device:send(Configuration:Get({ parameter_number = 10 })) - - device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) - - -- Default value - device:emit_event(MoldHealthConcern.moldHealthConcern.good()) - - -- Default value - device:emit_event(PowerSource.powerSource.battery()) - - device:send(Battery:Get({})) - - device:register_native_capability_attr_handler("temperatureMeasurement", "temperature") -end - -local function notification_report_handler(self, device, cmd) - local event - - -- POWER - if cmd.args.notification_type == Notification.notification_type.POWER_MANAGEMENT then - if cmd.args.event == Notification.event.power_management.AC_MAINS_DISCONNECTED then - event = capabilities.powerSource.powerSource.battery() - elseif cmd.args.event == Notification.event.power_management.AC_MAINS_RE_CONNECTED then - event = capabilities.powerSource.powerSource.dc() - elseif cmd.args.event == Notification.event.power_management.POWER_HAS_BEEN_APPLIED then - device:send(Battery:Get({})) - end - end - - -- MOLD - if cmd.args.notification_type == Notification.notification_type.WEATHER_ALARM then - if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then - event = MoldHealthConcern.moldHealthConcern.good() - elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then - event = MoldHealthConcern.moldHealthConcern.moderate() - end - end - - -- TAMPER - if cmd.args.notification_type == Notification.notification_type.HOME_SECURITY then - if cmd.args.event == Notification.event.home_security.STATE_IDLE then - event = TamperAlert.tamper.clear() - elseif cmd.args.event == Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED then - event = TamperAlert.tamper.detected() - end - end - - if (event ~= nil) then - device:emit_event(event) - end -end - -local aeotec_aerq_8 = { - supported_capabilities = { - capabilities.powerSource - }, - zwave_handlers = { - [cc.NOTIFICATION] = { - [Notification.REPORT] = notification_report_handler - }, - }, - lifecycle_handlers = { - added = added_handler, - }, - NAME = "Aeotec aerQ 8", - can_handle = can_handle_aeotec_aerq -} - -return aeotec_aerq_8 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua new file mode 100644 index 0000000000..c593063faf --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua @@ -0,0 +1,19 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS = { + { manufacturerId = 0x0371, productId = 0x0037 }, -- Aeotec Door Window Sensor 8 EU/US/AU + { manufacturerId = 0x0371, productId = 0x0039 } -- Aeotec Aerq 8 EU/US/AU +} + +local function can_handle_aeotec_door_window_sensor_8(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + local subdriver = require("aeotec-door-window-sensor-8") + return true, subdriver + end + end + return false +end + +return can_handle_aeotec_door_window_sensor_8 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index e208e26d42..a30e37a986 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -22,20 +22,6 @@ local TemperatureMeasurement = capabilities.temperatureMeasurement local RelativeHumidityMeasurement = capabilities.relativeHumidityMeasurement local DewPoint = capabilities.dewPoint -local AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS = { - { manufacturerId = 0x0371, productId = 0x0037 } -- Aeotec Door Window Sensor 8 EU/US/AU -} - -local function can_handle_aeotec_door_window_sensor_8(opts, driver, device, ...) - for _, fingerprint in ipairs(AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS) do - if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then - local subdriver = require("aeotec-door-window-sensor-8") - return true, subdriver - end - end - return false -end - local function added_handler(driver, device) device:send(Configuration:Get({ parameter_number = 10 })) @@ -173,7 +159,7 @@ local aeotec_door_window_sensor_8 = { added = added_handler }, NAME = "Aeotec Door Window Sensor 8", - can_handle = can_handle_aeotec_door_window_sensor_8 + can_handle = require("aeotec-door-window-sensor-8.can_handle"), } return aeotec_door_window_sensor_8 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua new file mode 100644 index 0000000000..ede9f0cd14 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua @@ -0,0 +1,18 @@ +-- Copyright 2025 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 + +local AEOTEC_WATER_SENSOR_8_FINGERPRINTS = { + { manufacturerId = 0x0371, productId = 0x0038 } -- Aeotec Water Sensor 8 EU/US/AU +} + +local function can_handle_aeotec_water_sensor_8(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_WATER_SENSOR_8_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + local subdriver = require("aeotec-water-sensor-8") + return true, subdriver + end + end + return false +end + +return can_handle_aeotec_water_sensor_8 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua b/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua index c553c2243b..167a68ad8d 100644 --- a/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua +++ b/drivers/SmartThings/zwave-sensor/src/sub_drivers.lua @@ -22,8 +22,6 @@ return { lazy_load_if_possible("timed-tamper-clear"), lazy_load_if_possible("wakeup-no-poll"), lazy_load_if_possible("firmware-version"), - lazy_load_if_possible("apiv6_bugfix"), lazy_load_if_possible("aeotec-door-window-sensor-8"), - lazy_load_if_possible("aeotec-aerq-8"), lazy_load_if_possible("aeotec-water-sensor-8") } diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" deleted file mode 100644 index fcf6098ff2..0000000000 --- "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_aerq_8.lua\342\200\216" +++ /dev/null @@ -1,257 +0,0 @@ --- Copyright 2025 SmartThings, Inc. --- Licensed under the Apache License, Version 2.0 - -local test = require "integration_test" -local capabilities = require "st.capabilities" -local zw = require "st.zwave" -local zw_test_utils = require "integration_test.zwave_test_utils" ---- @type st.zwave.CommandClass.Notification -local Notification = (require "st.zwave.CommandClass.Notification")({ version = 3 }) ---- @type st.zwave.CommandClass.Battery -local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) ---- @type st.zwave.CommandClass.SensorMultilevel -local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) ---- @type st.zwave.CommandClass.Configuration -local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) -local t_utils = require "integration_test.utils" - -local sensor_endpoints = { - { - command_classes = { - {value = zw.BATTERY}, - {value = zw.NOTIFICATION}, - {value = zw.SENSOR_MULTILEVEL}, - {value = zw.CONFIGURATION} - } - } -} - -local mock_sensor = test.mock_device.build_test_zwave_device({ - profile = t_utils.get_profile_definition("aeotec-aerq-8.yml"), - zwave_endpoints = sensor_endpoints, - zwave_manufacturer_id = 0x0371, - zwave_product_id = 0x0039, -}) - -local function test_init() - test.mock_device.add_test_device(mock_sensor) -end - -test.set_test_init_function(test_init) - -test.register_coroutine_test( - "Device added lifecycle event for profile", - function() - test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "added" }) - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Configuration:Get({ - parameter_number = 10 - }) - ) - ) - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) - ) - - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) - ) - - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) - ) - - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Battery:Get({}) - ) - ) - end -) - -test.register_message_test( - "Battery report should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.battery.battery(99)) - } - } -) - -test.register_message_test( - "Notification report AC_MAINS_DISCONNECTED event should be handled power source state battery", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.POWER_MANAGEMENT, - event = Notification.event.power_management.AC_MAINS_DISCONNECTED, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) - } - } -) - -test.register_message_test( - "Notification report AC_MAINS_RE_CONNECTED event should be handled power source state dc", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.POWER_MANAGEMENT, - event = Notification.event.power_management.AC_MAINS_RE_CONNECTED, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) - } - } -) - -test.register_message_test( - "Notification report POWER_HAS_BEEN_APPLIED event should be send battery get", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.POWER_MANAGEMENT, - event = Notification.event.power_management.POWER_HAS_BEEN_APPLIED, - })) } - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Battery:Get({}) - ) - } - } -) - -test.register_message_test( - "Temperature reports should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.TEMPERATURE, - scale = SensorMultilevel.scale.temperature.CELSIUS, - sensor_value = 21.5 })) - } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 21.5, unit = 'C' })) - }, - { - channel = "devices", - direction = "send", - message = { - "register_native_capability_attr_handler", - { device_uuid = mock_sensor.id, capability_id = "temperatureMeasurement", capability_attr_id = "temperature" } - } - } - } -) - -test.register_message_test( - "Humidity reports should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.RELATIVE_HUMIDITY, - sensor_value = 70 })) - } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70, })) - }, - } -) - -test.register_message_test( - "Sensor multilevel reports dew_point type command should be handled as dew point measurement", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.DEW_POINT, - sensor_value = 8, - scale = 0 - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.dewPoint.dewpoint({value = 8, unit = "C"})) - } - } -) - -test.register_message_test( - "Notification report type WEATHER_ALARM event STATE_IDLE should be handled mold healt concern state good", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WEATHER_ALARM, - event = Notification.event.weather_alarm.STATE_IDLE, - }))} - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) - } - } -) - -test.register_message_test( - "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", - { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WEATHER_ALARM, - event = Notification.event.weather_alarm.MOISTURE_ALARM, - }))} - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) - } - } -) - -test.run_registered_tests() diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua index 52cb6fd9c6..ab2a0c44ae 100644 --- a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua @@ -70,7 +70,10 @@ test.register_coroutine_test( Battery:Get({}) ) ) - end + end, + { + min_api_version = 17 + } ) test.register_coroutine_test( @@ -81,61 +84,73 @@ test.register_coroutine_test( mock_sensor:set_field("three_axis_x", 0) mock_sensor:set_field("three_axis_y", 0) mock_sensor:set_field("three_axis_z", 0) - end + end, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report STATE_IDLE event should be handled as tamperAlert clear", + "Notification report STATE_IDLE event should be handled as tamperAlert clear", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.HOME_SECURITY, - event = Notification.event.home_security.STATE_IDLE, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.STATE_IDLE, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report TAMPERING_PRODUCT_COVER_REMOVED event should be handled as tamperAlert detected", + "Notification report TAMPERING_PRODUCT_COVER_REMOVED event should be handled as tamperAlert detected", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.HOME_SECURITY, - event = Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.detected()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.detected()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( - "Battery report should be handled", + "Battery report should be handled", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.battery.battery(99)) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.battery.battery(99)) } + }, + { + min_api_version = 17 + } ) test.register_message_test( @@ -154,6 +169,9 @@ test.register_message_test( direction = "send", message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) } + }, + { + min_api_version = 17 } ) @@ -173,6 +191,9 @@ test.register_message_test( direction = "send", message = mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) } + }, + { + min_api_version = 17 } ) @@ -195,45 +216,54 @@ test.register_message_test( Battery:Get({}) ) } + }, + { + min_api_version = 17 } ) test.register_message_test( - "Notification report WINDOW_DOOR_IS_OPEN event should be handled contact sensor state open", + "Notification report WINDOW_DOOR_IS_OPEN event should be handled contact sensor state open", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.ACCESS_CONTROL, - event = Notification.event.access_control.WINDOW_DOOR_IS_OPEN, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.open()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.ACCESS_CONTROL, + event = Notification.event.access_control.WINDOW_DOOR_IS_OPEN, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.open()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report WINDOW_DOOR_IS_CLOSED event should be handled contact sensor state closed", + "Notification report WINDOW_DOOR_IS_CLOSED event should be handled contact sensor state closed", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.ACCESS_CONTROL, - event = Notification.event.access_control.WINDOW_DOOR_IS_CLOSED, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.closed()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.ACCESS_CONTROL, + event = Notification.event.access_control.WINDOW_DOOR_IS_CLOSED, + })) } + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.contactSensor.contact.closed()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( @@ -253,6 +283,9 @@ test.register_message_test( direction = "send", message = mock_sensor:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 21.5, unit = 'C' })) }, + }, + { + min_api_version = 17 } ) @@ -273,6 +306,9 @@ test.register_message_test( direction = "send", message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70, unit= '%' })) }, + }, + { + min_api_version = 17 } ) @@ -293,6 +329,9 @@ test.register_message_test( direction = "send", message = mock_sensor:generate_test_message("main", capabilities.dewPoint.dewpoint({value = 8, unit = "C"})) } + }, + { + min_api_version = 17 } ) @@ -312,7 +351,10 @@ test.register_coroutine_test( capabilities.threeAxis.threeAxis({value = {200, 0, 0}, unit = 'mG'}) ) ) - end + end, + { + min_api_version = 17 + } ) test.register_coroutine_test( @@ -331,7 +373,10 @@ test.register_coroutine_test( capabilities.threeAxis.threeAxis({value = {0, 200, 0}, unit = 'mG'}) ) ) - end + end, + { + min_api_version = 17 + } ) test.register_coroutine_test( @@ -350,45 +395,54 @@ test.register_coroutine_test( capabilities.threeAxis.threeAxis({value = {0, 0, 400}, unit = 'mG'}) ) ) - end + end, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report type WEATHER_ALARM event STATE_IDLE should be handled mold healt concern state good", + "Notification report type WEATHER_ALARM event STATE_IDLE should be handled mold healt concern state good", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WEATHER_ALARM, - event = Notification.event.weather_alarm.STATE_IDLE, - }))} - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.STATE_IDLE, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", + "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", + { { - { - channel = "zwave", - direction = "receive", - message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WEATHER_ALARM, - event = Notification.event.weather_alarm.MOISTURE_ALARM, - }))} - }, - { - channel = "capability", - direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) - } + channel = "zwave", + direction = "receive", + message = { mock_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WEATHER_ALARM, + event = Notification.event.weather_alarm.MOISTURE_ALARM, + }))} + }, + { + channel = "capability", + direction = "send", + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) } + }, + { + min_api_version = 17 + } ) test.run_registered_tests() diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" index 963e35193f..4c0533ecfb 100644 --- "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" +++ "b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" @@ -231,27 +231,33 @@ test.register_coroutine_test( Battery:Get({}) ) ) - end + end, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report STATE_IDLE event should be handled tamper alert state clear", + "Notification report STATE_IDLE event should be handled tamper alert state clear", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.HOME_SECURITY, + event = Notification.event.home_security.STATE_IDLE, + event_parameter = string.char(Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED) + })) } + }, { - { - channel = "zwave", - direction = "receive", - message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.HOME_SECURITY, - event = Notification.event.home_security.STATE_IDLE, - event_parameter = string.char(Notification.event.home_security.TAMPERING_PRODUCT_COVER_REMOVED) - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_water_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) - } + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.clear()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( @@ -271,23 +277,29 @@ test.register_message_test( direction = "send", message = mock_water_sensor:generate_test_message("main", capabilities.tamperAlert.tamper.detected()) } + }, + { + min_api_version = 17 } ) test.register_message_test( - "Battery report should be handled", + "Battery report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } + }, { - { - channel = "zwave", - direction = "receive", - message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Battery:Report({ battery_level = 0x63 })) } - }, - { - channel = "capability", - direction = "send", - message = mock_water_sensor:generate_test_message("main", capabilities.battery.battery(99)) - } + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.battery.battery(99)) } + }, + { + min_api_version = 17 + } ) test.register_message_test( @@ -306,6 +318,9 @@ test.register_message_test( direction = "send", message = mock_water_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) } + }, + { + min_api_version = 17 } ) @@ -325,6 +340,9 @@ test.register_message_test( direction = "send", message = mock_water_sensor:generate_test_message("main", capabilities.powerSource.powerSource.dc()) } + }, + { + min_api_version = 17 } ) @@ -347,45 +365,54 @@ test.register_message_test( Battery:Get({}) ) } + }, + { + min_api_version = 17 } ) test.register_message_test( - "Notification report LEAK_DETECTED event should be handled water sensor state wet", + "Notification report LEAK_DETECTED event should be handled water sensor state wet", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WATER, + event = Notification.event.water.LEAK_DETECTED, + })) } + }, { - { - channel = "zwave", - direction = "receive", - message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WATER, - event = Notification.event.water.LEAK_DETECTED, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.wet()) - } + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.wet()) } + }, + { + min_api_version = 17 + } ) test.register_message_test( - "Notification report STATE_IDLE event should be handled water sensor state dry", + "Notification report STATE_IDLE event should be handled water sensor state dry", + { + { + channel = "zwave", + direction = "receive", + message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ + notification_type = Notification.notification_type.WATER, + event = Notification.event.water.STATE_IDLE, + })) } + }, { - { - channel = "zwave", - direction = "receive", - message = { mock_water_sensor.id, zw_test_utils.zwave_test_build_receive_command(Notification:Report({ - notification_type = Notification.notification_type.WATER, - event = Notification.event.water.STATE_IDLE, - })) } - }, - { - channel = "capability", - direction = "send", - message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.dry()) - } + channel = "capability", + direction = "send", + message = mock_water_sensor:generate_test_message("main", capabilities.waterSensor.water.dry()) } + }, + { + min_api_version = 17 + } ) for param_value, data in pairs(DEVICE_PROFILES) do @@ -429,7 +456,10 @@ for param_value, data in pairs(DEVICE_PROFILES) do test.socket.capability:__expect_send( mock_device:generate_test_message("main", default_cap) ) - end + end, + { + min_api_version = 17 + } ) test.register_coroutine_test( @@ -449,7 +479,10 @@ for param_value, data in pairs(DEVICE_PROFILES) do test.socket.capability:__expect_send( mock_device:generate_test_message("main", default_cap) ) - end + end, + { + min_api_version = 17 + } ) test.register_coroutine_test( @@ -468,7 +501,10 @@ for param_value, data in pairs(DEVICE_PROFILES) do test.socket.capability:__expect_send( mock_device:generate_test_message("main", active_cap) ) - end + end, + { + min_api_version = 17 + } ) end diff --git a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua index 2b7ab951a0..bc523dc6a0 100644 --- a/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua +++ b/drivers/SmartThings/zwave-sensor/src/timed-tamper-clear/can_handle.lua @@ -53,6 +53,8 @@ local function can_handle_tamper_event(opts, driver, zw_device, cmd, ...) end end end + + return true, require("timed-tamper-clear") end return can_handle_tamper_event \ No newline at end of file From 4bf323fcbba346c901a17a183cde783c1964a391 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 29 Jul 2026 12:16:53 +0200 Subject: [PATCH 10/16] update water sensor 8 category --- .../zwave-sensor/profiles/aeotec-door-window-sensor-8.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml index fc8fe97af5..1007fa1002 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -42,8 +42,8 @@ components: version: 1 - id: refresh version: 1 -categories: - - name: ContactSensor + categories: + - name: ContactSensor metadata: deviceType: ContactSensor ocfDeviceType: x.com.st.d.sensor.contact From bfb66dbac4c82d386b78f896e798dd1faae44eae Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Mon, 10 Aug 2026 10:43:07 +0200 Subject: [PATCH 11/16] fixes --- .../aeotec-door-window-sensor-8/can_handle.lua | 4 ++-- .../src/aeotec-door-window-sensor-8/init.lua | 2 -- .../src/aeotec-water-sensor-8/init.lua | 18 ++---------------- .../zwave-sensor/src/preferences.lua | 2 +- ...ua => test_aeotec_door_window_sensor_8.lua} | 0 .../src/test/test_aeotec_water_sensor_8.lua | 0 6 files changed, 5 insertions(+), 21 deletions(-) rename drivers/SmartThings/zwave-sensor/src/test/{test_aeotec_door_window_sesnor_8.lua => test_aeotec_door_window_sensor_8.lua} (100%) rename "drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" => drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua (100%) diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua index c593063faf..34b3e3336b 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/can_handle.lua @@ -3,7 +3,7 @@ local AEOTEC_DOOR_WINDOW_SENSOR_8_FINGERPRINTS = { { manufacturerId = 0x0371, productId = 0x0037 }, -- Aeotec Door Window Sensor 8 EU/US/AU - { manufacturerId = 0x0371, productId = 0x0039 } -- Aeotec Aerq 8 EU/US/AU + { manufacturerId = 0x0371, productId = 0x0039 } -- Aeotec Aerq 8 EU/US/AU } local function can_handle_aeotec_door_window_sensor_8(opts, driver, device, ...) @@ -16,4 +16,4 @@ local function can_handle_aeotec_door_window_sensor_8(opts, driver, device, ...) return false end -return can_handle_aeotec_door_window_sensor_8 \ No newline at end of file +return can_handle_aeotec_door_window_sensor_8 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index a30e37a986..07b6689824 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -23,8 +23,6 @@ local RelativeHumidityMeasurement = capabilities.relativeHumidityMeasurement local DewPoint = capabilities.dewPoint local function added_handler(driver, device) - device:send(Configuration:Get({ parameter_number = 10 })) - device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) -- Default value diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua index eeb1c3b0bc..5118b5ba74 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua @@ -23,10 +23,6 @@ local PowerSource = capabilities.powerSource local ContactSensor = capabilities.contactSensor local PanicAlarm = capabilities.panicAlarm -local AEOTEC_WATER_SENSOR_8_FINGERPRINTS = { - { manufacturerId = 0x0371, productId = 0x0038 } -- Aeotec Water Sensor 8 EU/US/AU -} - local DEVICE_PROFILES = { [0] = { profile = "aeotec-water-sensor-8"}, [1] = { profile = "aeotec-water-sensor-8-smoke"}, @@ -39,21 +35,11 @@ local DEVICE_PROFILES = { [8] = { profile = "aeotec-water-sensor-8-panic"} } -local function can_handle_aeotec_water_sensor_8(opts, driver, device, ...) - for _, fingerprint in ipairs(AEOTEC_WATER_SENSOR_8_FINGERPRINTS) do - if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then - local subdriver = require("aeotec-water-sensor-8") - return true, subdriver - end - end - return false -end - local function set_profile(device, profile) local current = device:get_field("active_profile") if current ~= profile.profile then device:try_update_metadata({ profile = profile.profile }) - device:set_field("active_profile", profile.profile) + device:set_field("active_profile", profile.profile, {persist = true}) -- Set supported modes and default value based on profile if profile.profile == "aeotec-water-sensor-8" then @@ -233,7 +219,7 @@ local aeotec_water_sensor_8 = { added = added_handler, }, NAME = "Aeotec Water Sensor 8", - can_handle = can_handle_aeotec_water_sensor_8 + can_handle = require("aeotec-water-sensor-8.can_handle"), } return aeotec_water_sensor_8 diff --git a/drivers/SmartThings/zwave-sensor/src/preferences.lua b/drivers/SmartThings/zwave-sensor/src/preferences.lua index 5c4fac22cb..9da9450f40 100644 --- a/drivers/SmartThings/zwave-sensor/src/preferences.lua +++ b/drivers/SmartThings/zwave-sensor/src/preferences.lua @@ -184,7 +184,7 @@ local devices = { parameter64 = {parameter_number = 64, size = 1}, } }, - AEOTEC_DOOR_WINDOW_SENSOR_8 = { + AEOTEC_DOOR_WINDOW_SENSOR_8 = { MATCHING_MATRIX = { mfrs = 0x0371, product_types = {0x0002, 0x0102, 0x0202}, diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua similarity index 100% rename from drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sesnor_8.lua rename to drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua diff --git "a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua similarity index 100% rename from "drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua\342\200\216" rename to drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua From 70a38a8567a0afea600698a76ab0578d4488df45 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Mon, 10 Aug 2026 10:46:35 +0200 Subject: [PATCH 12/16] Update init.lua --- .../zwave-sensor/src/aeotec-door-window-sensor-8/init.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index 07b6689824..74cbeaf1e2 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -10,8 +10,6 @@ local Notification = (require "st.zwave.CommandClass.Notification")({ version = local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) --- @type st.zwave.CommandClass.SensorMultilevel local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) ---- @type st.zwave.CommandClass.Configuration -local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) local MoldHealthConcern = capabilities.moldHealthConcern local ContactSensor = capabilities.contactSensor From 7ec69723a97d34a4dd98abae449cefbe7a371ce9 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Mon, 10 Aug 2026 11:13:59 +0200 Subject: [PATCH 13/16] Update test_aeotec_door_window_sensor_8.lua --- .../src/test/test_aeotec_door_window_sensor_8.lua | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua index ab2a0c44ae..39d3faccd6 100644 --- a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua @@ -11,8 +11,6 @@ local Notification = (require "st.zwave.CommandClass.Notification")({ version = local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) --- @type st.zwave.CommandClass.SensorMultilevel local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) ---- @type st.zwave.CommandClass.Configuration -local Configuration = (require "st.zwave.CommandClass.Configuration")({ version = 4 }) local t_utils = require "integration_test.utils" local sensor_endpoints = { @@ -21,7 +19,6 @@ local sensor_endpoints = { {value = zw.BATTERY}, {value = zw.NOTIFICATION}, {value = zw.SENSOR_MULTILEVEL}, - {value = zw.CONFIGURATION} } } } @@ -43,14 +40,6 @@ test.register_coroutine_test( "Device added lifecycle event for profile", function() test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "added" }) - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_sensor, - Configuration:Get({ - parameter_number = 10 - }) - ) - ) test.socket.capability:__expect_send( mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) ) From e1705ad2f7bb22b3b5fe7cec499cebf4ff429d08 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 12 Aug 2026 16:32:47 +0200 Subject: [PATCH 14/16] Add a new line to all new profiles --- drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml | 2 +- .../zwave-sensor/profiles/aeotec-door-window-sensor-8.yml | 3 ++- .../zwave-sensor/profiles/aeotec-water-sensor-8-co.yml | 2 +- .../zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml | 2 +- .../zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml | 2 +- .../profiles/aeotec-water-sensor-8-glass-break.yml | 2 +- .../zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml | 2 +- .../zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml | 2 +- .../zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml index 01559b6453..797df3b09c 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml @@ -130,4 +130,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml index 1007fa1002..c5084c184f 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -194,4 +194,5 @@ preferences: definition: options: 0: "Celsius" - 1: "Fahrenheit" \ No newline at end of file + 1: "Fahrenheit" + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml index 302e300996..84d3d386e8 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml index 467715a161..3895ec0754 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml index f03f1b9fae..6e651eebfd 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml index 6da7037341..8146a336fc 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml index 22eeb3be2a..6e376c12d1 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml index 46ff2c8675..99e7e4d29c 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml index a0ab1d01df..ad6a6ba020 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 From 99596b24123a2efaf34a009d02f2a52c545f3190 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 16 Sep 2026 10:40:18 +0200 Subject: [PATCH 15/16] change moldHealthConcern and carbonDioxideHealthConcern from moderate to unhealthy --- .../zwave-sensor/src/aeotec-door-window-sensor-8/init.lua | 4 ++-- .../zwave-sensor/src/aeotec-water-sensor-8/init.lua | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index 74cbeaf1e2..9f8c2d7606 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -21,7 +21,7 @@ local RelativeHumidityMeasurement = capabilities.relativeHumidityMeasurement local DewPoint = capabilities.dewPoint local function added_handler(driver, device) - device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) + device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "unhealthy"})) -- Default value device:emit_event(MoldHealthConcern.moldHealthConcern.good()) @@ -66,7 +66,7 @@ local function notification_report_handler(self, device, cmd) if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then event = MoldHealthConcern.moldHealthConcern.good() elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then - event = MoldHealthConcern.moldHealthConcern.moderate() + event = MoldHealthConcern.moldHealthConcern.unhealthy() end end diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua index 5118b5ba74..6875c4f89c 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua @@ -48,7 +48,7 @@ local function set_profile(device, profile) device:emit_event(SoundDetection.supportedSoundTypes({"noSound", "glassBreaking"})) device:emit_event(SoundDetection.soundDetected.noSound()) elseif profile.profile == "aeotec-water-sensor-8-co2" then - device:emit_event(CarbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "moderate"})) + device:emit_event(CarbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "unhealthy"})) device:emit_event(CarbonDioxideHealthConcern.carbonDioxideHealthConcern.good()) elseif profile.profile == "aeotec-water-sensor-8-co" then device:emit_event(CarbonMonoxideDetector.carbonMonoxide.clear()) @@ -68,7 +68,7 @@ local function added_handler(driver, device) -- Get parameter 10 to switch device profile bsaed on the parameter value device:send(Configuration:Get({ parameter_number = 10 })) - device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "moderate"})) + device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "unhealthy"})) -- Default value device:emit_event(MoldHealthConcern.moldHealthConcern.good()) @@ -133,7 +133,7 @@ local function notification_report_handler(self, device, cmd) if cmd.args.event == Notification.event.weather_alarm.STATE_IDLE then event = MoldHealthConcern.moldHealthConcern.good() elseif cmd.args.event == Notification.event.weather_alarm.MOISTURE_ALARM then - event = MoldHealthConcern.moldHealthConcern.moderate() + event = MoldHealthConcern.moldHealthConcern.unhealthy() end end @@ -160,7 +160,7 @@ local function notification_report_handler(self, device, cmd) if cmd.args.event == Notification.event.co2.STATE_IDLE then event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.good() elseif cmd.args.event == Notification.event.co2.CARBON_DIOXIDE_DETECTED then - event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.moderate() + event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.unhealthy() end end From 0523723097664180bc484bb52d687af2027863b9 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 30 Sep 2026 15:26:11 +0200 Subject: [PATCH 16/16] update --- .../zwave-sensor/profiles/aeotec-aerq-8.yml | 4 +- .../profiles/aeotec-door-window-sensor-8.yml | 4 +- .../profiles/aeotec-water-sensor-8-co.yml | 6 +- .../profiles/aeotec-water-sensor-8-co2.yml | 6 +- .../aeotec-water-sensor-8-contact.yml | 6 +- .../aeotec-water-sensor-8-glass-break.yml | 6 +- .../profiles/aeotec-water-sensor-8-motion.yml | 6 +- .../profiles/aeotec-water-sensor-8-panic.yml | 6 +- .../profiles/aeotec-water-sensor-8-smoke.yml | 4 +- .../profiles/aeotec-water-sensor-8.yml | 8 +- .../src/aeotec-door-window-sensor-8/init.lua | 109 +++++++++--------- .../src/aeotec-water-sensor-8/can_handle.lua | 2 +- .../src/aeotec-water-sensor-8/init.lua | 8 +- .../test/test_aeotec_door_window_sensor_8.lua | 105 +++++++---------- .../src/test/test_aeotec_water_sensor_8.lua | 9 +- 15 files changed, 133 insertions(+), 156 deletions(-) diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml index 797df3b09c..8c4bf3c594 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-aerq-8.yml @@ -22,7 +22,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy version: 1 - id: tamperAlert version: 1 @@ -105,7 +105,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml index c5084c184f..6c6afdd6ca 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-door-window-sensor-8.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -179,7 +179,7 @@ preferences: default: 8 - name: "parameter36" title: "36 Min. acc. change to report" - description: "Minimum acceleration change to trigger report" + description: "Minimum acceleration change to trigger report." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml index 84d3d386e8..43f09c4400 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml index 3895ec0754..718d781fb3 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-co2.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml index 6e651eebfd..5677d6a6ce 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-contact.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml index 8146a336fc..ea0c23f435 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-glass-break.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml index 6e376c12d1..4b16ecf135 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-motion.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml index 99e7e4d29c..9c4fb503aa 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-panic.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml index ad6a6ba020..45274bc132 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8-smoke.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: diff --git a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml index a1f8a54f23..2b8d601d08 100644 --- a/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml +++ b/drivers/SmartThings/zwave-sensor/profiles/aeotec-water-sensor-8.yml @@ -25,7 +25,7 @@ components: - key: "moldHealthConcern.value" enabledValues: - good - - moderate + - unhealthy - id: tamperAlert version: 1 - id: powerSource @@ -80,7 +80,7 @@ preferences: default: 0 - name: "parameter5" title: "5 Dry contact sensor polarity" - description: "This parameter allows to set the states of alarm when the dry contact is closed" + description: "This parameter allows to set the states of alarm when the dry contact is closed." required: false preferenceType: enumeration definition: @@ -134,7 +134,7 @@ preferences: default: 43200 - name: "parameter25" title: "25 Offset value for temperature" - description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F" + description: "Calibrate temperature. Scale is defined by Param 64 .eg: Value 15 means 1.5°C or 1.5F." required: false preferenceType: integer definition: @@ -159,4 +159,4 @@ preferences: options: 0: "Celsius" 1: "Fahrenheit" - default: 0 \ No newline at end of file + default: 0 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua index 9f8c2d7606..d1b124d0ad 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-door-window-sensor-8/init.lua @@ -11,14 +11,19 @@ local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) --- @type st.zwave.CommandClass.SensorMultilevel local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 11 }) +local utils = require "st.utils" + +local TemperatureDefaults = require "st.zwave.defaults.temperatureMeasurement" +local HumidityDefaults = require "st.zwave.defaults.relativeHumidityMeasurement" +local DewPointDefaults = require "st.zwave.defaults.dewPoint" + local MoldHealthConcern = capabilities.moldHealthConcern local ContactSensor = capabilities.contactSensor local PowerSource = capabilities.powerSource local ThreeAxis = capabilities.threeAxis local TamperAlert = capabilities.tamperAlert -local TemperatureMeasurement = capabilities.temperatureMeasurement -local RelativeHumidityMeasurement = capabilities.relativeHumidityMeasurement -local DewPoint = capabilities.dewPoint + +local ACCELERATION_VECTOR_FIELD = "accelerationVector" local function added_handler(driver, device) device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "unhealthy"})) @@ -32,12 +37,6 @@ local function added_handler(driver, device) device:send(Battery:Get({})) end -local function device_init(driver, device) - device:set_field("three_axis_x", 0) - device:set_field("three_axis_y", 0) - device:set_field("three_axis_z", 0) -end - local function notification_report_handler(self, device, cmd) local event @@ -84,63 +83,66 @@ local function notification_report_handler(self, device, cmd) end end -local function sensor_multilevel_report_handler(self, device, cmd) - local event +local function custom_three_axis_report_handler(self, device, cmd) local sensor_type = cmd.args.sensor_type - local value = cmd.args.sensor_value - - local x = device:get_field("three_axis_x") or 0 - local y = device:get_field("three_axis_y") or 0 - local z = device:get_field("three_axis_z") or 0 - - local MIN_VAL = -10000 - local MAX_VAL = 10000 - value = math.max(MIN_VAL, math.min(MAX_VAL, value)) - - if (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_X_AXIS) then - x = value - device:set_field("three_axis_x", x) - event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) - elseif (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS) then - y = value - device:set_field("three_axis_y", y) - event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) - elseif (sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS) then - z = value - device:set_field("three_axis_z", z) - event = ThreeAxis.threeAxis({value = {x, y, z}, unit = 'mG'}) + local axis + + if sensor_type == SensorMultilevel.sensor_type.ACCELERATION_X_AXIS then + axis = "X" + elseif sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS then + axis = "Y" + elseif sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS then + axis = "Z" + else + return end - if (sensor_type == SensorMultilevel.sensor_type.TEMPERATURE) then - local scale = 'C' - if (SensorMultilevel.scale.temperature.FAHRENHEIT == cmd.args.scale) then - scale = 'F' - end - event = TemperatureMeasurement.temperature({value = value, unit = scale}) + local value = cmd.args.sensor_value + if value == nil then + return end - if (sensor_type == SensorMultilevel.sensor_type.RELATIVE_HUMIDITY) then - event = RelativeHumidityMeasurement.humidity({value = value, unit = "%"}) - end + -- Z-Wave: m/s²; SmartThings threeAxis: mG + local mg = utils.round(value / 9.81 * 1000) + mg = math.max(-10000, math.min(10000, mg)) - if (sensor_type == SensorMultilevel.sensor_type.DEW_POINT) then - local scale = 'C' - if (SensorMultilevel.scale.dew_point.FAHRENHEIT == cmd.args.scale) then - scale = 'F' - end - event = DewPoint.dewpoint({value = value, unit = scale}) + local vector = device:get_field(ACCELERATION_VECTOR_FIELD) or {} + vector[axis] = mg + device:set_field(ACCELERATION_VECTOR_FIELD, vector, { persist = true }) + + if vector.X ~= nil and vector.Y ~= nil and vector.Z ~= nil then + device:emit_event(ThreeAxis.threeAxis({ + value = { vector.X, vector.Y, vector.Z }, + unit = "mG" + })) end +end - if (event ~= nil) then - device:emit_event(event) - return; +local function sensor_multilevel_report_handler(self, device, cmd) + local sensor_type = cmd.args.sensor_type + + if sensor_type == SensorMultilevel.sensor_type.TEMPERATURE then + TemperatureDefaults.zwave_handlers[cc.SENSOR_MULTILEVEL][SensorMultilevel.REPORT]( + self, device, cmd + ) + elseif sensor_type == SensorMultilevel.sensor_type.RELATIVE_HUMIDITY then + HumidityDefaults.zwave_handlers[cc.SENSOR_MULTILEVEL][SensorMultilevel.REPORT]( + self, device, cmd + ) + elseif sensor_type == SensorMultilevel.sensor_type.DEW_POINT then + DewPointDefaults.zwave_handlers[cc.SENSOR_MULTILEVEL][SensorMultilevel.REPORT]( + self, device, cmd + ) + elseif sensor_type == SensorMultilevel.sensor_type.ACCELERATION_X_AXIS + or sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS + or sensor_type == SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS then + custom_three_axis_report_handler(self, device, cmd) end end local aeotec_door_window_sensor_8 = { supported_capabilities = { - capabilities.powerSource, - capabilities.threeAxis, + capabilities.powerSource }, zwave_handlers = { [cc.NOTIFICATION] = { @@ -151,7 +153,6 @@ local aeotec_door_window_sensor_8 = { } }, lifecycle_handlers = { - init = device_init, added = added_handler }, NAME = "Aeotec Door Window Sensor 8", diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua index ede9f0cd14..4aceab1d99 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/can_handle.lua @@ -15,4 +15,4 @@ local function can_handle_aeotec_water_sensor_8(opts, driver, device, ...) return false end -return can_handle_aeotec_water_sensor_8 \ No newline at end of file +return can_handle_aeotec_water_sensor_8 diff --git a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua index 6875c4f89c..cd3f325878 100644 --- a/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/aeotec-water-sensor-8/init.lua @@ -65,7 +65,7 @@ local function set_profile(device, profile) end local function added_handler(driver, device) - -- Get parameter 10 to switch device profile bsaed on the parameter value + -- Get parameter 10 to switch device profile based on the parameter value device:send(Configuration:Get({ parameter_number = 10 })) device:emit_event(MoldHealthConcern.supportedMoldValues({"good", "unhealthy"})) @@ -83,7 +83,7 @@ local function notification_report_handler(self, device, cmd) local event local event_parameter - if (0 ~= string.len(cmd.args.event_parameter)) then + if (cmd.args.event_parameter ~= nil and 0 ~= string.len(cmd.args.event_parameter)) then event_parameter = string.byte(cmd.args.event_parameter) end @@ -158,9 +158,9 @@ local function notification_report_handler(self, device, cmd) -- CO2 if cmd.args.notification_type == Notification.notification_type.CO2 then if cmd.args.event == Notification.event.co2.STATE_IDLE then - event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.good() + event = CarbonDioxideHealthConcern.carbonDioxideHealthConcern.good() elseif cmd.args.event == Notification.event.co2.CARBON_DIOXIDE_DETECTED then - event = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.unhealthy() + event = CarbonDioxideHealthConcern.carbonDioxideHealthConcern.unhealthy() end end diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua index 39d3faccd6..5b01d14e88 100644 --- a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_door_window_sensor_8.lua @@ -27,6 +27,7 @@ local mock_sensor = test.mock_device.build_test_zwave_device({ profile = t_utils.get_profile_definition("aeotec-door-window-sensor-8.yml"), zwave_endpoints = sensor_endpoints, zwave_manufacturer_id = 0x0371, + zwave_product_type = 0x0002, zwave_product_id = 0x0037, }) @@ -41,7 +42,7 @@ test.register_coroutine_test( function() test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "added" }) test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) + mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "unhealthy"})) ) test.socket.capability:__expect_send( @@ -52,7 +53,6 @@ test.register_coroutine_test( mock_sensor:generate_test_message("main", capabilities.powerSource.powerSource.battery()) ) - test.socket.zwave:__expect_send( zw_test_utils.zwave_test_build_send_command( mock_sensor, @@ -69,10 +69,6 @@ test.register_coroutine_test( "Device init lifecycle event", function() test.socket.device_lifecycle:__queue_receive({ mock_sensor.id, "init" }) - - mock_sensor:set_field("three_axis_x", 0) - mock_sensor:set_field("three_axis_y", 0) - mock_sensor:set_field("three_axis_z", 0) end, { min_api_version = 17 @@ -293,7 +289,7 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70, unit= '%' })) + message = mock_sensor:generate_test_message("main", capabilities.relativeHumidityMeasurement.humidity({ value = 70 })) }, }, { @@ -325,65 +321,46 @@ test.register_message_test( ) test.register_coroutine_test( - "Three Axis x reports should be correctly handled", + "Three Axis reports are converted, clamped and combined", function() - test.socket.zwave:__queue_receive({ - mock_sensor.id, - SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.ACCELERATION_X_AXIS, - sensor_value = 200, - scale = SensorMultilevel.scale.acceleration_x_axis.METERS_PER_SQUARE_SECOND } - ) - }) - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", - capabilities.threeAxis.threeAxis({value = {200, 0, 0}, unit = 'mG'}) - ) - ) - end, - { - min_api_version = 17 - } -) + local function receive_axis(sensor_type, value) + test.socket.zwave:__queue_receive({ + mock_sensor.id, + zw_test_utils.zwave_test_build_receive_command( + SensorMultilevel:Report({ + sensor_type = sensor_type, + sensor_value = value, + scale = 0 + }) + ) + }) + end -test.register_coroutine_test( - "Three Axis y reports should be correctly handled", - function() - test.socket.zwave:__queue_receive({ - mock_sensor.id, - SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS, - sensor_value = 200, - scale = SensorMultilevel.scale.acceleration_y_axis.METERS_PER_SQUARE_SECOND } - ) - }) - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", - capabilities.threeAxis.threeAxis({value = {0, 200, 0}, unit = 'mG'}) + local function expect_vector(x, y, z) + test.socket.capability:__expect_send( + mock_sensor:generate_test_message( + "main", + capabilities.threeAxis.threeAxis({ + value = { x, y, z }, + unit = "mG" + }) + ) ) - ) - end, - { - min_api_version = 17 - } -) + end -test.register_coroutine_test( - "Three Axis z reports should be correctly handled", - function() - test.socket.zwave:__queue_receive({ - mock_sensor.id, - SensorMultilevel:Report({ - sensor_type = SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS, - sensor_value = 400, - scale = SensorMultilevel.scale.acceleration_z_axis.METERS_PER_SQUARE_SECOND } - ) - }) - test.socket.capability:__expect_send( - mock_sensor:generate_test_message("main", - capabilities.threeAxis.threeAxis({value = {0, 0, 400}, unit = 'mG'}) - ) - ) + -- X: 9,81 m/s² -> 1000 mG. Noch kein vollständiger Vektor. + receive_axis(SensorMultilevel.sensor_type.ACCELERATION_X_AXIS, 9.81) + + -- Y: -9,81 m/s² -> -1000 mG. Noch kein vollständiger Vektor. + receive_axis(SensorMultilevel.sensor_type.ACCELERATION_Y_AXIS, -9.81) + + -- Z: 120 m/s² -> über 10000 mG -> auf 10000 begrenzt. + receive_axis(SensorMultilevel.sensor_type.ACCELERATION_Z_AXIS, 120) + expect_vector(1000, -1000, 10000) + + -- Ein neuer X-Report sendet einen Vektor mit den zuletzt bekannten Y/Z. + receive_axis(SensorMultilevel.sensor_type.ACCELERATION_X_AXIS, -120) + expect_vector(-10000, -1000, 10000) end, { min_api_version = 17 @@ -413,7 +390,7 @@ test.register_message_test( ) test.register_message_test( - "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state moderate", + "Notification report type WEATHER_ALARM event MOISTURE_ALARM should be handled mold healt concern state unhealthy", { { channel = "zwave", @@ -426,7 +403,7 @@ test.register_message_test( { channel = "capability", direction = "send", - message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.moderate()) + message = mock_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.unhealthy()) } }, { diff --git a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua index 4c0533ecfb..14c7d24080 100644 --- a/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua +++ b/drivers/SmartThings/zwave-sensor/src/test/test_aeotec_water_sensor_8.lua @@ -126,9 +126,9 @@ local DEVICE_PROFILES = { profile = "aeotec-water-sensor-8-co2", mock_device = mock_co2_sensor, default_cap = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.good(), - active_cap = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.moderate(), + active_cap = capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern.unhealthy(), default_cap_str = "good", - active_cap_str = "moderate", + active_cap_str = "unhealthy", notification_typ = Notification.notification_type.CO2, on_event = Notification.event.co2.CARBON_DIOXIDE_DETECTED, off_event = Notification.event.co2.STATE_IDLE @@ -196,7 +196,6 @@ local function test_init() test.mock_device.add_test_device(mock_co_sensor) test.mock_device.add_test_device(mock_co2_sensor) test.mock_device.add_test_device(mock_contact_sensor) - test.mock_device.add_test_device(mock_contact_sensor) test.mock_device.add_test_device(mock_motion_sensor) test.mock_device.add_test_device(mock_glass_break_sensor) test.mock_device.add_test_device(mock_panic_sensor) @@ -217,7 +216,7 @@ test.register_coroutine_test( ) ) test.socket.capability:__expect_send( - mock_water_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "moderate"})) + mock_water_sensor:generate_test_message("main", capabilities.moldHealthConcern.supportedMoldValues({"good", "unhealthy"})) ) test.socket.capability:__expect_send( mock_water_sensor:generate_test_message("main", capabilities.moldHealthConcern.moldHealthConcern.good()) @@ -449,7 +448,7 @@ for param_value, data in pairs(DEVICE_PROFILES) do ) elseif profile == "aeotec-water-sensor-8-co2" then test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.carbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "moderate"})) + mock_device:generate_test_message("main", capabilities.carbonDioxideHealthConcern.supportedCarbonDioxideValues({"good", "unhealthy"})) ) end