Skip to content

Instantly share code, notes, and snippets.

@imnotbob
Created May 20, 2020 02:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imnotbob/b048f2c061951a26d56e78e7312dfef4 to your computer and use it in GitHub Desktop.
Save imnotbob/b048f2c061951a26d56e78e7312dfef4 to your computer and use it in GitHub Desktop.
Hubi-poll that does not use runIn, notices reboots/restarts
/**
* Hubitat Import URL: https://raw.githubusercontent.com/HubitatCommunity/Hubi-Poll/master/Hubi-Poll.groovy
*/
/**
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.
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: "",
iconX2Url: "",
iconX3Url: ""
)
preferences{
display()
(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
}
}
}
// App Version ***** with great thanks and acknowlegment to Cobra (CobraVmax) for his original version checking code ********
void setAppVersion(){
state.version="2.0"
state.InternalName="HubiPoll"
state.Type="Application"
state.Copyright="Ⓒ 2018 tchoward"
}
void installed(){
initialize()
}
void updated(){
initialize()
}
private void initialize(){
setAppVersion()
unschedule()
unsubscribe()
LOG("initialize() with settings: ${settings}")
state.seconds=new Integer[5]
(1..4).each(){ n ->
state.seconds[n]=settings."interval_${n}".toInteger()
Integer size1=settings["group_${n}"]?.size() ?: 0
Integer size2=settings["refresh_${n}"]?.size() ?: 0
Integer seconds=(Integer)state.seconds[n]
Integer cnt=0
if(seconds>0 && (size1+size2)>0){
LOG("Scheduling polling task ${n} to run every ${seconds} seconds.")
/*
* so evertthing becomes one of:
* - seconds (and intervals)
* - minutes (and intervals)
* - hours (and intervals)
* - daily (and intervals)
*/
String sched
Integer secs=Math.round(59*Math.random())
Integer startmin= Math.round(59*Math.random())
Integer minutes=seconds/60
Integer hours=minutes/60
Integer days=hours/24
if(seconds<60){
secs= secs>1 ? Math.round((secs-1)*Math.random()) : secs
sched="0/${seconds} * * * * ?"
}
else if(seconds<3600) sched="${secs} 0/${minutes} * * * ?"
else if(seconds<(3600*24)) sched="${secs} ${startmin} 0/${hours} * * ?"
else sched="${secs} ${startmin} 0 1/${days} * ?"
schedule(sched, "pollingTask${n}")
state."trun${n}"=now()
if(minutes>0 || hours>0 || days>0) "pollingTask${n}"()
cnt+=1
//runIn(state.seconds[n], "pollingTask${n}")
}
if(cnt>0){
subscribe(location, "systemStart", onLocation)
subscribe(location, "sunrise", onLocation)
subscribe(location, "sunset", onLocation)
}
}
LOG("state: ${state}")
}
void onLocation(event){
LOG("onLocation(${event.value})")
watchdog()
}
void watchdog(){
//LOG("watchdog()")
(1..4).each(){ n ->
Integer size1=settings["group_${n}"]?.size() ?: 0
Integer size2=settings["refresh_${n}"]?.size() ?: 0
Integer seconds=(Integer)state.seconds[n]
if(seconds>0 && (size1+size2)>0){
Integer interval=getInterval(n)
Long lastRun=(Long)state."trun${n}"
//if(!(interval && lastRun)) return
Long t=now()
Long curDelta=t-lastRun
Long maxDelta=(interval+200) * 1000L
if(interval>0 && lastRun && curDelta>maxDelta){
log.warn "$app.label: Polling task #${n} stalled. now: $t last run: $lastRun delta: $curDelta max interval: $maxDelta intervalsecs: $interval"
//restart(n)
//return
}
}
}
}
Integer getInterval(Integer n){
Integer interval=settings."interval_${n}".toInteger()
return interval
}
void pollingTask(Integer n){
//LOG("pollingTask($n)")
Long t1=now()
state."trun${n}"=0L
if(settings."group_${n}"){
settings."group_${n}"*.poll()
state."trun${n}"=t1
}
if(settings."refresh_${n}"){
settings."refresh_${n}"*.refresh()
state."trun${n}"=t1
}
watchdog()
// runIn(state.seconds[n], "pollingTask${n}")
}
void pollingTask1(){
pollingTask(1)
}
void pollingTask2(){
pollingTask(2)
}
void pollingTask3(){
pollingTask(3)
}
void pollingTask4(){
pollingTask(3)
}
private void LOG(message){
log.trace message
}
// DISABLED FOR PRIVACY
// Check Version ***** with great thanks and acknowlegment to Cobra (CobraVmax) for his original version checking code ********
/*void version(){
updatecheck()
if(state.Type == "Application"){ schedule("0 0 14 ? * FRI *", updatecheck) }
if(state.Type == "Driver"){ schedule("0 45 16 ? * MON *", updatecheck) }
}*/
def display(){
//version()
section{
paragraph "Version Status: $state.Status"
paragraph "Current Version: $state.version - $state.Copyright"
}
}
/*
def updatecheck(){
setAppVersion()
def paramsUD=[uri: "https://hubitatcommunity.github.io/Hubi-Poll/versions.json"]
try{
httpGet(paramsUD){ respUD ->
// log.info " Version Checking - Response Data: ${respUD.data}"
def copyNow=(respUD.data.copyright)
state.Copyright=copyNow
def newver=(respUD.data.versions.(state.Type).(state.InternalName))
def updatecheckVer=(respUD.data.versions.(state.Type).(state.InternalName).replace(".", ""))
def updatecheckOld=state.version.replace(".", "")
if(updatecheckOld < updatecheckVer){
state.Status="<b>** New Version Available (Version: $newver) **</b>"
log.warn "** There is a newer version of this $state.Type available (Version: $newver) **"
}else{
state.Status="Current"
log.info "$state.Type is the current version"
}
}
}
catch(e){
log.error "Something went wrong: $e"
}
}*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment