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

问题描述

我用python编写了一个脚本,用于我的M5Stack Stick C(如raduino)和树莓派之间的串行通信。 一切正常。我可以将树莓派中的“ X”,“ Y”或“ Z”发送到棍子,他将把值(G-Force)返回给raspi!到目前为止一切顺利

代码

在raspy上使用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)

在脚本工作之前,我必须通过Blueman手动绑定m5Stak Stick-C 到/ 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")

确实找到了设备(只是测试)! 但是我真的需要制作第二个脚本/进程来从我的脚本进行连接吗?

M5stack Stick-C是服务器吗? (我是这样)

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

rfcomm是套接字还是我错了?

解决方法

在通信过程中使用了许多层,取决于您进入该堆栈的位置,将取决于您需要执行的编码。另一个复杂因素是,BlueZ(Linux上的蓝牙堆栈)在最近一段时间内改变了其工作方式,从而在互联网上留下了许多过时的信息,容易让人感到困惑。

使用两个蓝牙设备,他们需要建立配对。这通常是一次性配置步骤。可以使用Blueman之类的工具来完成此任务,也可以在命令行中使用bluetoothctl来完成。一旦在RPi和M5Stack Stick之间建立了配对,就无需再次发现附近的设备。如果告诉脚本要连接到哪个设备,脚本就应该能够连接。

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

有一篇博客文章介绍了如何通过标准的Python3安装来完成这种连接:http://blog.kevindoran.co/bluetooth-programming-with-python-3/

我的期望是,由于M5Stack Stick是服务器,因此您只需在RPi上执行client.py。您将需要知道其地址和连接哪个端口。可能会对端口号进行一些反复试验(似乎很常见的是1和3)。

我发现对SPP有用的另一个库是bluedot,因为它抽象了一些样板代码:https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient

因此,总而言之,我的建议是使用标准的Python Socket库或Bluedot。这将允许您在代码中指定希望连接的设备的地址,并且底层库将负责进行连接并设置串行端口(只要您已经将两个设备配对)。 / p>

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()