Im trying to write a simple python client to decode a binary stream generated from a program called sdrdaemon.
The protocol is described here (copied below for convenience). My understanding is the first 42 bytes should contain the meta frame which I thought to read/decode with the python struct module.
I started off with something very simple.
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
However Im unfamiliar enough with this kind of thing to understand how I would synchronise so Im decoding the right sections. The description below points to the CRC but Im unsure how to go about it. A bit of guidance would be great. A github issue got no response.
The full explanation of the protocol is given here but also copied below:
Packaging
The block of data retrieved from the hardware device is sliced into blocks of the UDP payload size. This sequence of blocks is called a "frame" in the following. A special block called the "meta" block is sent before a frame. It is used to convey "meta" data about the frame and its data that follows. A CRC on 64 bits is calculated on this "meta" data and appended to it. It serves as a verification and also to recognize the "meta" block from the data blocks thus achieving synchronization. There is effectively a very low probability to mix it up with a data block.
A compressed stream may pack several data blocks retrieved from the hardware in one frame to improve compression efficiency. So the case may arise that a change of meta data occurs from one "hardware" block to the next in the same frame. In this case the frame is split and a new frame is constructed with a starting "meta" block from the block where the meta data has changed. The first part of the original frame being sent immediately over UDP. This ensures that the data frame and its "meta" block are always consistent.
Meta data block
The block of "meta" data consists of the following (values expressed in bytes):
Total size is 42 bytes including the 8 bytes CRC.
Data blocks
When the stream is uncompressed UDP blocks of the payload size are stuffed with complete I/Q samples leaving a possible unused gap of less than an I/Q sample at the end of the block. The last block is filled only with the remainder samples. The number of maximally filled blocks and remainder samples in the last block is given in the "meta" data. Of course as the data stream is uncompressed these values can also be calculated from the total number of samples and the payload size.
When the stream is compressed UDP blocks are stuffed completely with bytes of the compressed stream. The last block being filled only with the remainder bytes. The number of full blocks and remainder bytes is given in the "meta" block and these values cannot be calculated otherwise.
Summary diagram
Uncompressed stream
hardware block (2 byte I or Q samples): |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| UDP block (22 bytes): |xxxxxxxxxxxxxxxxxxxxxx| Frame: |Meta: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:xxxxxxxxxx| Number of samples in a hardware block: 13 Number of blocks in a frame..........: 1 (always if uncompressed) Number of bytes in a frame...........: 52 (4 * 13) Complete blocks......................: 2 (calculated) Remainder samples....................: 3 (calculated)
Edit: : I ending up abandoning this approach (in favour of SoapySDR) soon after posting so can't really comment relevantly anymore.