Determining if a switch is on?


(Chrisb) #1

I’m writing an app to turn on a hallway light at a low percentage at night if motion is detected. Sort of a night light for the hallway in case someone gets up to use the bathroom. But I want this app to only trigger if the light is off.

Reasoning: I but my kids to bed at 9:00pm for example, so I want the app to watch for them to get up and light up at 10% if they do. At 10:30 my wife and I head to bed and turn the light on as we go upstairs. I don’t want the motion detector to see us and then trigger the app, dimming the lights to 10% at this point. So I’d like to poll the switch and see if it’s on before I try to turn it on at a dim level.

Right now I’ve subscribed to on/off changes with the switch. When the switch turns on a change a variable to 1. When the switch gets turned off, the variable is set to 0. It works, but it seems rather clunky. I imagine there’s got to be a more elegant solution to just poll the switch at the time motion is detected.

Any ideas?


(C Chen) #2

Probably something like this?

def motionEvent(evt) {
    if( dimmer.currentSwitch == "off" ) {
       dimmer.on() // This doesn't work with virtual devices selected using
                   // capability.switchLevel. But I assume it will work with 
                   // a physical device.
       dimmer.setLevel(10)
    }
}

(Solardave1) #3

I have an aeon motion/multi sensor mounted on the ceiling which I use for motion detection but the sensor also measures light levels (and temperature) so I would think you could use the luminance value in your code to accomplish what you want. So you have motion detection and luminance values as the variables that you would want to read and use to control the functionality and I suppose a simple timer to turn everything off after x mi uses with no motion detected.


(Chrisb) #4

Yeah, I’d like to use the luminance function, but unfortunately this doesn’t appear to update very quickly. This looks like one of those things that only updates every 5 minutes or so.


(Zach Naimon) #5

You could schedule it to poll.

Like

def initialize(){
def freq = 1
schedule("0 0/$freq * * * ?", checkLight)
}

def checkLight(){
myLightSensor.poll()
}

(Chrisb) #6

Trying to find info on the schedule command. I’m guessing that the 0’s and *'s are times and dates though I’m not sure which refers to which.

Generally speaking I think the 5 minutes or so delay will be fine. Obviously I’d like a quicker update, but I have live with 5 minutes for most situations.

The biggest problem area is when we head upstairs during during the “night light” time range. I turn on the AUX switch on the main level and my lights go on. Then after we go upstairs, the motion sensor “sees” us and runs the program. This is just a few seconds after the lights have turned on. Unless the schedule is running every second, it’s unlikely that it will even be able to poll the light sensor and report the new level before we come into range of the motion sensor.

On the plus side, SmartThings has stated that they are working on a Hub firmware update that will have the Hub performing low level polling on a near continuous basis causing much more rapid updates.


(Zach Naimon) #7

Freq is in minutes. So, currently, that would run a cron job every minute that polled the luminance, provided that’s what the sensor name was.

I mean, additionally, and I’m not entirely clear on what you’re trying to do, you could run a handler like:

def myMotionSensorHandler(evt){
  myLightSensor.poll()
}

thus whenever there’s motion, it polls your light sensor.


(Chrisb) #8

What I’m trying to do it make a “night time” light in the hallway. If someone gets up because they need to use the bathroom, I want my upstairs hallway lights to come on… but only at like 10-15% so it’s not blinding. Then after 5 minutes or so, they shut off. (actually, what they do is after 5 minutes they go up to full brightness, then shut off so that if I turn the switch on in the morning it comes on fully.) That part of course isn’t hard.

I also want this to happen only at night. Ideally I’d use the light sensor for this, but I’m still working on if that’s the best way. I think I’ll move to that but right now I just have it set so that it only works from 9:00pm to 5:30am.

I also want this to happen only if the light is off. If the light is on I don’t want the app to trigger. Because (feel free to skip the italics if you don’t want to read the whole story):

I put my kids to bed at 9:00 (for example). Then I go back downstairs with the wife for a few hours. Little Billy gets up to use the bathroom at 9:30. Hallway light is off, so it clicks on (dim)… Billy uses the bathroom, goes back to bed. Light turns off after 5 minutes. At 10:15 little Suzy needs a drink. She goes into the hallway, light turns on (dim), she gets her drink and goes back to bed. Light turns off.

Then around 11:00 the wife and I head to bed. We turn the light on using the AUX switch on the main level. Because this is an AUX switch it does NOT register with the HUB right away that the switch is on. (The main wouldn’t either actually as it’s thru the Mesh network, no directly tied to the Hub.) The light goes on but SmartThings doesn’t know this yet. We walk upstairs and the motion sensor sees us. At this point ST does not know that the light switch is on and the light sensor hasn’t updated either. ST thinks the light is off and the area is dark. So the motion sensor sees us and says: I have movement and the light is off, therefore I’ll turn the light to it’s dim level and turn it off in 5 minutes.

So what I need is a way to get (near) instant updated information on the light level or switch status. I’ll testing the polling command and see if that’s quick enough when I get a chance. My fear is that while it will be quick it may not be quick enough.

The steps in my program would be:

Motion seen
Poll light sensor.
Test light level, it’s above x, then don’t run app
Otherwise, run app.

Unless that poll function returns a lux level immediately the light level test is going to use old data. What I really need is a way to trigger a poll when I turn on the light on the main level. That gives at least 3-4 seconds before I come up the stairs and trip the motion sensor. But there’s no way to do this presently short of another sensor on the main level.

(The other option is to delay running the app slightly to allow updated lux info, but this also isn’t desirable. I want that light to come on as soon as possible when someone is leaving their bedroom at night. If it pauses 2-3 seconds before running that’s most of the distance to the bathroom.)

The firmware update mentioned by Duncan is promising:

In a future hub firmware update (the one after the next one), the hub will poll these out-of-range switches much faster than the current 5 minute poll that comes from the cloud, hopefully on the order of seconds. That change will help with getting timely updates of switch changes.
http://build.smartthings.com/forums/topic/manufacturer-review-gejasoc/#post-4663

Assuming this works as advertised, this should solve my problem.

Switch is turned on via Aux on main level.
We walk upstairs (2-3 seconds)
Sometime during this walk upstairs, the Hub polls the out of range switch and reports it as on.
We come into range of the motion sensor. The app triggers, but the test for if the light is on or not reports on, so it doesn’t dim.

I do NOT know of this updated polling proposed will update Lux levels on the order of seconds. If so, then I could also use the light sensor for this.


(Zach Naimon) #9

I see no reason why you would use a light sensor, and not just check the current switch value.

def initialize(){
  def freq = 1
  schedule("0 0/$freq * * * ?", checkSwitch)
}

def checkSwitch(){
  myLightSwitch.poll()
}

def myMotionHandler(evt){
  def lightVal = myLightSwitch.currentSwitch
  if (inTimeWindow()){
    if(lightVal == "off"){
      myLightSwitch.on()
      //Insert your specific dimmer code here.
    }
    else{
      log.debug "Do nothing.  Lights are already on...or something"
    }
  }

}

private inTimeWindow(){
        def now = now()
	def tz = timeZone
	def window1 = now >= timeToday(startTime, tz).time && now <= timeTodayAfter(startTime, endTime, tz).time
	def result = window1
	result
}

This will poll for a lightswitch value every minute.

Given your aux switch, this may or may not work. What I would suggest (if you have one) is placing a motion sensor at the bottom of the stairs that controls the upstairs switch, that way you guys trip the switch at the bottom, and it turns on.