Dynamic preference

Hi,

I'm writing a thermostat driver that has an option in the preference menu to set Fahrenheit or Celsius based temperature. Based on that information, I would like to set a specific range of temperatures for minimum and maximum set points also in the preference menu (5 to 30 Celsius or 41 to 86 Fahrenheit). How could I do that as a dynamic option?

Thanks in advance!

What's the reason for wanting / needing to set the scale (Fahrenheit or Celsius)? Is it to account for potential differences in the setup of the thermostat being integrated, or the different scale on the HE hub? Depending on why you want to do it may offer up different alternatives...

I'm trying to mimic all the options the thermostat provides in its website for setting it up to make it local and supporting all the features on the webpage.

1 Like

In that case I'm guessing you want to detect a change in the scale and adjust the temperatures in response to that change of scale, is that right?

Yeah, the thermostat provides a feature where you can predefined a minimum and maximum temperatures that the manual control on the thermostat itself can be set to.

I'm thinking I might leave it for others to offer suggestions, but if you get stuck you could set the scale up as an attribute and have a command to change, then you can do the conversion inside the command / method (the temperature settings could still be preferences, state variables or attributes). Not ideal and I only offer that up because I'm not sure what method is called when preferences are changed, if any.

That and the fact my internet decided to drop out mid-conversation....:tired_face:

1 Like

You can use all the dynamic capabilities of Groovy when writing the preferences { ... } in your driver. The biggest catch is that, unlike dynamic pages in apps, drivers do not have similar functionality to allow things like submitOnChange: true (if you're familiar with that). So, the user has to save preferences after switching units before the other preferences will be able to correctly read this value and adjust accordingly.

Here's a minimal example for you:

metadata {
   definition (name: "TEST - Dynamic Range", namespace: "RMoRobert", author: "Robert Morris") {
      capability "Actuator"
   }
   
   preferences {
      input name: "pref1",
            type: "enum",
            title: "Choose C or F (save preferences after selection):",
            options: ["C", "F"]
      input name: "pref2",
            type: "number",
            title: "Test for range:",
            range: (pref1 == "C") ? "5..30" : "41..86"
   }
}
3 Likes

That's exactly what I was looking for. I'm going to try it out. Thank you!

It should also be noted that, for this particular use case, it is common for apps and drivers to respect the temperature scale set at the location level so users don't have to choose in the app/driver.

To facilitate this, there are a few helper methods available in the Common Methods (These methods can be used in both Apps and Drivers):
https://docs.hubitat.com/index.php?title=Common_Methods_Object#getTemperatureScale
See:
getTemperatureScale
celsiusToFahrenheit
fahrenheitToCelsius

(undocumented; thanks @sburke781 ) String convertTemperatureIfNeeded(BigDecimal value, String scale, Integer precision)

4 Likes

There is also the covert if needed method as well.

2 Likes

Thanks. I thought there was another I was forgetting. I Updated my post above.

2 Likes

Thanks, your solution worked. The only minor problem now is when I try to set a default value based on the scale. When changing from Celsius to Fahrenheit (or vice-versa) the default value value is not taken into account and the interface show as if nothing was set requiring to update the value before saving when the save button is pressed. I guess I can live with that if there is no solution.

Download the Hubitat app