Background: I am writing a Python script that contains a gnuradio flowgraph object used to demodulate incoming IQ data. The flowgraph is started and runs while I periodically poll it for demodulated data.
In the past, I've used a message sink and msgq to pass data out of a flowgraph, but this has been deprecated. I'm now trying to do things using the newer blocks: specifically trying to pass the output data to a "Stream to Tagged Stream" block and then to a "Tagged Stream to PDU" block.
I'm now trying to figure out how to get the data out of the flowgraph and into my main python code. In the documentation and in forums, I've seen a host of information about how to develop OOT blocks, but very little on what I'm trying to do.
I've created a simplified version of what I'm trying to do. The flowgraph consists of a signal source ramp that feeds through to the "Tagged Stream to PDU" block. I don't care about the strings associated with the tags, I just want to read the stream data (the floats making up the input ramp data). Most of the references I see use the "get_tags_in_range" method, but this is private and not of help to my case. I have been able to query the block and get the item counts, but that's about it.
I don't know why it's giving me so much trouble, but I'd appreciate any help.
I've have attached the code below:
from gnuradio import analog
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import filter
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from gnuradio import digital
import pmt
import math
import numpy
# build simple flowgraph
class simple_flowgraph(gr.top_block):
def __init__(self):
gr.top_block.__init__(self)
samp_rate = 32000.0
# generate repeating ramp from 0 to 1
self.blocks_throttle_0 = blocks.throttle(
gr.sizeof_float*1,
samp_rate,
True)
self.blocks_tagged_stream_to_pdu_0 = blocks.tagged_stream_to_pdu(
blocks.float_t,
'packet_len')
self.blocks_stream_to_tagged_stream_0 = blocks.stream_to_tagged_stream(
gr.sizeof_float,
1,
32,
"packet_len")
self.analog_sig_source_x_0 = analog.sig_source_f(
samp_rate,
analog.GR_SAW_WAVE,
4e3,
1,
0)
##################################################
# Connections
##################################################
self.connect(
(self.analog_sig_source_x_0, 0),
(self.blocks_throttle_0, 0)
)
self.connect(
(self.blocks_stream_to_tagged_stream_0, 0),
(self.blocks_tagged_stream_to_pdu_0, 0)
)
self.connect(
(self.blocks_throttle_0, 0),
(self.blocks_stream_to_tagged_stream_0, 0)
)
flowgraph = simple_flowgraph()
flowgraph.start()
current_nitems_count = \
flowgraph.blocks_tagged_stream_to_pdu_0.nitems_read(0)
previous_nitems_count = current_nitems_count
print current_nitems_count
while True:
# get data from flowgraph when ready
current_nitems_count = \
flowgraph.blocks_tagged_stream_to_pdu_0.nitems_read(0)
tag_list = []
# while there is data,
if current_nitems_count > previous_nitems_count + 16:
print "Got new chunk of data\n Item Count: {}".format(current_nitems_count)
previous_nitems_count = current_nitems_count
#???
Thanks to Marcus' excellent information, I've gotten the things working with the ZMQ push/pull sinks. Here's the updated code:
from gnuradio import analog
from gnuradio import blocks
from gnuradio import gr
from gnuradio import zeromq
import zmq
import array
socket_str = "tcp://127.0.0.1:5557"
def zmq_consumer():
context = zmq.Context()
results_receiver = context.socket(zmq.PULL)
results_receiver.connect(socket_str)
while True:
# pull in raw binary data
raw_data = results_receiver.recv()
# convert to an array of floats
float_list = array.array('f', raw_data) # struct.unpack will be faster
# print flowgraph data
for signal_val in float_list:
print signal_val
# build simple flowgraph that outputs a repeating ramp from 0 to 1
class simple_flowgraph(gr.top_block):
def __init__(self):
gr.top_block.__init__(self)
samp_rate = 32000.0
# generate repeating ramp from 0 to 1
self.analog_sig_source_x_0 = analog.sig_source_f(
samp_rate,
analog.GR_SAW_WAVE,
4e3,
1,
0)
self.blocks_throttle_0 = blocks.throttle(
gr.sizeof_float*1,
samp_rate,
True)
self.zeromq_push_sink_0 = zeromq.push_sink(gr.sizeof_float,
1,
socket_str,
100,
False,
-1)
##################################################
# Connections
##################################################
self.connect(
(self.analog_sig_source_x_0, 0),
(self.blocks_throttle_0, 0)
)
self.connect(
(self.blocks_throttle_0, 0),
(self.zeromq_push_sink_0, 0)
)
# instantiate and start the flowgraph
flowgraph = simple_flowgraph()
flowgraph.start()
# start the receiver socket
zmq_consumer()