My First Rule: One-button on/off and brightness control

My intention is to have a single physical button control both on/off and brightness for my livingroom lights:

Press the button once, and it toggles ON/OFF
Press the button multiple times in relatively quick succession, and it increases the brightness by 20% for each button press. If you press the button enough times to increase the brightness beyond 100%, the light turns off.

I’ve created a virtual dimmer called LivingRoomBrightness and set it to restoreOnStartup
The virtual dimmer acts a way to store the last brightness used… perhaps there is a better way to do this using persistence and the actual state of the light itself?

Here’s the basic idea of how the rule would work. This is the first rule I’ve ever created myself, so I’m sure there are some syntax errors–this is basically pseudo-code to figure out the logic of the rule. I’d really appreciate any help cleaning it up and getting it working.

when LR_button.state==updated
then

//If the light is off, turn it on at the level of the LivingRoomBrightness dimmer

if LR_light.state==OFF,
then LR_light.state=LivingRoomBrightness

//If the light is on and button hasn't been pushed in 2.5 seconds or more, turn the light off.
//I'm not sure how to actually write the part of the code that determines the time since last button-press

else if Now - LR_button.lastUpdate > 2.5 seconds
then LR_light.state=OFF

//If the button was pushed in the last 2.5 seconds, increment the dimmer by 20% and 
//set the light to the value of the dimmer. 
//If the dimmer was already at 100%, turn the light off.

else if LivingRoomBrightness.state==100%, LR_light.state=OFF

else LivingRoomBrightness.state=LivingRoomBrightness+20% 
   LR_light.state=LivingRoomBrightness

Any hints on making this code work? I’m also open to any suggestions for ways to make operation of the lights more user-friendly. Maybe going 100% should wrap around to 0, then another press would bring back to 20%, etc?

Thanks!

What kind is the button?
Maybe you could measure the time from button.pressed to button.released. Then you could start dimming continuously when detected a long press and stop dimming when release was detected. Further you could remember the direction and toggle the direction every long press, so you could dimm up and down with one button. Short press would be a toggle ON/OFF.

I considered something similar when I first started thinking about how to set this rule up. Unfortunately, I don’t think it will work.

The physical button is on an Enerwave 7-button scene controller. It’s connected via Z-wave to my VeraEdge, which in turn is connected to OpenHAB via the MiOS binding.

Since it’s designed to serve as a simple scene trigger, I don’t think there’s any way of measuring the length of time that the button is pressed. In fact, I’m not sure that I can even directly detect the button press at all. My plan is to have the Enerwave trigger very simple scenes in the Vera that just flip a series of virtual switches, and then OpenHAB will detect the virtual switch state change via the MiOS binding.

@Chad_Hadsell,
You may want to try this in the Designer first, since it will guide you a little in the overall Rule Syntax.

That said, for your first Rule definition, you may want to start with something a little simpler since there are going to be a lot of nuances to learn along the way (not to mention the quirks of working with Scene controllers originating from MiOS)

Here’s a basic activation rule I’m using with my MiniMote (via MiOS Binding):

rule "Goodnight - MiniMote"
when
        Item MasterMiniMoteSceneActivated received update 1
then
        Thread::sleep(200)
        // Handle startup, where things aren't restored.
        var t = MasterMiniMoteLastSceneTime.state
        if (t instanceof DateTimeType) {
                var eventTime = new DateTime((t as DateTimeType).getCalendar())
                if (now.minus(1000).isBefore(eventTime)) {
                        callScript("goodnight")
                }
        }
end

It has basic structural elements you’ll need( like rule ... when ... then ... end), as outlined in the Rule Syntax line above, as well as some startup/timing problems you’ll need to contend with when working with MiOS-based Scene controllers and the issues of received update events firing during startup

In this case, because each Scene button can be pressed multiple times, and MiOS delivers the “same” data (the Button Id on the Scene Controller) you have to use timing-checks on the Scene Controllers “*LastSceneTime

For reference, my corresponding Item declarations look like:

house.items:Number   MasterMiniMoteSceneActivated "Master Minimote Scene Activated [%d]" (GPersist) {mios="unit:house,device:392/service/SceneController/sl_SceneActivated"}
house.items:Number   MasterMiniMoteSceneDeactivated "Master Minimote Scene Deactivated [%d]" (GPersist) {mios="unit:house,device:392/service/SceneController/sl_SceneDeactivated"}
house.items:DateTime MasterMiniMoteLastSceneTime "Master Minimote Last Scene Time [%d]" (GPersist) {mios="unit:house,device:392/service/SceneController/LastSceneTime"}

Another option would be to switch through brightness levels with every single tap, but when detect a double click switch off:

import org.joda.time.DateTime

var Timer tMios1 = null
var int iMiosS = 0

rule MyMultiStep
when
    Item MiosSwitch received command 
then
    if (tMios1!=null){
        tMios1.cancel
        tMios1=null
        logInfo("MyMultiStep","Double click")
        myDimmer.sendCommand(OFF)
        iMiosS = 0
    }
    else
        tMios1 = createTimer(now.plusMillis(500))[|{
            logInfo("MyMultiStep","Single click")
            iMiosS=iMiosS-1
            if (iMiosS<0)
                iMiosS=5
            logInfo("MyMultiStep","Step {}",iMiosS)
            myDimmer.sendCommand(iMiosS*20)
        }]
end

Even more you could store last level and return to this, if you double click from OFF.

Oh, I like that idea!
I think I’ll set up the simple toggle first, just to get some practice writing rules and using the MiOS binding. And then I’ll take a stab at implementing this, for the lights that dim.

OK, starting simple: I’ve got a “toggle” rule set up and working successfully for a couple of the buttons on the scene controller. I can now use one button to switch something on and off.
Next up is detecting a double-tap, but before i do that, I have a quick question about rule syntax.

While I was looking at how to do this, I found a few examples that use “sendCommand” differently. So, I tried both in my rules:

//Toggle the switch called Enerwave1Test on each press of the physical Enerwave button 1
    rule "Toggle Enerwave Button 1"
    when 
    	Item EnerwavesceneslSceneActivated received update 1
    then
    	Thread::sleep(200)
    	if (Enerwave1Test.state != ON) {
    		sendCommand(Enerwave1Test, ON)
    	}
    	else {
    		sendCommand(Enerwave1Test, OFF)
    	}
    end

//Toggle the switch called Enerwave2Test on each press of the physical Enerwave button 2
    rule "Toggle Enerwave Button 2"
    when 
    	Item EnerwavesceneslSceneActivated received update 2
    then
    	Thread::sleep(200)
    	if (Enerwave2Test.state != ON) {
    		Enerwave2Test.sendCommand(ON)
    	}
    	else {
    		Enerwave2Test.sendCommand(OFF)
    	}
    end

Is one of these “more correct” than the other? Is there a scenario where I would use one and not the other?

For sendCommand(), either style works, so it comes down to preference.

For sendMiosAction(), and sendMiosScene(), only the first style works and I have an issue open against myself to work out why the secondary form doesn’t work.

You’ll find the latter style handy if you have larger groups of Switch Items you want to turn on/off, just put them all into a named Group, and then you can do something akin to:

GManagedGoodnight.sendCommand(OFF)

it’ll save you a bunch of time writing loops manually.