Trying to figure out how to schedule a cron job except at night


(Jim) #1

I’m not sure if I can do this with a single expression or not.

schedule("0 0/30 14-6 * * ?", "checkWeather") //Check at top and half-past of every hour

I’m hoping to get a job that runs every 30 minutes after 6 am and before 10pm (PST), so I’ve time shifted, but that sets up an expression I’m not convinced is valid.

An alternate approach would be to have the job run 24x7, but have the notifications disabled after 6am and before 10pm. Do any of you have a suggested approach here?


(Todd Wackford) #2

I’d just run the cron job every 30 minutes regardless of time and then check the time inside the called function. If it’s between 6 and 10, do nothing, else do something.

Make sense?
Twack


(Jim) #3

Thanks, I’m going to do exactly that. Actually, I did. Now we’ll see if it texts my wife accidentally in the middle of the night or not ;-). Talk about a stress test.


(Jim) #4

Thanks again, that worked.

My little utility now:

  • Schedules a 15 minute check of the weather at my personal weather station via wunderground
  • Tests for the wind gust, wind speed, temperature and precipitation against input values
  • Notifies via push & SMS to up to three users
  • Throttles messaging to occur between specified input values, and once notified only notifies again IF the measurement gets worse by (n)
  • Resets notifications at 5am just before the day starts again

So far it’s the first one I’ve built that my wife really is excited about. :slight_smile: If anyone wants the code (it’s not particularly pretty, but…) let me know. I’m not a git master yet, but I’m hoping to put it on my git account.


(Redawg) #5

I’m interested in the code. I would like to try to pull the data from my wunderground feed to my smartthing apps for different things. I have davis pro, with meteobridge to wunderground and mysql db.


(Jim) #6

Happy to provide, sorry I didn’t see this sooner. So is everyone just putting things up in their own GIT repositories, or is there somewhere shared they’re using for new projects?


(tduffy) #7

Can I get this code too? I have a Davis Pro that I would love to be able to use in apps for when my garden gets watered. Thanks!


(Jim) #8

Sure thing. The Github repository I use for it is named inclement_weather_pws under the account jameslew.

If you just want the text of it:

/**
 *  Severe Weather Alert - PWS edition
 *
 *  Author: Jim Lewallen
 *  Date: 2013-03-04
 */
preferences {
	section ("Weather threshholds to alert at..."){
    	input "highwindspeed", "number", title: "Avg Wind Speed", required: false
    	input "hightempf", "number", title: "High Temperature", required: false
    	input "lowtempf", "number", title: "Low Temperature", required: false
    	input "highrainfall", "number", title: "Rainfall Threshhold", required: false    
        input "apikey", "string", title: "API Key", required: false
    }


	section ("In addition to push notifications, send text alerts to...") {
		input "phone1", "phone", title: "Phone Number 1", required: false
		input "phone2", "phone", title: "Phone Number 2", required: false
		input "phone3", "phone", title: "Phone Number 3", required: false
	}
	section("Which people should I watch for?") {
		input "people", "capability.presenceSensor", title: "Presence sensor", description: "Which people(s)?", multiple: true, required: false
	}
	section ("Weather Underground Weather Station ID") {
		input "stationid", "text", title: "Station ID", required: true
	}
    section ("Custom Weather Quotes") {
    	input "coldWeatherQuote", "text", title: "Custom Cold Comment", required: false
    }
}


def installed() {
	log.debug "Installed with settings: ${settings}"
	setDefaultWeather()
    checkWeather()
	schedule("0 0/15 * * * ?", "checkWeather") //Check at top and half-past of every hour
    schedule("0 0 5 * * ?", "setDefaultWeather") //Reset in the morning
    schedule("0 0 16 * * ?", "setDefaultWeather") //Reset in the afternoon


}


def updated() {
    log.debug "Updated with settings: ${settings}"
    unsubscribe()
    setDefaultWeather()
    checkWeather()
    schedule("0 0/15 * * * ?", "checkWeather") //Check at top and half-past of every hour
    schedule("0 0 5 * * ?", "setDefaultWeather") //Reset in the morning
    schedule("0 0 16 * * ?", "setDefaultWeather") //Reset in the afternoon
}


def checkWeather() {
	log.debug "Checking Weather"
	httpGet("http://api.wunderground.com/api/${apikey}/conditions/q/pws:${stationid}.json") 
    	{ response ->


	def windspeed = response.data.current_observation.wind_mph.floatValue()
        def tempf = response.data.current_observation.temp_f.floatValue()
	def hourlyprecip = Float.parseFloat(response.data.current_observation.precip_1hr_in)


        log.debug "Actual: ${windspeed}, ${tempf}, ${hourlyprecip}"
        log.debug "Threshholds: ${highwindspeed}, ${hightempf}, ${lowtempf}, ${hourlyprecip}"
        log.debug "State: ${state.lastHighWindSpeed}, ${state.lasthightempf}, ${state.lastlowtempf}, ${state.lasthourlyprecip}"
        
        if (windspeed > highwindspeed) {
        	if (windspeed >= state.lastHighWindSpeed + 3.0 ) {
				state.lastHighWindSpeed = windspeed
				notifyHousemates("High wind speed of ${windspeed}mph at the house")
            } else {log.debug "not enough wind speed change"}
        } else { state.lastHighWindSpeed = windspeed }
        
        if (tempf > hightempf) {
        	if (tempf >= state.lasthightempf + 3.0 ) {
                state.lasthightempf = tempf
        		notifyHousemates("It's damn hot at the house: ${tempf}F")
            } else {log.debug "not enough high temp change"}
        } else { state.lasthightempf = tempf }
        
        if (tempf < lowtempf) {
        	if (tempf <= state.lastlowtempf - 3.0 ) {
        		state.lastlowtempf = tempf
				notifyHousemates(coldWeatherQuote + ": ${tempf}")
            } else { log.debug "not enough low temp change" }
        } else { state.lastlowtempf = tempf }
        
	if (hourlyprecip > highrainfall) {
        	if (hourlyprecip  >= state.lasthourlyprecip + 1.0 ) {
				state.lasthourlyprecip = hourlyprecip 
        		notifyHousemates("It's raining buckets at the house: ${hourlyprecip} in.")
            } else {log.debug "not enough precip change"}
        } else { state.lasthourlyprecip = hourlyprecip }
       	
    }
}


def logTraceWithPush(message) {
    sendPush message
    log.debug message
}


def setDefaultWeather() {
	logTraceWithPush("Resetting the weather state")
    state.lastHighWindSpeed = 0.0
    state.lasthightempf = 65.0
    state.lastlowtempf = 40.0
    state.lasthourlyprecip = 0.0
    log.debug "state: ${state.lastHighWindSpeed}, ${state.lasthightempf}, ${state.lastlowtempf}, ${state.lasthourlyprecip}"
}


private notifyHousemates(message) {


    def t0 = new Date(now() - (8 * 60 * 60 * 1000))


	if (t0.getHours() >= 6 && t0.getHours() <= 22)
    {
        log.debug "We got one! ${message}"
        send(message)
    } else {
    	log.debug "Yikes, it's ${t0.getHours()}, discarding notification!"
        send(message)
    }
}

(tduffy) #9

This is great! Thank you :slight_smile:


(Jim) #10

No problem, let me know if you have questions.


(Jim) #12

Figure it out?

BTW, they changed the mechanism so instead of asking for the API key in the script, you can enter it on the app “registration” page instead of putting it in the script. At least that makes data entry on the device easier.

Another thing I toyed with was to make the Weather Underground entry a SmartDevice instead of a embedding the http calls in the SmartApp itself, and then having the SmartApp talk to the device. In some ways, I like the abstraction, but there aren’t Capability items for some of the data types so it’s not as full fidelity a solution.


(Tracy Horgan) #13

I got it! Thank you!!