I have made an MQTT binding which transfers two status byte from a central heating to openhab.
How can I select the individual bits from these status bytes to separate items in the user interface?
I prefer not to send all 16 status bits separately.
e.g.
status 0x80 is pump is running (0x00 = pump is off)
status 0x40 is on/off mode
status 0x20 is opentherm mode
Even though you prefer not to, I’ll tell you right now it will be FAR easier to send each separately than it will be to bit parse them out on the OH side. Parsing out bit-packed binary data in Java/Xtext is a huge pain and you will spend a lot more time figuring out and debugging the parsing back out of the bits than you will sending them separately.
Even if all you did was increase the binary so that each field falls on a byte or two byte boundary will save you tons and tons of work. And if you are worried about network throughput, don’t. Even if you put the 16 status bits as bytes you are still well within your average IP packet size, meaning your MQTT message will still fit in one packet, and even though MQTT is still super light weight you will face way more latency and network traffic with the overhead added by MQTT than the increase from a 2 byte message to a 16 byte message.
See this message at Stackoverflow for a decent explanation and example of what you are facing if you choose to forge ahead.
rule "Opmode Bath FirstFloor"
when
Item Heat_FF_Bath_Opmode received update //Opmode received from bus
then
var tmp = Heat_FF_Bath_Opmode.state as DecimalType //read value as Number
var state = tmp.toBigDecimal.toBigInteger //write as (big)integer
logDebug("heating.rules","Heat_FF_Bath_Opmode:"+state.toString)
if (state.testBit(0) ) { //test Bit 0
if (Heat_FF_Bath_Opset.state!=1)
Heat_FF_Bath_Opset.postUpdate(1) //if 1, then set Opmode to 1
}
else if (state.testBit(1)) { //test Bit 1
if (Heat_FF_Bath_Opset.state!=2)
Heat_FF_Bath_Opset.postUpdate(2) //if 1, then set Opmode to 2
}
else if (state.testBit(2)) { //test Bit 2
if (Heat_FF_Bath_Opset.state!=3)
Heat_FF_Bath_Opset.postUpdate(3) //if 1, then set Opmode to 3
}
else if (state.testBit(3)) { //test Bit 3
if (Heat_FF_Bath_Opset.state!=4)
Heat_FF_Bath_Opset.postUpdate(4) //if 1, then set Opmode to 4
}
else { //else
Heat_FF_Bath_Opset.postUpdate(2) //set Opmode to 2
}
end
I may be wrong, but I think, it would be something similar to this rule
I didn’t know about the testBit method (there really wasn’t a BigDecimal in Java the last time I had to deal with binary data in Java more than 10 years ago now, gee I’m getting old).
So as long as you can convert a two byte binary into a BigDecimal and toBigInteger without the sign bit being messed with this should work pretty well.
BigDecimal has been there for almost 20 years now (JDK 1.1, early 1997) so maybe it’s been longer than you thought. I only know that because I’m a lot older than you.
Well shoot. I though BigDecimal was introduced in 1.4. I could have saved a ton of work parsing TADL-J messages way back when if I knew about it. Learn something new every day.
Openhab designer show an error on toBigDecimal, toBigInteger and testBit.
Which libraries do I need to import?
Already tried import java.math.BigDecimal and import java.math.BigInteger but that does not work…
Hello
is there also a way to adress bits of a integer directly like it is described here: bit adressing codesys
I need to do a datatype conversion from single bits [switch] to 16 bit integer [number] because the modbus binding does not support datatypes <16 bit and I do not want to waste memory. See here: Datatype Modbus TCP Binding
How can I read indiviual bits with modbus?
With the explanation above I can do this with the testBit method. So I can convert a 16 bit value in bits.
But I also need the other way round to convert bits into 16 bit value with rules in OH. Is there a way to write direktly with the testBit method? How is this done?