Multi State Switches

I tried mysql, and have got persistence to work. However, the restoreOnStartup strategy is not working. Tried the workaround from MySQL & restoreOnStartup : KO · Issue #1194 · openhab/openhab1-addons · GitHub, however, that is not working either.

One more issue : getting following WARN : 2016-06-02 20:13:30.513 [WARN ] [t.i.s.MapTransformationService] - Could not find a mapping for ‘-’ in the file ‘3states.map’. could you point me on how to debug this problem?

Ah, yes. simply add a line

- = -

to the file 3states.map, this is due to the fact, that the item is not initialized. openHAB tries to lookup the mapping and doesn’t find an appropriate line in the mapping file.

Do you see any database entry for your item in MySQL?
First there should be an entry in the table items with the name of the item and the name of the data table associated to the item.
Secondly there should be the table with entries for your item.
Maybe the MySQL connection isn’t up in time to restore the state. This is the downside of the strictly asynchronous design of openHAB.

adding -=- sorted that issue.

On the other one, yes all items are getting populated in mySQL, however, state is not getting restored even after using the touch script on mysql.persist

That’s strange, it’s working for me with mysql. What’s your mysql.persist like?

Strategies {
//default = everyChange
everyMinute : “0 * * * * ?”
default = everyMinute
}

Items {
* : strategy = default, restoreOnStartup
}

tried with both everyChange and everyMinute - however, restoreOnStartup does not work using mySQL. However, have got it to work using mapDB now.

I’m looking to do almost the exact same thing, except my states are -1, 0, 1.
My 3states.map looks like this:
-1=Off 0=Auto 1=On
but I get `[WARN ] [t.i.s.MapTransformationService] - Could not find a mapping for ‘-’ in the file ‘3state.map’'
in my run.log.

I think I found that the message above is generated when the value is unknown at startup. I added -:unknown to the map file and it’s now gone. I’d like to move the Switch definition from the Sitemap into an item file, but I’m at a loss on the right syntax. I can’t find documentation on the usage of mappings= to understand whether I can use it in that context.

In fact, you can’t get the mappings-setting to the items file, this is sitemap-only.

Is there a way to have it shown in a group? My sitemap looks like this, but the Switch shows up at the top level; I’d like it in the Outdoors group:
Frame { Group item=gGF label="Main Floor" icon="groundfloor" Group item=gUpstairs label="Upstairs" icon="firstfloor" Group item=gBasement label="Basement" icon="cellar" 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" Group item=Temperature label="Temperatures" Text item=alarmPanelDisplay icon="garden" Group item=gAlarm label="Alarm System" icon="garden" }

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