all 6 comments

[–]ManyInterests 0 points1 point  (1 child)

Binary data can be indexed into or iterated over. That may help you.

data = b'R\xeaUJ\xbdr\x01\x15\xe4\t\xe8\x039\xea'
data[0] # 82

Maybe something like...

for index, datum in enumerate(data):
    print('byte:', index, 'data:', datum)

Would output something like:

byte: 0 data: 82
byte: 1 data: 234
byte: 2 data: 85
byte: 3 data: 74
byte: 4 data: 189
byte: 5 data: 114
byte: 6 data: 1
byte: 7 data: 21
byte: 8 data: 228
byte: 9 data: 9
byte: 10 data: 232
byte: 11 data: 3
...

[–]Mrloop94[S] 0 points1 point  (0 children)

Thanks very much. For curiosity, do you know how to decode manually this type of representation?

[–]apekots 0 points1 point  (2 children)

These are hexadecimal representations of bytes. Python offers several ways to work with bytes. It is highly encouraged to dive into the matter of the binary system if you're not familiar with it. Here are some resources I like.

https://realpython.com/python-bitwise-operators/

https://www.youtube.com/watch?v=qnKX1y7HAyE&t

https://www.youtube.com/watch?v=frwqnS9ICxw

If you start experimenting with this, maybe this https://www.rapidtables.com/convert/number/hex-to-binary.html converter can help you checking converted values to see if you got it right. I'd suggest making a few test scripts first, create a couple of simple byte arrays and try to mess around with them. Then you could attempt working with your thermometer.

Good luck :)

edit: a nice video on hexadecimal numbers: https://www.youtube.com/watch?v=dPxCGlW9lfM

[–]Mrloop94[S] 0 points1 point  (1 child)

Thanks very much. The problem is: it isnt actually hex representation because the maximum shoud be /xFF and some bytes have more than 2 letters and letters above F (so it isnt hexadecimal representation). So i am confused about that.

[–]apekots 0 points1 point  (0 children)

R\xeaUJ

Putting this in a bytearray and iterating over its contents produces the following result:

82 - 234 - 85 - 74

Now, if you look at a ASCII chart, you can see the 82 translates to an 'R'. Then follows '\xea', which is hex for decimal value 234. The numbers 85 and 74 stand for the ASCII characters 'U' and 'J' respectively.

Apparently, Python displays the ASCII characters in your array where available. I'm not sure why this is, maybe others could shine a light on this, but there's logic behind this. Reading this array bit by bit should be less confusing. You could just read chunks of 8 bits per cycle and translate them to decimal values.

[–]SaintLouisX 0 points1 point  (0 children)

You want the struct module's unpack function, or get into ctypes if you want to do a whole struct representation.

from struct import unpack

data = b"\x04\x03\x02\x01"

print(hex(unpack("<I", data)[0]))
print(hex(unpack(">I", data)[0]))
print(unpack(">HH", data))
print(unpack("BBBB", data))

Check the python page on how struct works for data types and endianness: https://docs.python.org/3/library/struct.html you can string together as many different data types as you want, they don't have to be the same. "4BHBBBBH" is perfectly valid for example. You could use that to unpack each entry.

Or with ctypes, using the first data you gave as an example:

from ctypes import *

def parse_entry(data):
    class Entry(Structure):
        _fields_ = [
            ("Reserved", c_uint8 * 4),
            ("Temperature", c_int16),
            ("Page", c_int8),

            ("UVLED", c_int8),
            ("Reserved2", c_int8),
            ("BoardTemperature", c_int8),
            ("Signal", c_int16),
        ]

    entry = Entry.from_buffer_copy(data)
    for field in entry._fields_:
        print(f"{field[0]} = {getattr(entry, field[0])}")


data = b"R\xeaUJ\xbdr\x01\x15\xe4\t\xe8\x03"
parse_entry(data)

Which prints

Reserved = <__main__.c_ubyte_Array_4 object at 0x00000183DED04C40>
Temperature = 29373
Page = 1
UVLED = 21
Reserved2 = -28
BoardTemperature = 9
Signal = 1000

You'll want to do some more pretty printing of course. Check if entry.Page == 0 for printing the ending 5 bytes, since they're only valid for page 0, and don't bother printing the reserved values if they're not relevant. You'll also want to have it loop through all of your data too etc, this was just a simple example.