diff --git a/drivers/SmartThings/zwave-sensor/fingerprints.yml b/drivers/SmartThings/zwave-sensor/fingerprints.yml index 727f02a2d6..3f536bfe3b 100644 --- a/drivers/SmartThings/zwave-sensor/fingerprints.yml +++ b/drivers/SmartThings/zwave-sensor/fingerprints.yml @@ -548,6 +548,13 @@ zwaveManufacturer: productType: 0x0100 productId: 0x0082 deviceProfileName: shelly-wave-motion + - id: shelly/wave/door/window + deviceLabel: Shelly Wave Door/Window + manufacturerId: 0x0460 + productType: 0x0100 + productId: 0x0081 + deviceProfileName: shelly-wave-door-window-sensor + zwaveGeneric: - id: "GenericSensorAlarm" deviceLabel: Z-Wave Sensor diff --git a/drivers/SmartThings/zwave-sensor/profiles/shelly-wave-door-window-sensor.yml b/drivers/SmartThings/zwave-sensor/profiles/shelly-wave-door-window-sensor.yml new file mode 100644 index 0000000000..b19ef1d47e --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/profiles/shelly-wave-door-window-sensor.yml @@ -0,0 +1,29 @@ +name: shelly-wave-door-window-sensor +components: +- id: main + capabilities: + - id: contactSensor + version: 1 + - id: illuminanceMeasurement + version: 1 + config: + values: + - key: "illuminance.value" + range: [0, 10000] + - id: battery + version: 1 + - id: refresh + version: 1 + categories: + - name: ContactSensor +preferences: + - name: "ledOpnClsChangeStat" + title: "P157: open/close change status" + description: "This parameter enables open/close status change by LED indicator." + required: false + preferenceType: enumeration + definition: + options: + 0 : "LED ind.disabled" + 1 : "LED ind.enabled" + default: 0 \ 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 d92a09fe56..64287ab54c 100644 --- a/drivers/SmartThings/zwave-sensor/src/init.lua +++ b/drivers/SmartThings/zwave-sensor/src/init.lua @@ -153,6 +153,7 @@ local driver_template = { lazy_load_if_possible("timed-tamper-clear"), lazy_load_if_possible("wakeup-no-poll"), lazy_load_if_possible("apiv6_bugfix"), + lazy_load_if_possible("shelly-wave-door-window-sensor"), }, lifecycle_handlers = { added = added_handler, diff --git a/drivers/SmartThings/zwave-sensor/src/preferences.lua b/drivers/SmartThings/zwave-sensor/src/preferences.lua index 4921a996bf..7b326496d3 100644 --- a/drivers/SmartThings/zwave-sensor/src/preferences.lua +++ b/drivers/SmartThings/zwave-sensor/src/preferences.lua @@ -162,6 +162,16 @@ local devices = { motionNotdetRepT = {parameter_number = 160, size = 2}, }, }, + SHELLY_WAVE_DOOR_WINDOW_SENSOR = { + MATCHING_MATRIX = { + mfrs = 0x0460, + product_types = 0x0100, + product_ids = {0x0081} + }, + PARAMETERS = { + ledOpnClsChangeStat = {parameter_number = 157, size = 1}, + }, + }, } local preferences = {} diff --git a/drivers/SmartThings/zwave-sensor/src/shelly-wave-door-window-sensor/init.lua b/drivers/SmartThings/zwave-sensor/src/shelly-wave-door-window-sensor/init.lua new file mode 100644 index 0000000000..c0e5e100e5 --- /dev/null +++ b/drivers/SmartThings/zwave-sensor/src/shelly-wave-door-window-sensor/init.lua @@ -0,0 +1,90 @@ +-- 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.SensorMultilevel +local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 5 }) + +local WAVE_DOOR_WINDOW_SENSOR_FINGERPRINTS = { + { manufacturerId = 0x0460, prod = 0x0100, productId = 0x0081 } -- Wave Door/Window sensor +} + +--- Determine whether the passed device is Wave Door/Window sensor +--- +--- @param driver Driver driver instance +--- @param device Device device isntance +--- @return boolean true if the device proper, else false +local function can_handle_wave_door_window_sensor(opts, driver, device, ...) + for _, fingerprint in ipairs(WAVE_DOOR_WINDOW_SENSOR_FINGERPRINTS) do + if device:id_match(fingerprint.manufacturerId, fingerprint.productType, fingerprint.productId) then + return true + end + end + return false +end + +--- Handler for notification report command class +--- +--- @param self st.zwave.Driver +--- @param device st.zwave.Device +--- @param cmd st.zwave.CommandClass.Notification.Report +local function notification_report_handler(self, device, cmd) + local notificationType = cmd.args.notification_type + local event = cmd.args.event + if cmd.args.notification_type == Notification.notification_type.ACCESS_CONTROL then + if cmd.args.event == Notification.event.home_security.ACCESS_CONTROL then + event = cmd.args.notification_status == 0 and capabilities.contactSensor.contact.closed() or capabilities.contactSensor.contact.open() + elseif notificationType == Notification.notification_type.ACCESS_CONTROL then + if event == Notification.event.access_control.WINDOW_DOOR_IS_OPEN then + device:emit_event(capabilities.contactSensor.contact.open()) + elseif event == Notification.event.access_control.WINDOW_DOOR_IS_CLOSED then + device:emit_event(capabilities.contactSensor.contact.closed()) + end + end + end + if (event ~= nil) then + device:emit_event(event) + end +end + +--- Handler for multilevel sensor report command class +--- @param self st.zwave.Driver +--- @param device st.zwave.Device +--- @param cmd st.zwave.CommandClass.SensorMultilevel.Report +local function sensor_multilevel_report_handler(self, device, cmd) + if cmd.args.sensor_type == SensorMultilevel.sensor_type.LUMINANCE then + device:emit_event(capabilities.illuminanceMeasurement.illuminance({value = cmd.args.sensor_value, unit = "lux"})) + elseif cmd.args.sensor_type == SensorMultilevel.sensor_type.DIRECTION then + device:emit_event(capabilities.relativeHumidityMeasurement.humidity({value = cmd.args.sensor_value, unit = "%"})) + end +end + +local wave_door_window_sensor = { + zwave_handlers = { + [cc.NOTIFICATION] = { + [Notification.REPORT] = notification_report_handler + }, + [cc.SENSOR_MULTILEVEL] = { + [SensorMultilevel.REPORT] = sensor_multilevel_report_handler + } + }, + NAME = "shelly wave door window sensor", + can_handle = can_handle_wave_door_window_sensor +} + +return wave_door_window_sensor \ No newline at end of file