蓝牙Mesh开发六 ESP32蓝牙Mesh Wifi共存(浅析)

背景

上一章节用到了低功耗的Ble蓝牙来开发mesh低功耗的应用,但是需要接入网络还需要一个网关。ESP32已经支持了蓝牙Mesh和WIFI协议栈,但是其硬件基础上仅单天线,并且受限其有限的资源;而令人叫喜的是,IDF4.2版本已经很好的支持共存,虽然目前仅只有Wi-Fi STA模式下支持共存,但是通过增加PSRAM可有效提高了BLE WIFI共存模式的数据吞吐率(1Mbps),作为BLE MESH的网关就在好不过
如有异议,欢迎留言指正

功能设计

网关发现未配网设备广播后,网关使能配网器功能将其配置到mesh网络中,并建立友谊连接,通过mqtt协议与云端进行交互
蓝牙Mesh开发六 ESP32蓝牙Mesh Wifi共存(浅析)_第1张图片

工程实例

共存的工程实例可以参考esp-idf\examples\bluetooth\esp_ble_mesh\ble_mesh_wifi_coexist

配置器配置
使能PSRAM

需要通过idf.py menuconfig配置器配置PSRAM(主要是提高吞吐率),可以参考上一篇博文
允许LWIP的内存在PSRAM中分配(给应用释放资源)
在这里插入图片描述

使能WIFI蓝牙共存

在这里插入图片描述

BLE扫描全窗

在这里插入图片描述

BLE使用动态内存

在这里插入图片描述

使能友谊功能

可以配置友谊功能节点的接收窗口、队列、支持的节点等相关参数
蓝牙Mesh开发六 ESP32蓝牙Mesh Wifi共存(浅析)_第2张图片

初始化BLE Mesh
配网功能

移植配网器的例程 examples\bluetooth\esp_ble_mesh\ble_mesh_provisioner,针对匹配的UUID未配网设备进行配网
这里也可以直接使用普通节点功能代码,后续通过代理来进行配网

uint8_t match[2] = {0xdd, 0xdd}; //uuid
.... //省略
err = esp_ble_mesh_provisioner_set_dev_uuid_match(match, sizeof(match), 0x0, false);//匹配uuid
if (err != ESP_OK) {
	ESP_LOGE(TAG, "Failed to set matching device uuid (err %d)", err);
	return err;
}
配置元素与模型

参考vendor_model例程,添加服务模型;(也可以使用客户端模型例程 )

static esp_ble_mesh_model_t root_models[] = {//根模型即配置模型
    ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
};
static esp_ble_mesh_model_op_t vnd_op[] = { //opcode 命令码
    ESP_BLE_MESH_MODEL_OP(ESP_BLE_MESH_VND_MODEL_OP_SEND, 2),
    ESP_BLE_MESH_MODEL_OP_END,
};
static esp_ble_mesh_model_t vnd_models[] = {//厂家模型(02E5 0001)
    ESP_BLE_MESH_VENDOR_MODEL(CID_ESP, ESP_BLE_MESH_VND_MODEL_ID_SERVER,
    vnd_op, NULL, NULL),
};
static esp_ble_mesh_elem_t elements[] = { //元素【根模型 + 厂家模型】
    ESP_BLE_MESH_ELEMENT(0, root_models, vnd_models),//仅一个主元素
};
static esp_ble_mesh_comp_t composition = { //填充数据
    .cid = CID_ESP,
    .elements = elements,
    .element_count = ARRAY_SIZE(elements),
};

乐鑫从SIG申请的厂家ID为0x02E5

#define CID_ESP             0x02E5
mesh通信数据

接收消息回调,需要在mesh初始化时注册回调

static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event,
                                             esp_ble_mesh_model_cb_param_t *param)
{
    switch (event) {
    case ESP_BLE_MESH_MODEL_OPERATION_EVT: //收到节点消息事件
        if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_SEND) {//匹配命令码
            //uint16_t tid = *(uint16_t *)param->model_operation.msg;         
			
           nodeBuf[param->model_operation.length] = '\0';           
			memcpy(nodeBuf, param->model_operation.msg, param->model_operation.length);//备份数据
           ESP_LOGI(TAG, "recv = %s \n",nodeBuf);//打印消息
/*			
            esp_err_t err = esp_ble_mesh_server_model_send_msg(&vnd_models[0],
                    param->model_operation.ctx, ESP_BLE_MESH_VND_MODEL_OP_STATUS,
                    sizeof(tid), (uint8_t *)&tid);//返回消息
            if (err) {
                ESP_LOGE(TAG, "Failed to send message 0x%06x", ESP_BLE_MESH_VND_MODEL_OP_STATUS);
            }
*/
        }
        break;
    case ESP_BLE_MESH_MODEL_SEND_COMP_EVT://发送完成事件
        if (param->model_send_comp.err_code) {
            ESP_LOGE(TAG, "Failed to send message 0x%06x", param->model_send_comp.opcode);
            break;
        }
        ESP_LOGI(TAG, "Send 0x%06x", param->model_send_comp.opcode);
        break;
    default:
        break;
    }
}
wifi配置

使用共存例程里面的wifi station配置

void config_wifi_station(void)
{
    wifi_config_t wifi_config =
    {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,//
            .password = EXAMPLE_ESP_WIFI_PASS,//
            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_ps(WIFI_PS_MIN_MODEM) ); //必须配置 must call this;
    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
    ESP_ERROR_CHECK( esp_wifi_start() );
    ESP_ERROR_CHECK( esp_wifi_connect() );
}
云端上传

移植的mqtt的例程

msg_id = esp_mqtt_client_publish(client, "/gwedYwAc0FA/meshDevice001/user/temp_value", nodeBuf, 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
总结
  1. 测试中两个低功耗节点每定时发送一次环境温度的消息到网关,再由网关在上报到某里云上,测试数据量不大,未有数据丢失的情况
    蓝牙Mesh开发六 ESP32蓝牙Mesh Wifi共存(浅析)_第3张图片

  2. ESP32使用代理配网时,如果此时在进行wifi数据通信,配网时间相对时间会变长

你可能感兴趣的:(蓝牙Mesh,esp32蓝牙wifi共存,蓝牙meshwifi共存,esp32,ble,mesh)