3 Bulbs in a room

Hi there,

I am coding since several hours, to get a quite easy ( i thought ) Rule.

I have in my bedroom 3 bulbs on the ceiling and want 2 things to happen:

First:
depending on the time of the day the lights should be dimmed ( i think i have that done )

second:
Every time i use the switch, i want to turn one bulb on, if all three are ON the turn them all off.
But if the last time the switch was used is longer than 10 seconds, it will torn all bulbs off.

The 10 Second thing is not working at all ( i think ).

And the part where i torn on one bulb and the next seems not to be very nice.

Is there somebody who could help me? I think, this could be a nice design Pattern anyway.

Here is what i have written in Rule:

rule "Schlafzimmer1_Click On"
when
	Item TA_SZ_1_Short changed to ON
then

	if (  ! TA_SZ_1_Short.changedSince(now.minusSeconds(10)) ) 
		{
			logInfo("SZ Click", "no change since 10 sec"+ now.minusSeconds(10))
			counter = 3
//			sendCommand(gSZDimmer,0)
//			return 
		}
	letzerClickSZ = now
	switch ( Time_Of_Day.state )
		{
			case "DAY" :
			{ 
				lichtStaerke = 100
			}
			case "MORNING" : {
				lichtStaerke = 100
			}
			case "NIGHT" :   {
				lichtStaerke = 20
			}
			case "EVENING" : 
			{
				lichtStaerke = 40
			}
			default:
			{
				lichtStaerke = 100
			}
		}

	logInfo("SZ Click", "Taster kurz geklickt, "+ counter + " Licht : " + lichtStaerke)
	gSZDeckenlicht.get	

	switch ( counter )
	{
		case 0 :
		{
			sendCommand(Schlafzimmer1_Dimmer,lichtStaerke)
			counter = 1
		}
		case 1 :
		{
			sendCommand(Schlafzimmer2_Dimmer,lichtStaerke)
			counter = 2
		}
		case 2:
		{
			sendCommand(Schlafzimmer3_Dimmer,lichtStaerke)
			counter = 3
		}
		case 3:
		{
			sendCommand(gSZDimmer,0)
			counter = 0
		}
		default:
		{
			counter = 0
			
			sendCommand(gSZDimmer,0)
		}
	}
end

regards

I was getting ready to point you to the Time of Day DP but see you are already using it. :smiley:

OK, so for your problem, behaviors like this feel like they should be easy but almost never are. You have a lot of cases that need to be taken into consideration. If I break your statement down:

OK, so we need a Rule triggered by using the switch. I assume TA_SZ_1_Short is the switch, correct?

So I’m interpreting this to mean if all the bulbs are OFF, you first turn on Schlafzimmer1_Dimmer. If one bulb is on you turn on Schlafzimmer2_Dimmer. If two bulbs are on you then turn on Schlafzimmer3_Dimmer. If three bulbs are on you turn them all OFF.

No matter how many bulbs are ON, if the last time TA_SZ_1_Short was updated BEFORE the current button press turn all the bulbs OFF.

Given this interpretation, I have to make a few additional assumptions, most important of which is that TA_SZ_1_Short goes from OFF to ON when pressed and immediately thereafter back to OFF.

So, given the above assumptions, the problem you have is that by the time the Rule executes, TA_SZ_1_Short has already turned back to OFF so your changedSince is not working.

There are a few ways you can handle this:

  • set timestamp in a global var
  • use a Timer

I’m going to use a timestamp in a global var as I think it is a little simpler and meets your requirements.

I’m also going to rework your logic a bit to make it a little shorter and more concise while also making it easier to expand (e.g. add more bulbs).

First, put your bulbs into a Group, I’ll call it gSchlafzimmer_Dimmer:

Group:Dimmer gSchlafzimmer_Dimmer
var lastClicked = now

rule "Schlafzimmer1_Click ON"
when
    Item TA_SZ_1_Short changed to ON
then
    val numOn = gSchlafzimmer_Dimmer.members.filter[dim|dim.state as Number > 0].size

    // Turn OFF all lights if it has been 10 seconds since the last time the switch was pressed or if all the lights are on
    if(now.minusSeconds(10).isAfter(lastClicked) && numOn > 0 || numOn == gSchlafzimmer_Dimmer.size) {
        gSchlafzimmer_Dimmer.sendCommand(0)
    }

    // Cycle the lights ON based on number of button presses
    else {
        // Determine the dimmer value
        var lichtStaerke = 100
        switch(Time_Of_Day.state){
            case "NIGHT": lichtStaerke = 20
            case "EVENING": lichtStaerke = 40
        }
        // DAY, MORNING, and DEFAULT are already handled by initializing lichtStaerke to 100, adding separate cases 
        // for them is redundant

        // Turn on the next light
        val nextLight = numOn + 1
        sendCommand("Schlafzimmer"+nextLight+"_Dimmer", lichtStaerke.toString) // This is a case where using the Action is warranted
    }

    // save the timestamp
    lastClicked = now
end

The above is just typed in and may have a bug or a typo. As long as your Dimmer Items are numbered sequentially you can have as many as you want be members of the Group and not have to change the Rule.

1 Like

Hi rlkoshak,

thanks for the answer, what you did seems very good to me.
I tried to implement that, but I got following Exception:

The name '<XFeatureCallImplCustom>.size' cannot be resolved to an item or type.

I am not very sure, how to debug openhab rules, maybe you can give me a hint while i am searching for the error :slight_smile:

regards

Use ESH Designer for one. It will tell you have something wrong as you type.

Add some logging statements to determine which specific line it is failing on.

At first look, it appears that the first line of the rule is where the failure is.

Did you create the Group in your .items file and assign your Dimmers to the Group?

1 Like

Hi,

I started using Visual Studio Code, but it does not show me any error. Would ESH be better?

I have already put some debug output inside the code, but am not finding the real issue.

I assume, that the size operator is not working proper, if the filter give no result.

Will try now ESH :wink:

regards

ESH has better and more thorough syntax checking than the VS plugin.

For day to day coding VS is probably better but when you run into potential syntax errors like this Designer will do a better job helping you out.

Hi again,

thanks for the help. I found the Problems yesterday evening, but could not test as my wife was already sleeping :slight_smile:

Here is the “final” Code with bugfixes:

rule "Schlafzimmer1_Click ON 2"
when
    Item TA_SZ_1_Short changed to ON
then	
        logInfo("SZ Click", "Taster kurz geklickt, "+ gSchlafzimmer_Dimmer.members.filter[State|State.state > 0])
	val Number numOn = gSchlafzimmer_Dimmer.members.filter[State|State.state as Number > 0].size
	
	logInfo("ClickOn","Anzahl Lampen mit Licht: "+ numOn)
	logInfo("ClickOn","Anzahl der Lampen: " + gSchlafzimmer_Dimmer.members.size)
    
    // Turn OFF all lights if it has been 10 seconds since the last time the switch was pressed or if all the lights are on
    if(now.minusSeconds(10).isAfter(lastClicked) && numOn > 0 || numOn == gSchlafzimmer_Dimmer.members.size) {
        gSchlafzimmer_Dimmer.sendCommand(0)
    }

    // Cycle the lights ON based on number of button presses
    else {
        // Determine the dimmer value
        var lichtStaerke = 100
        switch(Time_Of_Day.state){
            case "NIGHT": lichtStaerke = 20
            case "EVENING": lichtStaerke = 40
        }
        // DAY, MORNING, and DEFAULT are already handled by initializing lichtStaerke to 100, adding separate cases 
        // for them is redundant.,



        // Turn on the next light
        val nextLight = numOn + 1
        sendCommand("Schlafzimmer"+nextLight+"_Dimmer", lichtStaerke.toString) // This is a case where using the Action is warranted
    }
	logInfo("ClickOn","Anzahl Lampen mit Licht: "+ gSchlafzimmer_Dimmer.members.filter[State|State.state as Number > 0].size)
    // save the timestamp
    lastClicked = now
end 

thanks for your help

1 Like

Doh! That was a silly typo on my part. Glad you found the error and hope it works.

1 Like

Yes, definitly it worked, and you helped me a lot.

Best thing: I learned a lot :wink:

regards