Bit coded status item to separate items

Please whats wrong for decode bits 0,1,2,3,4,8,9,10 of an integer like 1042 decimal ?

Number I3056 "3056 Lockings flags [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_0 "3056_0 Inverter vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_1 "3056_1 Charger vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_2 "3056_2 Boost vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_3 "3056_3 Transfert vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_4 "3056_4 Injection vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_8 "3056_8 Multi vorbidden [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_9 "3056_9 Multi indenpedants allowed [%d]" <solarplant> (studer_Info_Group_02)
Number I3056_10 "3056_10 Standby slave allowed [%d]" <solarplant> (studer_Info_Group_02)
rule "3056 decode bits"
when
    Item I3056 received update
then
    var tmp = I3056.state  as DecimalType
    var state = tmp.toBigDecimal.toBigInteger

    postUpdate(I3056_0,0)
    postUpdate(I3056_1,0)
    postUpdate(I3056_2,0)    
    postUpdate(I3056_3,0)
    postUpdate(I3056_4,0)
    postUpdate(I3056_8,0)
    postUpdate(I3056_9,0)
    postUpdate(I3056_10,0)

    if (state.testBit(0) ) {         //test Bit 0
        if (I3056.state==1) 
            I3056_0.postUpdate(1)    //if 1, then set I3056_0 to 1
            }
    else if (state.testBit(1)) {     //test Bit 1
        if (I3056.state==2) 
            I3056_1.postUpdate(1)    //if 1, then set I3056_1 to 1
            }
    else if (state.testBit(2)) {     //test Bit 2
        if (I3056.state==4) 
            I3056_2.postUpdate(1)    //if 1, then set I3056_2 to 1
            }
    else if (state.testBit(3)) {     //test Bit 3
        if (I3056.state==8) 
            I3056_3.postUpdate(1)    //if 1, then set I3056_3 to 1
            }
    else if (state.testBit(4)) {     //test Bit 4
        if (I3056.state==16) 
            I3056_4.postUpdate(1)    //if 1, then set I3056_4 to 1
            }
    else if (state.testBit(8)) {     //test Bit 8
        if (I3056.state==256) 
            I3056_8.postUpdate(1)    //if 1, then set I3056_8 to 1
            }
    else if (state.testBit(9)) {     //test Bit 9
        if (I3056.state==512) 
            I3056_9.postUpdate(1)    //if 1, then set I3056_9 to 1
            }
    else if (state.testBit(10)) {     //test Bit 10
        if (I3056.state==1024) 
            I3056_10.postUpdate(1)    //if 1, then set I3056_10 to 1
            }
end

OR SOME BETTER/ NICE SOLUTION with state.bitwiseAnd PLEASE.

  • Platform information:
    • Hardware: RPI4 4GB
    • OS:Raspbian Buster
    • Java Runtime Environment: java 8
    • openHAB version: last 2.5

What happens when the rule is triggered? And what do you want it to do?

E.g you use if-else if, which means only one of the branches will run, is this what you want?

It’s hard to help you when we don’t know what you want the rule to do.

Thanks. I have one source item like I3056 with decimal value like 1024. I need to split the value into separate items I3056_x according bits from I3056.

Ok, what you have now is, if e.g the value of I3056 is 3, then bits 0 and 1 are set. When the rule executes if (state.testBit(0) ) will return true, so it enters this branch. However if (I3056.state==1) is false, so no action will be taken. The other branches will not be evaluated at all, since they are else if, which means only the first one to be true will be entered.

If I understand what you want to do correctly, remove all the elses, and just keep the ifs. This will make the rule test all the branches, regardless of the result of the others. Also, remove the inner if-statements entirely, unless you only want the items to be set if the state is exactly those numbers (which means only one can be set at a time). So something like this:

    if (state.testBit(0)) {         //test Bit 0
        I3056_0.postUpdate(1)    //if 1, then set I3056_0 to 1
    }
    if (state.testBit(1)) {     //test Bit 1
        I3056_1.postUpdate(1)    //if 1, then set I3056_1 to 1
    }
    if (state.testBit(2)) {     //test Bit 2
        I3056_2.postUpdate(1)    //if 1, then set I3056_2 to 1
    }
    if (state.testBit(3)) {     //test Bit 3
        I3056_3.postUpdate(1)    //if 1, then set I3056_3 to 1
    }
    if (state.testBit(4)) {     //test Bit 4
        I3056_4.postUpdate(1)    //if 1, then set I3056_4 to 1
    }
    if (state.testBit(8)) {     //test Bit 8
        I3056_8.postUpdate(1)    //if 1, then set I3056_8 to 1
    }
    if (state.testBit(9)) {     //test Bit 9
        I3056_9.postUpdate(1)    //if 1, then set I3056_9 to 1
    }
    if (state.testBit(10)) {     //test Bit 10
        I3056_10.postUpdate(1)    //if 1, then set I3056_10 to 1
    }
1 Like

Hi there - Slightly different approach below. I use ECMAscript 2021 to do exactly the same thing. I have slightly adapted my script with your parameters as an example below:

iflags = items.getItem("I3056").state;
setState("I3056_0",0,iflags);
setState("I3056_1",1,iflags);
setState("I3056_2",2,iflags);
setState("I3056_3",3,iflags);
setState("I3056_4",4,iflags);
setState("I3056_5",5,iflags);
setState("I3056_6",6,iflags);
setState("I3056_7",7,iflags);
setState("I3056_8",8,iflags);
setState("I3056_9",9,iflags);
setState("I3056_10",10,iflags);

function setState(item,bitpos,iflags) {
// Function to update status of items, based on a bit status
  switch(getBit(iflags,bitpos)){
    case "ON" :
        items.getItem(item).sendCommandIfDifferent("ON");
        //console.log("Changing state to ON for:",items.getItem(item).name);
      break;
    case "OFF" :
        items.getItem(item).sendCommandIfDifferent("OFF");
        //console.log("Changing state to OFF for:",items.getItem(item).name);
      break;    
    default:
      console.log("Unknown state for:",items.getItem(item).name);
  } 
}

function getBit(number, bitPosition) {
// Function to read individual bits and return status
  return (number & (1 << bitPosition)) === 0 ? "OFF" : "ON";
}

This script is triggered when the item (in your case I3056) is changed. I recommend that you uncomment the logging sections when you setting up/testing. You will also need to change the “ON” and “OFF” to align to your item requirements (1/0?)

Maybe this is of use/help to you?
Cheers - Glen
EDIT - So maybe I read the OP too quickly - Just spotted that your environment is OH2.5 - The above is probably not a lot of use to you just yet!! I won’t delete my reply though, as it took me sometime to convert this rule from rules.dsl to ECMAscript and get it working in my environment. So hopefully this will be of use to you when you make the jump to OH3.x. !!

1 Like

Thanks, but please leave your solution for OH3 users.

Thanks for help.

My solution in python script, witch is source of data aquisition.
Python split

If using a Group, the rule can be somewhat optimized:

// given Group Item gI3056, all Items I3056_0 to I3056_10 are member of the group

rule "3056 decode bits"
when
    Item I3056 received update
then
    var biState = (I3056.state as DecimalType).toBigDecimal.toBigInteger
    gI3056.members.forEach[i|
        val myBit = Integer::parseInt(i.name.split("_").get(1))
        i.postUpdate(biState.testBit(myBit))
    ]
end

Yepp, that’s all

And if you want to use other states than 1 and 0. just use ternary operator:

i.postUpdate(if(biState.testBit(myBit)) OPEN else CLOSED)
2 Likes