如何在GNURadio中检测按键,实现按键按下/抬起时改变变量?
刚好折腾过类似的需求,给你梳理两种在GNURadio里实现键盘按键检测(就是你说的按‘V’键切换发射状态的PTT功能)的方法,亲测靠谱:
方法一:自定义Python按键监听块(灵活全局监听)
这是我最常用的方式,因为可以全局监听键盘,哪怕GNURadio窗口不在前台也能触发,步骤如下:
1. 先装依赖
需要用到轻量的键盘监听库pynput,终端里装一下:
pip install pynput
2. 写自定义Python块
在GNURadio Companion里拖一个Python Block进来,把默认代码替换成下面这段——核心就是开个线程监听键盘的按下/释放事件,实时更新GNURadio变量:
from gnuradio import gr from pynput import keyboard class ptt_key_listener(gr.sync_block): def __init__(self, ptt_var): gr.sync_block.__init__( self, name='PTT Key Listener', in_sig=None, out_sig=None ) self.ptt_var = ptt_var # 传入我们要控制的GNURadio变量 self.listener = None # 按键按下的回调 def on_press(key): try: if key.char.lower() == 'v': # 大小写都支持 self.ptt_var.set(1) # 按下V,切换到音频输入(开始发射) except AttributeError: # 处理特殊按键(比如Shift、Ctrl),这里忽略 pass # 按键释放的回调 def on_release(key): try: if key.char.lower() == 'v': self.ptt_var.set(0) # 松开V,切回Null Source(停止发射) except AttributeError: pass # 启动监听线程 self.listener = keyboard.Listener(on_press=on_press, on_release=on_release) self.listener.start() def work(self, input_items, output_items): # 同步块的空实现,只需要返回0就行 return 0 def stop(self): # 程序退出时停止监听线程,避免残留 if self.listener: self.listener.stop() return True
3. 流图里配置
- 先加一个
Variable,命名为ptt_state,默认值设为0 - 把自定义的
PTT Key Listener块拖进来,参数里的ptt_var选刚才的ptt_state - 加一个
Selector块:输入0接Null Source,输入1接你的Audio Source,选择端口连ptt_state - 把Selector的输出接到你的发射链路(比如SDR的发射模块)
这样一来,按下V键时ptt_state变成1,Selector切到音频输入开始发射;松开就变回0,切回Null Source停止发射,完美实现PTT。
方法二:用QT GUI按钮绑定快捷键(简单但有局限)
如果不想写代码,也可以用GNURadio自带的GUI组件快速实现:
- 拖一个
QT GUI Push Button进来,设置它的Shortcut为V - 配置按钮的
Variable为ptt_state,Value on pressed设为1,Value on released设为0 - 同样把
ptt_state连到Selector的选择端口就行
这种方法优点是零代码,但缺点是只有当GNURadio的GUI窗口处于焦点时才能触发,如果你切到别的窗口按V就没用了,适合简单场景。
一些注意事项
- Linux下如果遇到权限问题,可能需要调整输入设备的权限,或者临时用
sudo运行(不过不推荐长期这么做,最好配置udev规则) - 确保你的SDR支持发射模式,流图的发射部分参数要匹配你的硬件
- 自定义块的
stop方法一定要写,不然程序退出后可能会残留监听线程
内容的提问来源于stack exchange,提问作者Jeremiah




