问题描述
我用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/5428612rfcomm是套接字还是我错了?
解决方法
在通信过程中使用了许多层,取决于您进入该堆栈的位置,将取决于您需要执行的编码。另一个复杂因素是,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()