Skip to content

Commit 455e198

Browse files
authored
Merge pull request #476 from SmartThingsCommunity/bugfix/CHAD-10123
CHAD-10123 Fix Stelpro thermostat setpoint logic
2 parents e3f5d08 + cc2cf67 commit 455e198

File tree

5 files changed

+560
-559
lines changed

5 files changed

+560
-559
lines changed

drivers/SmartThings/zwave-thermostat/profiles/thermostat-temperature-temperaturealarm.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ components:
99
config:
1010
values:
1111
- key: "heatingSetpoint.value"
12-
range: [ 4, 28 ]
12+
range: [ 5, 30 ]
1313
- id: thermostatMode
1414
version: 1
1515
- id: thermostatOperatingState

drivers/SmartThings/zwave-thermostat/src/init.lua

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,27 @@ local capabilities = require "st.capabilities"
1717
local ZwaveDriver = require "st.zwave.driver"
1818
--- @type st.zwave.defaults
1919
local defaults = require "st.zwave.defaults"
20-
--- @type st.zwave.CommandClass.Battery
21-
local Battery = (require "st.zwave.CommandClass.Battery")({version=1})
22-
--- @type st.zwave.CommandClass.SensorMultilevel
23-
local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({version=2})
20+
--- @type st.zwave.CommandClass
21+
local cc = require "st.zwave.CommandClass"
2422
--- @type st.zwave.CommandClass.ThermostatFanMode
2523
local ThermostatFanMode = (require "st.zwave.CommandClass.ThermostatFanMode")({version=3})
2624
--- @type st.zwave.CommandClass.ThermostatMode
2725
local ThermostatMode = (require "st.zwave.CommandClass.ThermostatMode")({version=2})
28-
--- @type st.zwave.CommandClass.ThermostatOperatingState
29-
local ThermostatOperatingState = (require "st.zwave.CommandClass.ThermostatOperatingState")({version=1})
3026
--- @type st.zwave.CommandClass.ThermostatSetpoint
3127
local ThermostatSetpoint = (require "st.zwave.CommandClass.ThermostatSetpoint")({version=1})
3228
local constants = require "st.zwave.constants"
3329
local utils = require "st.utils"
3430

35-
local do_refresh = function(self, device)
36-
device:send(ThermostatFanMode:SupportedGet({}))
37-
device:send(ThermostatFanMode:Get({}))
38-
device:send(ThermostatMode:SupportedGet({}))
39-
device:send(ThermostatMode:Get({}))
40-
device:send(ThermostatOperatingState:Get({}))
41-
device:send(SensorMultilevel:Get({}))
42-
device:send(ThermostatSetpoint:Get({setpoint_type = ThermostatSetpoint.setpoint_type.COOLING_1}))
43-
device:send(ThermostatSetpoint:Get({setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1}))
44-
device:send(Battery:Get({}))
31+
local function device_added(driver, device)
32+
if device:supports_capability_by_id(capabilities.thermostatMode.ID) and
33+
device:is_cc_supported(cc.THERMOSTAT_MODE) then
34+
device:send(ThermostatMode:SupportedGet({}))
35+
end
36+
if device:supports_capability_by_id(capabilities.thermostatFanMode.ID) and
37+
device:is_cc_supported(cc.THERMOSTAT_FAN_MODE) then
38+
device:send(ThermostatFanMode:SupportedGet({}))
39+
end
40+
device:refresh()
4541
end
4642

4743
--TODO: Update this once we've decided how to handle setpoint commands
@@ -90,16 +86,16 @@ local driver_template = {
9086
capabilities.energyMeter
9187
},
9288
capability_handlers = {
93-
[capabilities.refresh.ID] = {
94-
[capabilities.refresh.commands.refresh.NAME] = do_refresh
95-
},
9689
[capabilities.thermostatCoolingSetpoint.ID] = {
9790
[capabilities.thermostatCoolingSetpoint.commands.setCoolingSetpoint.NAME] = set_setpoint_factory(ThermostatSetpoint.setpoint_type.COOLING_1)
9891
},
9992
[capabilities.thermostatHeatingSetpoint.ID] = {
10093
[capabilities.thermostatHeatingSetpoint.commands.setHeatingSetpoint.NAME] = set_setpoint_factory(ThermostatSetpoint.setpoint_type.HEATING_1)
10194
}
10295
},
96+
lifecycle_handlers = {
97+
added = device_added
98+
},
10399
sub_drivers = {
104100
require("aeotec-radiator-thermostat"),
105101
require("popp-radiator-thermostat"),

drivers/SmartThings/zwave-thermostat/src/stelpro-ki-thermostat/init.lua

Lines changed: 14 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,13 @@
1414

1515
local log = require "log"
1616
local capabilities = require "st.capabilities"
17-
--- @type st.utils
18-
local utils = require "st.utils"
1917
--- @type st.zwave.CommandClass
2018
local cc = require "st.zwave.CommandClass"
21-
--- @type st.zwave.constants
22-
local constants = require "st.zwave.constants"
23-
--- @type st.zwave.CommandClass.ThermostatSetpoint
24-
local ThermostatSetpoint = (require "st.zwave.CommandClass.ThermostatSetpoint")({ version = 1 })
2519
--- @type st.zwave.CommandClass.SensorMultilevel
2620
local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 5 })
2721
--- @type st.zwave.CommandClass.ThermostatMode
2822
local ThermostatMode = (require "st.zwave.CommandClass.ThermostatMode")({ version = 2 })
2923

30-
local THERMOSTAT_MIN_HEATING_SETPOINT = 5.0
31-
local THERMOSTAT_MAX_HEATING_SETPOINT = 30.0
32-
3324
local STELPRO_KI_THERMOSTAT_FINGERPRINTS = {
3425
{ manufacturerId = 0x0239, productType = 0x0001, productId = 0x0001 } -- Stelpro Ki Thermostat
3526
}
@@ -44,35 +35,6 @@ local function can_handle_stelpro_ki_thermostat(opts, driver, device, cmd, ...)
4435
return false
4536
end
4637

47-
local function set_heating_setpoint(driver, device, command)
48-
local value = command.args.setpoint
49-
if (value >= 40) then -- assume this is a fahrenheit value
50-
value = utils.f_to_c(value)
51-
end
52-
if THERMOSTAT_MIN_HEATING_SETPOINT <= value and THERMOSTAT_MAX_HEATING_SETPOINT >= value then
53-
local scale = device:get_field(constants.TEMPERATURE_SCALE)
54-
if (scale == ThermostatSetpoint.scale.FAHRENHEIT) then
55-
value = utils.c_to_f(value) -- the device has reported using F, so set using F
56-
end
57-
58-
local set = ThermostatSetpoint:Set({
59-
setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1,
60-
scale = scale,
61-
value = value
62-
})
63-
device:send_to_component(set, command.component)
64-
65-
local follow_up_poll = function()
66-
device:send_to_component(
67-
ThermostatSetpoint:Get({setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1}),
68-
command.component
69-
)
70-
end
71-
72-
device.thread:call_with_delay(1, follow_up_poll)
73-
end
74-
end
75-
7638
local function sensor_multilevel_report_handler(self, device, cmd)
7739
if (cmd.args.sensor_type == SensorMultilevel.sensor_type.TEMPERATURE) then
7840
if cmd.args.scale ~= SensorMultilevel.scale.temperature.CELSIUS and cmd.args.scale ~= SensorMultilevel.scale.temperature.FAHRENHEIT then
@@ -115,22 +77,6 @@ local function thermostat_mode_report_handler(self, device, cmd)
11577
end
11678
end
11779

118-
local function thermostat_supported_modes_report_handler(self, device, cmd)
119-
-- The DTH for this device supported heat and eco, so we've mirrored that here, despite
120-
-- the existing, more accurate "energy save heat" mode
121-
local supported_modes = {}
122-
table.insert(supported_modes, capabilities.thermostatMode.thermostatMode.heat.NAME)
123-
table.insert(supported_modes, capabilities.thermostatMode.thermostatMode.eco.NAME)
124-
125-
device:emit_event_for_endpoint(
126-
cmd.src_channel,
127-
capabilities.thermostatMode.supportedThermostatModes(
128-
supported_modes,
129-
{ visibility = { displayed = false }}
130-
)
131-
)
132-
end
133-
13480
local function set_thermostat_mode(driver, device, command)
13581
local modes = capabilities.thermostatMode.thermostatMode
13682
local mode = command.args.mode
@@ -158,6 +104,19 @@ end
158104

159105
local function device_added(self, device)
160106
-- device:emit_event(capabilities.temperatureAlarm.temperatureAlarm.cleared())
107+
108+
-- The DTH for this device supported heat and eco, so we've mirrored that here, despite
109+
-- the existing, more accurate "energy save heat" mode
110+
local supported_modes = {}
111+
table.insert(supported_modes, capabilities.thermostatMode.thermostatMode.heat.NAME)
112+
table.insert(supported_modes, capabilities.thermostatMode.thermostatMode.eco.NAME)
113+
114+
device:emit_event(
115+
capabilities.thermostatMode.supportedThermostatModes(
116+
supported_modes,
117+
{ visibility = { displayed = false }}
118+
)
119+
)
161120
end
162121

163122
local stelpro_ki_thermostat = {
@@ -168,13 +127,10 @@ local stelpro_ki_thermostat = {
168127
},
169128
[cc.THERMOSTAT_MODE] = {
170129
[ThermostatMode.REPORT] = thermostat_mode_report_handler,
171-
[ThermostatMode.SUPPORTED_REPORT] = thermostat_supported_modes_report_handler
130+
[ThermostatMode.SUPPORTED_REPORT] = function(driver, device, cmd) end
172131
}
173132
},
174133
capability_handlers = {
175-
[capabilities.thermostatHeatingSetpoint.ID] = {
176-
[capabilities.thermostatHeatingSetpoint.commands.setHeatingSetpoint.NAME] = set_heating_setpoint
177-
},
178134
[capabilities.thermostatMode.ID] = {
179135
[capabilities.thermostatMode.commands.setThermostatMode.NAME] = set_thermostat_mode
180136
}

drivers/SmartThings/zwave-thermostat/src/test/test_stelpro_ki_thermoestat.lua renamed to drivers/SmartThings/zwave-thermostat/src/test/test_stelpro_ki_thermostat.lua

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,6 @@ test.register_coroutine_test(
6969
end
7070
)
7171

72-
test.register_coroutine_test(
73-
"Setting heating setpoint should not be handled",
74-
function()
75-
mock_device:set_field(constants.TEMPERATURE_SCALE, 1, {persist = true})
76-
77-
test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot")
78-
test.socket.capability:__queue_receive({ mock_device.id, { capability = "thermostatHeatingSetpoint", command = "setHeatingSetpoint", args = { 333.0 } } })
79-
end
80-
)
81-
82-
8372
test.register_message_test(
8473
"Sensor multilevel report (33 CELCIUS) should be handled",
8574
{
@@ -88,6 +77,13 @@ test.register_message_test(
8877
direction = "receive",
8978
message = { mock_device.id, "added" }
9079
},
80+
{
81+
channel = "capability",
82+
direction = "send",
83+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
84+
"heat", "eco"
85+
}, {visibility={displayed=false}}))
86+
},
9187
{
9288
channel = "zwave",
9389
direction = "receive",
@@ -117,6 +113,13 @@ test.register_message_test(
117113
direction = "receive",
118114
message = { mock_device.id, "added" }
119115
},
116+
{
117+
channel = "capability",
118+
direction = "send",
119+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
120+
"heat", "eco"
121+
}, {visibility={displayed=false}}))
122+
},
120123
{
121124
channel = "zwave",
122125
direction = "receive",
@@ -151,6 +154,13 @@ test.register_message_test(
151154
-- direction = "send",
152155
-- message = mock_device:generate_test_message("main", capabilities.temperatureAlarm.temperatureAlarm.cleared())
153156
-- },
157+
{
158+
channel = "capability",
159+
direction = "send",
160+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
161+
"heat", "eco"
162+
}, {visibility={displayed=false}}))
163+
},
154164
{
155165
channel = "zwave",
156166
direction = "receive",
@@ -185,6 +195,13 @@ test.register_message_test(
185195
-- direction = "send",
186196
-- message = mock_device:generate_test_message("main", capabilities.temperatureAlarm.temperatureAlarm.cleared())
187197
-- },
198+
{
199+
channel = "capability",
200+
direction = "send",
201+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
202+
"heat", "eco"
203+
}, {visibility={displayed=false}}))
204+
},
188205
{
189206
channel = "zwave",
190207
direction = "receive",
@@ -219,6 +236,13 @@ test.register_message_test(
219236
-- direction = "send",
220237
-- message = mock_device:generate_test_message("main", capabilities.temperatureAlarm.temperatureAlarm.cleared())
221238
-- },
239+
{
240+
channel = "capability",
241+
direction = "send",
242+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
243+
"heat", "eco"
244+
}, {visibility={displayed=false}}))
245+
},
222246
{
223247
channel = "zwave",
224248
direction = "receive",
@@ -248,6 +272,13 @@ test.register_message_test(
248272
-- direction = "send",
249273
-- message = mock_device:generate_test_message("main", capabilities.temperatureAlarm.temperatureAlarm.cleared())
250274
-- },
275+
{
276+
channel = "capability",
277+
direction = "send",
278+
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
279+
"heat", "eco"
280+
}, {visibility={displayed=false}}))
281+
},
251282
{
252283
channel = "zwave",
253284
direction = "receive",
@@ -265,7 +296,7 @@ test.register_message_test(
265296
)
266297

267298
test.register_message_test(
268-
"Supported thermostat modes report should generate an event with heat and eco, regardless of content",
299+
"Supported thermostat modes report should generate nothing",
269300
{
270301
{
271302
channel = "zwave",
@@ -275,13 +306,6 @@ test.register_message_test(
275306
cool = true,
276307
energy_save_heat = true
277308
})) }
278-
},
279-
{
280-
channel = "capability",
281-
direction = "send",
282-
message = mock_device:generate_test_message("main", capabilities.thermostatMode.supportedThermostatModes({
283-
"heat", "eco"
284-
}, {visibility={displayed=false}}))
285309
}
286310
}
287311
)

0 commit comments

Comments
 (0)