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/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 = {} 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