Simple Polling/Refresh App

I have been trying to get one switch to make a group of lights turn on. This is fairly easy with the use of Groups... Unfortunately as is mentioned in the forums, refreshing the status does not work on a timer like Smartthings. (This is a good thing). In any case, I wanted a simple straight-forward way to refresh only the switches/devices I cared about. The following is an app based of Pollster (Smartthings), but allows setting the number of seconds for up to four groups of devices. The wife is happy again, so I thought I would share.

/**
 *  Hubi-Poll.
 *
 *  Based off Pollster, this app works behind the scenes and periodically calls 'poll' or
 *  'refresh' commands for selected devices. Devices can be arranged into
 *  four polling groups with configurable polling intervals down to 1 second.
 *  Smartthings polls automatically every 10 seconds, which is overkill, but useful for some cases
 *  I am using the app to use one switch to control a group of switches.
 *  
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  --------------------------------------------------------------------------
 *
 *  Version 1.0
 */

definition(
    name: "Hubi-Poll",
    namespace: "tchoward",
    author: "thomas.c.howard@gmail.com",
    description: "Poll or refresh device status periodically",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")

preferences {

    (1..4).each() { n ->
        section("Scheduled Polling Group ${n}") {
            input "group_${n}", "capability.polling", title:"Select devices to be polled", multiple:true, required:false
            input "refresh_${n}", "capability.refresh", title:"Select devices to be refreshed", multiple:true, required:false
            input "interval_${n}", "number", title:"Set polling interval (in seconds)", defaultValue:10
        }
    }
}

mappings {
    path("/poll") {
        action: [ GET: "apiPoll" ]
    }
}

def installed() {
    initialize()
}

def updated() {
    initialize()
}

def onAppTouch(event) {
    LOG("onAppTouch(${event.value})")

    watchdog()
    pollingTask1()
    pollingTask2()
    pollingTask3()
    pollingTask4()

    if (settings.restPoll) {
        settings.restPoll*.poll()
    }

    if (settings.restRefresh) {
        settings.restRefresh*.refresh()
    }
}

def onLocation(event) {
    LOG("onLocation(${event.value})")

    watchdog()
}

def pollingTask1() {
    //LOG("pollingTask1()")

    if (settings.group_1) {
        settings.group_1*.poll()
    }

    if (settings.refresh_1) {
        settings.refresh_1*.refresh()
    }
    runIn(state.seconds[1], pollingTask1)
}

def pollingTask2() {
    //LOG("pollingTask2()")
    
    if (settings.group_2) {
        settings.group_2*.poll()
    }

    if (settings.refresh_2) {
        settings.refresh_2*.refresh()
    }
    runIn(state.seconds[2], pollingTask2)
}

def pollingTask3() {
    //LOG("pollingTask3()")

    if (settings.group_3) {
        settings.group_3*.poll()
    }

    if (settings.refresh_3) {
        settings.refresh_3*.refresh()
    }
    runIn(state.seconds[3], pollingTask3)
}

def pollingTask4() {
    //LOG("pollingTask4()")

    if (settings.group_4) {
        settings.group_4*.poll()
    }

    if (settings.refresh_4) {
        settings.refresh_4*.refresh()
    }
    runIn(state.seconds[4], pollingTask4)
}

private def initialize() {
    LOG("initialize() with settings: ${settings}")
	state.seconds = new int[5]
  
    Random rand = new Random(now())
    def numTasks = 0
    (1..4).each() { n ->
        state.seconds[n] = settings."interval_${n}".toInteger()
        def size1 = settings["group_${n}"]?.size() ?: 0
        def size2 = settings["refresh_${n}"]?.size() ?: 0

        safeUnschedule("pollingTask${n}")

        if (state.seconds[n] > 0 && (size1 + size2) > 0) {
            LOG("Scheduling polling task ${n} to run every ${state.seconds[n]} seconds.")
            runIn(state.seconds[n], "pollingTask${n}")
            numTasks++
        }
    }

    LOG("state: ${state}")
}

private def safeUnschedule() {
    try {
        unschedule()
    }

    catch(e) {
        log.error ${e}
    }
}

private def safeUnschedule(handler) {
    try {
        unschedule(handler)
    }

    catch(e) {
        log.error ${e}
    }
}

private def restart() {
    updated()
}

private def about() {
    def text =
        "Version ${version()}\n${copyright()}\n\n" 
}

private def version() {
    return "Version 1.0"
}

private def copyright() {
    return "No Copyright"
}

private def LOG(message) {
    log.trace message
}
2 Likes

Glad you were able to make pollster work for you here. I could never get that to work for me on ST.

I had Pollster working here early on and found it was better for my system to just create individual refresh rules in RM. One needs to be careful to not group too many z-wave refreshes at one time.

Some points of feeback.

You have a few methods that are never used so you can remove them:
onAppTouch
onLocation
restart
about
version ( only called by about)
copyright (only called by about)
safeUnschedule() (only safeUnschedule(handler) is used)

Random rand = new Random(now()) is never used

You define and increment numTasks, but never use it.

You do not define apiPoll so you can remove the whole mappings section

@thomas.c.howard

I was bored a bit.. so I modified the source per @chuck.schwer suggestions and put it out on github.

Oh, and I added Cobra's amazing Version checking code too.

3 Likes

How do I do this with RM?

1 Like

I am away from a computer currently, but iirc, I built a trigger with a periodic capability. Selected frequency. And for the action, selected the switch and refresh.

1 Like

This. I do this with a few devices. You can make a Christmas command if necessary as well. For example, I used to call initialize on the Google homes every figured minutes.

Thanks for making a great app :+1: :sunglasses::nerd_face:. It solved a few problems where a device state change wasn’t seen by WebCoRE during a 4 second window. Again thank you :+1::+1::+1::+1::+1::+1:

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