Skip to content

Matter Thermostat driver ignores configurable Min/Max heating and cooling setpoint limits #3263

Open

Description

@ldeora

Summary

The Matter Thermostat driver uses only the absolute setpoint limits (AbsMin* / AbsMax*) for SmartThings range events and command validation. It does not handle the configurable limits:

  • MinHeatSetpointLimit
  • MaxHeatSetpointLimit
  • MinCoolSetpointLimit
  • MaxCoolSetpointLimit

This can make the SmartThings range wider than the range currently permitted by the Matter device and can cause the driver to send a setpoint write that the device rejects with CONSTRAINT_ERROR.

Validated against main commit 43f47501b217336d17ed2fc92b64d08971f305ce.

Current implementation

In drivers/SmartThings/matter-thermostat/src/init.lua, the Thermostat handlers and subscriptions include only the absolute limits:

clusters.Thermostat.attributes.AbsMinHeatSetpointLimit
clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit
clusters.Thermostat.attributes.AbsMinCoolSetpointLimit
clusters.Thermostat.attributes.AbsMaxCoolSetpointLimit

The resulting cached limits are then used by attribute_handlers.lua for range events and by capability_handlers.lua for command validation.

Reproduction

For a heating thermostat reporting:

AbsMinHeatSetpointLimit =  5.00 C
AbsMaxHeatSetpointLimit = 30.00 C
MinHeatSetpointLimit    = 10.00 C
MaxHeatSetpointLimit    = 25.00 C

the driver currently exposes/validates against 5-30 C.

A setHeatingSetpoint(7) command therefore passes local validation even though 7 C is below the device's configured MinHeatSetpointLimit and may be rejected by the device.

The same issue applies to cooling.

Expected behavior

If configurable limits are supported and reported, they should define the effective SmartThings setpoint range and command-validation range. The absolute limits should remain the hard/fallback bounds.

Proposed fix

Keep absolute and configurable limits separately, subscribe to both, and prefer the configurable value when calculating the effective limit.

For example:

-- fields.lua
ABS_MIN_HEAT = "ABS_MIN_HEAT"
ABS_MAX_HEAT = "ABS_MAX_HEAT"
ABS_MIN_COOL = "ABS_MIN_COOL"
ABS_MAX_COOL = "ABS_MAX_COOL"

Register the configurable attributes in init.lua in addition to the existing absolute ones:

[clusters.Thermostat.attributes.MinHeatSetpointLimit.ID] =
  attribute_handlers.heat_setpoint_limit_factory(fields.setpoint_limit_device_field.MIN_HEAT),

[clusters.Thermostat.attributes.MaxHeatSetpointLimit.ID] =
  attribute_handlers.heat_setpoint_limit_factory(fields.setpoint_limit_device_field.MAX_HEAT),

[clusters.Thermostat.attributes.MinCoolSetpointLimit.ID] =
  attribute_handlers.cool_setpoint_limit_factory(fields.setpoint_limit_device_field.MIN_COOL),

[clusters.Thermostat.attributes.MaxCoolSetpointLimit.ID] =
  attribute_handlers.cool_setpoint_limit_factory(fields.setpoint_limit_device_field.MAX_COOL),

and add them to the corresponding subscribed_attributes entries.

A common helper can then be used by both range emission and command validation:

function ThermostatUtils.get_effective_setpoint_limit(
    device, configured_field, absolute_field, default_value)
  return device:get_field(configured_field)
      or device:get_field(absolute_field)
      or default_value
end

For heating:

local min = thermostat_utils.get_effective_setpoint_limit(
  device,
  fields.setpoint_limit_device_field.MIN_HEAT,
  fields.setpoint_limit_device_field.ABS_MIN_HEAT,
  MIN_TEMP_IN_C
)

local max = thermostat_utils.get_effective_setpoint_limit(
  device,
  fields.setpoint_limit_device_field.MAX_HEAT,
  fields.setpoint_limit_device_field.ABS_MAX_HEAT,
  MAX_TEMP_IN_C
)

The same logic applies to cooling.

If this is combined with the separate multi-endpoint state fix, these fields should be stored/read per thermostat endpoint rather than device-wide.

Regression test

With absolute heat limits 5-30 C and configurable limits 10-25 C, verify that:

  • the emitted SmartThings range is 10-25 C;
  • 7 C and 28 C are rejected locally;
  • a value inside 10-25 C is written;
  • a device without configurable-limit reports still falls back to the absolute limits.

Activity

  1. ldeora commented on Oct 8, 2026

    @ldeora
    Author

    Additional real-device observation

    I tested a modified version of the Matter Thermostat driver with a heating-only thermostat on endpoint 0x09.

    The device reports:

    AbsMinHeatSetpointLimit = 500  (5 °C)
    AbsMaxHeatSetpointLimit = 3000 (30 °C)
    

    However, its AttributeList does not contain any of the four configurable setpoint-limit attributes:

    • MinHeatSetpointLimit
    • MaxHeatSetpointLimit
    • MinCoolSetpointLimit
    • MaxCoolSetpointLimit

    When the modified driver requests these attributes, the device returns UNSUPPORTED_ATTRIBUTE for all four.

    The driver correctly falls back to the absolute limits and exposes a heating range of 5–30 °C.

    This does not reproduce the original defect, which concerns devices that do support configurable limits. However, it confirms an important requirement for the proposed fix: configurable limits must take precedence when supported, while devices without them must continue to use the absolute limits.

    Ideally, requests and subscriptions for these optional attributes should also be filtered against the endpoint's AttributeList to avoid unnecessary UNSUPPORTED_ATTRIBUTE responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions