Sunset program does not trigger with "Before" offset


(MrPresident) #1

I have a smartapp that turns on a lamp at sunset. Problem is that I’ve defined a sunset offset of 02:00 hours before.
The smartapp works great in that it turns on at sunset, but does not factor in the offset. So for example, Sunset yesterday was at 4:31pm. The lamp turned on at precisely 4:31pm. however, The offset is set as 2 hours before so I would have expected the lamp to turn on at 2:31pm.

Surely I am doing something wrong in not factoring in the offset. Can someone please advise?

The code is attached. which is a hacked up version of sunrise/sunset provided in the IDE Examples.

Thanks in advance.

definition(
    name: "foyerLampSunset",
    namespace: "mlupo",
    author: "michael lupo",
    description: "Turn the foyer lamp on 1.5 hours before sunset and leave on till 11:59pm.",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")


preferences {
	section ("At sunset...") {
		input "sunsetMode", "mode", title: "Change mode to?", required: false
		input "foyerOutlet", "capability.switch", title: "Turn on?", required: false, multiple: true
	}
    
    section ("Sunset offset (optional)...") {
		input "sunsetOffsetValue", "text", title: "HH:MM", required: false
		input "sunsetOffsetDir", "enum", title: "Before or After", required: false, options: ["Before","After"]
	}
    
    //section ("How long to leave the light on for? MINUTES (ie. 90)") {
	//	input name: "minutes", title: "Minutes?", type: "number", multiple: false
	//}
    
    section("What time to turn the light off?") {
    	input "time1", "time", title: "When?", required: true
    }
    
    section ("Zip code (optional, defaults to location coordinates)...") {
		input "zipCode", "text", required: false
	}
	section( "Notifications" ) {
		input "sendPushMessage", "enum", title: "Send a push notification?", options: ["Yes", "No"], required: false
		input "phoneNumber", "phone", title: "Send a text message?", required: false
	}
}

def installed() {
	initialize()
}

def updated() {
	unsubscribe()
	//unschedule handled in astroCheck method
	initialize()
}

def initialize() {
	subscribe(location, "position", locationPositionChange)
	subscribe(location, "sunsetTime", sunriseSunsetTimeHandler)
	
	astroCheck()
}

def locationPositionChange(evt) {
	log.trace "locationChange()"
	astroCheck()
}

def sunriseSunsetTimeHandler(evt) {
	log.trace "sunriseSunsetTimeHandler()"
	astroCheck()
}


def astroCheck() {
    log.debug "sunsetOffset is: $sunsetOffset"
	def s = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: sunriseOffset, sunsetOffset: sunsetOffset)
    def off = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: sunriseOffset, sunsetOffset: sunsetOffset)
	def now = new Date()
	def sunsetTime = s.sunset
    
	log.debug "sunsetTime: $sunsetTime"
	
	if (state.sunsetTime != sunsetTime.time) {
		state.sunsetTime = sunsetTime.time

		unschedule("sunsetHandler")
		if(sunsetTime.before(now)) {
			sunsetTime.next()
		}
		log.info "scheduling sunset handler for a sunset at: $sunsetTime"
		runDaily(sunsetTime, sunsetHandler)
	}
}

def sunsetHandler() {
	log.info "Executing sunset handler. Will turn off the outlet at 11:59pm."
	if (foyerOutlet) {
		foyerOutlet.on()
	}
	changeMode(sunriseMode)
    outletOff()
}

def changeMode(newMode) {
	if (newMode && location.mode != newMode) {
		if (location.modes?.find{it.name == newMode}) {
			setLocationMode(newMode)
			send "${label} has changed the mode to '${newMode}'"
		}
		else {
			send "${label} tried to change to undefined mode '${newMode}'"
		}
	}
}

private send(msg) {
	if ( sendPushMessage != "No" ) {
		log.debug( "sending push message" )
		sendPush( msg )
	}

	if ( phoneNumber ) {
		log.debug( "sending text message" )
		sendSms( phoneNumber, msg )
	}

	log.debug msg
}

private getLabel() {
	app.label ?: "SmartThings"
}

private getSunriseOffset() {
	log.debug "DEBUG: getting offset value"
	sunsetOffsetValue ? (sunsetOffsetDir == "Before" ? "-$sunsetOffsetValue" : sunsetOffsetValue) : null
}

def outletOff() {
    log.debug "called outletsOff() and delaying turning off the outlet till ${time1}"
    //log.debug "called outletsOff() and delaying turning off the outlet at 11:59pm"
    //schedule("00 59 23 * * ?", scheduledTurnOff)
    schedule(time1, scheduledTurnOff)
}

def scheduledTurnOff() {
	foyerOutlet.off()
	unschedule("scheduledTurnOff") // Temporary work-around to scheduling bug
}

(Eric R) #2

I see a few things that could be wrong. First, your getSunsetOffset() is actually getSunriseOffset(). Also, I don’t see that function called anywhere. I would expect the offset to happen after because you never check for the before in your code.

Also, to help with debugging, you can go to My Locations in the ide and click on smartapps. You can then see the status of the installed smartapp to see what time it is actually scheduling for.


(MrPresident) #3

Hi Eric,
Thanks for the reply. Sorry mine is so late. Busy weekend.

Anyway, I fixed the method name. But I don’t see where this method is even called (as you even stated). Even in the example sunrise/sunset app that is provided by ST, I don’t see where any either the getSunriseOffset or getSunsetOffset methods are even called. So it’s difficult to figure out what magic is going on behind the scenes…and how to apply that voodoo to my own smartapp.

Thanks for the dialog…

private getSunsetOffset() {
	sunsetOffsetValue ? (sunsetOffsetDir == "Before" ? "-$sunsetOffsetValue" : sunsetOffsetValue) : null
}

below is a copy of the settings that I see in the IDE. It still shows the incorrect scheduled runtime. Expected to see 2 Hours before sunset, What is see is precisely sunset.

Settings
Name Type Value
foyerOutlet capability.switch Foyer Outlet
phoneNumber phone
sendPushMessage enum Yes
sunsetMode mode ""
sunsetOffsetDir enum Before
sunsetOffsetValue 02:00

time1 time 11:59 PM EDT
zipCode 01234
Event Subscriptions
Name Handler Filter Source
position locationPositionChange true Reynolds (Location)
sunsetTime sunriseSunsetTimeHandler true Reynolds (Location)
Application State
Name Value
sunsetTime 1415654940000
Scheduled Jobs
Handler Next Run Time Prev Run Time Status Schedule
sunsetHandler 2014-11-11 4:29:00 PM EST 1969-12-31 6:59:59 PM EST WAITING 0 29 16 ? * * America/New_York
SmartApp Version foyerLampSunset
State COMPLETE
Health HEALTHY
Development App True


(Eric R) #4

try adding def sunsetOffest = getSunsetOffset() before your def s = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: sunriseOffset, sunsetOffset: sunsetOffset)