From 6b4cfeb75ddc0fa7cf756e9a81f91fd2fb86cafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20=C5=9Al=C4=99zak?= Date: Fri, 26 Jun 2026 11:41:04 +0200 Subject: [PATCH 1/9] Add support for Tuya thermostats --- .../Unofficial/tuya-zigbee/fingerprints.yml | 7 +- .../tuya-zigbee/profiles/thermostat.yml | 31 +++ drivers/Unofficial/tuya-zigbee/src/init.lua | 3 +- .../src/test/test_tuya_thermostat.lua | 241 ++++++++++++++++++ .../tuya-zigbee/src/thermostat/init.lua | 199 +++++++++++++++ 5 files changed, 479 insertions(+), 2 deletions(-) create mode 100644 drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml create mode 100644 drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua create mode 100644 drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua diff --git a/drivers/Unofficial/tuya-zigbee/fingerprints.yml b/drivers/Unofficial/tuya-zigbee/fingerprints.yml index 7ee7460696..75f7b6096e 100644 --- a/drivers/Unofficial/tuya-zigbee/fingerprints.yml +++ b/drivers/Unofficial/tuya-zigbee/fingerprints.yml @@ -43,4 +43,9 @@ zigbeeManufacturer: deviceLabel: Tuya Switch 1 manufacturer: _TZE204_h2rctifa model: TS0601 - deviceProfileName: basic-switch \ No newline at end of file + deviceProfileName: basic-switch + - id: _TZE284_fziifcxj/TS0601 + deviceLabel: Tuya Thermostat + manufacturer: _TZE284_fziifcxj + model: TS0601 + deviceProfileName: thermostat \ No newline at end of file diff --git a/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml new file mode 100644 index 0000000000..d05036be3a --- /dev/null +++ b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml @@ -0,0 +1,31 @@ +name: thermostat +components: + - id: main + categories: + - name: Thermostat + capabilities: + - id: temperatureMeasurement + version: 1 + - id: thermostatHeatingSetpoint + version: 1 + config: + values: + - key: "heatingSetpoint.value" + range: [5, 30] + step: 0.5 + - id: thermostatMode + version: 1 + config: + values: + - key: "thermostatMode.value" + enabledValues: + - antifreezing + - auto + - comfort + - eco + - off + - on + - id: battery + version: 1 + - id: refresh + version: 1 diff --git a/drivers/Unofficial/tuya-zigbee/src/init.lua b/drivers/Unofficial/tuya-zigbee/src/init.lua index 8fb452abb2..6313132933 100644 --- a/drivers/Unofficial/tuya-zigbee/src/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/init.lua @@ -26,7 +26,8 @@ local unofficial_tuya_driver_template = { require("curtain"), require("motion-sensor"), require("smoke-detector"), - require("switch") + require("switch"), + require("thermostat") }, health_check = false, } diff --git a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua new file mode 100644 index 0000000000..60a81e6988 --- /dev/null +++ b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua @@ -0,0 +1,241 @@ +-- Copyright 2026 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. + +-- Mock out globals +local test = require "integration_test" +local t_utils = require "integration_test.utils" +local zigbee_test_utils = require "integration_test.zigbee_test_utils" +local capabilities = require "st.capabilities" +local clusters = require "st.zigbee.zcl.clusters" +local tuya_utils = require "tuya_utils" + +local Basic = clusters.Basic + +local mock_simple_device = test.mock_device.build_test_zigbee_device( + { + profile = t_utils.get_profile_definition("thermostat.yml"), + zigbee_endpoints = { + [1] = { + id = 1, + manufacturer = "_TZE284_fziifcxj", + model = "TS0601", + server_clusters = { 0xEF00 } + } + } + } +) + +zigbee_test_utils.prepare_zigbee_env_info() + +local function test_init() + test.mock_device.add_test_device(mock_simple_device) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "Handle doConfigure lifecycle event", + function() + test.socket.zigbee:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_simple_device.id, "doConfigure" }) + test.socket.zigbee:__expect_send({ mock_simple_device.id, tuya_utils.build_tuya_magic_spell_message(mock_simple_device) }) + test.socket.zigbee:__expect_send({ mock_simple_device.id, Basic.attributes.ApplicationVersion:configure_reporting(mock_simple_device, 30, 300, 1) }) + test.socket.zigbee:__expect_send({ mock_simple_device.id, zigbee_test_utils.build_bind_request(mock_simple_device, zigbee_test_utils.mock_hub_eui, Basic.ID) }) + mock_simple_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end, + {} +) + +test.register_coroutine_test( + "Handle added lifecycle event", + function() + test.socket.device_lifecycle:__queue_receive({ mock_simple_device.id, "added" }) + + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.supportedThermostatModes( + { + capabilities.thermostatMode.thermostatMode.antifreezing.NAME, + capabilities.thermostatMode.thermostatMode.auto.NAME, + capabilities.thermostatMode.thermostatMode.comfort.NAME, + capabilities.thermostatMode.thermostatMode.eco.NAME, + capabilities.thermostatMode.thermostatMode.off.NAME, + capabilities.thermostatMode.thermostatMode.on.NAME, + }, + { + visibility = { displayed = false } + } + ) + ) + ) + + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message( + "main", + capabilities.thermostatHeatingSetpoint.heatingSetpoint({value = 15.0, unit = "C"}) + ) + ) + + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message( + "main", + capabilities.temperatureMeasurement.temperature({value = 20.0, unit = "C"}) + ) + ) + + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.auto() + ) + ) + + test.socket.capability:__expect_send( + mock_simple_device:generate_test_message( + "main", + capabilities.battery.battery(100) + ) + ) + end, + {} +) + +test.register_message_test( + "Handle thermostatHeatingSetpoint setHeatingSetpoint", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatHeatingSetpoint", + component = "main", + command = "setHeatingSetpoint", + args = {12.5} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x04", + tuya_utils.DP_TYPE_VALUE, + "\x00\x00\x00\x7D", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle thermostatMode setThermostatMode", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"comfort"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x03", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (heatingSetpoint)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x04", + tuya_utils.DP_TYPE_VALUE, + "\x00\x00\x00\x7D", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatHeatingSetpoint.heatingSetpoint({value = 12.5, unit = "C"}) + ) + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x03", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.comfort() + ) + } + }, + {} +) + +test.run_registered_tests() diff --git a/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua new file mode 100644 index 0000000000..871535f10f --- /dev/null +++ b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua @@ -0,0 +1,199 @@ +-- Copyright 2026 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + + +local capabilities = require "st.capabilities" +local defaults = require "st.zigbee.defaults" +local device_management = require "st.zigbee.device_management" +local clusters = require "st.zigbee.zcl.clusters" +local tuya_utils = require "tuya_utils" +local Basic = clusters.Basic +local packet_id = 0 + +local FINGERPRINTS = { + { mfr = "_TZE284_fziifcxj", model = "TS0601"} +} + +local function is_tuya_thermostat(opts, driver, device) + for _, fingerprint in ipairs(FINGERPRINTS) do + if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then + return true + end + end + return false +end + +local function device_added(self, device) + device:emit_event(capabilities.thermostatMode.supportedThermostatModes({ + capabilities.thermostatMode.thermostatMode.antifreezing.NAME, + capabilities.thermostatMode.thermostatMode.auto.NAME, + capabilities.thermostatMode.thermostatMode.comfort.NAME, + capabilities.thermostatMode.thermostatMode.eco.NAME, + capabilities.thermostatMode.thermostatMode.off.NAME, + capabilities.thermostatMode.thermostatMode.on.NAME, + }, { visibility = { displayed = false } })) + device:emit_event(capabilities.thermostatHeatingSetpoint.heatingSetpoint({value = 15.0, unit = "C"})) + device:emit_event(capabilities.temperatureMeasurement.temperature({value = 20.0, unit = "C"})) + device:emit_event(capabilities.thermostatMode.thermostatMode.auto()) + device:emit_event(capabilities.battery.battery(100)) +end + +local function do_configure(driver, device) + -- configure ApplicationVersion to keep device online, tuya hub also uses this attribute + tuya_utils.send_magic_spell(device) + device:send(Basic.attributes.ApplicationVersion:configure_reporting(device, 30, 300, 1)) + device:send(device_management.build_bind_request( + device, + Basic.ID, + driver.environment_info.hub_zigbee_eui + )) +end + +local function increase_packet_id(pid) + return (pid + 1) % 65536 +end + +local function do_refresh(driver, device) + print("do_refresh called") +end + +local MODE_MAP = { + [capabilities.thermostatMode.thermostatMode.auto.NAME] = "\x00", + [capabilities.thermostatMode.thermostatMode.off.NAME] = "\x01", + [capabilities.thermostatMode.thermostatMode.on.NAME] = "\x02", + [capabilities.thermostatMode.thermostatMode.comfort.NAME] = "\x03", + [capabilities.thermostatMode.thermostatMode.eco.NAME] = "\x04", + [capabilities.thermostatMode.thermostatMode.antifreezing.NAME] = "\x05", +} + +local function set_thermostat_mode(driver, device, command) + local mode_value = MODE_MAP[command.args.mode] + if mode_value ~= nil then + tuya_utils.send_tuya_command(device, "\x02", tuya_utils.DP_TYPE_ENUM, mode_value, packet_id) + packet_id = increase_packet_id(packet_id) + end +end + +local function set_heating_setpoint(driver, device, command) + local value = command.args.setpoint + local setpoint_raw = math.floor(value * 10 + 0.5) + tuya_utils.send_tuya_command( + device, + "\x04", + tuya_utils.DP_TYPE_VALUE, + string.pack(">I4", setpoint_raw), + packet_id + ) + packet_id = increase_packet_id(packet_id) +end + +local function tuya_cluster_handler(driver, device, zb_rx) + local event + local raw = zb_rx.body.zcl_body.body_bytes + local dp = raw:byte(3) + local dp_type = raw:byte(4) + local dp_data_len = string.unpack(">I2", raw:sub(5, 6)) + local dp_data = raw:sub(7, 6 + dp_data_len) + + if dp == 0x04 then -- Target temperature + if dp_type == 0x02 and dp_data_len >= 4 then -- value + local target_temp_raw = string.unpack(">I4", dp_data:sub(1, 4)) + local target_temp = target_temp_raw / 10.0 + event = capabilities.thermostatHeatingSetpoint.heatingSetpoint({ + value = target_temp, + unit = "C" + }) + end + + elseif dp == 0x05 then -- Current temperature + if dp_type == 0x02 and dp_data_len >= 4 then -- value + local temp_raw = string.unpack(">I4", dp_data:sub(1, 4)) + local temp = temp_raw / 10.0 + event = capabilities.temperatureMeasurement.temperature({ + value = temp, + unit = "C" + }) + end + + elseif dp == 0x02 then -- Thermostat mode + if dp_type == 0x04 and dp_data_len >= 1 then -- enum + local mode = dp_data:byte(1) + if mode == 0x00 then -- auto + event = capabilities.thermostatMode.thermostatMode.auto() + elseif mode == 0x01 then -- off + event = capabilities.thermostatMode.thermostatMode.off() + elseif mode == 0x02 then -- on + event = capabilities.thermostatMode.thermostatMode.on() + elseif mode == 0x03 then -- comfort + event = capabilities.thermostatMode.thermostatMode.comfort() + elseif mode == 0x04 then -- eco + event = capabilities.thermostatMode.thermostatMode.eco() + elseif mode == 0x05 then -- antifreezing + event = capabilities.thermostatMode.thermostatMode.antifreezing() + end + end + + elseif dp == 0x06 then -- Battery level + if dp_type == 0x02 and dp_data_len >= 4 then -- value + local battery_level = string.unpack(">I4", dp_data:sub(1, 4)) + event = capabilities.battery.battery(battery_level) + end + end + + if event ~= nil then + device:emit_event(event) + end +end + +local tuya_thermostat_driver = { + NAME = "tuya thermostat", + supported_capabilities = { + capabilities.temperatureMeasurement, + capabilities.thermostatHeatingSetpoint, + capabilities.thermostatMode, + capabilities.battery, + capabilities.refresh + }, + zigbee_handlers = { + cluster = { + [tuya_utils.TUYA_PRIVATE_CLUSTER] = { + [tuya_utils.TUYA_PRIVATE_CMD_REPORT] = tuya_cluster_handler, + [tuya_utils.TUYA_PRIVATE_CMD_RESPONSE] = tuya_cluster_handler, + } + } + }, + capability_handlers = { + [capabilities.thermostatMode.ID] = { + [capabilities.thermostatMode.commands.setThermostatMode.NAME] = set_thermostat_mode, + }, + [capabilities.thermostatHeatingSetpoint.ID] = { + [capabilities.thermostatHeatingSetpoint.commands.setHeatingSetpoint.NAME] = set_heating_setpoint, + }, + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh, + }, + }, + lifecycle_handlers = { + added = device_added, + doConfigure = do_configure + }, + can_handle = is_tuya_thermostat +} + +defaults.register_for_default_handlers( + tuya_thermostat_driver, + tuya_thermostat_driver.supported_capabilities, + {} +) +return tuya_thermostat_driver \ No newline at end of file From a087e48a644208bbccbf272251b6080762187515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20=C5=9Al=C4=99zak?= Date: Fri, 26 Jun 2026 13:29:31 +0200 Subject: [PATCH 2/9] Add more unit tests --- .../src/test/test_tuya_thermostat.lua | 319 +++++++++++++++++- 1 file changed, 317 insertions(+), 2 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua index 60a81e6988..27da0a8cb8 100644 --- a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua +++ b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua @@ -147,7 +147,109 @@ test.register_message_test( ) test.register_message_test( - "Handle thermostatMode setThermostatMode", + "Handle thermostatMode setThermostatMode (auto)", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"auto"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x00", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle thermostatMode setThermostatMode (off)", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"off"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x01", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle thermostatMode setThermostatMode (on)", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"on"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x02", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle thermostatMode setThermostatMode (comfort)", { { channel = "capability", @@ -180,6 +282,74 @@ test.register_message_test( {} ) +test.register_message_test( + "Handle thermostatMode setThermostatMode (eco)", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"eco"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x04", + 0x00 + ) + } + } + }, + {} +) + +test.register_message_test( + "Handle thermostatMode setThermostatMode (antifreezing)", + { + { + channel = "capability", + direction = "receive", + message = { + mock_simple_device.id, + { + capability = "thermostatMode", + component = "main", + command = "setThermostatMode", + args = {"antifreezing"} + } + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_simple_device.id, + tuya_utils.build_send_tuya_command( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x05", + 0x00 + ) + } + } + }, + {} +) + test.register_message_test( "Handle tuya cluster message report (heatingSetpoint)", { @@ -210,7 +380,94 @@ test.register_message_test( ) test.register_message_test( - "Handle tuya cluster message report (setThermostatMode)", + "Handle tuya cluster message report (setThermostatMode, auto)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x00", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.auto() + ) + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode, off)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x01", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.off() + ) + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode, on)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x02", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.on() + ) + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode, comfort)", { { channel = "zigbee", @@ -238,4 +495,62 @@ test.register_message_test( {} ) +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode, eco)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x04", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.eco() + ) + } + }, + {} +) + +test.register_message_test( + "Handle tuya cluster message report (setThermostatMode, antifreezing)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_simple_device.id, + tuya_utils.build_test_attr_report( + mock_simple_device, + "\x02", + tuya_utils.DP_TYPE_ENUM, + "\x05", + 0x01 + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_simple_device:generate_test_message( + "main", + capabilities.thermostatMode.thermostatMode.antifreezing() + ) + } + }, + {} +) + test.run_registered_tests() From 4649038fd59ba6e0155bb8644e92801c2e6fcc95 Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:14:33 +0200 Subject: [PATCH 3/9] Update copyright notice in test_tuya_thermostat.lua Updated copyright information in test_tuya_thermostat.lua. --- .../tuya-zigbee/src/test/test_tuya_thermostat.lua | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua index 27da0a8cb8..9cfb1d12b8 100644 --- a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua +++ b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua @@ -1,16 +1,5 @@ --- Copyright 2026 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 -- Mock out globals local test = require "integration_test" From 457d9de6414f56ffdd246a98bff171ec8f89e115 Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:15:08 +0200 Subject: [PATCH 4/9] Update copyright and license comments in init.lua Updated copyright notice and licensing information. --- .../tuya-zigbee/src/thermostat/init.lua | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua index 871535f10f..cd529a6e78 100644 --- a/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua @@ -1,17 +1,5 @@ --- Copyright 2026 SmartThings --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. - +-- Copyright 2026 SmartThings, Inc. +-- Licensed under the Apache License, Version 2.0 local capabilities = require "st.capabilities" local defaults = require "st.zigbee.defaults" @@ -196,4 +184,4 @@ defaults.register_for_default_handlers( tuya_thermostat_driver.supported_capabilities, {} ) -return tuya_thermostat_driver \ No newline at end of file +return tuya_thermostat_driver From 17875cf5deb0f8b38cfd9b405f6bcd2866c1bd6f Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:11:28 +0200 Subject: [PATCH 5/9] Update test_tuya_thermostat.lua --- .../Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua index 9cfb1d12b8..4df634bf18 100644 --- a/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua +++ b/drivers/Unofficial/tuya-zigbee/src/test/test_tuya_thermostat.lua @@ -90,7 +90,7 @@ test.register_coroutine_test( capabilities.thermostatMode.thermostatMode.auto() ) ) - + test.socket.capability:__expect_send( mock_simple_device:generate_test_message( "main", From 44318afde89b15aa4540e6f5656ab80c9a8d7c63 Mon Sep 17 00:00:00 2001 From: Konrad K <33450498+KKlimczukS@users.noreply.github.com> Date: Tue, 30 Jun 2026 10:03:39 +0200 Subject: [PATCH 6/9] Update drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua Co-authored-by: Harrison Carter <137556605+hcarter-775@users.noreply.github.com> --- drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua index cd529a6e78..2179fb28a4 100644 --- a/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua +++ b/drivers/Unofficial/tuya-zigbee/src/thermostat/init.lua @@ -53,7 +53,7 @@ local function increase_packet_id(pid) end local function do_refresh(driver, device) - print("do_refresh called") + device.log.info("do_refresh called") end local MODE_MAP = { From 48c0ba3c73d6af713184b71c91070f4f57ba1dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20=C5=9Al=C4=99zak?= Date: Tue, 30 Jun 2026 10:46:12 +0200 Subject: [PATCH 7/9] Remove thermostatMode enabledValues from profile --- drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml index d05036be3a..61319f0e07 100644 --- a/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml +++ b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml @@ -18,13 +18,6 @@ components: config: values: - key: "thermostatMode.value" - enabledValues: - - antifreezing - - auto - - comfort - - eco - - off - - on - id: battery version: 1 - id: refresh From a62bca2c0a3be732bf504944efff35b5de0d95bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20=C5=9Al=C4=99zak?= Date: Tue, 30 Jun 2026 10:47:29 +0200 Subject: [PATCH 8/9] Move category to be below capabilities in Tuya Zigbee thermostat profile --- drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml index 61319f0e07..66ecb5661b 100644 --- a/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml +++ b/drivers/Unofficial/tuya-zigbee/profiles/thermostat.yml @@ -1,8 +1,6 @@ name: thermostat components: - id: main - categories: - - name: Thermostat capabilities: - id: temperatureMeasurement version: 1 @@ -22,3 +20,5 @@ components: version: 1 - id: refresh version: 1 + categories: + - name: Thermostat From 6a41eb9fd286c55b71ef775a63596ccfb7dd7afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20=C5=9Al=C4=99zak?= Date: Tue, 30 Jun 2026 10:48:00 +0200 Subject: [PATCH 9/9] Add newline at end of Tuya Zigbee fingerprints --- drivers/Unofficial/tuya-zigbee/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/Unofficial/tuya-zigbee/fingerprints.yml b/drivers/Unofficial/tuya-zigbee/fingerprints.yml index 75f7b6096e..5c77617d1d 100644 --- a/drivers/Unofficial/tuya-zigbee/fingerprints.yml +++ b/drivers/Unofficial/tuya-zigbee/fingerprints.yml @@ -48,4 +48,4 @@ zigbeeManufacturer: deviceLabel: Tuya Thermostat manufacturer: _TZE284_fziifcxj model: TS0601 - deviceProfileName: thermostat \ No newline at end of file + deviceProfileName: thermostat