I would like to have a rule where only the lower byte is used. Normaly you just add xFF to the 2byte Number and you will have the lower byte.
How do I have to enter this in an rule?
I tried the following ways
rule "MB_I_Reg_10" when Item MB_I_Reg_10 changed then SpitzbodenRT.sendCommand (((MB_I_Reg_10.state & 255) as DecimalType) / 10) end
or
rule "MB_I_Reg_10" when Item MB_I_Reg_10 changed then SpitzbodenRT.sendCommand (((MB_I_Reg_10.state as DecimalType) & 255) / 10) end
both are not working. I get no error. The byte number goes just thru. The “& 255” works here like an inline comment.
given MB_I_Reg_10 as Number, you have to cast the state to byte (this would cut away the high byte)
Maybe this will do it (did not test it, as I’m at work)
rule "MB_I_Reg_10"
when
Item MB_I_Reg_10 changed
then
SpitzbodenRT.sendCommand(MB_I_Reg_10.state as Byte)
end
If this does not work as expected, type conversion should work:
SpitzbodenRT.sendCommand((MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger && 255)
I’m using .testBit(n) to get various boolean informations from a BigInt:
((MB_I_Reg_10.state as DecimalType).byteValue / 10)
This one seems to work… The only outstanding problem is, that the byte value is interpreted as signed I want to intepret it as unsigned.
Question: Where did you get the “.toBigDecimal” or “.toBigInteger” get from?
This was the hint for me to try “byteValue”. Later I noticed that I forgot the “to”
Can you give me a link to the page where this kind of functions are described all together?
Hey @peaeater,
great to see that you found help in this thread. While @Udo_Hartmann is hopefully able to help you the rest of the way, I can answer your second question.
rule "MB_I_Reg_10" when Item MB_I_Reg_10 changed then SpitzbodenRT.sendCommand
((MB_I_Reg_10.state as DecimalType).toBigInteger && 255) end
runs into following messeage:
==> /var/log/openhab2/openhab.log <==
2016-10-22 19:33:43.450 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XCastedExpressionImpl>.toBigInteger' cannot be resolved to an item or type.
I changed to the rule
rule "MB_I_Reg_10" when Item MB_I_Reg_10 changed then SpitzbodenRT.sendCommand
((MB_I_Reg_10.state as DecimalType)% 255) end
runs into the error
==> /var/log/openhab2/openhab.log <==
2016-10-22 19:40:30.200 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XCastedExpressionImpl> % <XNumberLiteralImpl>' cannot be resolved to an item or type.
I just noticed, that I forgott the toBigDecimal part in the rule. With that in runs into:
==> /var/log/openhab2/openhab.log <==
2016-10-22 20:51:35.718 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XMemberFeatureCallImplCustom> && <XNumberLiteralImpl>' cannot be resolved to an item or type.
If I change the “&&” to just “&” it is running without error, but the AND is not calculated.
Hello Udo,
yes I noticed the 256 allready yesterday.
Here comes the error messeage:
2016-10-23 11:02:07.149 [ItemStateChangedEvent ] - MB_I_Reg_10 changed from 16580 to 16581
==> /var/log/openhab2/openhab.log <==
2016-10-23 11:02:07.165 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XCastedExpressionImpl> % <XNumberLiteralImpl>' cannot be resolved to an item or type.
This is a realy good question. I defined the item SpitzbodenRT as number like the MB_I_Reg_10
Number SpitzbodenRT "Raumtemperatur Spitzboden [%.1f °C]" <temperature>
Number MB_I_Reg_10 "Modbus Register 10 raw value [%.1f]" (gModbusRegister)
I just copy a Modbus Integer via the rest interface to MB_I_Reg_10
For testing purpose you can use the openhab REST API put /items/{itemname}/state command and send just the value ( for example 16587) to the MB_I_Reg_10 (by pressing the “try it” Button)
I have no problem with the modbus integer at all. Only with this one. Due to the modbus limitations, where you do not have so much memory space this integer has a space keeping format. The “High byte” seems to be the target value and the low byte is the actual value. As we here only measure the room temperature the measuring range goes from 0°C to 255°C (? this is not realy true, because 255 = 25.5°C there for it is possible that the temperture is not only the lower byte more probable is that the lower 10 to 12 bit equals the temperature.the upper 6 to 4 bit is the target value offset [here you specify normaly from -3° to +3°]), which is pretty engough. So we can transmit in only one integer 2 values. I have no documentation about that. I only can do here reverse engineering.
What I do not understand is, why is it not possible to just “AND” a number, this is a pretty fundamental function for programming languages…
Another aproach could be right and left shifting of the bits of the number. Is this somehow possible to do wihtin a rule?
rule "MB_I_Reg_10"
when
Item MB_I_Reg_10 changed
then
var Number MyVal = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger
SpitzbodenRT.sendCommand(MyVal-(MyVal/256).intValue*256) //do % manually
end
It seem’s that we have to go over the middle step creating the variable MyVal.
I tried the “%” with MyVal as well as the “&” both run still into error.
I change your rule to
rule "MB_I_Reg_10"
when
Item MB_I_Reg_10 changed
then
var Number MyVal = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger
SpitzbodenRT.sendCommand((MyVal-(MyVal/4096).intValue*4096)/10) //do % manually
end
This will cover the lower 12 Bits. I will start with that. Thank you very much for your help.
It is a complicated but working way to solve my problem.
Interessting for the future may be how to get the upper 4 bits.
But at the moment I’am lucky that I do not need it.
Rules do not normally get executed on startup. You need to specify this explicitly by rule "..." when System started then. A rule is executed only on the event you specified: Item MB_I_Reg_10 changed.
My guess: These rules event triggers on system start. Just a coincidence.
This would be ok, but in my case the 16586 becomes written just after startup, The same to all other values. All
the other values are divided by 10 this is correct. By 16586 only the division by 10 worked (not the manually calculated modulo).
rule "MB_I_Reg_10"
when
Item MB_I_Reg_10 changed
then
var Number MyVal = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger
SpitzbodenRT.sendCommand((MyVal-(MyVal/4096).intValue*4096)/10) //do % manually
end
Now I have the unfortunate situation, that in my rdd4j Database the first entry is 1658.6 and all the rest is around 20. The scale of the habmin chart is now to big (what is logical).
How can I delete the first value in rdd4j Database?
And how can I avoid that situation after the next reboot?
import org.openhab.core.library.types.*
import org.openhab.model.script.actions.*
import org.openhab.core.types.Command
var Number i = 2048
rule "MB_I_Reg_10"
when
Time cron "0 45 * * * ?" // get the rule triggered
then
while(i < 2305) {
logInfo("test","i = {} i % 256 = {} i & 255 = {}",i, i.intValue % 256 , i.intValue.bitwiseAnd(255))
i = i + 1
}
end
So there is mod() and and() available… (EDIT: but the names are different…)
In question of the mysterious 16586, I think, this is not written by the rule, does this happen at every start?
Maybe my problem was anything else. This Special Temperatur was created without having any groups. After adding the groups the temperature was not shown on the sitemap and I did not become persistence data. (To test this I was writing the value via RestAPI, maybe I wrote the value to the wrong item? But why the division by ten) Because of the missing group entry in the sitemap I decided to reboot.
Should be engough for testing on my rule. Am I right, or do I have to do all the other import as well.
I just would change
SpitzbodenRT.sendCommand((MyVal-(MyVal/4096).intValue*4096)/10) //do % manually
to
SpitzbodenRT.sendCommand((MyVal.and(4095))/10) // Getting only the lower 12 bit
What is the diference between .and() and .bitwiseAnd(). I think a bitwiseAnd you only can use, if your value has the same bitlength as the “and” value.
In my case I have got a bigdecimal (16 or more bits?) and I just want to “and” 12bits (4095). So the bitwiseAnd should not work.
==> /var/log/openhab2/openhab.log <==
2016-10-25 14:52:08.946 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XFeatureCallImplCustom>.and(<XNumberLiteralImpl>)' cannot be resolved to an item or type.
my rule looks like
import org.openhab.core.library.types.*
import org.openhab.model.script.actions.*
import org.openhab.core.types.Command
rule "MB_I_Reg_10"
when
Item MB_I_Reg_10 changed
then
var Number MyVal = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger
// SpitzbodenRT.sendCommand((MyVal-(MyVal/4096).intValue*4096)/10) //do % manually
SpitzbodenRT.sendCommand((MyVal.and(4095))/10) // Getting only the lower 12 bit
end
So it does not work for me. There has to be a special trick to become such functions to work.
Do I have to reboot again?
No, the same error occurs after reboot as well.
I ried no also the bitwiseAnd()
2016-10-25 15:00:24.198 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'MB_I_Reg_10': An error occured during the script execution: The name '<XFeatureCallImplCustom>.bitwiseAnd(<XNumberLiteralImpl>)' cannot be resolved to an item or type.
I get the same error messeage.
Do I have to import anything more? Is the import to do in every rules file or just in one? (I’am lucky I only have one, but maybe you have more. In this rules file you may have an import I do not have at the moment)