diff --git a/drivers/SmartThings/zwave-thermostat/src/init.lua b/drivers/SmartThings/zwave-thermostat/src/init.lua index 22ad3cdf43..ed3e1d6c0f 100755 --- a/drivers/SmartThings/zwave-thermostat/src/init.lua +++ b/drivers/SmartThings/zwave-thermostat/src/init.lua @@ -25,9 +25,20 @@ local ThermostatFanMode = (require "st.zwave.CommandClass.ThermostatFanMode")({v local ThermostatMode = (require "st.zwave.CommandClass.ThermostatMode")({version=2}) --- @type st.zwave.CommandClass.ThermostatSetpoint local ThermostatSetpoint = (require "st.zwave.CommandClass.ThermostatSetpoint")({version=1}) +local ThermostatSetpointV3 = (require "st.zwave.CommandClass.ThermostatSetpoint")({version=3}) local constants = require "st.zwave.constants" local utils = require "st.utils" +local function device_supports_thermostat_setpoint(device) + return ( + ( + device:supports_capability_by_id(capabilities.thermostatCoolingSetpoint.ID) or + device:supports_capability_by_id(capabilities.thermostatHeatingSetpoint.ID) + ) and + device:is_cc_supported(cc.THERMOSTAT_SETPOINT) + ) +end + local function device_added(driver, device) if device:supports_capability_by_id(capabilities.thermostatMode.ID) and device:is_cc_supported(cc.THERMOSTAT_MODE) then @@ -37,6 +48,10 @@ local function device_added(driver, device) device:is_cc_supported(cc.THERMOSTAT_FAN_MODE) then device:send(ThermostatFanMode:SupportedGet({})) end + if device_supports_thermostat_setpoint(device) then + device:send(ThermostatSetpointV3:CapabilitiesGet({setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1})) + device:send(ThermostatSetpointV3:CapabilitiesGet({setpoint_type = ThermostatSetpoint.setpoint_type.COOLING_1})) + end device:refresh() end @@ -87,6 +102,33 @@ local function set_setpoint_factory(setpoint_type) end end +local function setpoint_capabilites_report(driver, device, cmd) + local args = cmd.args + local min_temp = args.min_value + local max_temp = args.max_value + + local scale = 'C' + if args.scale1 == ThermostatSetpoint.scale.FAHRENHEIT then + scale = 'F' + end + + local capability_constructor = nil + if args.setpoint_type == ThermostatSetpoint.setpoint_type.HEATING_1 then + capability_constructor = capabilities.thermostatHeatingSetpoint.heatingSetpointRange + elseif args.setpoint_type == ThermostatSetpoint.setpoint_type.COOLING_1 then + capability_constructor = capabilities.thermostatCoolingSetpoint.coolingSetpointRange + end + + if capability_constructor then + device:emit_event_for_endpoint(cmd.src_channel, capability_constructor( + { + unit = scale, + value = {minimum = min_temp, maximum = max_temp} + } + )) + end +end + local driver_template = { supported_capabilities = { capabilities.temperatureAlarm, @@ -109,6 +151,11 @@ local driver_template = { [capabilities.thermostatHeatingSetpoint.commands.setHeatingSetpoint.NAME] = set_setpoint_factory(ThermostatSetpoint.setpoint_type.HEATING_1) } }, + zwave_handlers = { + [cc.THERMOSTAT_SETPOINT] = { + [ThermostatSetpoint.CAPABILITIES_REPORT] = setpoint_capabilites_report + } + }, lifecycle_handlers = { added = device_added }, diff --git a/drivers/SmartThings/zwave-thermostat/src/test/test_zwave_thermostat.lua b/drivers/SmartThings/zwave-thermostat/src/test/test_zwave_thermostat.lua index f57f7cc6cf..189c5b4c7b 100644 --- a/drivers/SmartThings/zwave-thermostat/src/test/test_zwave_thermostat.lua +++ b/drivers/SmartThings/zwave-thermostat/src/test/test_zwave_thermostat.lua @@ -19,6 +19,7 @@ local Battery = (require "st.zwave.CommandClass.Battery")({ version = 1 }) local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version = 5 }) local ThermostatMode = (require "st.zwave.CommandClass.ThermostatMode")({ version = 2 }) local ThermostatSetpoint = (require "st.zwave.CommandClass.ThermostatSetpoint")({ version = 1 }) +local ThermostatSetpointV3 = (require "st.zwave.CommandClass.ThermostatSetpoint")({ version = 3 }) local ThermostatOperatingState = (require "st.zwave.CommandClass.ThermostatOperatingState")({ version = 1 }) local ThermostatFanMode = (require "st.zwave.CommandClass.ThermostatFanMode")({ version = 3 }) local zw = require "st.zwave" @@ -140,6 +141,22 @@ test.register_message_test( ThermostatFanMode:SupportedGet({}) ) }, + { + channel = "zwave", + direction = "send", + message = zw_test_utilities.zwave_test_build_send_command( + mock_device, + ThermostatSetpointV3:CapabilitiesGet({setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1}) + ) + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utilities.zwave_test_build_send_command( + mock_device, + ThermostatSetpointV3:CapabilitiesGet({setpoint_type = ThermostatSetpoint.setpoint_type.COOLING_1}) + ) + }, table.unpack(refresh_commands) }, { @@ -379,6 +396,138 @@ test.register_message_test( } ) +test.register_message_test( + "Thermostat heating setpoint capability reports should be sent to the capabilities channel.", + { + { + channel = "zwave", + direction = "receive", + message = { + mock_device.id, + zw_test_utilities.zwave_test_build_receive_command( + ThermostatSetpointV3:CapabilitiesReport( + { + setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1, + scale1 = ThermostatSetpoint.scale.CELSIUS, + min_value = 7.22, + scale2 = ThermostatSetpoint.scale.CELSIUS, + max_value = 27.2 + } + ) + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.thermostatHeatingSetpoint.heatingSetpointRange( + { + unit = 'C', + value = {minimum = 7.22, maximum = 27.2} + } + ) + ) + }, + { + channel = "zwave", + direction = "receive", + message = { + mock_device.id, + zw_test_utilities.zwave_test_build_receive_command( + ThermostatSetpointV3:CapabilitiesReport( + { + setpoint_type = ThermostatSetpoint.setpoint_type.HEATING_1, + scale1 = ThermostatSetpoint.scale.FAHRENHEIT, + min_value = 44.9, + scale2 = ThermostatSetpoint.scale.FAHRENHEIT, + max_value = 80.9 + } + ) + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.thermostatHeatingSetpoint.heatingSetpointRange( + { + unit = 'F', + value = {minimum = 44.9, maximum = 80.9} + } + ) + ) + } + } +) + +test.register_message_test( + "Thermostat cooling setpoint capability reports should be sent to the capabilities channel.", + { + { + channel = "zwave", + direction = "receive", + message = { + mock_device.id, + zw_test_utilities.zwave_test_build_receive_command( + ThermostatSetpointV3:CapabilitiesReport( + { + setpoint_type = ThermostatSetpoint.setpoint_type.COOLING_1, + scale1 = ThermostatSetpoint.scale.CELSIUS, + min_value = 7.22, + scale2 = ThermostatSetpoint.scale.CELSIUS, + max_value = 27.2 + } + ) + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.thermostatCoolingSetpoint.coolingSetpointRange( + { + unit = 'C', + value = {minimum = 7.22, maximum = 27.2} + } + ) + ) + }, + { + channel = "zwave", + direction = "receive", + message = { + mock_device.id, + zw_test_utilities.zwave_test_build_receive_command( + ThermostatSetpointV3:CapabilitiesReport( + { + setpoint_type = ThermostatSetpoint.setpoint_type.COOLING_1, + scale1 = ThermostatSetpoint.scale.FAHRENHEIT, + min_value = 44.9, + scale2 = ThermostatSetpoint.scale.FAHRENHEIT, + max_value = 80.9 + } + ) + ) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", + capabilities.thermostatCoolingSetpoint.coolingSetpointRange( + { + unit = 'F', + value = {minimum = 44.9, maximum = 80.9} + } + ) + ) + } + } +) + test.register_coroutine_test( "Setting the thermostat fan mode should generate the appropriate commands", function()