postUpdate virtual dimmer using switch-case and average of dimmer values

Using OH 2.4.0-1 on Debian 9.
I have 5 dimmer items (Philips Hue) and a dimmer switch (Philips Hue).
I also have a virtual dimmer in the Items-file for controlling all the Hue-lamps and two zwave on/of lamps.

Dimmer Woonkamer_keuken "Woonk./keuken" <light>
Dimmer Licht_bank "Licht bank" <light> (Verlichting,Woonkamer, Schemer, gTest) {channel="hue:0100:0017887ff168:3:brightness"}
Dimmer Licht_bobbie "Licht bobbie" <light> (Verlichting,Woonkamer, Schemer, gTest) {channel="hue:0100:0017887ff168:1:brightness"}
Dimmer Licht_TVL "Licht TV links" <light> (Verlichting,Woonkamer, Schemer, gTest) {channel="hue:0100:0017887ff168:2:brightness"}
Dimmer Licht_TVR "Licht TV recht" <light> (Verlichting,Woonkamer, Schemer, gTest) {channel="hue:0100:0017887ff168:6:brightness"}
Dimmer Licht_vak "Licht vakjeskast" <light> (Verlichting,Woonkamer, Schemer, gTest) {channel="hue:0100:0017887ff168:5:brightness"}

//two zwave lamps:
Switch Lamp_K_Aanrecht "Lamp keuken aanrecht" <light>  (Verlichting, Keuken) {channel="zwave:device:512:node6:switch_binary"}
Switch Lamp_K_koelkast "Lampjes koelkast" <light>  (Verlichting, Keuken) {channel="zwave:device:512:node27:switch_binary"}

What I like to accomplish is that if I use the general dimmer ‘Woonkamer_keuken’, it also switches on 2 zwave sitches for on/of-lamps. This is working through a rule.
Also I want to accomplish that I can set the dimmer value of the 5 Hue-dimmers all at once from the OH-app in steps. This is also working:

Selection item=Woonkamer_keuken mappings=[0="uit", 10="10%", 30="30%", 50="50%", 90="90%", 100="100%"]

But when I change just one of the Hue lamps to another level, this causes the ‘general’ dimmer item ‘Woonkamer_leulen’ to not show it’s status because the value is not one of the presets.

I thought if using postUpdate to set the virtual dimmer ‘Woonkamer_keuken’ to the pre-set value that is closest to the average of the 5 real dimmer values. But two things don’t work out with my rule: the postUpdate really sets the value like senCommand while I thought it would just show the new value and not switch on it.
And the second thing that doesn’t work is that the switch case does not do a thing.
Any help is welcome, also if it means changing the way to do this, but I really would like to better understand the postUpdate behaviour and the switch-case-thing.

rule "DIm-gemiddelde lampen -> keuken"
when
    Item Licht_bank changed or
    Item Licht_bobbie changed or
    Item Licht_TVL changed or
    Item Licht_TVR changed or
    Item Licht_vak changed
then
var Number avgLevel = (Licht_bank.state as Number + Licht_bobbie.state as Number + Licht_TVL.state as Number + Licht_TVR.state as Number +Licht_vak.state as Number) / 5
   logInfo("DIm-gemiddelde lampen -> keuken", "Huidig gemiddelde: "+avgLevel) //this shows up in log alright
    if (avgLevel <= 20) {
        Lamp_K_Aanrecht.sendCommand(OFF)
        Lamp_K_koelkast.sendCommand(OFF)
    } else {
        Lamp_K_Aanrecht.sendCommand(ON)
        Lamp_K_koelkast.sendCommand(ON)
    }
    var newLevel = 0
    switch avgLevel {
        case (avgLevel > 0 && avgLevel < 15) : newLevel == 10
        case  avgLevel >= 15 && avgLevel < 25 : newLevel == 20
        case  avgLevel >= 25 && avgLevel < 35 : newLevel == 30
        case  avgLevel >= 35 && avgLevel < 55 : newLevel == 50
        case  avgLevel >= 55 && avgLevel < 95 : newLevel == 90
        default : newLevel == 100
    }
   logInfo("DIm-gemiddelde lampen -> keuken", "Nieuw gemiddelde: "+newLevel) //this always show whatever I use to initiate 'newLevel'
    Woonkamer_keuken.postUpdate(newLevel)
end

I also tried using the group gTest to set al dimmers using the same presets from the sitemap, but this is not working. Therefore I went back to the virtual dimmer again.

I tried rewriting the switch case to an if-statement. This showed errors telling that the setting of the variable newLevel was not going allright. Therefor I went for the following which seams to work except for the fact that Woonkamer_keuken.postUpdate(90) still changes the value in such a way that the other rule fires, changing all the dimmers to value 90.

    if (avgLevel > 0 && avgLevel < 15){
        Woonkamer_keuken.postUpdate(10)
    } else if (avgLevel >= 25 && avgLevel < 35){
        Woonkamer_keuken.postUpdate(30)
    } else if (avgLevel >= 35 && avgLevel < 55){
        Woonkamer_keuken.postUpdate(50)
    } else (avgLevel >= 55 && avgLevel < 95){
        Woonkamer_keuken.postUpdate(90)
    }

Try your switch case using true.
Example:

switch true {
        case  avgLevel > 0 && avgLevel < 15     : newLevel == 10
        case  avgLevel >= 15 && avgLevel < 25 : newLevel == 20
        case  avgLevel >= 25 && avgLevel < 35 : newLevel == 30
        case  avgLevel >= 35 && avgLevel < 55 : newLevel == 50
        case  avgLevel >= 55 && avgLevel < 95 : newLevel == 90
        default : newLevel == 100
    }
1 Like

Thanks, that helps. I got an error about the ‘==’ so I changed those to ‘=’.
Now I am stuck with the following error without a row number:

Rule 'DIm-gemiddelde lampen -> keuken': An error occurred during the script execution: null

Without the “Huidige gemiddelde” log before that error?
Then probably something is going wrong in the line that calculates the avgLevel.
Can you add a logInfo() before that, so right after then, containing each of the states like so:

logInfo("TestGemiddelde", "Bank: " + Licht_bank.state.toString + ", bobbie: " + Licht_bobbie.state.toString + ", TVL: " + Licht_TVL.state.toString + ", TVR: " + Licht_TVR.state.toString + ", Vak: " + Licht_vak.state.toString)

And see if any of these give a null as result, or another unexpected value?

I don’t have a clue what this error means, but I tried this:

    switch true {
        case  avgLevel > 0 && avgLevel < 15   : Woonkamer_keuken.postUpdate(10)
        case  avgLevel >= 15 && avgLevel < 25 : Woonkamer_keuken.postUpdate(20)
        case  avgLevel >= 25 && avgLevel < 35 : Woonkamer_keuken.postUpdate(30)
        case  avgLevel >= 35 && avgLevel < 55 : Woonkamer_keuken.postUpdate(50)
        case  avgLevel >= 55 && avgLevel < 95 : Woonkamer_keuken.postUpdate(90)
        default : Woonkamer_keuken.postUpdate(100)
    }

Now the error is gone, I see in the log that the average is calculated correctly, the switch-case is working! I still dont understand the switch-case statement I’m affraid.
The only thing not working is that the postUpdate of item ‘Woonkamer_keuken’ still causes the other rule to trigger. Now I have the case running, I guess I have to look at the other rule to see why that is running.

I have that rule triggering by:

when
    Item Woonkamer_keuken changed

Should I change that to something else to prevent triggering by ‘postUpdate’?

I’m sorry, I didn’t see your post. I guess the var-declaration was not working. Without the var 'newLevel’it is working. Just not without triggering the other rule that sets all dimmers to the value of Woonkamer_keuken.

A Item xxx received command rule doesn’t get triggered by a postUpdate. But of course you will have to check if that doesn’t have any other impact that we can’t oversee from here.

What the switch case statement does, is that it compares when whatever you have in the case part equals whatever you have in the switch part. And with somewhat more complex scenario’s, you can just set the switch part to true to make sure that the case that equals to true gets executed. So if avgLevel is 90, avgLevel > 0 && avgLevel < 15 and so on results in false and only avgLevel >= 55 && avgLevel < 95 results in true (as 55<90<95), so that means that Woonkamer_keuken.postUpdate(90) gets executed.

I hope this makes it a bit more understandable.

Yes, that is working correctly! Thank you RolfV and H102! My rules are behaving like I wanted.

About the switch case: so do you have an example where you use the switch-case with variable that hold numbers and where you do not use ‘true’ in the switch-line?

I just did in an edit of my post above :slight_smile:

another option:

var Number newLevel = 100
if (avgLevel == 0)
    newLevel = 0
else if(avgLevel < 15)
    newLevel = 10 
else if(avgLevel < 25)
    newLevel = 20 
else if(avgLevel < 35)
    newLevel = 30 
else if(avgLevel < 55)
    newLevel = 50 
else if(avgLevel < 95)
    newLevel = 90 

@Guido_van_Haasteren glad to hear your rules are working as intended.:+1:

Here’s a link I keep bookmarked to help with conditional statements. Look at the left side and notice the next description down is about switch case.
https://www.w3schools.com/js/js_if_else.asp

With @RolfV excellent description above and this link hopefully everything will start to make since.:wink:

Unfortunately all is not working fine anymore. Two rules are colliding. But When I have the time I will start over and use your input. Thank you!