Noob questions regarding capturing values from subscriptions and events

Hi guys,

I just did my first ever groovy app by following the instructions and example in the Hubitat documentation (Pls see code below). The goal of the script is eventually to become a thermostate based mainly on outside temperature, outside light levels and inside temperature. The script so far works fine as far as it gets values for outside light and outside temperature every time the sensor is sending a chagned value. But, as you can see it is no where near complete. The next hurdle I am working on now is as follows:

  • The values sent by the sensors disapears as soon as they are reported. (1) I would like to capture them and store them into variables. (2) I would also like to ping the sensor and get the current value and store that, rather than waiting for the sensor to change. I have read a lot in the documentation and tried lots and lots of variation of getcurrentvalue() and state. but seemingly nothing happens or works. I've also looked at the sample code in the Hubitat official GitHub Archive but I to far back knowledge wise to understand. I tried searching for info regarding handlers and there options but not found anything useful yet. The reason I want to do this is to start building the logic based around the paramter values.

Any and all thoughts appreciated.

Thanks for your time and your patiens

 preferences{
    page(name: "mainPage", title: "Heat and cooling control", install: true, uninstall: true) {
            section("GrundlÀggande parametrar", hideable: true, hidden: true) {
            paragraph "VÀrdena nedan styr de brytpunkter dÄ vÀrme alternativt kyla skall slÄs av och 
            pÄ. Appen anvÀnder en kombination av ljusstyrka och temeratur utomhus och eller 
            inomhus för att avgöra nÀr en brytpunkt uppnÄtts."

        input (name: "outside_light_heating_point_v", type: "integer", title: "Ljusbrytpunkt för 
                      uppvÀrmning (Lux)", required: true, defaultValue: 5000)
        input (name: "outside_temp_heating_point_v", type: "integer", title: "Brytpunkt utomhustemperatur för uppvÀrmning (C)", required: true, defaultValue: 10)            
        input (name: "outside_light_cooling_point_v", type: "integer", title: "Ljusbrytpunkt för kylning (Lux)", required: true, defaultValue: 10000)
        input (name: "outside_temp_cooling_point_v", type: "integer", title: "Brytpunkt utomhustemperatur för kylning (C)", required: true, defaultValue: 25)
        input (name: "inside_temp_cooling_point_v", type: "integer", title: "Brytpunkt inomhustemperatur för kylning (C)", required: true, defaultValue: 25)
    }


    section("Temperatursensor", hideable: true, hidden: true) {
        paragraph "VÀlj vilken sensor som skall anvÀndas för att mÀta temperaturen"
        input "tempSensor", "capability.temperatureMeasurement", title: "Select Temperature Sensor", submitOnChange: true, required: true, multiple: false
     }

    section("Ljussensor", hideable: true, hidden: true) {
       paragraph "VÀlj vilken sensor som skall anvÀndas för att mÀta ljusinflödet"
       input "lightSensor", "capability.illuminanceMeasurement", title: "Select Light Sensor", 
 submitOnChange: true, required: true, multiple: false
     }
  }
}

def installed() {
     log.debug "Heatcontroller 0.2: installed()"
 updated()
 }
def updated() {
    log.debug "Heatcontroller 0.2: updated()"
subscribe(tempSensor, "temperature", tempHandler)
    subscribe(lightSensor, "illuminance", lightHandler)
}
def uninstalled() {}

def tempHandler(evt) {
       log.debug "Heatcontroller 0.2: tempHandler() called: ${evt.name} is currently ${evt.value}" 
}

def lightHandler(evt) {
      log.debug "Heatcontroller 0.2: lightHandler() called: ${evt.name} is currently ${evt.value}"
 }
1 Like

Every app (and driver) has a built-in map object called state available to it. This is a method to store values between executions of your app, as normally they will "wake up" in response to a subscription, go sleep, then wake up when something happens again. This lets you persist values between these executions. When you say that you want to "store [the values] into variables," this is probably what you mean. A normal Groovy variable won't do much here since it will disappear the next time your app runs, though technically you could make this work with static field variables--but that's a bit more work and not something you need in 99% of cases.

Regarding this:

This will depend on your device. However, most sensors are battery powered, and this is not the way they work--you'll have to wait for a report. Some might have a refresh() command or something you can run to fetch current values (though if they are battery powered, this may still not do anything, depending on the device). If that works, your app could call this command, wait a few seconds or so for new information to come in, then read the device attributes the normal way--i.e., with getCurrentValue().

Notably, nothing about getCurrentValue() causes the device to do anything; it's just a way to get the current attribute values, as reported by the device to the hub (or really the driver). That is why the above is the only solution you can do at the app level that might help for some devices. This would be a bit unusual; normally, apps just wait for device events. If your device is not reporting how you want, it may be better to look at possible configuration options you can change on the device.

4 Likes

Thank you Bertabcd1234 for taking the time to share your thoughts regarding my app script. I very much appreciate this.

I asumed that when I hade defined and object called tempSensor and the user had defined the sensor to provide the value for tempSensor, that I could write for instance

log.info "state.tempSensor"

and get a value, but that is apparently not how it works? It seems regardless of the syntax the log commande never writes anything in the log, and this makes me unsure if I am using the wrong syntax, the wrong command or why there are never an entriy ?

Regarding storing the current value, I did the thermostate functionality using RM and got it to work reasonably well, but the rule is long and cumbersome to manage. I set a condition that if the light outside is lower than 5000 lux and the outside temperature is lower than 10 degrees, the rule sends a command to the heater to start heating. Using the groovy app script, only one of the values will ever be available at any given time, and, if I understand it correct, the values will disapear when the app has reported one of the values. This is why I want to store or retrieve the second value to be able to make the comparison. So getCurrentValue() or Refresh() is the way forward to get this to succeed as I understand you?
A thought I had to go around the problem with missing values, was to create calls to the two ready made hubitat scripts that calculates a mean for temperature and ilumination and use those values. But I thought it better to learn how to do it on my own first.

Again, thanks for your thoughts.

No, tempSensor, the name that you gave the input, is equivalent to settings.tempSensor, and it refers to the value of the input. In your case, that is the device, not the temperature reading, but it's easy to get that with currentState().

There is also the issue of state, which is just an empty map to start. If you want to store something there, you will need to put it there yourself. You could write state.myValue = 1, for example, and later if you retrieve the value of state.myValue, you'll get back 1. In your case, maybe you want state.lastTemp = tempSensor.currentValue("temperature") or something along those lines.

These are different and mostly unrelated. How did your old rule work? If you weren't running refresh() there, you should not need to do so in your app. The getCurrentValue() method is just a way to get the value of the attribute, as reported by "Current States" on the device detail page (among other ways you might find this information). If that information is always what you want, you do not need to do anything else.

1 Like

Thank you @bertabcd1234 . I will continue this quest tomorrow.

Cheers,

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.