Hi Luke,
I've had this issue before.
The problem is that the Function Probe block is not actually a block,
it's just a way to write code directly into the top_block python file,
and do the top_block object is the one calling the block you want, which
is not an issue since, it knows them, it created them.
Now, whatever block you create doesn't have reference to the other
blocks, and I could not find a way to give it to them directly, so what
I found is to give the top_block object to yours, and also the name of
the block(s) you want, and call them with getattr(top_block_object,
wanted_block_name).whatever_function() . It needs to be the name used
for the exact block you want, not the type, you can find it in the id
field in the parameters, or by reading the top_block file.
The other issue is the fact that, with an embedded block, when you save
it, GRC creates an instance of the object automatically with the default
parameters, possibly to find out its signature and be able to display it
properly. But, at that point, the top block object doesn't exist, so the
execution will stop and GRC will complain.
If you work with an OOT python block, you won't have this issue, but if
you really want to stick with embedded, I've done that too:
If the constructor is not the function that gets the top_block as input,
but another function (not called in the init phase), you can have it be
called by a function probe (the frequency doesn't need to be high) and
put "self" as argument. Then you can use it to call whatever in your
function, or even store it in your block object for later use.
This is really hacky, and there may be a better way to do it but I
couldn't find at the time, and it works without issue.
Tell me if this was not clear, or if you need example code.
Cyrille
Le 21/02/2020 à 00:24, Lukas Haase a écrit :
Hi,
I am using the "Embedded Python Block" to create a simple controller that
controls my USRP Source/Sink blocks.
These blocks support a message interface but unfortunately this is pretty
useless except for the simplest applications (I need to control advanced tuning
with timed commands, GPIO ports etc).
Hence I need to call the methods of these objects directly but I need a
reference to them inside my custom block.
Within my python block I cannot reference the parent blocks, hence I need to
pass a reference to these two objects via the constructor (and parameters).
Basically I want to do the same as parameter "Block ID" from the block "Function
Probe" does.
What is the best way to implement this?
Thanks,
Luke
PS: Example:
class blk(gr.sync_block): # other base classes are basic_block, decim_block,
interp_block
def __init__(self, sample_rate=1.0, usrp_source_block=''): # only default
arguments here
"""arguments to this function show up as parameters in GRC"""
gr.sync_block.__init__(
self,
name='Controller', # will show up in GRC
in_sig=[np.float32],
out_sig=[np.float32]
)
# if an attribute with the same name as a parameter is found,
# a callback is registered (properties work, too).
self.sample_rate = sample_rate
self.usrp_source_block = usrp_source_block
# here I want to execute for example
self.usrp_source_block.set_gain(5.0)
When I then create an USRP Sink object with ID uhd_usrp_sink_0 and enter as
parameter I get the error:
Param - Usrp Source Block(usrp_source_block):
Value "uhd_usrp_sink_0" cannot be evaluated:
name 'uhd_usrp_sink_0' is not defined