通过 python 以编程方式将蓝牙设备绑定到 rfcomm

Bind Bluetooth device programmatically to rfcomm via python in

我在 python 中编写了一个脚本,用于我的 M5Stack Stick C(如 raduino)和 raspberry pi 之间的串行通信。 一切正常。我可以将“X”、“Y”或“Z”从 raspberry py 发送到 stick,他会将值(G-Force)回复给 raspi!到目前为止一切顺利

代码:

Python 刺耳:

import serial
import time
import threading


ser = serial.Serial('/dev/rfcomm5') #init serial port
input_line = []#init input char array

def process_data(_data):
    #called every time a sream is terminated by \n 
    #and the command string is ready to use
    command = convert(_data)
    print(command)
    
def convert(s):   #convert the char list in a string
    
    new = "" #init string to append all chars from char array
    
    for x in s:     # traverse in the string  
        new += str(x)  
  
    return new    # return string  
    
def processIncomingByte(inByte):#adding incoming chars to input_line
    
    global input_line# globalize the input_line
    
    if(inByte == '\n'):#if \n is incoming, end the chararray and release process data method
        process_data(input_line)
        input_line = []#reset input_line for next incoming string
    elif(inByte == '\r'):
        pass
        
    else:#put all incoming chars in input_line 
        input_line.append(inByte)
        

while True:
    while(ser.in_waiting > 0):#while some data is waiting to read....
        processIncomingByte(ser.read())#.... process bytes whit method
    ser.write(b'X\n')
    time.sleep(0.5)

在脚本运行之前,我必须手动将 m5Stak Stick-C 绑定到 Blueman 至 /dev/Rfcomm5。它在 GUI 或控制台上工作得很好....

但现在我想通过 python 将棒连接到 rfcomm5(只要知道 MAC 地址,稍后将在配置文件中找到...) 我开始调查了一下,但我研究得越多,我就越困惑!! 我读了一些关于套接字和服务器-客户端方法的东西。在一个单独的脚本等等.... 我测试了这段代码:

from bluetooth import *

target_name = "M5-Stick-C"
target_address = None
nearby_devices = discover_devices()

for address in nearby_devices:
    if (target_name == lookup_name( address )):
        target_address = address
        break
if (target_address is not None):
    print ("found target bluetooth device with address ", target_address)
else:
    print ("could not find target bluetooth device nearby")

它确实找到了设备(只是在测试)! 但是我真的需要再 script/process 从我的脚本连接到吗?

M5stack Stick-C是服务器吗? (我也这么认为)

我对这些东西很困惑。我编写了很多代码,但从来没有编写套接字、服务器-客户端的东西。 基本上通信(server/client?)有效。 我只需要通过 macadress 将我在第二个脚本中找到的设备连接到 rfcomm5(或任何 rfcomm)。 我需要蓝牙插座吗?像这个例子 https://gist.github.com/kevindoran/5428612

rfcomm 不是套接字还是我错了?

在通信过程中使用了多个层,并且取决于您进入该堆栈的位置将取决于您需要执行的编码。另一个问题是 BlueZ(linux 上的蓝牙堆栈)最近改变了它的工作方式,在互联网上留下了很多过时的信息,很容易让人们感到困惑。

有两个蓝牙设备,他们需要建立配对。这通常是一次性供应步骤。这可以使用 Blueman 等工具或使用 bluetoothctl 在命令行上完成。在 RPi 和 M5Stack Stick 之间建立配对后,您应该不需要再次发现附近的设备。如果您告诉脚本要连接到哪个设备,您的脚本应该能够连接。

M5Stack 棒正在宣传具有串行端口配置文件 (SPP)。这是 rfcomm 之上的一层。

有一篇博客 post 介绍了如何使用标准 Python3 安装完成此类连接:http://blog.kevindoran.co/bluetooth-programming-with-python-3/

我的期望是您只需在 RPi 上执行 client.py,因为 M5Stack Stick 是服务器。您需要知道它的地址和要连接的端口。可能在端口号上进行了一些试验和错误(1 和 3 似乎很常见)。

我发现另一个对 SPP 有帮助的库是 bluedot as it abstracts away some of the boilerplate code: https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient

所以总而言之,我的建议是使用标准 Python 套接字库或 Bluedot。这将允许您在代码中指定要连接的设备的地址,底层库将负责建立连接和设置串行端口(只要您已经将两个设备配对)。

以上示例与 Bluedot

from bluedot.btcomm import BluetoothClient
from signal import pause
from time import sleep

# Callback to handle data
def data_received(data):
    print(data)
    sleep(0.5)
    c.send("X\n")

# Make connection and establish serial connection
c = BluetoothClient("M5-Stick-C", data_received)
# Send initial requests
c.send("X\n")

# Cause the process to sleep until data received
pause()

使用 Python 套接字库的示例:

import socket
from time import sleep

# Device specific information
m5stick_addr = 'xx:xx:xx:xx:xx:xx'
port = 5 # This needs to match M5Stick setting

# Establish connection and setup serial communication
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((m5stick_addr, port))

# Send and receive data
while True:
    s.sendall(b'X\n')
    data = s.recv(1024)
    print(data)
    sleep(0.5)
s.close()