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.
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
}
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. !!
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)