简体   繁体   English

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

[英]Bind Bluetooth device programmatically to rfcomm via python in

i wrote a script in python for serial communication between my M5Stack Stick C (like raduino) and the raspberry pi.我在 python 中编写了一个脚本,用于我的 M5Stack Stick C(如 raduino)和树莓派之间的串行通信。 all work fine.一切正常。 i can send "X","Y" or "Z" from raspberry py to the stick and he will reply the value (G-Force) back to the raspi!我可以将“X”、“Y”或“Z”从树莓派发送到棍子,他会将值(G-Force)回复给 raspi! so far so good到目前为止,一切都很好

Codes:代码:

Python on 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)

before the script work, i have to manually bind the m5Stak Stick-C over Blueman to /dev/Rfcomm5.在脚本工作之前,我必须通过 Blueman 手动将 m5Stak Stick-C 绑定到 /dev/Rfcomm5。 it work just fine over GUI or Console....它在 GUI 或控制台上工作得很好......

but now i would like to connect the stick via python to rfcomm5 (just by know the MAC adress, will be found in a config file later on...) i startet to investigate a bit, but the more i research the more confused i am.. i read some stuff over sockets and server-client aproaches.但现在我想通过 python 将摇杆连接到 rfcomm5(只需知道 MAC 地址,稍后将在配置文件中找到......)我开始调查一下,但我研究得越多,我就越困惑上午.. 我读了一些关于 sockets 和服务器客户端方法的东西。 over a seperated script and so on..:.在一个单独的脚本等等..:. i tested this code:我测试了这段代码:

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

and indeed it found the device (just testing)?它确实找到了设备(只是测试)? but do i realy need to make a second script/process to connect to from my script?但我真的需要制作第二个脚本/进程来连接我的脚本吗?

is the the M5stack Stick-C the server? M5stack Stick-C 是服务器吗? (i think so) (我认同)

im so confused about all that stuff.我对所有这些东西都很困惑。 i coded a lot, but never whit sockets, server-client stuff.我编写了很多代码,但从未使用过 sockets,服务器-客户端的东西。 basically the communication (server/client?) works.基本上通信(服务器/客户端?)有效。 i just need to connect the device i found in the second script via macadress to rfcomm5 (or whatever rfcomm).我只需要通过 macadress 将我在第二个脚本中找到的设备连接到 rfcomm5(或任何 rfcomm)。 do i need a bluetooth socket?我需要蓝牙插座吗? like in this example https://gist.github.com/kevindoran/5428612就像在这个例子中https://gist.github.com/kevindoran/5428612

isnt the rfcomm the socket or am i wrong? rfcomm 不是套接字还是我错了?

There are a number of layers that are used in the communication process and depending where you tap into that stack will depend what coding you need to do.在通信过程中使用了许多层,并且取决于您进入该堆栈的位置将取决于您需要执行什么编码。 The other complication is that BlueZ (the Bluetooth stack on linux) changed how it works over recent times leaving a lot of out of date information on the internet and easy for people to get confused.另一个复杂因素是 BlueZ(Linux 上的蓝牙堆栈)最近改变了它的工作方式,在互联网上留下了很多过时的信息,很容易让人们感到困惑。

With two Bluetooth devices, they need to establish a pairng.使用两个蓝牙设备,它们需要建立配对。 This is typically a one off provisioning step.这通常是一次性供应步骤。 This can be done with tools like Blueman or on the command line with bluetoothctl .这可以使用 Blueman 之类的工具或在命令行中使用bluetoothctl来完成。 Once you have a pairing established between your RPi and the M5Stack Stick, you shouldn't need to discover nearby devices again.在 RPi 和 M5Stack Stick 之间建立配对后,您无需再次发现附近的设备。 Your script should just be able to connect if you tell it which device to connect to.如果您告诉它要连接到哪个设备,您的脚本应该能够连接。

The M5Stack stick is advertising as having a Serial Port Profile (SPP). M5Stack 棒宣传为具有串行端口配置文件 (SPP)。 This is a layer on top of rfcomm.这是 rfcomm 之上的一层。

There is a blog post about how this type of connection can be done with the standard Python3 installation: http://blog.kevindoran.co/bluetooth-programming-with-python-3/有一篇关于如何使用标准 Python3 安装完成这种类型的连接的博客文章: http://blog.kevindoran.co/bluetooth-programming-with-python-3/

My expectation is that you will only have to do the client.py on your RPi as the M5Stack Stick is the server.我的期望是您只需在 RPi 上执行 client.py,因为 M5Stack Stick 是服务器。 You will need to know its address and which port to connect on.您将需要知道它的地址以及要连接的端口。 Might be some trial and error on the port number (1 and 3 seem to be common).可能是端口号上的一些试验和错误(1 和 3 似乎很常见)。

Another library that I find helpful for SPP, is bluedot as it abstracts away some of the boilerplate code: https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient我发现对 SPP 有帮助的另一个库是bluedot ,因为它抽象了一些样板代码: https://bluedot.readthedocs.io/en/latest/btcommapi.html#bluetoothclient

So in summary, my recommendation is to use the standard Python Socket library or Bluedot.所以总而言之,我的建议是使用标准的 Python Socket 库或 Bluedot。 This will allow you to specify the address of the device you wish to connect to in your code and the underlying libraries will take care of making the connection and setting up the serial port (as long as you have already paired the two devices).这将允许您在代码中指定要连接的设备的地址,并且底层库将负责建立连接和设置串行端口(只要您已经将两个设备配对)。

Example of what the above might look like with 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()

Example using the Python socket library:使用 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM