How do I decode data when I don't know the specific encoding

寵の児 提交于 2019-12-24 07:11:56

问题


I'm receiving data using an OSC server and the data looks like this:

b'Muse-C46F/elements/alpha_absolute\x00\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'Muse-C46F/elements/alpha_relative\x00\x00\x00,ffff\x00\x00\x00\x7f\xc0\x00\x00\x7f\xc0\x00\x00\x7f\xc0\x00\x00\x7f\xc0\x00\x00'
b'Muse-C46F/elements/alpha_session_score\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'Muse-C46F/elements/alpha_absolute\x00\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

I'm trying to decode 4 floats from those encoded sequences.

This is my whole code:

print('Program Initiated')
UDP_IP = "192.168.2.57"
UDP_PORT = 4000

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

while True:
    data, addr = sock.recvfrom(1024)  # buffer size is 1024 bytes
    if 'alpha' in str(data):
        print(struct.unpack('>32s8sffff', data))

I saw a similar question and used the print(struct.unpack('>32s8sffff', data)), but I get unpack requires a buffer of 56 bytesas error.


回答1:


These OSC messages consists of three parts:

  • An address (which ought to start with b'/')
  • A type tag string, which starts with b',', and defines the type and number of arguments that follow
  • The messages arguments, as defined by the type tag string.

In the data provided in the question, each message consists of 36 or 40 bytes of address, then 5 bytes of tag type string. Disregarding the initial comma, the tag type string consists of four 'f's, so we expect the arguments to consist of four floats, consisting of 16 bytes (4 per float).

Each message has some extra bytes after the 16 required for the four floats; let's assume* that these are padding that can be discarded.

Therefore the struct format is going to be: a variable number of address characters, five tag type characters and four floats.

Then the code required to extract the data looks like this:

$ cat osc.py

  import struct

  data = [
     b"Muse-C46F/elements/alpha_absolute\x00\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
     b"Muse-C46F/elements/alpha_relative\x00\x00\x00,ffff\x00\x00\x00\x7f\xc0\x00\x00\x7f\xc0\x00\x00\x7f\xc0\x00\x00\x
     b"Muse-C46F/elements/alpha_session_score\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
     b"Muse-C46F/elements/alpha_absolute\x00\x00\x00,ffff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
  ]

  if __name__ == "__main__":
      for msg in data:
          num_address_bytes = msg.index(b",")
          num_argument_bytes = len(msg) - (num_address_bytes + 5)
          num_extra_bytes = num_argument_bytes - 16
          address, type_, *floats = struct.unpack(
              ">{}s5s4f".format(num_address_bytes), msg[:-num_extra_bytes]
          )
          print(address, type_, floats)

This output is generated:

b'Muse-C46F/elements/alpha_absolute\x00\x00\x00' b',ffff' [0.0, 0.0, 0.0, 0.0]
b'Muse-C46F/elements/alpha_relative\x00\x00\x00' b',ffff' [1.7796490496925177e-43, -2.000030279159546, -2.000030279159546, -2.000030279159546]
b'Muse-C46F/elements/alpha_session_score\x00\x00' b',ffff' [0.0, 0.0, 0.0, 0.0]
b'Muse-C46F/elements/alpha_absolute\x00\x00\x00' b',ffff' [0.0, 0.0, 0.0, 0.0]

* It's generally a bad idea to make assumptions. If the OSC server has documentation, check whether its formats deviate from the OSC spec.



来源:https://stackoverflow.com/questions/54757258/how-do-i-decode-data-when-i-dont-know-the-specific-encoding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!