Rule for using only the lower byte of an 2 Byte value?

I tried to find there something to be able to interpret a byte value as unsigned.

It seems that via the Formatter Option and Flag “o” it may be possible.

But I do not understand how I have to write that. Every way I tried runs into errors.

Does somebody know which Language is used within the rules definitions. Is it javascript our java or something special?

Normaly it should not be a big issue to interpret a byte or eaven integer as signed or unsigned.

I had now a little bit of time to study, what is happening here in my rule:

rule "MB_I_Reg_10" when Item MB_I_Reg_10 changed then SpitzbodenRT.sendCommand       
      (((MB_I_Reg_10.state as DecimalType).byteValue)) 
end

When the “changed” is fired the content of MB_I_Reg_10.state = 16587
after applying the rule the contend of SpitzbodenRT = -53

If write that in binary representation you get:

16587 = ‭0100 0000 1100 1011‬
  -53 = ‭1111 1111 1100 1011‬

So something in the conversion to DecimalTyp and then to byteValue goes completly wrong.
What changed the high byte to set all bits?

I just would like to have following conversion

     16587 <=> ‭0100 0000 1100 1011‬
AND    255 <=> 0000 0000 1111 1111
=      203 <=> 0000 0000 1100 1011

This is pretty easy.

But how do I formulate this in a openHAB 2 rule?

Did you try

myInt = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger && 255

already?
Maybe another aproach: do a MOD 256:

var Int myInt = (MB_I_Reg_10.state as DecimalType) % 256

I did not test this yet.

Hello Udo,

your example

which I changed to the following rule

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.:frowning:

Please try

rule "MB_I_Reg_10"
when
    Item MB_I_Reg_10 changed
then
    SpitzbodenRT.sendCommand(((MB_I_Reg_10.state as DecimalType) % 256))
end

(yes, it’s 256)
What’s the item type of SpitzbodenRT?

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?

I think we did not find the correct function yet :slight_smile: What I don’t understand is, the modulo operator is defined in xtend, this should definitely work…

Ok, tested (with OH1.8):

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

I confirm this function works with OH2 too.

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. :slight_smile:

Because of the not automatic appending of my item in the groups I had to reboot my device.

After rebooting the rule is not excuted an the raw value is passed through.
With the first update the rule becomes executed.

All the other rules excute direct at startup. Why is that?

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?

I did some more testing :slight_smile:

This works for me:

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?

I just made a reboot. It did not occur again.

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.

I will test it.

I just made the test

==> /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)

It worked for Udo using an intValue. Maybe time to use that number type instead of BigInteger. (an int will easily hold 16 bits)

There is no such function like and() for integer, the function is called bitwiseAnd() - using openHAB Designer makes these things a lot easier.

I tested with that function as well. Igot the same error messeage

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.

only the “and” is changed here for “bitwiseAnd”.

I tried to use the openhab Designer as well. But I see no advantage at the moment in comparison to the notespad++

The only positive thing is the syntax highlighting and it should show errors. In my case the error (small “e” at the lefthand side of the line) is shown very often. But the line contains no error. I will try to use the openhab Designer on writing the rule, maybe he will show me the options I have (until now I never noticed that).

You think I should kill that line

var Number MyVal = (MB_I_Reg_10.state as DecimalType).toBigDecimal.toBigInteger

and change the rule to

rule "MB_I_Reg_10"
when Item MB_I_Reg_10 changed then
  SpitzbodenRT.sendCommand((MB_I_Reg_10.state.bitwiseAnd(4095))/10) // where MB_I_Reg_10 is defined as number item
end

I will try this today in the afternoon.
Do I have to do the imports as well?