From 666c6f09dfacf1238d88437131c499dce19f603c Mon Sep 17 00:00:00 2001 From: Steven Green Date: Thu, 24 Jul 2025 15:40:48 -0700 Subject: [PATCH 1/6] CHAD-15784 Zigbee: WindowShadePreset capability updates --- .gitignore | 1 + .../src/axis/axis_version/init.lua | 4 +- .../zigbee-window-treatment/src/axis/init.lua | 4 +- .../src/feibit/init.lua | 4 +- .../src/hanssem/init.lua | 4 +- .../zigbee-window-treatment/src/init.lua | 18 +++++++++ .../src/invert-lift-percentage/init.lua | 6 +-- .../src/screen-innovations/init.lua | 6 +-- .../src/somfy/init.lua | 4 +- .../src/test/test_zigbee_window_treatment.lua | 37 ++++++++++++++++++- .../test_zigbee_window_treatment_feibit.lua | 22 ++++++++++- .../src/vimar/init.lua | 4 +- .../src/window_shade_utils.lua | 27 ++++++++++++++ .../src/yoolax/init.lua | 4 +- .../src/test/test_fibaro_roller_shutter.lua | 2 +- .../src/test/test_qubino_flush_shutter.lua | 2 +- .../test_zwave_iblinds_window_treatment.lua | 8 ++-- .../test_zwave_springs_window_treatment.lua | 2 +- .../src/test/test_zwave_window_treatment.lua | 2 +- .../tuya-zigbee/src/curtain/init.lua | 5 ++- 20 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua diff --git a/.gitignore b/.gitignore index ea01709e90..c5bbdc6f99 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ lua_libs-api_* tools/test_output/* tools/coverage_output/* .DS_Store +.venv/ diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/axis_version/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/axis_version/init.lua index 1bc09cbb6b..c0682d73c0 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/axis_version/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/axis_version/init.lua @@ -13,7 +13,7 @@ -- limitations under the License. local capabilities = require "st.capabilities" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local utils = require "st.utils" @@ -52,7 +52,7 @@ local function window_shade_level_cmd_handler(driver, device, command) end local function window_shade_preset_cmd(driver, device, command) - local level = device.preferences and device.preferences.presetPosition or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) window_shade_set_level(device, command, level) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua index acd67d2d32..a47de06df7 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua @@ -14,7 +14,7 @@ local capabilities = require "st.capabilities" local device_management = require "st.zigbee.device_management" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local utils = require "st.utils" @@ -50,7 +50,7 @@ local function window_shade_level_cmd_handler(driver, device, command) end local function window_shade_preset_cmd(driver, device, command) - local level = device.preferences and device.preferences.presetPosition or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) window_shade_set_level(device, command, level) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/feibit/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/feibit/init.lua index 0c1d20be11..f33bf81cbd 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/feibit/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/feibit/init.lua @@ -14,7 +14,7 @@ local capabilities = require "st.capabilities" local zcl_clusters = require "st.zigbee.zcl.clusters" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local window_shade_defaults = require "st.zigbee.defaults.windowShade_defaults" local device_management = require "st.zigbee.device_management" local Level = zcl_clusters.Level @@ -50,7 +50,7 @@ local function level_attr_handler(driver, device, value, zb_rx) end local function window_shade_preset_cmd(driver, device, command) - local level = device.preferences.presetPosition or device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) set_shade_level(device, level, command.component) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua index bc974706b6..be956d79b2 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua @@ -16,7 +16,7 @@ local Messages = require "st.zigbee.messages" local data_types = require "st.zigbee.data_types" local ZigbeeConstants = require "st.zigbee.constants" local generic_body = require "st.zigbee.generic_body" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local TUYA_CLUSTER = 0xEF00 local DP_TYPE_VALUE = "\x02" @@ -148,7 +148,7 @@ local function SetShadeLevelHandler(driver, device, capability_command) end local function PresetPositionHandler(driver, device, capability_command) - local level = device.preferences.presetPosition or device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, capability_command.component) SetShadeLevelHandler(driver, device, {args = { shadeLevel = level }}) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/init.lua index fc3535c043..92076d9456 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/init.lua @@ -15,6 +15,23 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" + +local function init_handler(self, device) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + + local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) + if preset_position == nil and device.preferences ~= nil and device.preferences.presetPosition ~= nil then + preset_position = device.preferences.presetPosition + device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, device.preferences.presetPosition, {persist = true}) + end + + if preset_position ~= nil then + device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) + end + end +end local function added_handler(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false }})) @@ -40,6 +57,7 @@ local zigbee_window_treatment_driver_template = { require("hanssem"), require("screen-innovations")}, lifecycle_handlers = { + init = init_handler, added = added_handler }, health_check = false, diff --git a/drivers/SmartThings/zigbee-window-treatment/src/invert-lift-percentage/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/invert-lift-percentage/init.lua index 62c3afc7eb..19532bc847 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/invert-lift-percentage/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/invert-lift-percentage/init.lua @@ -14,6 +14,7 @@ local capabilities = require "st.capabilities" local zcl_clusters = require "st.zigbee.zcl.clusters" +local window_shade_utils = require "window_shade_utils" local WindowCovering = zcl_clusters.WindowCovering @@ -75,9 +76,8 @@ local function window_shade_level_cmd(driver, device, command) end local function window_shade_preset_cmd(driver, device, command) - if device.preferences ~= nil and device.preferences.presetPosition ~= nil then - set_shade_level(device, device.preferences.presetPosition, command) - end + local level = window_shade_utils.get_preset_level(device, command.component) + set_shade_level(device, level, command) end local ikea_window_treatment = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua index 11d4ff17f9..868e92af56 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua @@ -15,7 +15,7 @@ -- require st provided libraries local capabilities = require "st.capabilities" local clusters = require "st.zigbee.zcl.clusters" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local device_management = require "st.zigbee.device_management" local utils = require "st.utils" @@ -52,9 +52,9 @@ end -- this is window_shade_preset_cmd local function window_shade_preset_cmd(driver, device, command) - local go_to_level = device.preferences.presetPosition or device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) -- send levels without inverting as: 0% closed (i.e., open) to 100% closed - device:send_to_component(command.component, WindowCovering.server.commands.GoToLiftPercentage(device, go_to_level)) + device:send_to_component(command.component, WindowCovering.server.commands.GoToLiftPercentage(device, level)) end -- this is device_added diff --git a/drivers/SmartThings/zigbee-window-treatment/src/somfy/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/somfy/init.lua index c90a0c833a..ffc9541b64 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/somfy/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/somfy/init.lua @@ -14,7 +14,7 @@ local capabilities = require "st.capabilities" local utils = require "st.utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local WindowCovering = zcl_clusters.WindowCovering @@ -109,7 +109,7 @@ local function window_shade_level_cmd(driver, device, command) end local function window_shade_preset_cmd(driver, device, command) - local level = device.preferences.presetPosition or device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) command.args.shadeLevel = level window_shade_level_cmd(driver, device, command) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua index b177eaacec..6a93845752 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua @@ -219,7 +219,42 @@ test.register_message_test( mock_device.id, clusters.WindowCovering.server.commands.GoToLiftPercentage(mock_device, 50) } - } + }, + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { + capability = "windowShadePreset", component = "main", + command = "setPresetPosition", args = {20} + } + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.windowShadePreset.position(20)) + }, + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + { + capability = "windowShadePreset", component = "main", + command = "presetPosition", args = {} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + clusters.WindowCovering.server.commands.GoToLiftPercentage(mock_device, 20) + } + }, } ) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua index 747895e515..25b3685ec0 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua @@ -267,7 +267,16 @@ test.register_coroutine_test( test.register_coroutine_test( "windowShadePreset capability should be handled with preset value = 1 ", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 1}})) + test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 10}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {1} } + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(1)) + ) test.wait_for_events() test.socket.capability:__queue_receive( { @@ -285,7 +294,16 @@ test.register_coroutine_test( test.register_coroutine_test( "windowShadePreset capability should be handled with a positive preset value of < 1", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 0}})) + test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 1}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {0} } + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(0)) + ) test.wait_for_events() test.socket.capability:__queue_receive( { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua index 6d2d6bb11d..b1a5db22a0 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua @@ -14,7 +14,7 @@ local capabilities = require "st.capabilities" local utils = require "st.utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local WindowCovering = zcl_clusters.WindowCovering local windowShade = capabilities.windowShade.windowShade @@ -124,7 +124,7 @@ end -- COMMAND HANDLER for PresetPosition local function window_shade_preset_handler(driver, device, command) - local level = device.preferences.presetPosition or device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or window_preset_defaults.PRESET_LEVEL + local level = window_shade_utils.get_preset_level(device, command.component) command.args.shadeLevel = level window_shade_set_level_handler(driver, device, command) end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua b/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua new file mode 100644 index 0000000000..1970587d24 --- /dev/null +++ b/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua @@ -0,0 +1,27 @@ +-- 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 window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" + +local utils = {} + +utils.get_preset_level = function(device, component) + local level = device:get_latest_state(component, "windowShadePreset", "position") or + device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + (device.preferences ~= nil and device.preferences.presetPosition) or + window_preset_defaults.PRESET_LEVEL + + return level +end + +return utils \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-window-treatment/src/yoolax/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/yoolax/init.lua index d98924f54a..46cb33fed2 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/yoolax/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/yoolax/init.lua @@ -17,6 +17,7 @@ local zcl_clusters = require "st.zigbee.zcl.clusters" local zcl_global_commands = require "st.zigbee.zcl.global_commands" local Status = require "st.zigbee.generated.types.ZclStatus" local WindowCovering = zcl_clusters.WindowCovering +local window_shade_utils = require "window_shade_utils" local device_management = require "st.zigbee.device_management" @@ -79,7 +80,8 @@ local function window_shade_level_cmd(driver, device, command) end local function window_shade_preset_cmd(driver, device, command) - set_shade_level(driver, device, device.preferences.presetPosition, command) + local level = window_shade_utils.get_preset_level(device, command.component) + set_shade_level(driver, device, level, command) end local function set_window_shade_level(level) diff --git a/drivers/SmartThings/zwave-window-treatment/src/test/test_fibaro_roller_shutter.lua b/drivers/SmartThings/zwave-window-treatment/src/test/test_fibaro_roller_shutter.lua index 9c800e7070..9c879806f6 100644 --- a/drivers/SmartThings/zwave-window-treatment/src/test/test_fibaro_roller_shutter.lua +++ b/drivers/SmartThings/zwave-window-treatment/src/test/test_fibaro_roller_shutter.lua @@ -303,7 +303,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_fibaro_roller_shutter.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.zwave:__expect_send( diff --git a/drivers/SmartThings/zwave-window-treatment/src/test/test_qubino_flush_shutter.lua b/drivers/SmartThings/zwave-window-treatment/src/test/test_qubino_flush_shutter.lua index ce5ed9fb81..5431ed1e70 100644 --- a/drivers/SmartThings/zwave-window-treatment/src/test/test_qubino_flush_shutter.lua +++ b/drivers/SmartThings/zwave-window-treatment/src/test/test_qubino_flush_shutter.lua @@ -233,7 +233,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_qubino_flush_shutter.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.zwave:__expect_send( diff --git a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_iblinds_window_treatment.lua b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_iblinds_window_treatment.lua index bdc41956ec..f1a841c626 100644 --- a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_iblinds_window_treatment.lua +++ b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_iblinds_window_treatment.lua @@ -214,7 +214,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_blind.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.capability:__expect_send( @@ -251,7 +251,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_blind.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.capability:__expect_send( @@ -374,7 +374,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_blind_v3.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.capability:__expect_send( @@ -415,7 +415,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_blind_v3.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.capability:__expect_send( diff --git a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_springs_window_treatment.lua b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_springs_window_treatment.lua index 4335ae3b41..0b2d209f2a 100644 --- a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_springs_window_treatment.lua +++ b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_springs_window_treatment.lua @@ -48,7 +48,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_springs_window_fashion_shade.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.zwave:__expect_send( diff --git a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_window_treatment.lua b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_window_treatment.lua index bf60c1797b..bc3a087093 100644 --- a/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_window_treatment.lua +++ b/drivers/SmartThings/zwave-window-treatment/src/test/test_zwave_window_treatment.lua @@ -304,7 +304,7 @@ test.register_coroutine_test( test.socket.capability:__queue_receive( { mock_window_shade_switch_multilevel.id, - { capability = "windowShadePreset", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) test.socket.zwave:__expect_send( diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index 1eb2e94340..0449ea9f83 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -97,7 +97,10 @@ local function window_shade_level(driver, device, command) end local function window_shade_preset(driver, device) - local level = device.preferences and device.preferences.presetPosition or window_preset_defaults.PRESET_LEVEL + local level = device:get_latest_state("main", "windowShadePreset", "position") or + device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + (device.preferences ~= nil and device.preferences.presetPosition) or + window_preset_defaults.PRESET_LEVEL tuya_utils.send_tuya_command(device, '\x02', tuya_utils.DP_TYPE_VALUE, '\x00\x00'..string.pack(">I2", level), packet_id) packet_id = increase_packet_id(packet_id) end From 0a6bba4bba146fbd94cfe57431a520e58cb77e6f Mon Sep 17 00:00:00 2001 From: Steven Green Date: Fri, 25 Jul 2025 11:57:01 -0700 Subject: [PATCH 2/6] update init and added handlers, tests --- .../src/aqara/curtain-driver-e1/init.lua | 3 + .../src/aqara/init.lua | 3 + .../src/aqara/roller-shade/init.lua | 3 + .../zigbee-window-treatment/src/axis/init.lua | 3 + .../src/hanssem/init.lua | 3 + .../zigbee-window-treatment/src/init.lua | 19 ++++--- .../src/screen-innovations/init.lua | 3 + .../test_zigbee_window_shade_battery_ikea.lua | 17 +++++- ...est_zigbee_window_shade_battery_yoolax.lua | 12 +++- .../src/test/test_zigbee_window_treatment.lua | 21 ++++++- .../test_zigbee_window_treatment_axis.lua | 32 ++++++++++- .../test_zigbee_window_treatment_feibit.lua | 27 ++++++++- .../test_zigbee_window_treatment_hanssem.lua | 23 +++++++- ...ee_window_treatment_screen_innovations.lua | 15 ++++- .../test_zigbee_window_treatment_somfy.lua | 55 +++++++++++++------ .../src/vimar/init.lua | 15 +++++ .../tuya-zigbee/src/curtain/init.lua | 20 +++++++ .../src/test/test_tuya_curtain.lua | 15 ++++- 18 files changed, 248 insertions(+), 41 deletions(-) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua index 3af5364bbe..8f1f653fa6 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua @@ -16,6 +16,7 @@ local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Groups = clusters.Groups local Basic = clusters.Basic @@ -47,6 +48,8 @@ local function device_added(driver, device) device:emit_event(hookLockState.hookLockState.unlocked()) device:emit_event(chargingState.chargingState.stopped()) device:emit_event(capabilities.battery.battery(100)) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) end local function do_refresh(self, device) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua index 929d5b713d..8daceb4402 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua @@ -3,6 +3,7 @@ local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering @@ -172,6 +173,8 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShadeLevel.shadeLevel(0)) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(deviceInitialization.initializedState.notInitialized()) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua index 6239fb52f0..2eedf58f5c 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua @@ -4,6 +4,7 @@ local cluster_base = require "st.zigbee.cluster_base" local FrameCtrl = require "st.zigbee.zcl.frame_ctrl" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering @@ -97,6 +98,8 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(initializedStateWithGuide.initializedStateWithGuide.notInitialized()) device:emit_event(shadeRotateState.rotateState.idle({ visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua index a47de06df7..8134fdc47d 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua @@ -17,6 +17,7 @@ local device_management = require "st.zigbee.device_management" local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local utils = require "st.utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = zcl_clusters.Basic local Level = zcl_clusters.Level @@ -116,6 +117,8 @@ local device_added = function(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false } })) device:set_field(SOFTWARE_VERSION, 0) device:send(Basic.attributes.SWBuildID:read(device)) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) end local axis_handler = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua index be956d79b2..8afe202096 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua @@ -17,6 +17,7 @@ local data_types = require "st.zigbee.data_types" local ZigbeeConstants = require "st.zigbee.constants" local generic_body = require "st.zigbee.generic_body" local window_shade_utils = require "window_shade_utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local TUYA_CLUSTER = 0xEF00 local DP_TYPE_VALUE = "\x02" @@ -194,6 +195,8 @@ local function device_added(driver, device) SetShadeLevelHandler(driver, device, {args = { shadeLevel = 50 }}) end) end + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) end local function device_info_changed(driver, device, event, args) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/init.lua index 92076d9456..403016eaeb 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/init.lua @@ -21,20 +21,23 @@ local function init_handler(self, device) if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) - if preset_position == nil and device.preferences ~= nil and device.preferences.presetPosition ~= nil then - preset_position = device.preferences.presetPosition - device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, device.preferences.presetPosition, {persist = true}) - end + -- These should only ever be nil once (and at the same time) for already-installed devices + -- It can be removed after migration is complete + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if preset_position ~= nil then - device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) - end + local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + (device.preferences ~= nil and device.preferences.presetPosition) or + window_preset_defaults.PRESET_LEVEL + + device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) + device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) end end local function added_handler(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) end local zigbee_window_treatment_driver_template = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua index 868e92af56..59c84d67ed 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua @@ -18,6 +18,7 @@ local clusters = require "st.zigbee.zcl.clusters" local window_shade_utils = require "window_shade_utils" local device_management = require "st.zigbee.device_management" local utils = require "st.utils" +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering @@ -62,6 +63,8 @@ local function device_added(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" }, {visibility = {displayed = false}})) -- initialize motor state device:set_field(MOTOR_STATE, MOTOR_STATE_IDLE) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) device.thread:call_with_delay(3, function(d) do_refresh(self, device) end) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_ikea.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_ikea.lua index 4fee02c00f..4fe49568eb 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_ikea.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_ikea.lua @@ -37,7 +37,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -162,7 +169,13 @@ test.register_coroutine_test( test.register_coroutine_test( "windowShadePreset capability should be handled", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 30}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {30}} + } + ) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadePreset.position(30))) test.wait_for_events() test.socket.capability:__queue_receive( { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_yoolax.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_yoolax.lua index 106730e7fd..d51f303378 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_yoolax.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_shade_battery_yoolax.lua @@ -67,7 +67,14 @@ end zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -136,9 +143,10 @@ test.register_coroutine_test( { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) + -- newly added devices will ignore the preference test.socket.zigbee:__expect_send({ mock_device.id, - WindowCovering.server.commands.GoToLiftPercentage(mock_device, 70) + WindowCovering.server.commands.GoToLiftPercentage(mock_device, 50) }) end ) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua index 6a93845752..1c413c9b41 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua @@ -25,7 +25,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -265,6 +272,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") @@ -288,6 +301,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua index 3148f48965..3805dc4839 100755 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua @@ -43,7 +43,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -458,8 +465,9 @@ test.register_coroutine_test( } ) test.socket.capability:__set_channel_ordering("relaxed") + -- freshly joined devices will ignore the preference value test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadeLevel.shadeLevel(30)) + mock_device:generate_test_message("main", capabilities.windowShadeLevel.shadeLevel(50)) ) test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.windowShade.opening()) @@ -467,7 +475,7 @@ test.register_coroutine_test( test.socket.zigbee:__expect_send( { mock_device.id, - WindowCovering.server.commands.GoToLiftPercentage(mock_device, 100 - 30) + WindowCovering.server.commands.GoToLiftPercentage(mock_device, 100 - 50) } ) end @@ -517,6 +525,12 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.zigbee:__queue_receive( { @@ -559,6 +573,12 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.capability:__queue_receive({ @@ -594,6 +614,12 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua index 25b3685ec0..0ba047dd6e 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua @@ -37,7 +37,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -221,9 +228,10 @@ test.register_coroutine_test( { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) + -- newly joined devices will ignore the preference test.socket.zigbee:__expect_send({ mock_device.id, - Level.server.commands.MoveToLevelWithOnOff(mock_device,math.floor(30/100 * 254)) + Level.server.commands.MoveToLevelWithOnOff(mock_device,math.floor(50/100 * 254)) }) end ) @@ -257,9 +265,10 @@ test.register_coroutine_test( { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } } ) + -- newly joined devices will ignore the preference test.socket.zigbee:__expect_send({ mock_device.id, - Level.server.commands.MoveToLevelWithOnOff(mock_device,math.floor(100/100 * 254)) + Level.server.commands.MoveToLevelWithOnOff(mock_device,math.floor(50/100 * 254)) }) end ) @@ -350,6 +359,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") @@ -373,6 +388,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua index a0e0fbf844..9908888240 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua @@ -43,7 +43,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -88,6 +95,12 @@ test.register_coroutine_test( ) test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadeLevel.shadeLevel(0))) test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShade.windowShade.closed())) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.mock_time.advance_time(3) test.socket.zigbee:__expect_send({ mock_device.id, @@ -278,7 +291,13 @@ test.register_coroutine_test( test.register_coroutine_test( "Preset position handler", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 30}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {30}} + } + ) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadePreset.position(30))) test.wait_for_events() test.socket.zigbee:__queue_receive({ diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua index 717731124e..13d2265ce5 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua @@ -45,7 +45,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -259,6 +266,12 @@ test.register_coroutine_test( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua index 2e7c140f17..19758ba8ab 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua @@ -38,7 +38,14 @@ local mock_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_device)end + test.mock_device.add_test_device(mock_device) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -356,7 +363,13 @@ test.register_message_test( test.register_coroutine_test( "windowShadePreset capability should be handled with preset value of 1", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 1}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {1}} + } + ) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadePreset.position(1))) test.wait_for_events() test.socket.capability:__queue_receive( { @@ -374,7 +387,13 @@ test.register_coroutine_test( test.register_coroutine_test( "windowShadePreset capability should be handled with preset value of 100", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 100}})) + test.socket.capability:__queue_receive( + { + mock_device.id, + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {100}} + } + ) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadePreset.position(100))) test.wait_for_events() test.socket.capability:__queue_receive( { @@ -408,27 +427,15 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "windowShadePreset capability should be handled with preset value of > 100", + "windowShadePreset capability should be handled with preset value of < 1 (but positive)", function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 101}})) - test.wait_for_events() test.socket.capability:__queue_receive( { mock_device.id, - { capability = "windowShadePreset", component = "main", command = "presetPosition", args = {} } + { capability = "windowShadePreset", component = "main", command = "setPresetPosition", args = {0}} } ) - test.socket.zigbee:__expect_send({ - mock_device.id, - WindowCovering.server.commands.GoToLiftPercentage(mock_device, 0) - }) - end -) - -test.register_coroutine_test( - "windowShadePreset capability should be handled with preset value of < 1 (but positive)", - function() - test.socket.device_lifecycle():__queue_receive(mock_device:generate_info_changed({preferences = {presetPosition = 0}})) + test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadePreset.position(0))) test.wait_for_events() test.socket.capability:__queue_receive( { @@ -450,6 +457,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.capability:__queue_receive({ @@ -472,6 +485,12 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua index b1a5db22a0..76c9e4d498 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua @@ -18,6 +18,7 @@ local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local WindowCovering = zcl_clusters.WindowCovering local windowShade = capabilities.windowShade.windowShade +local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" -- VIMAR WINDOW SHADES BEHAVIOR -- 1. Open/Close/SetToLevel command is invoked normally @@ -134,6 +135,20 @@ local device_init = function(self, device) -- Reset Status device:set_field(VIMAR_SHADES_CLOSING, false) device:set_field(VIMAR_SHADES_OPENING, false) + + -- for windowshadepreset update migration + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + + -- These should only ever be nil once (and at the same time) for already-installed devices + -- It can be removed after migration is complete + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + + local preset_position = window_shade_utils.get_preset_level(device, "main") + + device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) + device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) + end end -- DRIVER HANDLER CONFIGURATION diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index 0449ea9f83..391de36d7d 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -34,6 +34,23 @@ local function is_tuya_curtain(opts, driver, device) return false end +local function init_handler(self, device) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + + -- These should only ever be nil once (and at the same time) for already-installed devices + -- It can be removed after migration is complete + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + + local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + (device.preferences ~= nil and device.preferences.presetPosition) or + window_preset_defaults.PRESET_LEVEL + + device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) + device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) + end +end + local do_configure = function(driver, device) -- configure ApplicationVersion to keep device online, tuya hub also uses this attribute tuya_utils.send_magic_spell(device) @@ -45,6 +62,8 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" }, {visibility = {displayed = false}})) device:emit_event(capabilities.windowShadeLevel.shadeLevel(0)) device:emit_event(capabilities.windowShade.windowShade.closed()) + device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) end local function increase_packet_id(packet_id) @@ -130,6 +149,7 @@ end local tuya_curtain_driver = { NAME = "tuya curtain", lifecycle_handlers = { + init = init_handler, added = device_added, infoChanged = device_info_changed, doConfigure = do_configure diff --git a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_curtain.lua b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_curtain.lua index d6beda0de8..024a58cdc5 100644 --- a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_curtain.lua +++ b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_curtain.lua @@ -39,7 +39,14 @@ local mock_simple_device = test.mock_device.build_test_zigbee_device( zigbee_test_utils.prepare_zigbee_env_info() local function test_init() - test.mock_device.add_test_device(mock_simple_device)end + test.mock_device.add_test_device(mock_simple_device) + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) +end test.set_test_init_function(test_init) @@ -107,6 +114,12 @@ test.register_coroutine_test( capabilities.windowShade.windowShade.closed() ) ) + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) + ) + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) + ) end ) From d8ad82d59fff50c93ad6f2f5b0c012f8304fd209 Mon Sep 17 00:00:00 2001 From: Steven Green Date: Fri, 25 Jul 2025 17:11:40 -0700 Subject: [PATCH 3/6] fixup --- .../src/aqara/curtain-driver-e1/init.lua | 5 ++++- .../SmartThings/zigbee-window-treatment/src/aqara/init.lua | 5 ++++- .../zigbee-window-treatment/src/aqara/roller-shade/init.lua | 5 ++++- .../SmartThings/zigbee-window-treatment/src/axis/init.lua | 5 ++++- .../SmartThings/zigbee-window-treatment/src/hanssem/init.lua | 5 ++++- drivers/SmartThings/zigbee-window-treatment/src/init.lua | 5 ++++- .../zigbee-window-treatment/src/screen-innovations/init.lua | 5 ++++- drivers/Unofficial/tuya-zigbee/src/curtain/init.lua | 5 ++++- 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua index 8f1f653fa6..78bfb13a9f 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua @@ -49,7 +49,10 @@ local function device_added(driver, device) device:emit_event(chargingState.chargingState.stopped()) device:emit_event(capabilities.battery.battery(100)) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end end local function do_refresh(self, device) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua index 8daceb4402..7abade09c6 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua @@ -174,7 +174,10 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(deviceInitialization.initializedState.notInitialized()) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua index 2eedf58f5c..6797b875f9 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua @@ -99,7 +99,10 @@ local function device_added(driver, device) device:emit_event(initializedStateWithGuide.initializedStateWithGuide.notInitialized()) device:emit_event(shadeRotateState.rotateState.idle({ visibility = { displayed = false }})) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua index 8134fdc47d..80f8a1fc9f 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua @@ -118,7 +118,10 @@ local device_added = function(self, device) device:set_field(SOFTWARE_VERSION, 0) device:send(Basic.attributes.SWBuildID:read(device)) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end end local axis_handler = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua index 8afe202096..861f5592df 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua @@ -196,7 +196,10 @@ local function device_added(driver, device) end) end device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end end local function device_info_changed(driver, device, event, args) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/init.lua index 403016eaeb..267af0e0d3 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/init.lua @@ -37,7 +37,10 @@ end local function added_handler(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false }})) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end end local zigbee_window_treatment_driver_template = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua index 59c84d67ed..e941769bf3 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua @@ -64,7 +64,10 @@ local function device_added(self, device) -- initialize motor state device:set_field(MOTOR_STATE, MOTOR_STATE_IDLE) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end device.thread:call_with_delay(3, function(d) do_refresh(self, device) end) diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index 391de36d7d..b0b482d1cc 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -63,7 +63,10 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShadeLevel.shadeLevel(0)) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and + device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then + device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) + end end local function increase_packet_id(packet_id) From c149ba701a15f96059edc652d74e1bd93caac2de Mon Sep 17 00:00:00 2001 From: Steven Green Date: Mon, 28 Jul 2025 15:33:38 -0700 Subject: [PATCH 4/6] remove preference --- .../profiles/window-treatment-battery.yml | 3 --- .../profiles/window-treatment-powerSource.yml | 5 +---- ...ow-treatment-profile-no-firmware-update.yml | 5 +---- .../profiles/window-treatment-profile.yml | 4 ---- .../profiles/window-treatment-reverse.yml | 2 -- .../src/aqara/curtain-driver-e1/init.lua | 5 ----- .../zigbee-window-treatment/src/aqara/init.lua | 5 ----- .../src/aqara/roller-shade/init.lua | 5 ----- .../zigbee-window-treatment/src/axis/init.lua | 5 ----- .../src/hanssem/init.lua | 5 ----- .../zigbee-window-treatment/src/init.lua | 7 +------ .../src/screen-innovations/init.lua | 5 ----- .../src/test/test_zigbee_window_treatment.lua | 12 ------------ .../test/test_zigbee_window_treatment_axis.lua | 18 ------------------ .../test_zigbee_window_treatment_feibit.lua | 12 ------------ .../test_zigbee_window_treatment_hanssem.lua | 6 ------ ...bee_window_treatment_screen_innovations.lua | 6 ------ .../test_zigbee_window_treatment_somfy.lua | 12 ------------ .../tuya-zigbee/src/curtain/init.lua | 5 ----- 19 files changed, 3 insertions(+), 124 deletions(-) diff --git a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-battery.yml b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-battery.yml index 275697cb27..be0ae73d76 100644 --- a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-battery.yml +++ b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-battery.yml @@ -16,6 +16,3 @@ components: version: 1 categories: - name: Blind -preferences: - - preferenceId: presetPosition - explicit: true diff --git a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-powerSource.yml b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-powerSource.yml index 7c5255527f..7323ee0218 100644 --- a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-powerSource.yml +++ b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-powerSource.yml @@ -17,7 +17,4 @@ components: - id: firmwareUpdate version: 1 categories: - - name: Blind -preferences: - - preferenceId: presetPosition - explicit: true \ No newline at end of file + - name: Blind \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile-no-firmware-update.yml b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile-no-firmware-update.yml index ded16d963b..8e641e6b42 100644 --- a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile-no-firmware-update.yml +++ b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile-no-firmware-update.yml @@ -11,7 +11,4 @@ components: - id: refresh version: 1 categories: - - name: Blind -preferences: - - preferenceId: presetPosition - explicit: true + - name: Blind \ No newline at end of file diff --git a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile.yml b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile.yml index 933dd85321..b10a5ea101 100644 --- a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile.yml +++ b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-profile.yml @@ -14,7 +14,3 @@ components: version: 1 categories: - name: Blind -preferences: - - preferenceId: presetPosition - explicit: true - diff --git a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-reverse.yml b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-reverse.yml index 91b21811f9..0eb666a5d2 100644 --- a/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-reverse.yml +++ b/drivers/SmartThings/zigbee-window-treatment/profiles/window-treatment-reverse.yml @@ -18,5 +18,3 @@ components: preferences: - preferenceId: reverse explicit: true - - preferenceId: presetPosition - explicit: true diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua index 78bfb13a9f..6901c98ce7 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua @@ -48,11 +48,6 @@ local function device_added(driver, device) device:emit_event(hookLockState.hookLockState.unlocked()) device:emit_event(chargingState.chargingState.stopped()) device:emit_event(capabilities.battery.battery(100)) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end end local function do_refresh(self, device) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua index 7abade09c6..e7a7ec510a 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua @@ -173,11 +173,6 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShadeLevel.shadeLevel(0)) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(deviceInitialization.initializedState.notInitialized()) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua index 6797b875f9..c515466485 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua @@ -98,11 +98,6 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShade.windowShade.closed()) device:emit_event(initializedStateWithGuide.initializedStateWithGuide.notInitialized()) device:emit_event(shadeRotateState.rotateState.idle({ visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID, aqara_utils.PRIVATE_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Uint8, 1)) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua index 80f8a1fc9f..3b940e30e3 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua @@ -117,11 +117,6 @@ local device_added = function(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false } })) device:set_field(SOFTWARE_VERSION, 0) device:send(Basic.attributes.SWBuildID:read(device)) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end end local axis_handler = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua index 861f5592df..54c86313f8 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua @@ -195,11 +195,6 @@ local function device_added(driver, device) SetShadeLevelHandler(driver, device, {args = { shadeLevel = 50 }}) end) end - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end end local function device_info_changed(driver, device, event, args) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/init.lua index 267af0e0d3..4dde13c590 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/init.lua @@ -22,7 +22,7 @@ local function init_handler(self, device) device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then -- These should only ever be nil once (and at the same time) for already-installed devices - -- It can be removed after migration is complete + -- It can be relocated to `added` after migration is complete device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or @@ -36,11 +36,6 @@ end local function added_handler(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({"open", "close", "pause"}, { visibility = { displayed = false }})) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end end local zigbee_window_treatment_driver_template = { diff --git a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua index e941769bf3..df5f38b3cc 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua @@ -63,11 +63,6 @@ local function device_added(self, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" }, {visibility = {displayed = false}})) -- initialize motor state device:set_field(MOTOR_STATE, MOTOR_STATE_IDLE) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end device.thread:call_with_delay(3, function(d) do_refresh(self, device) end) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua index 1c413c9b41..6380e5ce51 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment.lua @@ -272,12 +272,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") @@ -301,12 +295,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua index 3805dc4839..5068f889a5 100755 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_axis.lua @@ -525,12 +525,6 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.zigbee:__queue_receive( { @@ -573,12 +567,6 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.capability:__queue_receive({ @@ -614,12 +602,6 @@ test.register_coroutine_test( mock_device.id, Basic.attributes.SWBuildID:read(mock_device) }) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua index 0ba047dd6e..c65d38281a 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_feibit.lua @@ -359,12 +359,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") @@ -388,12 +382,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua index 9908888240..23814eff28 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_hanssem.lua @@ -95,12 +95,6 @@ test.register_coroutine_test( ) test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShadeLevel.shadeLevel(0))) test.socket.capability:__expect_send(mock_device:generate_test_message("main", capabilities.windowShade.windowShade.closed())) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.mock_time.advance_time(3) test.socket.zigbee:__expect_send({ mock_device.id, diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua index 13d2265ce5..b7f630cf71 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_screen_innovations.lua @@ -266,12 +266,6 @@ test.register_coroutine_test( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua index 19758ba8ab..c861b3470c 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/test/test_zigbee_window_treatment_somfy.lua @@ -457,12 +457,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.capability:__queue_receive({ @@ -485,12 +479,6 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" },{ visibility = { displayed = false }})) ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, {visibility = {displayed=false}})) - ) - test.socket.capability:__expect_send( - mock_device:generate_test_message("main", capabilities.windowShadePreset.position(50, {visibility = {displayed=false}})) - ) test.wait_for_events() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index b0b482d1cc..052a9ede98 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -62,11 +62,6 @@ local function device_added(driver, device) device:emit_event(capabilities.windowShade.supportedWindowShadeCommands({ "open", "close", "pause" }, {visibility = {displayed = false}})) device:emit_event(capabilities.windowShadeLevel.shadeLevel(0)) device:emit_event(capabilities.windowShade.windowShade.closed()) - device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and - device:get_latest_state("main", capabilities.windowShadePreset.ID, capabilities.windowShadePreset.position.NAME) == nil then - device:emit_event(capabilities.windowShadePreset.position(window_preset_defaults.PRESET_LEVEL, { visibility = {displayed = false}})) - end end local function increase_packet_id(packet_id) From 8ec7af328844396be880c10a65da3d222ff1810d Mon Sep 17 00:00:00 2001 From: Steven Green Date: Wed, 6 Aug 2025 15:23:10 -0700 Subject: [PATCH 5/6] update drivers to work on older lua_libs versions --- .../src/aqara/curtain-driver-e1/init.lua | 1 - .../src/aqara/init.lua | 1 - .../src/aqara/roller-shade/init.lua | 1 - .../zigbee-window-treatment/src/axis/init.lua | 1 - .../src/hanssem/init.lua | 1 - .../zigbee-window-treatment/src/init.lua | 14 +++++++---- .../src/screen-innovations/init.lua | 1 - .../src/vimar/init.lua | 3 +-- .../src/window_shade_utils.lua | 23 ++++++++++++++++--- .../tuya-zigbee/src/curtain/init.lua | 22 ++++++++++++------ 10 files changed, 46 insertions(+), 22 deletions(-) diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua index 6901c98ce7..3af5364bbe 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua @@ -16,7 +16,6 @@ local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Groups = clusters.Groups local Basic = clusters.Basic diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua index e7a7ec510a..929d5b713d 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua @@ -3,7 +3,6 @@ local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering diff --git a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua index c515466485..6239fb52f0 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/aqara/roller-shade/init.lua @@ -4,7 +4,6 @@ local cluster_base = require "st.zigbee.cluster_base" local FrameCtrl = require "st.zigbee.zcl.frame_ctrl" local data_types = require "st.zigbee.data_types" local aqara_utils = require "aqara/aqara_utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering diff --git a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua index 3b940e30e3..a47de06df7 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/axis/init.lua @@ -17,7 +17,6 @@ local device_management = require "st.zigbee.device_management" local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local utils = require "st.utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = zcl_clusters.Basic local Level = zcl_clusters.Level diff --git a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua index 54c86313f8..be956d79b2 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua @@ -17,7 +17,6 @@ local data_types = require "st.zigbee.data_types" local ZigbeeConstants = require "st.zigbee.constants" local generic_body = require "st.zigbee.generic_body" local window_shade_utils = require "window_shade_utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local TUYA_CLUSTER = 0xEF00 local DP_TYPE_VALUE = "\x02" diff --git a/drivers/SmartThings/zigbee-window-treatment/src/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/init.lua index 4dde13c590..933e0d6977 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/init.lua @@ -15,7 +15,7 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local window_shade_utils = require "window_shade_utils" local function init_handler(self, device) if device:supports_capability_by_id(capabilities.windowShadePreset.ID) and @@ -25,12 +25,12 @@ local function init_handler(self, device) -- It can be relocated to `added` after migration is complete device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + local preset_position = device:get_field(window_shade_utils.PRESET_LEVEL_KEY) or (device.preferences ~= nil and device.preferences.presetPosition) or - window_preset_defaults.PRESET_LEVEL + window_shade_utils.PRESET_LEVEL device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) - device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) + device:set_field(window_shade_utils.PRESET_LEVEL_KEY, preset_position, {persist = true}) end end @@ -61,6 +61,12 @@ local zigbee_window_treatment_driver_template = { init = init_handler, added = added_handler }, + capability_handlers = { + [capabilities.windowShadePreset.ID] = { + [capabilities.windowShadePreset.commands.setPresetPosition.NAME] = window_shade_utils.set_preset_position_cmd, + [capabilities.windowShadePreset.commands.presetPosition.NAME] = window_shade_utils.window_shade_preset_cmd, + } + }, health_check = false, } diff --git a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua index df5f38b3cc..868e92af56 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/screen-innovations/init.lua @@ -18,7 +18,6 @@ local clusters = require "st.zigbee.zcl.clusters" local window_shade_utils = require "window_shade_utils" local device_management = require "st.zigbee.device_management" local utils = require "st.utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local WindowCovering = clusters.WindowCovering diff --git a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua index 76c9e4d498..9fa928645a 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/vimar/init.lua @@ -18,7 +18,6 @@ local window_shade_utils = require "window_shade_utils" local zcl_clusters = require "st.zigbee.zcl.clusters" local WindowCovering = zcl_clusters.WindowCovering local windowShade = capabilities.windowShade.windowShade -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" -- VIMAR WINDOW SHADES BEHAVIOR -- 1. Open/Close/SetToLevel command is invoked normally @@ -147,7 +146,7 @@ local device_init = function(self, device) local preset_position = window_shade_utils.get_preset_level(device, "main") device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) - device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) + device:set_field(window_shade_utils.PRESET_LEVEL_KEY, preset_position, {persist = true}) end end diff --git a/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua b/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua index 1970587d24..262e549c2d 100644 --- a/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua +++ b/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua @@ -11,17 +11,34 @@ -- 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 window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" +local capabilities = require "st.capabilities" +local zcl_clusters = require "st.zigbee.zcl.clusters" local utils = {} +utils.PRESET_LEVEL = 50 +utils.PRESET_LEVEL_KEY = "_presetLevel" + utils.get_preset_level = function(device, component) local level = device:get_latest_state(component, "windowShadePreset", "position") or - device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + device:get_field(utils.PRESET_LEVEL_KEY) or (device.preferences ~= nil and device.preferences.presetPosition) or - window_preset_defaults.PRESET_LEVEL + utils.PRESET_LEVEL return level end +utils.window_shade_preset_cmd = function(driver, device, command) + local level = device:get_latest_state(command.component, "windowShadePreset", "position") or + device:get_field(utils.PRESET_LEVEL_KEY) or + (device.preferences ~= nil and device.preferences.presetPosition) or + utils.PRESET_LEVEL + device:send_to_component(command.component, zcl_clusters.WindowCovering.server.commands.GoToLiftPercentage(device, level)) +end + +utils.set_preset_position_cmd = function(driver, device, command) + device:emit_component_event({id = command.component}, capabilities.windowShadePreset.position(command.args.position)) + device:set_field(utils.PRESET_LEVEL_KEY, command.args.position, {persist = true}) +end + return utils \ No newline at end of file diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index 052a9ede98..64fb048657 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -17,10 +17,12 @@ local clusters = require "st.zigbee.zcl.clusters" local utils = require "st.utils" local device_management = require "st.zigbee.device_management" local tuya_utils = require "tuya_utils" -local window_preset_defaults = require "st.zigbee.defaults.windowShadePreset_defaults" local Basic = clusters.Basic local packet_id = 0 +PRESET_LEVEL = 50 +PRESET_LEVEL_KEY = "_presetLevel" + local FINGERPRINTS = { { mfr = "_TZE284_nladmfvf", model = "TS0601"} } @@ -42,12 +44,12 @@ local function init_handler(self, device) -- It can be removed after migration is complete device:emit_event(capabilities.windowShadePreset.supportedCommands({"presetPosition", "setPresetPosition"}, { visibility = { displayed = false }})) - local preset_position = device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + local preset_position = device:get_field(PRESET_LEVEL_KEY) or (device.preferences ~= nil and device.preferences.presetPosition) or - window_preset_defaults.PRESET_LEVEL + PRESET_LEVEL device:emit_event(capabilities.windowShadePreset.position(preset_position, { visibility = {displayed = false}})) - device:set_field(window_preset_defaults.PRESET_LEVEL_KEY, preset_position, {persist = true}) + device:set_field(PRESET_LEVEL_KEY, preset_position, {persist = true}) end end @@ -115,13 +117,18 @@ end local function window_shade_preset(driver, device) local level = device:get_latest_state("main", "windowShadePreset", "position") or - device:get_field(window_preset_defaults.PRESET_LEVEL_KEY) or + device:get_field(PRESET_LEVEL_KEY) or (device.preferences ~= nil and device.preferences.presetPosition) or - window_preset_defaults.PRESET_LEVEL + PRESET_LEVEL tuya_utils.send_tuya_command(device, '\x02', tuya_utils.DP_TYPE_VALUE, '\x00\x00'..string.pack(">I2", level), packet_id) packet_id = increase_packet_id(packet_id) end +local function set_preset_position_cmd(driver, device, command) + device:emit_component_event({id = command.component}, capabilities.windowShadePreset.position(command.args.position)) + device:set_field(PRESET_LEVEL_KEY, command.args.position, {persist = true}) +end + local function tuya_cluster_handler(driver, device, zb_rx) local window_shade_level_event, window_shade_val_event local raw = zb_rx.body.zcl_body.body_bytes @@ -162,7 +169,8 @@ local tuya_curtain_driver = { [capabilities.windowShadeLevel.commands.setShadeLevel.NAME] = window_shade_level }, [capabilities.windowShadePreset.ID] = { - [capabilities.windowShadePreset.commands.presetPosition.NAME] = window_shade_preset + [capabilities.windowShadePreset.commands.presetPosition.NAME] = window_shade_preset, + [capabilities.windowShadePreset.commands.setPresetPosition.NAME] = set_preset_position_cmd } }, zigbee_handlers = { From 3337da15231e624af77d9ea28970757f163dbd20 Mon Sep 17 00:00:00 2001 From: Steven Green Date: Wed, 6 Aug 2025 15:25:16 -0700 Subject: [PATCH 6/6] fixup --- drivers/Unofficial/tuya-zigbee/src/curtain/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua index 64fb048657..bbd20396a0 100644 --- a/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/curtain/init.lua @@ -20,8 +20,8 @@ local tuya_utils = require "tuya_utils" local Basic = clusters.Basic local packet_id = 0 -PRESET_LEVEL = 50 -PRESET_LEVEL_KEY = "_presetLevel" +local PRESET_LEVEL = 50 +local PRESET_LEVEL_KEY = "_presetLevel" local FINGERPRINTS = { { mfr = "_TZE284_nladmfvf", model = "TS0601"}