New to ST, Groovy - global defs?


(Kevin Carney) #1

How do you properly define a Global/Instance variable in ST/Groovy?

I’m trying to :
Send a notification when a temperature sensor is past a maximum
Then continue sending reminders every 5 minutes until…
The temperature falls 3 degrees under the maximum
send a final text saying temperature is OK.

I could do this in a dozen different languages in 5 seconds but I’m new to Groovy and even newer to SmartThings implementation of Groovy.

Here’s the logic I’m trying to translate into groovy:

preferences {
    section("Temperature Sensors"){
	input "temperatureSensor", "capability.temperatureMeasurement", title: "Choose Sensor"
   } 
    section("Temperature"){
        input "maxTemperature", "decimal", title: "Maximum Temperature"
   }     
    section("Contacting You"){
    	input "phone1", "phone", title: "Phone Number", required: false
        input "phone2", "phone", title: "Alternate Phone Number", required: false
   }
}
def installed() {
    subscribe(temperatureSensor, "temperature", eTemperatureHandler) 
}
def updated() {
    unsubscribe()
    subscribe(temperatureSensor, "temperature", eTemperatureHandler)
}
def tooHot = false;/*apparently this is not ok.....*/
def sendNotifHi(){
    def currentTemperature =temperatureSensor.latestValue("temperature")
    sendSms(phone1,"Not Good...")
}
def eTemperatureHandler(evt){  
        if(currentTemperature > maxTemperature && !tooHot){
            /*send initial warning*/
            sendSms(phone1, "The ${location.name} temperature is ${temperatureSensor.latestValue("temperature")} degrees Farenheit.")
            /*schedule a text for every 5 minutes*/
            runEvery5Minutes(sendNotifHi)
            tooHot = true
        } 
        if(currentTemperature < maxTemperature-3 && tooHot)
        {
            sendSms(phone1,"All Good...")
            unschedule() /*remove scheduled texts*/
            tooHot = false
        }
}

tooHot is always null, and if I set tooHot at the beginning of the temperaturehandler I get a missing property exception. How do I get this logic to work in SmartThings?

Thanks!


(Jim Anderson) #2

Hey @Milsoft, that’s a great question, and one that comes up often when new to SmartThings.

It’s not a Groovy thing, but rather a function of the fact that SmartApps don’t continuously run, but instead are executed according to certain events or schedules. To store data across those executions, you can use the state variable available in every SmartApp:

state.myvar = "myvalue"

And then get it back like this: state.mybar // returns "myvalue"

You can read more about it here: http://docs.smartthings.com/en/latest/smartapp-developers-guide/state.html


(Kevin Carney) #3

Very helpful, thank you!

but…
I keep getting an error when trying to use the simulator now…

grails.validation.ValidationException: Validation Error(s) occurred during save():

  • Field error in object ‘physicalgraph.app.InstalledSmartApp’ on field ‘state’: rejected value [COMPLETE];

I added the ‘state.’ prefix to everywhere I reference tooHot and moved my ‘global variable’ to both the installed() and updated() methods…


(John S) #4

Repost the code… the initial use of state does NOT have a def, so in installed or updated initialize it as

state.tooHot = false

and then just use state.tooHot elsewhere as needed


(Kevin Carney) #5

yeah, that’s how I’m using it.

I think the simulator might just be acting up… Im running code now after saving/publishing a bunch…

Thank you so much!!!


(Patrick Stuart [@pstuart]) #6

Globals beyond state are kind of allowed.

You could do this:

def tooHot() {
return false
}

so it could be accessed later as

def isHot = tooHot()

But ultimately state vars are a better and more accessible way to go.


#8

Sorry, a little late to the convo, but having this same issue. Is there really no way to have constant global variables? I want a global “debug” variable that disables code that activates devices, routines, and push notifications. Reading this post (link below) about groovy global vars, you’re supposed to be able to have global vars that aren’t "def"ed. However it doesn’t work in ST. I am using the def debug() { return true } but then if (!debug) always returns false. Have to use if(!debug())… just a little annoying…

Edit: Hmm… this does appear to work…

import groovy.transform.Field
@Field debug = true