关于esp32 microPython 蓝牙只能发送20个字节问题(发送与接受)

目录

问题描述

原因分析:

解决方案:


问题描述

关于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))

关于esp32 microPython 蓝牙只能发送20个字节问题(发送与接受)_第1张图片

关于esp32 microPython 蓝牙只能发送20个字节问题(发送与接受)_第2张图片

代码核心

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个字节

关于esp32 microPython 蓝牙只能发送20个字节问题(发送与接受)_第3张图片


解决方案:

源码:

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.')


你可能感兴趣的:(服务器,运维,单片机,esp32,python)