目录
问题描述
原因分析:
解决方案:
关于esp32 microPython 蓝牙只能发送20个字节问题(发送与接收)
def gatts_write(
self, value_handle: memoryview, data: bytes, send_update: bool = False, /
) -> None:
写入此句柄的本地值,该值可由客户端读取。
如果*send_update*为‘ ’ True ' ',那么所有订阅的客户端都会收到通知
(或指示,取决于它们订阅了什么和哪些操作
特性支持)关于此写。
初始化加入
self.ble.gatts_write(self.tx, bytes(512))
self.ble.gatts_write(self.rx, bytes(256))
代码核心
def send(self, data):
# 数据发送前检查连接状态:
if self.connected_flag:
try:
full_data = (data + '\n').encode('utf-8')
# 直接写入特征值
# 触发通知(无需传递数据)
self.ble.gatts_write(self.tx, full_data,True)
self.ble.gatts_notify(1, self.tx)
except OSError as e:
print("发送失败:", e)
else:
print("未连接,跳过发送")
本人踩的大坑没有修改手机MTU,大家注意一下,不然还是20个字节
源码:
from machine import Pin, PWM from machine import Timer from time import sleep_ms import bluetooth import machine # 全局变量:存储接收到的蓝牙消息 BLE_MSG = "" machine.freq(160000000) # 提升时钟频率 class ESP32_BLE(): def __init__(self, name): # 初始化PWM控制LED(引脚8) self.led = PWM(Pin(10)) # 设置PWM频率为1000Hz(修正后的写法) self.led.freq(1000) # 创建定时器对象(定时器0) self.timer1 = Timer(0) # 存储蓝牙设备名称 self.name = name self.conn_handle = None # 初始化连接句柄为None # 初始化蓝牙模块 self.ble = bluetooth.BLE() # 激活蓝牙硬件 self.ble.active(True) # 设置蓝牙设备名称 self.ble.config(gap_name=name) # 连接状态标志(新增) self.connected_flag = False # 初始化设备为断开状态 self.disconnected() # 设置蓝牙中断处理函数 self.ble.irq(self.ble_irq) # 注册GATT服务和特征 self.register() self.ble.gatts_write(self.tx, bytes(512)) self.ble.gatts_write(self.rx, bytes(256)) # 开始蓝牙广播 self.advertiser() def connected(self): # 设备连接时: # 1. 点亮LED(占空比100%) self.led.duty(1023) # 2. 停止心跳定时器 self.timer1.deinit() # 3. 更新连接状态 self.connected_flag = True def disconnected(self): # 设备断开时: # 1. 启动心跳定时器(LED闪烁) self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.duty(0)) # 2. 更新连接状态 self.connected_flag = False def ble_irq(self, event, data): global BLE_MSG # 处理不同蓝牙事件: if event == 1: # 设备连接事件 self.connected() elif event == 2: # 设备断开事件 self.advertiser() self.disconnected() elif event == 3: # 接收到数据事件 # 读取特征值数据 buffer = self.ble.gatts_read(self.rx) # 解码并存储消息(去除首尾空格) BLE_MSG = buffer.decode('UTF-8').strip() print(BLE_MSG) def register(self): # 定义自定义的 UUID 名称和对应的 UUID 值 uuid_names = { 'UART_SERVICE': 'AE25A5C1-4601-143C-12BB-8BC45A18749C', 'READER_CHAR': 'AE25A5C2-4601-143C-12BB-8BC45A18749C', 'SENDER_CHAR': 'AE25A5C3-4601-143C-12BB-8BC45A18749C' } # 配置服务结构(元组嵌套) services = ( ( bluetooth.UUID(uuid_names['UART_SERVICE']), ( (bluetooth.UUID(uuid_names['SENDER_CHAR']), bluetooth.FLAG_NOTIFY | bluetooth.FLAG_READ), # 通知特征 (bluetooth.UUID(uuid_names['READER_CHAR']), bluetooth.FLAG_WRITE), # 写入特征 ) ), ) # 注册服务并获取特征对象 ((self.tx, self.rx,),) = self.ble.gatts_register_services(services) #print(self.tx,self.rx) def send(self, data): # 数据发送前检查连接状态: if self.connected_flag: try: full_data = (data + '\n').encode('utf-8') # 直接写入特征值 # 触发通知(无需传递数据) self.ble.gatts_write(self.tx, full_data,True) self.ble.gatts_notify(1, self.tx) except OSError as e: print("发送失败:", e) else: print("未连接,跳过发送") """ # 定义分片大小(根据MTU调整,默认20) chunk_size = 20 # 将数据转换为字节并添加换行符 data_bytes = (data + '\n').encode('utf-8') # 分片发送 for i in range(0, len(data_bytes), chunk_size): chunk = data_bytes[i:i+chunk_size] try: self.ble.gatts_notify(1, self.tx, chunk) # 可选:添加短暂延时避免堵塞 # time.sleep_ms(10) except OSError as e: print("发送失败:", e) break # 可选:根据需求决定是否继续发送后续分 """ def advertiser(self): # 构造广播数据: name = bytes(self.name, 'UTF-8') # 设备名称 # 固定广播头部(通用可发现模式) adv_data = bytearray(b'\x02\x01\x06') # 添加完整设备名称字段 adv_data.extend(bytes([len(name) + 1, 0x09])) # 字段长度+类型 adv_data.extend(name) # 设备名称 # 开始广播(间隔100ms) self.ble.gap_advertise(100, adv_data) print("广播数据:", adv_data, "\r\n") ble = ESP32_BLE("ESP32BLE") def lanya_run(): if ble.connected_flag: ble.send('"stm32_temperature":25.22,"PM25":0,"roll":0.69,"pitch":-2.53,"uvs_raw":0,"raw_voc":197,"raw_nox":127,"light":48,"Temperature":41.07,"humidity":15.87,"BMP_Temperature":41.83,"BMP_Pressure":101035.82,"BMP_Altitude":24.10,"ppm_MP_2":7547.43,"ppm_MP_5":459.90,"ppm_MP_4":453.29,"ppm_MP_7":315.14,"ppm_MP_135":828.32,"ppm_MP_503":0.33}') # 周期性发送状态 if __name__ == "__main__": # 创建蓝牙对象(设备名"ESP32BLE") ble = ESP32_BLE("ESP32BLE") # 初始化LED控制(再次确认引脚) led = PWM(Pin(10)) while True: # 连接状态指示灯逻辑 lanya_run() sleep_ms(1000) # 处理接收的命令: if BLE_MSG == 'LED ON': print("收到命令:", BLE_MSG) # 渐亮效果 for i in range(0, 1023): led.duty(i) sleep_ms(3) BLE_MSG = "" print("LED已打开") ble.send('LED is ON.') # 发送确认信息 elif BLE_MSG == 'LED OFF': print("收到命令:", BLE_MSG) # 渐灭效果 for i in range(1023, -1, -1): led.duty(i) sleep_ms(3) BLE_MSG = "" print("LED已关闭") ble.send('LED is OFF.')