如何重新连接蓝牙连接与PySerial(算法问题)复盆子Pi-蓝牙设备



Goodday程序员,

我正在处理Raspberry Pi 3B+和几个蓝牙设备之间的连接,目前每个Pi最多5个。我可以建立连接,与设备进行所有交互,但在设备长时间失去连接后,我很难重新连接。请把你伟大的头脑借给我,并帮助我制作一个始终有效连接设备的防弹脚本。

一些信息:

  • Pi 3B+运行Raspbian Buster
  • 蓝牙设备使用bluetoothctl配对,并绑定到rc.local中的rfcomm[x](sudo bind…(
  • Python脚本使用PySerial连接到设备,使用线程和队列进行读写
  • 启动脚本时连接所有设备
  • 主脚本以.config/lxsession/LXDE pi/autostart启动
  • 使用PySerial连接到蓝牙设备会导致相当长的连接时间,大约2-3秒

每个设备运行3个线程,Watchdog、Read、Write。Watchdog大约每5秒向写入队列添加一条伪消息(由写入线程发送到设备(,如果它做出反应(命令响应不正确(,我知道它是活动的。如果它在大约30秒内没有反应,我知道它失去了连接,我必须尝试重新连接。我有一个表示连接状态(connectionAlive(的变量,可以是0、1或2。0处于非活动状态,1正在重新连接,2已连接。只有当connectionAlive>0问题是,当设备处于待机状态或关机给电池充电而失去连接时。读取和写入线程非常直接,所以我认为重新连接的算法是个问题。我在下面添加了看门狗代码:

def Watchdog(self):
logging.info('Start watchdog thread for: {}'.format(self.tool_id))
while(True):
if self.connectionAlive == 0:
self.ChangeAlive(1)
time.sleep(0.2)
if self.wq.qsize() < 3:
self.wq.put(['ping', ''])
time.sleep(0.5)
#if last alive longer than 20 ticks
if (time.time() - self.last_alive) > 30: #or self.errorQ.qsize() > 0
last_tick = time.time() - self.last_alive
#if it was alive, tell thread its dead.
if self.connectionAlive == 2 and self.com != False:
logging.error('Tool {} is taking longer to respond'.format(self.tool_id))
self.ChangeAlive(0)
if self.com != False:
try:
self.com.close()
time.sleep(0.1)
except:
#com wasnt alive (never connected since thread started)
pass
self.connectionTryCount += 1
try:
self.com = serial.Serial(port=self.comport, baudrate=9600, timeout=5, write_timeout=5)
#time.sleep(3)
except:
if self.connectionTryCount < 2:
logging.error('Tool {} is unable to connect!'.format(self.tool_id)) #com port not available
#time.sleep(5)
else:
if self.connectionTryCount > 0:
logging.info('Tool {} connected after {} tries'.format(self.tool_id, self.connectionTryCount))
self.connectionTryCount = 0
if self.connectionAlive != 2:
self.ChangeAlive(2)
while self.errorQ.qsize() > 0:
self.errorQ.get()
time.sleep(0.05)
time.sleep(4)

我认为线程处于休眠状态,并以某种方式使连接和读取"活动"消息的窗口太小,无法保持连接,结果是它断开连接的速度太快,无法尝试重新连接。读取线程具有0.1的睡眠,而写入线程具有0.05的睡眠。

编辑:蓝牙设备连接到一个需要发送参数的测量设备。当蓝牙部分仍处于连接状态时,测量设备可以进入待机状态,但这意味着设备未激活,也未准备好接收参数,设备没有内置队列。

是我的剧本写得不好,还是我从一开始就注定要使用PySerial或Pi?

非常感谢您的任何意见或建议!

rfcomm是BlueZ开发人员不赞成使用的8种工具之一,因此我建议不要在rc.local.中使用rfcomm

在Linux上,蓝牙串行连接可以使用标准Python套接字库进行,如本博客所述:http://blog.kevindoran.co/bluetooth-programming-with-python-3/

Bluedot库中还有一些功能可能会有所帮助。除了文档之外,还有一些示例。

根据您的脚本所做的工作,您可能希望在启动时使用systemd来运行程序。我发现以下博客是一个有用的参考:https://blog.usedbytes.com/2019/11/run-at-startup-without-rc.local/

最新更新