初级教程(3)创建和修改 Python 块3-Python 块消息传递

3.Python 块消息传递

本教程介绍如何使用Embedded Python Block读取和写入消息。

上一教程Python Block with Vectors演示了如何编写带有矢量输入和输出的嵌入式 Python Block。下一个教程Python 块标签描述了如何在 Python 块中读取和写入标签。

内容

消息概述

消息是一种在块之间发送信息的异步​​方式。消息擅长传递控制数据,跨块保持一致的状态,并向流程图中的块提供某种形式的非数据反馈。

消息有几个独特的属性:

  • 消息到达时没有基于采样时钟的保证
  • 消息不与标签等特定样本相关联
  • 消息输入输出端口在GRC中不必连接
  • 消息端口使用多态类型 (PMT)

消息端口用灰色表示,它们的连接用虚线区分:

MessageBlockExample.png

有关使用 PMT 传递消息的更多信息,请参见此处:消息传递

流程图概述

以下流程图演示了如何:

  • 给Python块添加消息收发端口
  • 发送信息
  • 接收和处理消息
  • 根据收到的消息调整work()函数中的块行为

创建 两个自定义嵌入式 Python 块以:

本教程假设您已经创建了至少一个Embedded Python Block。如果没有,请在继续之前 完成创建您的第一个块的教程。

首先将以下块添加到流程图并连接它们:

  • 噪声源
  • 信号源
  • 蟒蛇块
  • 风门
  • QT GUI 时间接收器
StartingFlowgraphMessagePassing.png

多路复用器:定义块

双击Embedded Python Block并在编辑器中打开源代码:

编辑MultiplexerProperties.png


不需要 example_param,因此 从__init __()函数中删除变量example_param

def __init__(self): # 这里只有默认参数

并删除该行:

self.example_param = example_param

将块的名称更改为Multiplexer

name='多路复用器',

向块添加第二个输入:

in_sig=[np.complex64, np.complex64],

删除乘以example_param

output_items[0][:] = input_items[0]
AddSecondInputEmbeddedPythonBlock.png


回想一下,Python 需要适当的缩进。默认情况下,嵌入式 Python 块使用 4 个空格的倍数缩进。混用制表符和空格会引发语法错误:

TabsSpacesError.png


保存代码 (CTRL+S) 并返回 GRC。请注意块的名称发生了怎样的变化,并且块现在有两个输入。将噪声源信号源连接到两个输入:

MultiplexerWithTwoInputs.png

多路复用器:定义消息输入端口

返回代码编辑器。需要添加一个输入消息端口。创建一个变量来存储消息端口名称:

self.selectPortName = 'selectPort'

添加一行以创建或注册消息输入端口:

self.message_port_register_in(pmt.intern(self.selectPortName))

添加一行以将输入端口与消息处理程序连接起来。

self.set_msg_handler(pmt.intern(self.selectPortName),self.handle_msg)
AddMessageHandler.png


保存代码 (CTRL+S)。请注意,语法错误列在Embedded Python Block的属性中:

代码编辑器错误示例.png


此错误表示需要导入pmt库。返回代码编辑器并添加正确的导入语句:

导入PMT
导入PMT.png

多路复用器:创建消息处理程序

消息处理程序是在收到消息时调用的函数。

必须定义消息处理函数。此消息处理程序根据收到的消息在两个输入端口之间切换。收到的消息是一个布尔值,即 True 或 False。在__init__()下定义一个新变量,它是输入选择器,

self.selector = True

定义handle_msg()函数:

def handle_msg(自我,味精):
    self.selector = pmt.to_bool(msg)

函数pmt.to_bool()获取消息 PMT,然后将数据类型转换为 Python 的布尔数据类型。PMT 用于将消息传递给抽象数据类型。例如,消息可用于发送和接收字符串、浮点数、整数甚至列表。有关 PMT 的更多信息,请访问多态类型 (PMT) 维基页面

添加选择器属性.png

多路复用器:在work()中使用消息

多路复用器的外部接口是完整的。修改块的work()函数以添加多路复用操作。将以下代码添加到work()函数中:

如果(自我选择器):
    output_items[0][:] = input_items[0]
别的:
    output_items[0][:] = input_items[1]
多路复用器WorkFunction.png


如果self.selector = True 多路复用器块选择端口0 ,如果self.selector = False则选择端口1self.selector的默认值在__init__()函数中定义。

保存代码 (CTRL+S) 并返回 GRC。Multiplexer块有一个消息端口selectPort

CompletedMultiplexerBlock.png


在继续之前运行流程图以确保一切正确。如简介中所述,不必连接消息端口即可运行流图。因为self.selector的默认值为True ,多路复用器的work()函数将选择端口0并将其发送到输出。QT GUI Time Sink显示噪音:

多路复用器NoiseInput.png

选择器控件:定义块

另一个嵌入式 Python 块用于计算它收到的样本数,然后将控制消息发送到多路复用器块以切换选择器。

首先在MultiplexerThrottle之间的流程图中添加一个新的Python 块

警告!从块库中拖放一个新的 Python 块!不要复制和粘贴现有的多路复用器块,它只会创建该块的第二个副本。

添加PythonBlockToFlowgraph.png


编辑Embedded Python Block 的代码。更改__init__()函数中的参数example_param

def __init__(self, Num_Samples_To_Count=128):

更改块的名称:

name='选择器控件',

将Num_Samples_To_Count存储为私有变量:

self.Num_Samples_To_Count = Num_Samples_To_Count

移除work()函数中的example_param乘法:

ReplaceExampleParamWithNumSamples.png

选择器控件:定义消息输出端口

导入pmt库:

导入PMT

在__init__()函数中创建一个变量 ( self.portName ) ,其中包含字符串形式的输出端口名称messageOutput

self.portName = 'messageOutput'


通过在__init__()函数中添加以下行来创建或注册 消息端口:

self.message_port_register_out(pmt.intern(self.portName))
AddControlSelectorMessageOutput.png


保存代码 (CTRL + S) 并返回 GRC。选择器控制块有一个消息输出端口:

MessageOutputSelectorControlBlock.png

选择器控件:在work()中发送消息

不需要为输出端口定义消息处理程序。但是,需要修改 work()函数以创建发送消息的逻辑。

首先在__init__()中创建两个变量:

self.state = 真
self.counter = 0

添加行以增加每次调用work()的计数样本数:

self.counter = self.counter + len(output_items[0])
DefineCounterInBlock.png


添加逻辑以在超过计数器后发送消息:

如果(self.counter > self.Num_Samples_To_Count):
    PMT_msg = pmt.from_bool(self.state)
    self.message_port_pub(pmt.intern(self.portName),PMT_msg)
    self.state = not(self.state)
    self.counter = 0

该逻辑使用pmt.from_bool()函数调用将self.state的 Python 布尔数据类型转换为 PMT ,然后在输出消息端口上发送或发布消息。self.state变量被切换到它的相反值并且计数器被重置。

CompletedSelectorControlBlock.png


保存代码并返回到 GRC。在Selector Control块的属性中为Num_Samples_To_Count输入32000

选择器控件属性.png


添加Message Debug块并将messageOutput端口连接到它。运行流程图显示消息正在以每秒一次的速率发送,在#t (True) 和#f (False) 之间交替:

MessageDebugExample.png

但是,选择器控件的输出消息端口尚未连接到多路复用器的输入消息端口,因此QT GUI Time Sink仅显示噪声。

最终流程图

将Selector Control的输出消息端口连接到Multiplexer的输入消息端口。请注意,虚线在两个块后面移动并且很难看到:

连接消息端口.png

Virtual SinksVirtual Sources可用于清理一些连接并使流程图更易于理解。单击虚线并将其删除。将Virtual SinkVirtual Source拖放到工作区中。将Virtual SinkVirtual Source的Stream ID更改为message,然后在流程图中连接它们:

MessageVirtualSourceSink.png


运行流程图。QT GUI Time Sink显示噪声源信号源之间的交替输出:

交替输出时间接收器.png

下一个教程Python 块标签描述了如何在 Python 块中读取和写入标签。

发表回复 0

Your email address will not be published. Required fields are marked *