Looking for very simple groovy app example

I have read a bunch of discussions about how all of the things that can be done in Rule Machine could be done in Groovy, but how Rule Machine can make things simpler for those looking to avoid any programming. I am looking for the opposite. If I wanted to put together via Groovy some logic that could just as easily be done in Rule Machine, what would that look like? I would love to see the Groovy App equivalent of this logic from Rule Machine:

5 Likes

I would try to post this in the Developer category, might get a faster reply there.
+1 for the question!

1 Like

I've moved this to a Developer category as suggested above. Hope you don't mind! Hubitat has a few basic app examples on their Github. That may be a good place to start:

Most of these are very simple but will give you an idea of how inputs/preferences and whatnot work. Most of the rest you'd need would be general Groovy knowledge. There at also a ton of community apps you can look at.

4 Likes

It ends up being relatively simple to write apps once you get started, but getting started takes a bit of learning.

I bumped around through the developer docs as well as a lot of really useful existing app code examples from the community (especially @jwetzel1492's for examples of installation and configuration pages for parent and child apps).

Here's a quick example that shows how to do what you have in your RM snippet.
EDIT: @chuck.schwer's example included the unsubscribe() call that I omitted. I edited mine to show that. His is a simpler example, to boot, so you should totally use that one.

   /*

 */

definition(
    name: "Simple Triggered App Instance",
    namespace: "tomw",
    author: "tomw",
    description: "simple triggered app example",
    category: "Convenience",
    iconUrl: "",
    iconX2Url: "",
    iconX3Url: "")

preferences
{
    page(name: "mainPage1")
}

def mainPage1()
{
    dynamicPage(name: "mainPage1", title: "", install: true, uninstall: true)
    {
        section
        {
            input name:	"inputMotionSensors", type: "capability.motionSensor", title: "Input Motion Sensors", multiple: true, required: true
        }
        section
        {
            input name:	"outputSwitches", type:	"capability.switch", title: "Output Switches", multiple: true, required: true
        }
        section
        {
            input name: "instanceName", type: "string", title: "Name For This App Instance", required: true
            input name:	"enableLogging", type: "bool", title: "Enable Debug Logging?", defaultValue: true, required: true
        }
        
    }
}

def logDebug(msg)
{
    if(enableLogging)
    {
        log.debug "${msg}"
    }
}

def installed()
{
    logDebug("installed()")    
    app.updateLabel("Simple Triggered App Instance - ${instanceName}")
    
    initialize()
}

def updated()
{
    logDebug("updated()")
    installed()
}

def initialize()
{
    logDebug("initialize()")
    unsubscribe()
    subscribeToEvents()
}

def uninstalled()
{
    logDebug("uninstalled()")
    unsubscribe()
}

def subscribeToEvents()
{
    logDebug("subscribeToEvents()")
    
    inputMotionSensors.each
    { ms ->
        subscribe(ms, "motion", changedHandler)
    }
}

def changedHandler(evt)
{
    logDebug("evt.getDevice().name = ${evt.getDevice().name}")
    logDebug("evt.name = ${evt.name}")
    logDebug("evt.value = ${evt.value}")
    // see other Event Object members here: https://docs.hubitat.com/index.php?title=Event_Object
    
    evtTime = evt.getUnixTime()
    Date tempDate = new Date()
    logDebug("event lag = ${tempDate.getTime() - evtTime}")
    
    outputSwitches.each
    {
        switch(it.currentValue("switch"))
        {
            case "on":
                it.off()
                break
            
            case "off":
            default:
                it.on()
                break
        }
    }
}
11 Likes

There are some advanced coding practices in the above example, here is the simplest example I could come up with, I don't understand the use case you presented, but here is the example app that does what you want:

definition(
    name: "Simple App Example",
    namespace: "anonymous",
    author: "anonymous",
    description: "Toggle output switch when motion and logic switch is on.",
    category: "Convenience",
    iconUrl: "",
    iconX2Url: "",
    iconX3Url: "")

preferences
{
    section
    {
        input name: "motionSensor", type: "capability.motionSensor", title: "Motion Sensor", multiple: false, required: true
        input name: "logicSwitch", type: "capability.switch", title: "Logic Switch", multiple: false, required: true
        input name: "outputSwitch", type: "capability.switch", title: "Output Switch", multiple: false, required: true
    }
}

void installed()
{
    updated()
}

void updated()
{
    unsubscribe()
    subscribe(motionSensor, "motion", eventHandler)
}

void uninstalled()
{
    // unsubscribe to all events
    unsubscribe()
}

void eventHandler(evt)
{
    // we don't care if the motion was active or inactive, so don't check the status of the motion event just continue with our logic below.
    // otherwise we would check evt.value or we would subscribe to motion.active or motion.inactive depending on what we wanted to do.

    // check if logic switch is on
    if(logicSwitch.currentValue("switch") == "on") {
        // toggle outputSwitch, need to check which method to run.
        if(outputSwitch.currentValue("switch") == "on")
            outputSwitch.off()
        else
            outputSwitch.on()
    }
}
9 Likes

Thank you all. I am not sure why it didn't occur to me to put this in the developer category. I also agree that my example was a bit nonsensical or at least impractical. That said, these code examples are great. They are just what I am looking for. Having 2 versions is especially great.

I had been looking at the examples, but I really appreciate the time you put into giving me an example where I can focus on the code because I know exactly what it is trying to accomplish.

2 Likes

Yeah, agree. Small steps at a time usually leads to great knowledge over time.

Small step for man, a great new contributor to HE community? :slight_smile:

RogerThat

I have a suite of apps for different things, that I've been working on for a long time, having started where you're at. I'd like to think they're now moderately advanced, while doing a relatively wide variety of tasks. I don't have the very first versions on GitHub, but the earliest ones are relatively rudimentary. I know it would have helped me to see a progression, while have a wide(ish) base of use-case scenarios.

Earliest commits: GitHub - roguetech2/hubitat at c34aa1877e19ad59e03de950afa7304e4b78e2f2

4 Likes

Thanks for the pointer. This looks like an interesting way for me to move beyond the basics in the future. My single feedback is that it would be great if your github repository had a readme to explain what each these items is for and how they fit together.

I was able to track it down by searching in the community and finding this post:
Introduction to roguetech's app.

Thanks. I will in time. Still working on getting it ready for release. edit: It's on my "to-do" list, as well as maybe starting a change log.