Multi State Switches

There are two options, either you can set curly brackets around the Switch:

{Switch item=PondMode label="Pond mode" mappings=["-1"="Off",0="Auto",1="On"]}

which is the same as:

Group item=GF_Outdoor label="Outdoors" icon="garden" {
    Switch item=PondMode label="Pond mode" mappings=["-1"="Off",0="Auto",1="On"]
    }
Group item=Holiday label="Holiday"

or (better option) don’t rely on groups for building the UI at all. This is a nice “quick 'n dirty” feature to have a quick result, but you have very low possibilities to control the UI, e.g. what if you want the same items in a different order at another position of sitemap? So best practice is to write down the whole sitemap :slight_smile:

2 Likes

Is it possible to add a autoupdate=“false” for the My3stateSwitch?
I have tried this, but than the status of My3stateSwitch do not change to ON, it will chagen to 0.0, and so the rule will not start.

autoupdate="false" will cause openHAB not to update the state of an item within openHAB when sending a command to the bound binding, whether this command was caused by a UI click or via a myItem.sendCommand() in a rule.

Afaik autoupdate="false" is default behavior in OH2.3

Do i understand it correctly, that we need an additonal item.postUpdate() if the binding doesn’t update the state by itself?

I do not understand in which cases this default makes sense (as a default) . @Udo_Hartmann, do you have a link to a discussion or CR or issue? Thanks

In most cases, openHAB should show the real state of an object, not the state, that it should be.

Communication is normally like that:

openHAB sends command to item -> sends command to bound channel -> 
sends command to bus -> actuator receives command -> actuator executes command -> 
actuator sends state update to bus -> sends state update to openHAB -> 
sets channel respectively -> sets item state.

So no, you should not need a .postUpdate() to get the correct state. But if you use a hardware which does not support state updates, autoupdate="true" would be your friend.

First of all, I want to thank you all for the inspirations for the multi-state switch, I got mine working so far, ON and OFF toggle a Fibaro FGS 213 directly, and AUTO switches to a rule which uses a PIR-Sensor to switch light on and off with a expire item. I did like this (not elegant, but working):

Items:

// Logic Switches

Switch 		OG_Nazar_Licht_Timer_Active

//Timer Switches

Switch 		OG_Nazar_Licht_Timer	{expire="15s,command=OFF" }

//Physical Switches
Switch   	OG_Nazar_Licht      		"Licht Nazar"        			<light>             (ogLight)       	["Lighting"]   {channel="zwave:device:3a7e4c2a:node3:switch_binary1"}

Rules:

//Dreifachschalter

rule "3state"
when
    Item My3stateSwitch changed
then
    switch (My3stateSwitch.state as DecimalType) {
        case 0 : {
		OG_Nazar_Licht.sendCommand(OFF)
		OG_Nazar_Licht_Timer_Active.sendCommand(OFF)
		}
        case 1 : {
		OG_Nazar_Licht.sendCommand(ON)
		OG_Nazar_Licht_Timer_Active.sendCommand(OFF)
		}
        case 2 : {
		OG_Nazar_Licht_Timer_Active.sendCommand(ON)
		}
    }
end

//Bewegungsmelder

rule "Bewegungsmelder an"
when
  Item PIR_Sensor_1 changed from OFF to ON then
 if(OG_Nazar_Licht_Timer_Active.state==ON) {
  OG_Nazar_Licht_Timer.sendCommand(ON)}
end

//Switch Light with timer

rule "Nazar Licht Auto ON"
when
  Item OG_Nazar_Licht_Timer changed to ON
then
  OG_Nazar_Licht.sendCommand(ON)
end

rule "Nazar Licht Auto OFF"
when
  Item OG_Nazar_Licht_Timer changed to OFF
then
  OG_Nazar_Licht.sendCommand(OFF)
end

The logic is like this: State 0 of multiswitch switches off light directly, 1 switch on directly. State 2 sets a control variable (OG_Nazar_Licht_Timer_Active), and if this is set to ON, the events of PIR activate OG_Nazar_Licht_Timer which is expiring item. The last rule switches physical switch according to expiring item. This all works so far, in AUTO mode the light is switched on by PIR-Event and goes off after 15s.

But now I have one more nut to crack:

The FGS 213 can also be switched physically in the socket. So for example, the Multiswitch is set to AUTO, I enter the room and switch light physically. In this case, I want the multiswitch to change from “AUTO” to “ON”. At the moment, it remains in AUTO, because there is no feedback from switch item to multiswitch. But if I connect it by the item of the physical switch (OG_Nazar_Licht), it will leave auto mode even when timer expires, so AUTO will only work one time.

How can I achive that physical switching from FGS213 leaves the AUTO mode?

…as so often, thinking helps :smile:

I realised that I just had to check if the change of physical switch state occurs while the item expires, cause this means someone switched manually while AUTO was active. So two more rules did it:

//End Auto Mode when Light is switched on manually

rule "End Auto Mode ON"

when
  Item OG_Nazar_Licht changed from OFF to ON then
		if(OG_Nazar_Licht_Timer.state==OFF)
		{
			My3stateSwitch.postUpdate(1)}
end

rule "End Auto Mode OFF"

when
  Item OG_Nazar_Licht changed from ON to OFF then
		if(OG_Nazar_Licht_Timer.state==ON)
		{
			My3stateSwitch.postUpdate(0)}
end

In addition, I needed two more rules to reflect physical switch actions to the multiswitch:

//Multiswitch syncen bei manueller Auslösung

rule "Sync Multiswitch ON"

when
  Item OG_Nazar_Licht changed from OFF to ON then
		if(My3stateSwitch.state==0)
		{
  My3stateSwitch.postUpdate(1)}
end

rule "Sync Multiswitch OFF"

when
  Item OG_Nazar_Licht changed from ON to OFF then
		if(My3stateSwitch.state==1)
		{
  My3stateSwitch.postUpdate(0)}
end

Now everything works as desired sigh

To restate your problem, when the real device bound to OG_Nazar_Licht changes state, but the change wasn’t just commanded by openHAB, you want to take a special action.

But openHAB is event driven, stateless. There is no easy way to remember that it’s just sent a command (also, how long is “just” anyway).

One way is to have two Items - one linked to the real device, and one dummy for rules to send commands to. If the real device changes state to match the dummy, it was an openHAB action.If they don’t match, it was a physical button press.

//Physical Switch
Switch OG_Nazar_Licht 	"Licht Nazar" <light> {channel="zwave:device:3a7e4c2a:node3:switch_binary1"}
//Dummy Switch
Switch OG_Nazar_Licht_Proxy <light> "Licht Nazar proxy"
rule "pass on commands"
when
   Item OG_Nazar_Licht_Proxy changed
then
   if ( OG_Nazar_Licht_Proxy.state != OG_Nazar_Licht.state) {  // if not already as commanded
      OG_Nazar_Licht.sendCommand(OG_Nazar_Licht_Proxy.state) // send command
   }
end

rule "detect physical changes"
when
   Item OG_Nazar_Licht changed
then
   if (OG_Nazar_Licht_Proxy.state != OG_Nazar_Licht.state) {  // unexpected change
      // here do whatever you do for a manual pushbutton
      // then 
      OG_Nazar_Licht_Proxy.postUpdate(OG_Nazar_Licht.state)  // make matching now
   }
end

Have your other rules send commands to the Proxy.
Choose if you want UI commands to act like manual commands, and either put the real or proxy in your sitemap.
Choose which one to link with [tags] in a similar way…

1 Like

Thanks for your explanation, yes you restated my problem correct, and your solution is much more elegant since you used only two rules where I needed six rules :wink:

I will implement it that way.

Hi Udo,

I know this thread is very old but I wanted to say that I love thay way of setting up a 3 or even 4 state button in OH.

Based on your answer, I’ve set up a 4 state button for my air extractor : ON LOW HIGH OFF

The difficulty was that the extractor could not be turned on with the remote (only set the speed).

So in my case, case 0 sends a switch ON command to a wireless plug
case 1 sends LOW command via RFXCOM
case 2 sends HIGH command via RFXCOM
case 3 sends a switch OFF command to a wireless plug

Thanks. :slight_smile:

You could use a three state switch but send more than one command:

...
switch ((My3stateSwitch.state as Number).intValue) {
        case 0 : {
            MyPlug.sendCommand(OFF)
        }
        case 1 : {
            if(MyPlug.state != ON) {
                MyPlug.sendCommand(ON)
                Thread::sleep(500)
            }
            MySpeed.sendCommand("LOW")
        }
        case 2 : {
            if(MyPlug.state != ON) {
                MyPlug.sendCommand(ON)
                Thread::sleep(500)
            }
            MySpeed.sendCommand("High")
        }
    }
...

If half a second is not enough for the vent to get ready to receive messages, it would be better not to use Thread::sleep but a timer.

1 Like