Send command to serial port and receive a answer

What about https://www.baeldung.com/string/get-bytes
There is an older thread with may need a bit of adaption Rule to convert ASCII to HEX

Your input string is binary, not characters…
Break the string into bytes - almost certainly by using getBytes. Have another look at examples already given.

When you say this sort of thing, remember we cannot see what you are doing. What’s a ‘split error’, for example? Show us the logs when relevant.

As first step I tried modify part of code from this :

https://community.openhab.org/t/help-with-binary-data-serial-binding-3-1/126859

So my code is :

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID)
val char[] hexArray = "0123456789ABCDEF".toCharArray()
val byte[] bytes = RawType.valueOf(POSLAT.state.toString()).getBytes()
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)
logger.info(outString)

but I have a error:

The code you took the example from is written in DSL syntax.
Looks like you try to run it with the javascript interpreter. Javascript expects a semicolon at end of rows.

That’s DSL rule, written in the original oH1 rules language.
You’ve decided to use javascript, so you can’t just copy/paste, the syntax is different. You don’t declare variables in javascript with val, for example.

oh, my error. I have a mixture of java and DSL
I think if I will run it as DSL then first line

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID)

isn’t ok.
Is also under DSL any logger for debug ?

Yes, see examples for different log levels at Logging | openHAB

so i took my code

val char[] hexArray = "0123456789ABCDEF".toCharArray()
val byte[] bytes = RawType.valueOf(POSLAT.state.toString()).getBytes()
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)
stav.postUpdate(outString)

and switched rule to DSL and started again
Received new error :

In meantime I’m playing/testing/learning java.
I copied simple example text and placed as jave rule :

      try {
 
            // taking input string
            String s = "GeeksForGeeks";
 
            // name of supported charset
            // UTF-16 is an encoding constant
            String charsetName = "UTF-16";
 
            // UTF-16 charset encoding and storing the
            // resultant bytearray.
            byte[] byteArray = s.getBytes("UTF-16");
 
            // printing the byte array to convert it into
            // string
            System.out.println(Arrays.toString(byteArray));
 
            // printing the length of input string and
            // resultant byte array
            System.out.println("Length of String"
                               + " " + s.length() + " "
                               + "Length of byte Array"
                               + " " + byteArray.length);
        }
        catch (UnsupportedEncodingException e) {
            System.out.println("Unsupported charset :" + e);
        }

also there I have a error (same as before regarding ; ):

I know that code isn’t perfect, but first of all compilation must work

The error message about invalid URI syntax is coming from RawType.valueOf.

If you are trying to decode binary data then you need to be using the binary channel from the serial bridge.

1 Like

Thank you. I reworked, so now I have serial bridge with string channel and binary channel :

in the rule I’m sending a command to the string channel :

var testoutput = '\u0010\u0001\u00FF\u00FF\u0000\u0060\u0008\u0002\u00D3\u00D1\u00FF'
SerialBridge_StringData.sendCommand(testoutput)

and response I’m reading from the binary channel and decoding to HEX:

val char[] hexArray = "0123456789ABCDEF".toCharArray()
val byte[] bytes = RawType.valueOf(SerialBridge_BinaryData.state.toString()).getBytes()
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)
stav.postUpdate(outString)

and yes, now I have a HEX answer from the external unit:

Now I will try decode important informations for me and do next actions.

2 Likes

I want ask following
during transformation to hex I’m creating a array :

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

is it possible read somehow exact byte from this array ?

I tried this :
val outString = new String(hexChars.getBytes(1))
val outString = new String(hexChars.get(1))
but it’s not a right one

That’s what this part does

v is an “exact byte”.
It’s not a string like “0”, “F”, it’s an integer with a value that might be expressed as 16 decimal or 0F hex.

What do you want to do with it, might be the right question? Compare, multiply, convert to a string like “0F” etc.?

I received this :
FFFF1017FFFF1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F0000BFAD
FFFF1017FFFF - it’s start information
but next 16x 1F is 16 temperatures for 16 rooms. 1F = 31. To this value is added a constant (for me 5) and then this 16 values I want link to items (room temperature)

Okay, so work out what you want to do. Something like “get the twentieth byte, get the numeric value, divide by ten, add a unit, and pass to a Number:Temperature Item”
You can’t code until you have an objective.

Sorry maybe my explanation error.
My idea was take 2 bytes - 1F and then convert to decimal - 31
Add to this value +5 = 36 and this value link with item (temperature)

Unit answer is always the same, co I know that first value is byte 8 and 9 (when counted from 0)
My understanding was, that hexchars is a array of Hex, so no problem read exact bytes.

var int v8 = bytes.get(7)
// this is an 'exact byte'
// it is the eigth byte, as the first byte is 0
var int v9 = bytes.get(8)
// this is the ninth byte

// now lets see what we got
logInfo("test", "bytes 8 and 9 are " + v8 + " " + v9)

I’m not sure what “take two bytes” means - a sixteen-bit integer maybe?

var int vBoth = (256 * v8) + v9
// now lets see what we got
logInfo("test", "word 8-9 is " + vBoth)

// now for some reason you want to subtract 1F, that is 31 decimal
var int vAdjust = vBoth - 31
// next you want to add 5
// its best to work in Number types when possible
var Number vFinal = vAdjust + 5
// now you want to update some Item
someItem.postUpdate( vFinal.toString )
// update can be fussy about types, post a string if you can
//or 
someTemperatureItem.postUpdate( vFinal.toString + " °C" )

My amateur idea was :
result of this code

val char[] hexArray = "0123456789ABCDEF".toCharArray()
val byte[] bytes = RawType.valueOf(SerialBridge_BinaryData.state.toString()).getBytes()
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)

for me is string = “FFFF1017FFFF1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F0000BFAD”
so when I cut off (crop) this string :
image
I will have a string 1F and this string I will transfer to dec = 31.
But maybe it was my bad amateur idea

Well, you can do that - just get the Nth characters of outString.

But you are converting your binary bytes to ascii string characters, extracting a few, and then converting ascii string characters to binary (numbers) again. It’s a bit pointless.