Home > Back-end >  How do I read the data sent from this simulator?
How do I read the data sent from this simulator?

Time:07-20

I'm required to make a 'height sensing subsystem' to read the data sent from a moonlander by making a UDP protocol. The client is already set up for me, and is a 64bit executable on linux run by using ./simulator. So I need to make the UDP server in linux to connect with the client.

The client sends readings from many subsystems in the moonlander, but I only need to read one of them, which is the laser altimeter reading that corresponds to the a type specified by 0xaa01, there are other types such as 0xaa##, and 0xff##, but those correspond to different subsystems of the moonlander I assume. The data sent from the ./simulator file is sent through the type, which I then need to decode to find if its the laser altimeter, and then I need to decode the values to convert into distance to find when the moonlander has touched down. I need to read the time first, which has a size of 4 bytes and is an unsigned 32 bit integer, and the laser altimeter reading is 3 unsigned 16-bit integers that correspond to 3 different measurements (as there are 3 different sensors on the altimeter, max height of 1000m, convert by dividing by 65.535 which is UINT16_MAX, and multiplying by 100 to convert to cm). I need to then take those readings, convert them into height, and then acknowledge that we've landed once we've hit 40cm away from the ground.

How do I read the data from the ./simulator file? Below is my code in python, and the output in a linux terminal. I can see that this is in hexadecimal format, but how do I convert this to read into actual numbers?

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 12778

sock = socket.socket(socket.AF_INET, # Internet
                      socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(8192) # buffer size is 1024 bytes
    print("received message: %s" % data)


output:

received message: b'\xff\x06\x13\x81(6iF~\xecB<\x951v\xe5\xebr\xd1\xf0r\x91'
received message: b'\xff\x05\x13\x81(6\x06\xef\x06\xfa^\x00\x08O'
received message: b'\xaa\x08\x13\x81(6\xef.\x10@\xba[\x95_-\x0c\xa8\xacD{\xad:\xca\x8c\x14\xc5\xc5\x8c\x84\xdd1Ui\xa5\xf5\xf1\xd4\x98\xc7\xe1\x02R\x11;\xf6\xff{\xd8\x0b\x9b\xae\xe9\x8f\x12)\x08\xe7\xcf|\x13>\xa4\xe4\xe9X\r\xf6\x87.\xfcmc\x06UP#\x89Y\x7f"f=e\x81\x88\xb2&\xcfl\xd7\xbb/ p\x1a\x1f\x1e\xaa\x88\x82\xb1\x82<\xec`\xed\x1c\x86\x1bM)\xef\n\xba|\xa7\xc8\xa6\x86\xa0\\\x13\xab\xda\xeb]\x1435]\x8a\'\x1a\xba'
received message: b'\xff\x01\x13\x81(6Ydo\x03\xadJ\xdc7\xb8\x05\xa0-'
received message: b'\xaa\x10\x13\x81(7d\x805wF\x90\xf2\x9c bq'
received message: b'\xff\x02\x13\x81(6\xa2\xb0\xe5\x94'
received message: b'\xaa\x12\x13\x81(7=\x9f\xea\xe9\xc3\x94\xf0\x82.\x9epWNn\xa0\x8c\xd3\xa2\x99\x08#\xc8\xeb\xb0_#r\x0b\xb8\xdb\xeeZ'
received message: b'\xaa\x01\x13\x81(6\x00\r\x00\x0f\x00\x0e'

All of the output except the last one correspond to different subsystems in the moonlander, so we don't need those. All I need is the last one. How do I read data? Some things about the data:

  1. It is sent through big endian form through: type (2 bytes) --> time (4 bytes) --> payload data (0-4096 bytes)
  2. Am I reading this correctly? ''\xaa\x01\x13\x81(6\x00\r\x00\x0f\x00\x0e'', I know that (xaa\x01) are the first 2 bytes that correspond to the type, the next 4 bytes, (x13\x81(6) (not sure why that isnt 4 different data points), and then the other 6 correspond to 3 different 2 16 bit integers which are measurements from the laser altimeter.

How do I convert this hexadecimal data format into real information I can then use to detect when the moonlander has indeed landed?

CodePudding user response:

You'd need a way of determining which message is the one you want to process. I assumed here that b'\xaa\x01' is the identifier for your message.

So if I understand you correctly,

while True:
    ...
    if not data.startswith(b'\xaa\x01'):
        continue
    else:
        num_values = (len(data) - 6) // 2
        values = struct.unpack('>'   'h' * num_values, data[6:])

Essentially ignore every message that doesn't start with specific bytes in the given order. Then figure number of values you have by looking at the length of the message after type and time (6 bytes). Use struct to read them.

Note: '>' is means Big-Endian and 'h' is signed short (2 bytes integer). Refer to struct documentation for more information.

  • Related