Virtual Thermostat - temp range broken?

What’s happening with the virtual thermostat device?


Something is clearly wrong here …

The native virtual thermostat device? Try to set the values through a routine.

Is this one of the native ones and is it freshly setup? If that’s a yes and yes then I suspect that it remains the case that as part of their creation process they get initialised with synthetic events which seem to be random and often improbable in the real world. This was something that started a while back. I found it particularly annoying that they did it with custom virtual devices as well as the standard ones as I was already handling that.

The bottom line is that you may need to initialise the attributes to sensible values yourself. That includes the valid values.

If it is a previously working device then that’s another matter.

Yes, the native virtual thermostat. And no, I can’t just set the values using a routine because the range of accepted “valid” values appears to be completely out of whack…

You need to use the CLI (or the API in some other way) to set the values.

Nope, doesn’t work. Get “unprocessable entity” error when trying a POST command.

Again, this would clearly seem to be because the accepted range is broken - and indeed, appears to return as “[object Object],” which can’t be a good sign!

*Update: so I can manually set a set point through the CLI, but it still shows as “out of range” & can’t be adjusted in the app.

It shouldn’t be broken but it is unlikely to be what you want until you have set it yourself.

The range you mean?

I’ve tried to change that through the CLI, but it won’t take. Do you happen to know how I can go about setting it properly?

To be specific, I’ve tried setting the range value to [0,100], which the CLI accepts, but the value for the device range attribute doesn’t change. (I’ve also tried various other numbers and also null and also including a step value…)

I think it helps to delve into the Device Object. I tend to use YAML when working with the CLI but in this case JSON is probably a better bet.

> st devices:status dcbef186-de4a-478b-8491-a949db27ed15 -j
{
    "components": {
        "main": {
            "thermostatOperatingState": {
                "supportedThermostatOperatingStates": {
                    "value": null
                },
                "thermostatOperatingState": {
                    "value": "cooling",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                }
            },
            "thermostatHeatingSetpoint": {
                "heatingSetpoint": {
                    "value": 3488.742297519437,
                    "unit": "F",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "heatingSetpointRange": {
                    "value": {
                        "maximum": 3172.7486900591894,
                        "step": 9352.068174000222,
                        "minimum": 2511.107519266267
                    },
                    "unit": "F",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                }
            },
            "temperatureMeasurement": {
                "temperatureRange": {
                    "value": {
                        "maximum": 1472.3277964062681,
                        "step": 3069.548365505363,
                        "minimum": 5436.449358625785
                    },
                    "unit": "F",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "temperature": {
                    "value": 8065.069520923942,
                    "unit": "F",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                }
            },
            "thermostatFanMode": {
                "thermostatFanMode": {
                    "value": "auto",
                    "data": {},
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "supportedThermostatFanModes": {
                    "value": null
                }
            },
            "thermostatMode": {
                "thermostatMode": {
                    "value": "bath",
                    "data": {},
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "supportedThermostatModes": {
                    "value": null
                }
            },
            "battery": {
                "quantity": {
                    "value": 50,
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "battery": {
                    "value": 100,
                    "unit": "%",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                },
                "type": {
                    "value": "25500",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                }
            },
            "thermostatCoolingSetpoint": {
                "coolingSetpointRange": {
                    "value": {
                        "maximum": 100,
                        "minimum": 0,
                        "step": 1
                    },
                    "unit": "C",
                    "timestamp": "2025-07-19T21:07:40.672Z"
                },
                "coolingSetpoint": {
                    "value": 7632.650490536766,
                    "unit": "F",
                    "timestamp": "2025-07-19T20:56:55.533Z"
                }
            }
        }
    }
}

That gives an idea of what needs fixing and suggests the format of the input. As an example I’ve tried to make the cooling setpoint range less ridiculous. It seems the CLI is smart enough to prompt for the value and unit of the attribute object separately.

> smartthings virtualdevices:events dcbef186-de4a-478b-8491-a949db27ed15
──────────────────────────────
 #  Id
──────────────────────────────
 1  battery
 2  temperatureMeasurement
 3  thermostatCoolingSetpoint
 4  thermostatFanMode
 5  thermostatHeatingSetpoint
──────────────────────────────
 6  thermostatMode
 7  thermostatOperatingState
──────────────────────────────
? Select a capability. 3
─────────────────────────
 #  Attribute Name
─────────────────────────
 1  coolingSetpoint
 2  coolingSetpointRange
─────────────────────────
? Select an attribute. 2
? Enter 'coolingSetpointRange' attribute value: { "maximum": 100, "minimum": 0, "step": 1 }
─────────
 #  Unit
─────────
 1  C
 2  F
─────────
? Select a unit. 1
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Component  Capability                 Attribute             Value                                 State Change?
 main       thermostatCoolingSetpoint  coolingSetpointRange  {"maximum":100,"minimum":0,"step":1}  undefined
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note that I added the device status (shown earlier) after I had already made the above change.

I shall also concede that I was being far too generous previously. If allowing the device to be initialised with a range where the minimum is higher than the maximum, and then where the value is outside the range, isn’t broken behaviour I don’t know what is.

If it is considered desirable to initialise the attribute values then it should be to sensibly designed values, not ridiculous random floating point numbers with a bazillion decimal places.

Thanks, I really appreciate your comprehensive assistance! So following your guidance I was able to adjust the range and I’m no longer seeing the out of range error …BUT I’m still not able to adjust the set points through the app (routines also still dont work).

The new error is a generic “network or server error” box:

Is there something else I need to initialize / tweak?

You could paste the device status here. See the first smartthings CLI command in the comment above.

Edit: there’s so much wrong with it. supportedThermostatOperatingStates and supportedThermostatFanModes is empty, as well as supportedThermostatModes, but the thermostatMode is set to bath

The thing is I’m able to adjust the thermostat mode and fan mode in the app without any problem. The only values I can’t adjust are the two setpoints…

I took a brief look in the app and it seemed particularly confused with the temperature units, displaying the cooling setpoint range as F when it was set to C.

After several years the mobile app still seems to particularly struggle with temperature units.

Another baffling thing. Why on earth initialise all the units on my virtual device to F when my Location default is C?

Hi @jghoffer just to confirm, did you create the Virtual Thermostat using the Advanced Users app? We’re checking to make sure you’re using the standard version of the driver.

Thanks!

I created it using the “advanced” web portal (my,smartthings,com/advanced).

Could you please let me know the name of your device so I can proceed with the investigation?

I appreciate the effort, but don’t worry about it. It’s not worth the nonsense so I deleted it — and I’m not especially motivated to recreate it!

Hi @Itati,

I created a Virtual Thermostat using the “Advanced” part of the my.smartthings.com portal.

The device id is 1779377b-1098-48e2-a833-f4e2de5cc8e0.

These are the attributes of the device:

[
    {
        "component": "main",
        "capability": "battery",
        "attribute": "battery",
        "value": 100,
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "battery",
        "attribute": "quantity",
        "value": 34,
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "battery",
        "attribute": "type",
        "value": "67v5",
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "temperatureMeasurement",
        "attribute": "temperature",
        "value": 1786.9673965681777,
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "temperatureMeasurement",
        "attribute": "temperatureRange",
        "value": {
            "maximum": 5177.557504370481,
            "step": 5376.912904603048,
            "minimum": 8470.396104225656
        },
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "thermostatCoolingSetpoint",
        "attribute": "coolingSetpoint",
        "value": 4500.605380814425,
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "thermostatCoolingSetpoint",
        "attribute": "coolingSetpointRange",
        "value": {
            "maximum": 207.61327835303655,
            "step": 5456.32309044133,
            "minimum": 1800.5152318808587
        },
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "thermostatFanMode",
        "attribute": "supportedThermostatFanModes",
        "value": null
    },
    {
        "component": "main",
        "capability": "thermostatFanMode",
        "attribute": "thermostatFanMode",
        "value": "followschedule",
        "timestamp": "2026-02-03T11:30:37.378Z"
    },
    {
        "component": "main",
        "capability": "thermostatHeatingSetpoint",
        "attribute": "heatingSetpoint",
        "value": 20,
        "timestamp": "2026-02-03T11:30:49.904Z"
    },
    {
        "component": "main",
        "capability": "thermostatHeatingSetpoint",
        "attribute": "heatingSetpointRange",
        "value": {
            "maximum": 4854.634384996987,
            "step": 1229.4805005275737,
            "minimum": 1493.3880908551782
        },
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "thermostatMode",
        "attribute": "supportedThermostatModes",
        "value": null
    },
    {
        "component": "main",
        "capability": "thermostatMode",
        "attribute": "thermostatMode",
        "value": "hot",
        "timestamp": "2026-02-03T08:15:40.439Z"
    },
    {
        "component": "main",
        "capability": "thermostatOperatingState",
        "attribute": "supportedThermostatOperatingStates",
        "value": null
    },
    {
        "component": "main",
        "capability": "thermostatOperatingState",
        "attribute": "thermostatOperatingState",
        "value": "vent economizer",
        "timestamp": "2026-02-03T08:15:40.439Z"
    }
]

If you want fix odd ranges you can try to use smartthings CLI and @orangebucket instructions