首页 > 解决方案 > 使用 pexpect 检测和处理来自蓝牙 LE 的通知

问题描述

我一直在编写一个 python 代码来读取蓝牙 LE 接收的 Raspberry Pi 3 Model B 上的值。我可以通过以下方式读取正确的值:

child.sendline("char-read-hnd handle")
child.expect("Characteristic value/descripto: ",timeout=5)

我现在要做的是随时检查通知,所以我有一个线程可以搜索预期的模式“通知句柄=”,如下所示:

def run():
  patterns = ['Notification handle=','Indication handle=']
  while True:
    try:
      matched_pattern_index = child.expect(patterns,timeout=1)
      if matched_pattern_index in {0,1}:
        print("Received Notification")
        handleNotification()
    except pexpect.TIMEOUT:
      pass

现在在我的主要代码中,我总是在做一些 child.sendline 来检查新值以及 child.expect 。问题是我在上面对 pexpect.expect 的 Thread 调用阻塞了我的代码中的其他 pexpect.expect。我已经尝试让第二个孩子类似于第一个孩子在 Thread 内工作,但结果是一样的。所以有人知道我怎么能做到这一点吗?

任何帮助,将不胜感激。提前致谢

标签: pythonpexpect

解决方案


我正在考虑子类化pexpect.spawn并提供一种expect_before(p,c)方法来保存模式p和回调函数列表,然后在调用实际函数之前c覆盖以将该列表作为该调用列表的expect(p2)前缀。pp2spawn.expect

如果真正的函数返回一个i在列表大小内的匹配索引p,我们可以调用函数c[i]并再次循环。当索引超出该列表时,我们将其调整为列表中的索引p2并从调用中返回。这是一个近似值:

#!/usr/bin/python
# https://stackoverflow.com/q/51622025/5008284
from __future__ import print_function
import sys, pexpect

class Myspawn(pexpect.spawn):
  def __init__(self, *args, **kwargs):
    pexpect.spawn.__init__(self, *args, **kwargs)

  def expect_before(self, patterns, callbacks):
    self.eb_pat = patterns
    self.eb_cb = callbacks

  def expect(self, patlist, *args, **kwargs):
    numbefore = len(self.eb_pat)
    while True:
      rc = pexpect.spawn.expect(self, self.eb_pat+patlist, *args, **kwargs)
      if rc>=numbefore:
        break
      self.eb_cb[rc]() # call callback
    return rc-numbefore

def test():
    child = Myspawn("sudo bluetoothctl", logfile=sys.stdout)
    patterns = ['Device FC:A8:9A:..:..:..', 'Device C8:FD:41:..:..:..']
    callbacks = [lambda :handler1(), lambda :handler2()]
    child.expect_before(patterns, callbacks)
    child.sendline('scan on')
    while True:
      child.expect(['[bluetooth].*?#'], timeout=5)

推荐阅读