我正在尝试编写一个简单的 python 客户端来解码从名为sdrdaemon的程序生成的二进制流。
此处描述了该协议(为方便起见,复制如下)。我的理解是前 42 个字节应该包含我想用 python struct模块读取/解码的元帧。
我从一些非常简单的事情开始。
import select, socket
from struct import *
port = 19090
bufferSize = 512
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('localhost', port))
s.setblocking(0)
i=0
while i<10:
result = select.select([s],[],[])
msg = result[0][0].recv(bufferSize)
# The meta section?
msg = msg[:42]
# Log raw bytes
#print ' '.join('{0:08b}'.format(ord(x), 'b') for x in msg)
print unpack(">QIxBHIHIIIQ", msg) # big endian
i += 1
但是我对这种事情不熟悉,无法理解我将如何同步,所以我解码了正确的部分。下面的描述指向 CRC,但我不确定如何去做。一点指导会很棒。一个 github 问题没有得到回应。
此处给出了该协议的完整解释,但也复制如下:
打包
从硬件设备检索的数据块被分割成 UDP 有效负载大小的块。该块序列在下文中称为“帧”。一个称为“元”块的特殊块在帧之前发送。它用于传达有关帧及其随后数据的“元”数据。对此“元”数据计算 64 位 CRC 并将其附加。它用作验证并从数据块中识别“元”块,从而实现同步。实际上,将其与数据块混合的可能性非常低。
一个压缩流可以把从硬件检索到的多个数据块打包在一帧中,以提高压缩效率。因此,可能会出现元数据在同一帧中从一个“硬件”块到下一个块发生变化的情况。在这种情况下,该帧被拆分,并使用来自元数据已更改的块的起始“元”块构造一个新帧。原始帧的第一部分立即通过 UDP 发送。这确保了数据帧和它的“元”块总是一致的。
元数据块
“元”数据块由以下内容组成(以字节表示的值):
总大小为 42 字节,包括 8 字节 CRC。
数据块
当流未压缩时,有效载荷大小的 UDP 块被填充完整的 I/Q 样本,在块的末尾留下一个可能小于 I/Q 样本的未使用间隙。最后一个块仅填充剩余样本。在“元”数据中给出了最后一个块中最大填充块和剩余样本的数量。当然,由于数据流是未压缩的,这些值也可以从样本总数和有效负载大小中计算出来。
当流被压缩时,UDP 块完全被压缩流的字节填充。最后一个块仅用剩余字节填充。完整块和剩余字节的数量在“元”块中给出,否则无法计算这些值。
概要图
未压缩流
硬件块(2 字节 I 或 Q 样本): |I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I/Q:I /问| UDP 块(22 字节): |xxxxxxxxxxxxxxxxxxxxxxxx| 框架: |元:xxxxxxxxxxxxxxxxx|I/Q:I/Q:I/Q:I/Q:I/Q:xx|I/Q:I/Q:I/Q:I/Q:I/Q:xx|I /Q:I/Q:I/Q:xxxxxxxxx| 硬件块中的样本数:13 一帧中的块数............:1(总是在未压缩的情况下) 一帧字节数............:52(4 * 13) 完整块......................:2(计算) 剩余样本.......................:3(计算)
编辑::我在发布后不久就放弃了这种方法(支持 SoapySDR),因此无法再真正发表相关评论。