Created
May 20, 2020 02:39
-
-
Save imnotbob/b048f2c061951a26d56e78e7312dfef4 to your computer and use it in GitHub Desktop.
Hubi-poll that does not use runIn, notices reboots/restarts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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