Sunrise/Sunset magic?


(Aaron) #1

In the Sunrise/Sunset SmartApp by SmartThings there is this code:

subscribe(location, "sunriseTime", sunriseSunsetTimeHandler)
subscribe(location, "sunsetTime", sunriseSunsetTimeHandler)

Is ‘location’ some sort of pre-defined virtual device that is tied into the physical location information of the hub?

Where does ‘sunriseTime’ come from? Also some ST built-in, undocumented magic? Is this in seconds? Minutes? Format?

In order for the listed methods to be triggered, does the sunrise or sunset time have to vary by at least on minute day to day? I don’t think this is necessarily a good assumption based on a quick search on the interwebs . . . unless the resolution of the value is to the seconds.

If these are stupid questions answered in documentation I should have found, please accept my apologies and please point me in the right direction.


Hello, Home Phrase Director - Control modes (through hello home phrases) based on occupancy and "sun state"
(Sully) #2

Pretty sure this is the location that you define for your hub… It’s something you’ve already defined for your setup. In the simulator it’s the first thing you select.

As far as sunrise and sunset, I don’t use it, but it’s got to be a time code, and usually those resolve down to the millisecond, if they’re like the other time functions ST uses.


(Tim Slagle) #3

This is an APi that is built into the STs environment.

Its an event that is triggered automatically every day when those events occur. you can just watch for those events and run code based on them.

Hope that helps


(Aaron) #4

@jsulliweb and @tslagle13 - Thanks. Very helpful. So, is this documented somewhere? Does ‘everyday’ mean sometime in the middle of the night or precisely at sunrise and sunset? Thanks again.


(Tim Slagle) #5

You got it.



(Geko) #6

https://graph.api.smartthings.com/ide/doc/location


(Aaron) #7

Thanks @geko. I was aware of this and looked but didn’t find attributes related to sunset/rise. That’s what made me think that ‘location’ in this context may not be the ‘location’ class. The documentation for the subscription method defines the first argument as a device or group of devices - thus was born the idea of a virtual device called ‘location’ with attributes including sunrise and sunset… Just normal newb challenges, I suppose.


(Matt Nohr) #8

I know there have been a number of questions around this, so I thought I’d try to clear it up a bit. We’ll try to get the documentation updated as well.

The location object you use is in fact your location class for this installation of the SmartApp. You don’t see sunrise/sunset attributes, because those are actually events that we send out as a platform.

There are two different sets of events that get sent out. First off are the sunrise and sunset events. These happen at the minute when it is sunrise or sunset at your specific latitude and longitude. Use these when you need something to happen right at those times. For example, you might want to turn on your yard lights when it is sunset, and off again when it is sunrise. The value for these events is always just true so the use is just to trigger some action based on the sun.

The other types of events are sunriseTime and sunsetTime. The value for these is the time when the next sunrise or sunset is going to happen. How it works behind the scenes is whenever it is sunrise, we (the platform) then look for tomorrow’s sunrise time and if it is different, which typically is every day, we send out a new sunriseTime event. And of course the same for sunset. This is in the format 2014-11-20T13:17:00.000Z which is 7:17 AM CST. The value is in UTC time. Typically you would use these events if you need an offset, like you want your lights to turn on 30 minutes before sunset and off 30 minutes after sunrise. That is what the Sunrise/Sunset app does that as @AaronZON noticed, if you want an example of how to use the offsets.

If you ever want to see your sunrise, sunset, sunriseTime, or sunsetTime events, you can look them up in the Web IDE by going to: My Locations > [Location Name] > events > from location

If you have any questions, let me know!


Sunrise and sunset calculation not working
Current "sunrise" or "sunset" state?
(Aaron) #9

@matthewnohr - Super! This is very helpful. Much appreciated.

Are you the author of Sunrise/Sunset? The author is listed in the code as ‘SmartThings’. I used some of the code from this in a SmartApp in an app I did for a dusk-to-dawn light implementation and I found either an error or something I don’t fully understand (probably the later). I can take this up with you off-line or start a new thread.


(Matt Nohr) #10

I’ve done some work on that app, yes. If you found an error, please do let me know.


(Im Brian) #11

@matthewnohr - debugging an app that depends on firing of that is kinda…tough. Any way to simulate a sunrise / sunset in the IDE?


(Iker) #12

What is wrong with my simple code below?
I have a null pointer exception on the first line I try to subscribe for the sunrise event (subscribe(location, “sunrise”, sunriseHandler))

Here it is:

definition(
name: “Curtains Control”,
namespace: “iker.pryszo”,
author: “Iker Pryszo”,
description: “Allows a virtual switch to control the curtains and provides an option to open and close automatically the curtains for sunrise and sunset”,
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”,
iconX3Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”)

preferences {
section(“Select the switch that controls the curtains”) {
input “mySwitch”, “capability.switch”, multiple: false
}
section(“Open and Close automatically for sunrise and sunset ?”) {
input “autoMode”, “bool”, title: “Auto Mode”, defaultValue: true
}
}

def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}

def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}

def initialize() {
subscribe(mySwitch, “switch”, switchHandler)
subscribe(location, “sunrise”, sunriseHandler)
subscribe(location, “sunset”, SunsetHandler)
}

def switchHandler(evt) {
log.trace "The event is: $evt.value: $evt"
if (evt.value == ‘on’) {
log.trace “Open Curtains”
//TO DO
} else {
if (evt.value == ‘off’) {
log.trace “Close Curtains”
//TO DO
}
}
}

def sunriseHandler(evt) {
log.info "Executing sunrise handler"
if (autoMode) {
log.info "Open Curtain Automatically"
mySwitch.on()
}
}

def sunsetHandler(evt) {
log.info "Executing sunset handler"
if (autoMode) {
log.info "Close Curtain"
mySwitch.off()
}
}

Thanks a lot!


(Aaron) #13

You’ve got a typo here. should be sunsetHandler (first s is small, not cap).

Not sure why/how this created the error you saw but correcting the typo made your code work for me.


(Iker) #14

That was it! Thanks.
I was confused by the exception and looked in the wrong place…

I tested it tonight and the Sunset event worked correctly!
I’ll finish my automatic curtains project and then post it for everybody.


(Tony Gutierrez) #15

Is there a way to ask the location if it is currently after sunrise or sunset?


(Aaron) #16

@Tony_Gutierrez, this method from one of my apps shows how you might do what you asked:

def initialSunPosition() {  
	//Determine if sun is down at time of initializtion and run sunsetHandler() if so
    //Light meter is not evaluated initially, light level first evaluated at first luminance event
    log.debug "initialSunPosition()"
	def s = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: sunriseOffset, sunsetOffset: sunsetOffset)
	def now = new Date()
    def riseTime = s.sunrise
	def setTime = s.sunset
	state.ambient = "light"  //initialize to "light"
    state.sunPosition = "up" //initialize to "up"
	
    if(setTime.before(now) || riseTime.after(now)) {   //before midnight/after sunset or after midnight/before sunset
	  	log.info "Sun is already down, run sunsetHandler"
        sunsetHandler()
    }
    
	scheduleSunEvents()													//setting initial rise/set 
    
    unschedule(scheduleSunEvents)
    schedule(timeToday("12:13",location.timeZone),scheduleSunEvents) 	//subsequent evaluation of rise/set times
    																	//at 12:13PM every day
}

The getSunriseAndSunset() method is documented in the docs.

Hope this helps. If not, post a follow up. . .


(Tony Gutierrez) #17

That is useful, but I was more curious if there was a native “get” method in the Location class that would return the current night/day status. If so we could easily avoid a lot of use of state vars, apps wouldn’t have to run for a full day before being on time, etc.

Ill implement the chunk you sent for now. Thanks!


(Aaron) #18

Understood. I agree this would be handy but it doesn’t exist (see posts earlier in this thread for some discussion on this. . . I pretty much asked the same question as you). IMO, the code to do this in the SmartApp is not so bad, however.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #19

(And @Tony_Gutierrez…).

I have a ‘hack’ idea bouncing around my head…

Create a new virtual Device (ideally with a new Capability, but we can’t add capabilities yet) whose purpose is to be a global data storage object.

We can be more tailored and create one just with one attribute: sunState [up, down] and a simple daily SmartApp (or polling within the Device?) can keep this Attribute current.

Crazy?


(Ron S) #20

Nope. Not crazy… attribute: sunState [morning, day, evening, night] :wink: