Convert string to octal string

I am trying to set a RFID code in a zigbee driver. According to the Zigbee documentation it should be sent as octstr.

I have a code snippet that I took from a generic zigbee lock driver to convert from string to octstr. This works great with a 4-digit code but not with a RFID..

def codeHex = "" + zigbee.convertToHexString(code.length(), 4)
	for(int i = 0; i < code.length(); i++) {
		codeHex += "" + zigbee.convertToHexString((int) code.charAt(i), 2)
	}

Example RFID: B51D1010.
Code converts to: 00084235314431303130
When using a online converter I get: 102 065 061 104 061 060 061 060

When trying to send the output from the snippet the lock does not responde at all. When sending the string from the online converter I get a success respond. But the RFID-tag is not accepted by the lock, so I think that that conversion isn't correct?

From the zigbee documentation:

My command: 0x921D 0x0B 0x0101 0x16 {01 01 00 00084235314431303130},

Does anyone know how to point me in the right direction?

RECOMMENDED READING

https://docs.groovy-lang.org/docs/ant/api/org/apache/tools/tar/TarUtils.html#parseOctal(byte[],%20int,%20int)

1 Like

I have read the pages you linked but I still can't figure out how to make it work..

Sadly, you are not alone, but those links represent the closest I could conjure up in the way of working coding examples. Let me please clarify your objective while we wait for an experienced Groovy programmer (@thebearmay ) to chime in...

You want to take an existing hexadecimal string (e.g. "B51D1010") and convert it directly into octal for the express purpose of passing the resultant (here, "26507210020") as part of an HTTP GET request.

In the meantime, if you're willing to utilize WebCoRE (now a built-in app on Hubitat) rather than a coding solution, this one seems to work according to your specs:

Of course, it would need to be modified to act on @@ Hub Variables (instead of the local ones employed here for testing purposes in WC), but otherwise should produce the results you want.

1 Like

Should be something like:


    hexStr = "B51D1010"
    hexBytes = hexStr.getBytes("UTF-8")
    octalValue =""
    hexBytes.each {
        octalValue += "${Integer.toString(it, 8)} "
    }

   log.debug octalValue
2 Likes

That would get you close, but I suspect that the hex string is actually the raw hex bytes as characters. You don't want the byte array of those as ASCII characters but rather for them to be turned back into integers.

I would do:

hexBytes = hubitat.helper.HexUtils.hexStringToByteArray(hexStr)

2 Likes

Thank you for your answers.

I have done some testing.

Sending 26507210020 - no respond from the device

This returns "102 65 61 104 61 60 61 60 ". Sending this to the device results in no response from the device.

This returns "-113 35 20 20". When sending this I get a response from the device.
"catchall: 0104 0101 0B 01 0040 00 921D 01 00 0000 16 01 01".
The last 01 means general failure.

1 Like

Ouch, that one stings. :wink:

Have you sent anything successfully to the device yet? I didn't understand this comment from earlier:

When sending the string from the online converter I get a success respond. But the RFID-tag is not accepted by the lock, so I think that that conversion isn't correct?

If you can show an input value in hex and an octal format that works (that you generate using an online tool or whatever), then that provides a test case to see whether the code is correct.

I can successfully set pin-codes with the code in my first post. Success every time.

I switched to another tag. "D51E1070"
Using Convert a String to Octal – Online String Tools I get 104 65 61 105 61 60 67 60.
Sending this returns success. (catchall: 0104 0101 0B 01 0040 00 921D 01 00 0000 16 01 00) But when I put the tag on the reader the tag is not recognized.

But... If i try with "AB0392D2" = 101 102 60 63 71 62 104 62 then I get no response from the lock.
Just to make sure that the lock isn't "offline" I tested to send the first one again and then I instantly got a success response.

I am almost starting to think that maybe my lock does not support setting RFIDs over zigbee. But if that is the case I still don't understand why I sometimes get success, other times failure and most of the times no answer at all.

Edit. The output from Online String Tools matches the output of thebearmay's code.

1 Like

I would guess that the format isn't correct for the conversion from the hex ID, but some of the values you are sending are still considered valid in general by the lock. So, they're getting added to the lock, but it means something different than the actual ID that the lock reads from the tag, if that makes sense.

Total shot in the dark, but maybe try removing the spaces? Is there any working example, where you get both a success response AND the tag is properly recognized?

Removing the spaces resulted in not getting any response.

Nope.

What is the model of the device?

Nimly Touch Pro. There is almost no documentation on this device. I found a PDF for the zigbee module on github, but it doesn't mention the set rfid command. But it does mention the response that should be returned for that command. All commands and responses follow the zigbee standard. https://csa-iot.org/wp-content/uploads/2022/01/07-5123-08-Zigbee-Cluster-Library-1.pdf

This seems important. At the very least, this first octect representing octet count is missing from the raw conversion.

But also "application-defined format" leaves it open to interpretation. I'd look for an open-source implementation that is known to work and see if you can mimic the same data format. But start by prepending the octet count in your testing.

I wonder if @jvm33 can offer any pointers on this data format.

1 Like

Does the lock already have RFID tags programmed in it?

If so, perhaps try reading one (Get RFID Code Command) and see what is returned.

That would give you a starting point for a known working RFID (AABBCCDD) value as an Octet String.

1 Like

I've tested adding the count in the same way that it is done for when setting code and in other ways/formats but still no success.

This lock does not support Get RFID code or Get Pin Code. :frowning:

I have sent a mail to Nimly to see if they want to help with how to format it. I doubt it but it is worth a try.
I have searched around for other open-source codes but can't find anything.

If it requires the leading zeroes you could try

    hexStr = "B51D1010"
    byte[] hexBytes =  hexStr.getBytes()
    octalValue =""
    hexBytes.each {
        oVal=Integer.toString(it, 8)
        if (oVal.size() == 1)
            oVal="00$oVal"
        else if (oVal.size() ==2)
            oVal="0$oVal"
        octalValue += "$oVal "
    }
log.debug octalValue

I solved it!! :slight_smile:

D51E1070 is actually four different hex numbers. D5 1E 10 70. So the command is 0004D51E1070. (0004 for the octet count).

I almost feel a little bit dumb now that I found out that it was actually that simple.

Thank you guys for all your help and support. Without you I would have given up a long time ago.

4 Likes

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.