Skip to content

Commit

Permalink
Chad 12671 (#1354)
Browse files Browse the repository at this point in the history
Dynamically request and set heat/cool min/max setpoints for zigbee thermosts

If the device supports these attributes
  • Loading branch information
matthewdehaven authored Oct 18, 2024
1 parent be23f51 commit ea0625d
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 1 deletion.
44 changes: 43 additions & 1 deletion drivers/SmartThings/zigbee-thermostat/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,40 @@ local thermostat_mode_setter = function(mode_name)
end
end

local setpoint_limit_handler_factory = function(min_or_max, heat_or_cool)

local field = 'setpoint_' .. min_or_max .. '_' .. heat_or_cool
local paired_field = 'setpoint_min_' .. heat_or_cool
if min_or_max == 'min' then
paired_field = 'setpoint_max_' .. heat_or_cool
end

return function(driver, device, setpoint)
local celsius_value = setpoint.value / 100.0
device:set_field(field, celsius_value)
if device:get_field(field) and device:get_field(paired_field) then

local event_constructor = capabilities.thermostatHeatingSetpoint.heatingSetpointRange
if heat_or_cool == 'cool' then
event_constructor = capabilities.thermostatCoolingSetpoint.coolingSetpointRange
end

device:emit_event(event_constructor(
{
unit = 'C',
value = {
minimum = device:get_field('setpoint_min_' .. heat_or_cool),
maximum = device:get_field('setpoint_max_' .. heat_or_cool)
}
}
))

device:set_field(field, nil)
device:set_field(paired_field, nil)
end
end
end

local set_thermostat_fan_mode = function(driver, device, command)
for zigbee_attr_val, st_cap_val in pairs(FAN_MODE_MAP) do
if command.args.mode == st_cap_val.NAME then
Expand Down Expand Up @@ -235,6 +269,10 @@ local do_refresh = function(self, device)
Thermostat.attributes.ControlSequenceOfOperation,
Thermostat.attributes.ThermostatRunningState,
Thermostat.attributes.SystemMode,
Thermostat.attributes.MinHeatSetpointLimit,
Thermostat.attributes.MaxHeatSetpointLimit,
Thermostat.attributes.MinCoolSetpointLimit,
Thermostat.attributes.MaxCoolSetpointLimit,
FanControl.attributes.FanModeSequence,
FanControl.attributes.FanMode,
PowerConfiguration.attributes.BatteryVoltage,
Expand Down Expand Up @@ -280,7 +318,11 @@ local zigbee_thermostat_driver = {
[Thermostat.attributes.ControlSequenceOfOperation.ID] = supported_thermostat_modes_handler,
[Thermostat.attributes.ThermostatRunningState.ID] = thermostat_operating_state_handler,
[Thermostat.attributes.ThermostatRunningMode.ID] = thermostat_mode_handler,
[Thermostat.attributes.SystemMode.ID] = thermostat_mode_handler
[Thermostat.attributes.SystemMode.ID] = thermostat_mode_handler,
[Thermostat.attributes.MinHeatSetpointLimit.ID] = setpoint_limit_handler_factory('min', 'heat'),
[Thermostat.attributes.MaxHeatSetpointLimit.ID] = setpoint_limit_handler_factory('max', 'heat'),
[Thermostat.attributes.MinCoolSetpointLimit.ID] = setpoint_limit_handler_factory('min', 'cool'),
[Thermostat.attributes.MaxCoolSetpointLimit.ID] = setpoint_limit_handler_factory('max', 'cool'),
},
[FanControl.ID] = {
[FanControl.attributes.FanModeSequence.ID] = supported_fan_modes_handler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,62 @@ test.register_message_test(
}
)

test.register_message_test(
"Thermostat cooling setpoint bounds are handled",
{
{
channel = "zigbee",
direction = "receive",
message = { mock_device.id, Thermostat.attributes.MinCoolSetpointLimit:build_test_attr_report(mock_device,
1000)}
},
{
channel = "zigbee",
direction = "receive",
message = { mock_device.id, Thermostat.attributes.MaxCoolSetpointLimit:build_test_attr_report(mock_device,
3500)}
},
{
channel = "capability",
direction = "send",
message = mock_device:generate_test_message("main", capabilities.thermostatCoolingSetpoint.coolingSetpointRange(
{
unit = 'C',
value = {minimum = 10.0, maximum = 35.0}
}
))
}
}
)

test.register_message_test(
"Thermostat heating setpoint bounds are handled",
{
{
channel = "zigbee",
direction = "receive",
message = { mock_device.id, Thermostat.attributes.MinHeatSetpointLimit:build_test_attr_report(mock_device,
1000)}
},
{
channel = "zigbee",
direction = "receive",
message = { mock_device.id, Thermostat.attributes.MaxHeatSetpointLimit:build_test_attr_report(mock_device,
3500)}
},
{
channel = "capability",
direction = "send",
message = mock_device:generate_test_message("main", capabilities.thermostatHeatingSetpoint.heatingSetpointRange(
{
unit = 'C',
value = {minimum = 10.0, maximum = 35.0}
}
))
}
}
)

test.register_coroutine_test(
"Supported thermostat modes reports are handled",
function()
Expand Down Expand Up @@ -607,6 +663,38 @@ test.register_message_test(
Thermostat.attributes.SystemMode:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MinHeatSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MaxHeatSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MinCoolSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MaxCoolSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
Expand Down Expand Up @@ -698,6 +786,38 @@ test.register_message_test(
Thermostat.attributes.SystemMode:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MinHeatSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MaxHeatSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MinCoolSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
message = {
mock_device.id,
Thermostat.attributes.MaxCoolSetpointLimit:read(mock_device)
}
},
{
channel = "zigbee",
direction = "send",
Expand Down

0 comments on commit ea0625d

Please sign in to comment.