Use of the function def


(Arno) #1

Hi there,

i would like to understand more about the “def” function.
Please see below the part of my code i do not understand:

def modeChangeHandler(evt)
{
log.trace "modeChangeHandler $evt.name: $evt.value ($closeModeSet)"
log.trace "Mode is now ${location.mode}."
if (evt.value in closeModeSet)
{
log.debug "Mode changed to $evt.value."
def triggeredMode = "$evt.value"
log.debug "Mode triggered: $triggeredMode"
closeMode()
}
}
def closeMode()
{
log.debug "Closing Garage Door when entering mode $triggeredMode…"
sendPush “$doorSensor is closing when entering mode $triggeredMode…”
}

I would like to display $triggeredMode pulled from the modeChangeHandler(evt) in closeMode(). it looks like the “def” function does not work across sections of the app…

What should i do? I might have to use the “private” fonction but i am not sure how to use it.

Please let me know…


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #2

Could you post the whole code or link to the code, please?

I can perhaps help explain the difference better in full context.

Surround pasted code with three back quotes to get pre formatting (```)


(Arno) #3

definition(
name: “Test”,
namespace: “Arno”,
author: “Arno”,
description: “Testing…”,
category: “Safety & Security”,
iconUrl: “http://solutionsetcetera.com/stuff/STIcons/GDO.png”,
iconX2Url: “http://solutionsetcetera.com/stuff/STIcons/GDO@2x.png
)

preferences
{
section(“Test”)
{
input “closeModeAsk”, “bool”, title: “Garage door closing when entering specific mode”, required: true
input “closeModeSet”, “mode”, title: “Mode?”, required: false, multiple: true
}
}

def installed()
{
log.debug "Installed with settings: ${settings}"
unsubscribe()
subscribeToEvents()
initialize()
}

def updated()
{
log.debug "Updated with settings: ${settings}"
unsubscribe()
unschedule()
subscribeToEvents()
initialize()
}

def subscribeToEvents()
{
if (closeModeSet)
{
subscribe(location, modeChangeHandler)
}
}

def initialize()
{
if (closeModeAsk == true && closeModeSet != null && closeModeSet != “”)
{
log.debug “Garage door scheduled to close when entering one of these modes: $closeModeSet.”
}
}

def modeChangeHandler(evt)
{
log.trace "modeChangeHandler $evt.name: $evt.value ($closeModeSet)"
log.trace "Mode is now ${location.mode}."
if (evt.value in closeModeSet)
{
log.debug "Mode changed to $evt.value."
def triggeredMode = "$evt.value"
log.debug "Mode triggered: $triggeredMode."
closeMode()
}
}

def closeMode()
{
log.debug "Closing Garage Door when entering mode $triggeredMode…"
sendPush “$doorSensor is closing when entering mode $triggeredMode…”
}


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #4

Thanks for pasting in the full code… I have an idea of what may be going wrong…

def” is a Groovy language shortcut (not a function) for defining a variable, object, function without specifying its datatype. “private def” is similar, it just limits the access to members of the same class, like in Java.

Frankly, variable scope in Groovy is somewhat confusing to me since I prefer strict languages like Java that enforce datatypes; and because Groovy is a “scripting-like” language, it has quirks I need to learn more about. (Reference: http://groovy.codehaus.org/Scoping+and+the+Semantics+of+“def”)

Suggested Fix:

Indulge me a let’s ignore the confusing and complexity for a moment and try this fix:

Every SmartApp comes with an object called state that is available throughout the entire scope of the SmartApp, and also is persistent (data is saved and recalled from database storage automatically). It is documented in the SmartApp Guide: http://docs.smartthings.com/en/latest/smartapp-developers-guide/state.html

So try, please:

state.triggeredMode = ..., and you will find that no def is required. (i.e., you can create as many attributes inside state as you want to, on the fly, without definition). Just always refer to them with the “state.” prefix.

Give that a try and let me know?

…Terry.


(Keith Croshaw) #5

Pardon my barging in on the topic. I’m used to strict languages as well, so would state be someplace I could put a global variable? to the app at least, accessible by and subroutine?


(Brice; SmartRulesApp.com) #6

Yes, in my experience, it seems like you can write into “state” for “globals” within your SmartApp.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #7

Yup!

If I understand SmartThings + Groovy correctly in this context, a SmartApp is only a set of metadata (definition, prefereces{}, etc.) and a set of methods (installed(), etc.); thus there is no place to declare your own global variables.

So you must use the existing variables, and we have been provided with “state”, which is a global, persistent, and extensible list object.


(Keith Croshaw) #8

Thanks, I’ll start messing with that. Any idea where to find some examples? Also is this isn’t global to my location correct? Just the SmartApp?


(Keith Croshaw) #9

Actually found some in the documentation, thanks!


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #10

Right… There are no accessible globals between apps or device handlers, even on the same account, location, or hub.


(Arno) #12

You guys are grea,t i am sorry to be such a noob!

i guess it was an easy fix for you experts! :smile:

A BIG Thank You!!!


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #13

My / our pleasure!

Welcome to the Community – I’m sure you’ll contribute some great things too!

Cheers,
…CP / Terry.


(Keith Croshaw) #14

I’ve been brute forcing my way through my first app so far, you’re not the only noob here. I wrapped my code in another app called Pollster because I had a problem getting subscriptions and scheduling to work.