上一章节用到了低功耗的Ble蓝牙来开发mesh低功耗的应用,但是需要接入网络还需要一个网关。ESP32已经支持了蓝牙Mesh和WIFI协议栈,但是其硬件基础上仅单天线,并且受限其有限的资源;而令人叫喜的是,IDF4.2版本已经很好的支持共存,虽然目前仅只有Wi-Fi STA模式下支持共存,但是通过增加PSRAM可有效提高了BLE WIFI共存模式的数据吞吐率(1Mbps),作为BLE MESH的网关就在好不过
如有异议,欢迎留言指正
网关发现未配网设备广播后,网关使能配网器功能将其配置到mesh网络中,并建立友谊连接,通过mqtt协议与云端进行交互
共存的工程实例可以参考esp-idf\examples\bluetooth\esp_ble_mesh\ble_mesh_wifi_coexist
需要通过idf.py menuconfig配置器配置PSRAM(主要是提高吞吐率),可以参考上一篇博文
允许LWIP的内存在PSRAM中分配(给应用释放资源)
移植配网器的例程 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初始化时注册回调
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 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);