[SOLVED] Read 3 bytes from Serial Port

I need to read from serial port 3 bytes and process them afterwards. It’s for a light switch with up to 6 buttons.

Format is as following:
first byte:
- current status
- button pressed/released
second byte:
number of wall switch
third byte:
00 - no button pressed
01-06 - number of button which is pressed

Testdata read with minicom from serial port RS232:

ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 00 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 bb 02 08 ff 02 08 ff 03 00 ff 04 00 bb 02 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 bb 02 04 ff 04 00 ff 05 00 ff 06 00 bb 02 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 0c ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 0c ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 0c ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 0c ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 0c ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 bb 02 04 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 bb 02 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 09 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00 ff 06 00 ff 1f 00 ff 20 08 ff 01 00 ff 02 08 ff 03 00 ff 04 00 ff 05 00

How can I read 3 bytes and give them some logic? I also want the function “long pressed” to dim the light. I’m completely new to this and don’t know where to start.

Thanks for any help or hints!

You would use the Serial binding. I think you will need to use both the REGEX and Base64.

The REGEX will need to match the three bytes you want.

Thanks for answering. I already played around with this binding but without success. I just don’t see the hex values to be able to do the REGEX.

If i use this items file (without BASE64):

String serialsT1 "Key1 [%s]" { serial="/dev/ttyAMA0@9600"}

This is the result:

18:02:31.438 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from �������  to ������
18:02:32.069 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ������ to �� ����
18:02:32.584 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from �� ���� to ���� �
18:02:33.207 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ���� � to ������
18:02:33.836 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ������ to � �����
18:02:34.457 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from � ����� to ��� ���
18:02:35.075 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ��� ��� to ����� �
18:02:35.701 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ����� � to ������
18:02:36.224 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from ������ to � ����
18:02:36.870 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from � ���� to ���� ��

If I use this items definition (with BASE64):

String serialsT1 "Key1 [%s]" { serial="/dev/ttyAMA0@9600,BASE64"}

This is the result:

18:05:59.410 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG to 77+9AQDvv70CAO+/vQMA77+9BADvv70FAO+/vQYA
18:06:00.038 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AQDvv70CAO+/vQMA77+9BADvv70FAO+/vQYA to 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA
18:06:00.762 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA to 77+9BQDvv70GAO+/vR8A77+9IAfvv70BAO+/vQIA77+9AwA=
18:06:03.259 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BQDvv70GAO+/vR8A77+9IAfvv70BAO+/vQIA77+9AwA= to 77+9BADvv70FAO+/vQYA77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA77+9BQDvv70GAO+/vR8A77+9IAbvv70BAO+/vQIA77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG77+9AQDvv70CAO+/vQMA
18:06:03.882 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BADvv70FAO+/vQYA77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA77+9BQDvv70GAO+/vR8A77+9IAbvv70BAO+/vQIA77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG77+9AQDvv70CAO+/vQMA to 77+9BADvv70FAO+/vQYA77+9HwDvv70gBu+/vQEA
18:06:04.714 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BADvv70FAO+/vQYA77+9HwDvv70gBu+/vQEA to 77+9AgDvv70DAO+/vQQA77+9BQDvv70GAO+/vR8A77+9IAbvv70BAA==
18:06:05.233 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AgDvv70DAO+/vQQA77+9BQDvv70GAO+/vR8A77+9IAbvv70BAA== to 77+9AgDvv70DAO+/vQQA77+9BQDvv70GAA==
18:06:05.958 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AgDvv70DAO+/vQQA77+9BQDvv70GAA== to 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA77+9BQA=
18:06:06.491 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA77+9BQA= to 77+9BgDvv70fAO+/vSAG77+9AQDvv70CAA==
18:06:07.113 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BgDvv70fAO+/vSAG77+9AQDvv70CAA== to 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG
18:06:07.731 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG to 77+9AQDvv70CAO+/vQMA77+9BADvv70FAO+/vQYA
18:06:08.354 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AQDvv70CAO+/vQMA77+9BADvv70FAO+/vQYA to 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA
18:06:08.987 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9HwDvv70gBu+/vQEA77+9AgDvv70DAO+/vQQA to 77+9BQDvv70GAO+/vR8A77+9IAbvv70BAO+/vQIA
18:06:09.610 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BQDvv70GAO+/vR8A77+9IAbvv70BAO+/vQIA to 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG

What I’m doing wrong so I don’t get the 3 byte HEX values which I could then pass via REGEX to an item and use in rules to update values?

Thanks for any comments!

Probably the easiest thing will be to just set a String Item to the full message (Base64) and use String manipulation inside a Rule to extract the values you need.

I think if you look at serialsT1.state.toString it will look more like the bytes you expect.

Thanks for the inputs.

Tried now with rule and BASE64 but still no correct data. I’m frustrated…

My current items file:

String serialsT1 "Key1 [%s]" { serial="/dev/ttyAMA0@9600,BASE64"}

My current rule:

import javax.xml.bind.DatatypeConverter

rule  "check values"
when
    Item serialsT1 changed 
then
    logInfo("rule check values", "serial value: "+DatatypeConverter::parseBase64Binary(serialsT1.state.toString()))
end

Log entries:

22:30:36.743 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BQDvv70GAO+/vR8A77+9IAfvv70BAe+/vQIA77+9AwA= to 77+9BADvv70FAO+/vQYA77+9HwDvv70gBg==
22:30:36.756 [INFO ] [rthome.model.script.rule check values] - serial value: [B@c70c91
22:30:37.375 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BADvv70FAO+/vQYA77+9HwDvv70gBg== to 77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA
22:30:37.390 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1ef0856
22:30:38.009 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA to 77+9HwDvv70gBu+/vQEB77+9AgDvv70DAO+/vQQA
22:30:38.016 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1b5511a
22:30:38.633 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9HwDvv70gBu+/vQEB77+9AgDvv70DAO+/vQQA to 77+9BQDvv70GAO+/vR8A77+9IAbvv70BAe+/vQIA
22:30:38.651 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1b00477
22:30:39.251 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BQDvv70GAO+/vR8A77+9IAbvv70BAe+/vQIA to 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG
22:30:39.268 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1efb1c4
22:30:39.865 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AwDvv70EAO+/vQUA77+9BgDvv70fAO+/vSAG to 77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA
22:30:39.871 [INFO ] [rthome.model.script.rule check values] - serial value: [B@15338da
22:30:40.385 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA to 77+9HwDvv70gBu+/vQEB77+9AgDvv70DAA==
22:30:40.396 [INFO ] [rthome.model.script.rule check values] - serial value: [B@11ccf35
22:30:41.010 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9HwDvv70gBu+/vQEB77+9AgDvv70DAA== to 77+9BADvv70FAO+/vQYA77+9HwDvv70gBu+/vQEB
22:30:41.032 [INFO ] [rthome.model.script.rule check values] - serial value: [B@180c522

As long as I can’t read the data correctly REGEX can’t be used.

At least let us see what you are feeding this DatatypeConverter

Added a line in rules to show value of serialsT1.state.toString:

enabled also DEBUG mode on serial binding, but didn’t gave any valueable data… :disappointed_relieved:

import javax.xml.bind.DatatypeConverter

rule  "check values"
when
    Item serialsT1 changed 
then
    logInfo("plain value", "serial plain value:"+serialsT1.state.toString)
    logInfo("rule check values", "serial value: "+DatatypeConverter::parseBase64Binary(serialsT1.state.toString()))
end
22:56:21.635 [DEBUG] [.binding.serial.internal.SerialDevice] - Received message '���� �����' on serial port /dev/ttyAMA0
22:56:21.660 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BgDvv70fAO+/vSAG77+9AQHvv70CAO+/vQMA77+9BAA= to 77+9BQDvv70GAO+/vR8A77+9IAfvv70BAe+/vQIA77+9AwDvv70EAO+/vQUA
22:56:21.730 [INFO ] [se.smarthome.model.script.plain value] - serial plain value:77+9BQDvv70GAO+/vR8A77+9IAfvv70BAe+/vQIA77+9AwDvv70EAO+/vQUA
22:56:21.742 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1ea91a1
22:56:22.776 [DEBUG] [.binding.serial.internal.SerialDevice] - Received message '��� �������� ' on serial port /dev/ttyAMA0
22:56:22.807 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BQDvv70GAO+/vR8A77+9IAfvv70BAe+/vQIA77+9AwDvv70EAO+/vQUA to 77+9BgDvv70fAO+/vSAG77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA77+9HwDvv70gBg==
22:56:22.831 [INFO ] [se.smarthome.model.script.plain value] - serial plain value:77+9BgDvv70fAO+/vSAG77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA77+9HwDvv70gBg==
22:56:22.847 [INFO ] [rthome.model.script.rule check values] - serial value: [B@a083e9
22:56:23.608 [DEBUG] [.binding.serial.internal.SerialDevice] - Received message '�������� ' on serial port /dev/ttyAMA0
22:56:23.645 [INFO ] [smarthome.event.ItemStateChangedEvent] - serialsT1 changed from 77+9BgDvv70fAO+/vSAG77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA77+9HwDvv70gBg== to 77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA77+9HwDvv70gBg==
22:56:23.656 [INFO ] [se.smarthome.model.script.plain value] - serial plain value:77+9AQHvv70CAO+/vQMA77+9BADvv70FAO+/vQYA77+9HwDvv70gBg==
22:56:23.675 [INFO ] [rthome.model.script.rule check values] - serial value: [B@1fb1adb

The values you are getting from the binding are Base64. When you decode the Base64 you end up back to raw bytes.

To use the REGEX you need to do so on the Base64 encoded value.

Otherwise you need to do binary manipulation with is not easy to do in Rules DSL.

You will not be able to look for “ff 05 00”.

You will have to do a little looking to see how Base64 encoding works so you can figure out which Base64 characters represent the hex values.

Or you will have to figure out how to manage and work with pure binary data. Look at how to do this in Java as there is no native support in Xtend for this. But the Java classes are available in Xtend so what ever examples you find in Java will apply to Rules.

Writing for @Fridolin22 (working on this together with him).

We got it to work to print the serial value. It seems kind of okay, but is different from what we actually should get. We get lines like:

EF BF BD 01 00 
EF BF BD 02 00 

So somehow it seems like we get EF BF BD instead of FF. But the question is why? If we check the serial directly (with minicom) then we get FF 01 00 correctly. So it has to happen somewhere on the way.
Could it be that the conversion from byte[] to String in the SerialBinding is causing the problem? Would there be any way around that?

EF BF BD is the UTF-8 “replacement” character, shows up as � in the log strings.
Somewhere you’ve got UTF-8 encoding, probably by a default setting. Think you have to get into EXTRA_JAVA_OPTS to change this. Or if you’re scripting, who cares so long as its consistent?

Thanks for the answer. Any suggestion what would be the correct charset?

No idea. What is “correct”?
This might help

Thanks all for the help/hints.

Finally we where able to solve it as following:

  • System is still running with Locale UTF-8. No need to change it nor to change any EXTRA_JAVA_OPTS definitions. Just add “CHARSET(ISO-8859-1)” to items definition.

items file:

String serialsT1 "key1 [%s]" { serial="/dev/ttyAMA0@9600,CHARSET(ISO-8859-1),BASE64" }

rules file:

import javax.xml.bind.DatatypeConverter

rule  "check values"
when
    Item serialsT1 changed 
then
    val char[] hexArray = "0123456789ABCDEF".toCharArray()

    val byte[] bytes = DatatypeConverter::parseBase64Binary(serialsT1.state.toString())

    val char[] hexChars = newCharArrayOfSize(bytes.length() * 2)
    for ( var j = 0; j < bytes.length(); j++ ) {
        var int v = bytes.get(j).bitwiseAnd(0xFF)
        hexChars.set(j * 2,  hexArray.get(v >>> 4))
        hexChars.set(j * 2 + 1,  hexArray.get(v.bitwiseAnd(0x0F)))
    }
    val outString = new String(hexChars)
    logInfo("rule check values", "serial value: " + outString)

    for (String command : outString.split("(?=FF)|(?=BB)")) {
        logInfo("rule check values", "command: " + command)
    }
end
1 Like