alibaba / AliOS-Things

面向IoT领域的、高可伸缩的物联网操作系统,可去官网了解更多信息https://www.aliyun.com/product/aliosthings
Apache License 2.0
4.58k stars 1.14k forks source link

蓝牙辅助配网问题ESP32-C3/Breeze SDK/云智能App #1934

Closed HuXioAn closed 2 years ago

HuXioAn commented 2 years ago

移植Breeze SDK进行蓝牙配网时,遇到了一些困难,十分苦恼。内容中日志较多,但都写了注解,还烦请各位不吝赐教。

运行环境

硬件:ESP32-C3-DevkitC以及mini等原厂模组

软件:Breeze SDK 2.0.7(BZ_VERSION="2.0.7",来自ali-smartliving-device-alios-things-rel_1.6.6),ESP-IDF4.4+FreeRTOS,BLE4.2协议栈,breeze_hal_xxx.c三个自己实现的。

问题描述

我最近一直在向ESP32-C3芯片移植基于IDF+FreeRTOS的阿里Breeze SDK,以便接入生活物联平台以及使用公版云智能APP进行蓝牙辅助配网。

在按照官方文档移植完主要的hal/breeze_hal_xxx.c这三个文件后,我将breeze这部分内容作为idf工程的component加入到一个空的工程中。并按照combo实例程序,将main.c写为如下程序,用以测试连接与配网。

测试主函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "breeze_export.h"
#include "esp_system.h"
#include "esp_log.h"

//下列5个字段都填入了申请自物联平台的内容,使用一机一密。
#define PRODUCT_ID     xxxxxxx
#define DEVICE_SECRET  xxxxxxx
#define DEVICE_NAME    xxxxxxx
#define PRODUCT_KEY    xxxxxx
#define PRODUCT_SECRET xxxxxxxx

static bool ble_connected = false;

/* @brief Event handler for Ali-SDK. */
static void dev_status_changed_handler(breeze_event_t event)
{
    ESP_LOGD("COMBO_CHANGE","EVENT:%d",event);
    switch (event) {
        case CONNECTED:
            ble_connected = true;
            printf("dev_status_changed(): Connected.\n");
            break;

        case DISCONNECTED:
            ble_connected = false;
            printf("dev_status_changed(): Disconnected.\n");
            break;

        case AUTHENTICATED:
            printf("dev_status_changed(): Authenticated.\n");
            break;

        case TX_DONE:
            printf("dev_status_changed(): Tx-done.\n");
            break;

        default:
            break;
    }
}

/* @brief Data handler for control command 0x00. */
static void set_dev_status_handler(uint8_t *buffer, uint32_t length)
{
    printf("%s command (len: %d) received.\r\n", __func__, length);
}

/* @brief Data handler for query command 0x02. */
static void get_dev_status_handler(uint8_t *buffer, uint32_t length)
{
    /* echo the receiving data */
    uint8_t cmd = 0x03;
    breeze_post_ext(cmd, buffer, length);
}

static void apinfo_handler(breeze_apinfo_t *ap)
{
    printf("Hello %s:SSID:%s,PWD:%s\r\n", __func__,ap->ssid,ap->pw);
}

int application_start(void)
{
    static uint8_t bt_mac[6] = {0};//等待自动获取

    breeze_dev_info_t dev_info = {
        .product_id = PRODUCT_ID,
        .product_key = PRODUCT_KEY,
        .product_secret = PRODUCT_SECRET,
        .device_name = DEVICE_NAME,
        .device_secret = DEVICE_SECRET,
        .dev_adv_mac = bt_mac
    };

    //在内部调用了breeze_start
    breeze_awss_init(&dev_info,dev_status_changed_handler,\
                    set_dev_status_handler,get_dev_status_handler,\
                    apinfo_handler,NULL);
    //awss_start是个空函数,没有调用

    //开启ble广播
    breeze_start_advertising(0,1);
    return 0;
}

void app_main(void)
{
    application_start();
}

Breeze作为component

为了符合idf工程要求,我将breeze放置于components目录内,并为其编写了CMakeLists.txt用来测试,工程结构与CMakeLists如下:

工程结构

#breeze component 的CMakeLists.txt
idf_component_register( SRCS  
                        "./api/breeze_awss_export.c"
                        "./api/breeze_export.c"
                        "./core/auth.c"
                        "./core/ble_service.c"
                        "./core/core.c"
                        "./core/extcmd.c"
                        "./core/sha256.c"
                        "./core/transport.c"
                        "./core/utils.c"
                        "./hal/ble/breeze_hal_ble.c"
                        "./hal/ble/breeze_hal_os.c"
                        "./hal/ble/breeze_hal_sec.c"

                        INCLUDE_DIRS "./api" "./hal/include" "./include"
                        REQUIRES mbedtls nvs_flash freertos bt)
#宏定义以开启认证配网等功能
add_compile_definitions(EN_AUTH)
add_compile_definitions(EN_AUTH_OFFLINE)
add_compile_definitions(EN_COMBO_NET)
add_compile_definitions(EN_LONG_MTU)
add_compile_definitions(BLE_4_2)

target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-but-set-variable -Wno-unused-variable -Wno-pointer-sign)

物联平台注册情况

注册节点类型为:设备

是否接入网关:否

联网方式:WiFi

配网方式选择蓝牙辅助配网,使用公版App

测试表现情况

nFR connect

使用nRF connect查看广播内容,按照文档中BLE 协议来看正常,raw data如下: adv_raw_data 连接查看service以及characteristic如下,都符合AIS以及breeze要求: 图片 使用nRF以及其他ble助手将不会断连,直到breeze内部AUTH的30s定时回调触发。

云智能App

可以搜到设备并正确显示名称、mac,点击右边加号进行配网,在输入WiFi密码之后等待到12%左右会失败。

图片

在输入密码开始配网之后,设备将会被连接,紧接着App发起enable indicate 和 enable notify。 图片

失败后连接将会断开,ESP32-C3端显示断开原因为:“terminated by peer”。而后得到错误码101616+61601,错误码字典显示原因为蓝牙连接失败,比较笼统。

设备端LOG

设备端由于调试时间很长,开启的log很多。。。比如attr table等都打印出来了。

下面是注册的Attr table:

D (822) HAL_BLE: 0 service_declaration
UUID:0x2800
Length:2
value:
0xb3 0xfe

D (822) HAL_BLE: 1 RC_chara_declaration
UUID:0x2803
Length:5
value:
0x2 0x2a 0x0 0xd4 0xfe

D (832) HAL_BLE: 2 RC_value
UUID:0xfed4
Length:247
value:
省略value内容,为247字节空白。

D (922) HAL_BLE: 3 WC_chara_declaration
UUID:0x2803
Length:5
value:
0xa 0x2c 0x0 0xd5 0xfe

D (932) HAL_BLE: 4 WC_value
UUID:0xfed5
Length:247
value:
省略value内容,为247字节空白。

D (1022) HAL_BLE: 5 IC_chara_declaration
UUID:0x2803
Length:5
value:
0x22 0x2e 0x0 0xd6 0xfe

D (1022) HAL_BLE: 6 IC_value
UUID:0xfed6
Length:247
value:
省略value内容,为247字节空白。

D (1112) HAL_BLE: 7 IC_ccc
UUID:0x2902
Length:2
value:
0x0 0x0

D (1122) HAL_BLE: 8 WWNRC_chara_declaration
UUID:0x2803
Length:5
value:
0x6 0x31 0x0 0xd7 0xfe

D (1132) HAL_BLE: 9 WWNRC_value
UUID:0xfed7
Length:247
value:
省略value内容,为247字节空白。

D (1222) HAL_BLE: 10 NC_chara_declaration
UUID:0x2803
Length:5
value:
0x12 0x33 0x0 0xd8 0xfe

D (1232) HAL_BLE: 11 NC_value
UUID:0xfed8
Length:247
value:
省略value内容,为247字节空白。

D (1322) HAL_BLE: 12 NC_ccc
UUID:0x2902
Length:2
value:
0x0 0x0

下面是初始化过程末期的部分LOG:

D (1662) breeze: Breeze adv per device
D (1672) breeze: Breeze unbind
D (1672) breeze: need awss
I (1672) BREEZE_HAL_BLE: Local addr got (84:f7:03:0b:d3:c6).

I (1682) BREEZE_HAL_BLE: Starting advertising ADV.
I (1692) BREEZE_HAL_BLE: advertising start successfully
I (1692) BREEZE_HAL_BLE: Starting advertising SCAN_RSP.
I (1702) BREEZE_HAL_BLE: advertising start successfully
//初始化完毕,不断广播,至此开始等待连接

使用云智能App连接配网的后续LOG:

//App开始连接。
D (727152) HAL_BLE_APP_EVENT: event:14      //esp蓝牙连接事件
I (727152) BREEZE_HAL_BLE: ESP_GATTS_CONNECT_EVT, conn_id = 0
I (727152) BREEZE_HAL_BLE: 49 47 90 d6 12 31 

D (727162) AIS_CORE_HANDLER: EVENT_CODE:0   //breeze的连接事件,从回调传递过来的
D (727162) COMBO_CHANGE: EVENT:0
dev_status_changed(): Connected.

I (727522) BREEZE_HAL_BLE: update connection params status = 0, min_int = 16, max_int = 32,conn_int = 6,latency = 0, timeout = 500              //第一次param update

D (727712) HAL_BLE_APP_EVENT: event:4
I (727712) BREEZE_HAL_BLE: ESP_GATTS_MTU_EVT, MTU 255   //MTU更新

D (727742) HAL_BLE_APP_EVENT: event:2       //esp write事件,写入IC_CCC,开启indicate
I (727742) BREEZE_HAL_BLE: GATT_WRITE_EVT, handle = 47, value len = 2, value :
I (727742) BREEZE_HAL_BLE: 02 00 
D (727742) HAL_BLE_CCC_WRITE: IC:CCC_VALUE:2,PRESENT_VALUE:2

I (727782) BREEZE_HAL_BLE: update connection params status = 0, min_int = 0, max_int = 0,conn_int = 24,latency = 0, timeout = 400               //第二次param update

D (727792) HAL_BLE_APP_EVENT: event:2       //esp write事件,写入IC_CCC,开启indicate,第二次???
I (727792) BREEZE_HAL_BLE: GATT_WRITE_EVT, handle = 47, value len = 2, value :
I (727802) BREEZE_HAL_BLE: 02 00 
D (727802) HAL_BLE_CCC_WRITE: IC:CCC_VALUE:2,PRESENT_VALUE:2

D (727842) HAL_BLE_APP_EVENT: event:2       //esp write事件,写入NC_CCC,开启notify
I (727842) BREEZE_HAL_BLE: GATT_WRITE_EVT, handle = 52, value len = 2, value :
I (727842) BREEZE_HAL_BLE: 01 00 
D (727852) HAL_BLE_CCC_WRITE: NC:CCC_VALUE:1,PRESENT_VALUE:1

//breeze 内部回调处理
D (727852) breeze: Let's notify that service is enabled
D (727862) breeze: Breeze mtu:255, mpu:244
D (727862) breeze: [BZ auth]: start
//App 开始配网

//大约12%,手机端显示失败,断开连接
D (738792) HAL_BLE_APP_EVENT: event:15
I (738792) BREEZE_HAL_BLE: ESP_GATTS_DISCONNECT_EVT, reason = 0x13  //原因为手机端终止连接
D (738792) AIS_CORE_HANDLER: EVENT_CODE:1
D (738802) COMBO_CHANGE: EVENT:1
dev_status_changed(): Disconnected.

使用nRF connect连接的后续LOG:

如果使用nRF连接,则只会有:

I (17812) BREEZE_HAL_BLE: update connection params status = 0, min_int = 16, max_int = 32,conn_int = 6,latency = 0, timeout = 500
I (18062) BREEZE_HAL_BLE: update connection params status = 0, min_int = 0, max_int = 0,conn_int = 32,latency = 0, timeout = 400

两次更新,indicate 和 notify 可以通过手动开启。

如果使用某ble调试助手,也将会连接正常,将会自动开启indicate和notify。

一些疑问

在这个App断连问题上卡了挺长时间,各种LOG以及数据包都看不出原因,十分困惑。

感谢各位,希望能得到您的帮助和指导! @whwxxstsyd @luxuguang-leo @librae8226 @YiluMao @ElliottSeer

skylarCai commented 2 years ago
感谢您提出的宝贵问题,我们有7x24小时服务的“HaaS百事通”客服系统,
您可以先尝试能否解决您的问题(https://haas.iot.aliyun.com/?ask=1&f=a2cre.b82925042)

如果“HaaS百事通”没有解决您的问题,请回复“人工支持”,我们会在工作日(10:00-12:00/14:00-18:00)10分钟内回复您。
HuXioAn commented 2 years ago

人工支持

HuXioAn commented 2 years ago

@skylarCai