利用mesh ble_mesh_provisioner和 onoff_server建立网络传输温湿度以及pm2.5等数据

ble_mesh_provisioner和 onoff_server建立网络

其实仔细看来,利用mesh单单传输这些数据着实有点大材小用了,不过我也是小白处于学习阶段,就是拿这个练习一下,大佬就别看了。
话不多说,咱们直接上代码(有出错的地方希望大家多多谅解)

ble_mesh_provisioner例程

provisioner其实在demo里面是一个代理,发送数据要有client端才可以,这个例程里,我是把provisioner即作为代理组网,又作为client发送数据。

这三个回调函数很重要(mesh的核心)
esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);//建立mesh网络
esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);//配置client
esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb);//接收来自client的事件
static void example_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_t event,esp_ble_mesh_generic_client_cb_param_t *param)
{esp_ble_mesh_client_common_param_t common = {0};esp_ble_mesh_node_info_t *node = NULL;uint32_t opcode;uint16_t addr;int err;opcode = param->params->opcode;//接收来自client的opcodeaddr = param->params->ctx.addr;ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",__func__, param->error_code, event, param->params->ctx.addr, opcode);if (param->error_code) {ESP_LOGE(TAG, "Send generic client message failed, opcode 0x%04x", opcode);return;}node = example_ble_mesh_get_node_info(addr);if (!node) {ESP_LOGE(TAG, "%s: Get node info failed", __func__);return;}if(num1==0){num1=1;vTaskDelay(8000 / portTICK_PERIOD_MS);}//开机时延时8s等待设备链接if(read_ok_flag==0){vTaskDelay(100/portTICK_RATE_MS);   //延时100msif(sht30_get_value()==ESP_OK)   //获取温湿度{//算法参考sht30 datasheetg_temp    =( ( (  (sht30_buf[0]*256) +sht30_buf[1]) *175   )/65535.0  -45  );//获取温度g_rh  =  ( ( (sht30_buf[3]*256) + (sht30_buf[4]) )*100/65535.0) ;//获取湿度}            vTaskDelay(100/portTICK_RATE_MS);xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL);//创建串口接收任务,接收pm2.5数据pvdf_buf[1]=g_temp;//将采集到的数据放在数组里pvdf_buf[2]=g_rh;//将采集到的数据放在数组里pvdf_buf[3]=pm;//将采集到的数据放在数组里read_ok_flag=1;//设置读取成功标志位}if(read_ok_flag==1){event=ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT;//注意这个位置,这里本应是从client接收的事件,接收成功后,通过代理端向server发送数据,这里我人为始终使event=ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT;发送条件始终成立opcode=ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET;vTaskDelay(200/ portTICK_PERIOD_MS);}else{event=ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT;}switch (event) {case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:switch (opcode) {case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {//进入发送事件中esp_ble_mesh_generic_client_set_state_t set_state = {0};node->onoff = param->status_cb.onoff_status.present_onoff;ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);/* After Generic OnOff Status for Generic OnOff Get is received, Generic OnOff Set will be sent */example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);set_state.onoff_set.op_en = false;ESP_LOGI("SHT30", "temp:%4.2f C \r\n", g_temp); //℃打印出来是乱码,所以用CESP_LOGI("SHT30", "hum:%4.2f %%RH \r\n", g_rh);ESP_LOGI("PM2.5", "pm:%4.2f %%g/m3 \r\n", pm);switch (num){   case 0 : { set_state.onoff_set.onoff = pvdf_buf[num];num=num+1;break;}//这里循环发送数据case 1 :{ set_state.onoff_set.onoff =  pvdf_buf[num];num=num+1;break;}case 2 :{ set_state.onoff_set.onoff =  pvdf_buf[num];num=num+1;break;}case 3 :{ set_state.onoff_set.onoff =  pvdf_buf[num];num=0;read_ok_flag=0;break;}}set_state.onoff_set.tid = 0;err = esp_ble_mesh_generic_client_set_state(&common, &set_state);if (err) {ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);return;}break;}default:break;}break;case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:switch (opcode) {case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:node->onoff = param->status_cb.onoff_status.present_onoff;ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET onoff: 0x%02x", node->onoff);break;default:break;}break;case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:break;case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:/* If failed to receive the responses, these messages will be resend */switch (opcode) {case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {esp_ble_mesh_generic_client_get_state_t get_state = {0};example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);err = esp_ble_mesh_generic_client_get_state(&common, &get_state);if (err) {ESP_LOGE(TAG, "%s: Generic OnOff Get failed", __func__);return;}break;}case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: {esp_ble_mesh_generic_client_set_state_t set_state = {0};node->onoff = param->status_cb.onoff_status.present_onoff;ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);set_state.onoff_set.op_en = false;set_state.onoff_set.onoff = 0x00;set_state.onoff_set.tid = 0;err = esp_ble_mesh_generic_client_set_state(&common, &set_state);if (err) {ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);return;}break;}default:break;}break;default:ESP_LOGE(TAG, "Not a generic client status message event");break;}
}

onoff_server例程

 mesh配置回调函数  esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);//注册配网回调函数esp_ble_mesh_register_config_server_callback(example_ble_mesh_config_server_cb);//注册服务配置回调函数esp_ble_mesh_register_generic_server_callback(example_ble_mesh_generic_server_cb);//注册通用服务函数,就是用于开关led
static void example_ble_mesh_generic_server_cb(esp_ble_mesh_generic_server_cb_event_t event,esp_ble_mesh_generic_server_cb_param_t *param)
{esp_ble_mesh_gen_onoff_srv_t *srv;event =ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT;//同上原理,使该事件始终为真,接收数据switch (event) {case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT://server状态改变事件if (param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET ||param->ctx.recv_op == ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK) {ESP_LOGI(TAG, "onoff 0x%02x", param->value.state_change.onoff_set.onoff);//接收数据oled_show_str(0,0,  "Made by Qinxueyi", &Font_7x10, 1);//oled显示驱动程序oled_show_str(0,15, "TEMP :", &Font_7x10, 1);//oled显示驱动程序oled_show_str(0,30, "HUM  :" , &Font_7x10, 1);//oled显示驱动程序oled_show_str(0,45, "PM2.5:" , &Font_7x10, 1);//oled显示驱动程序oled_show_str(70,15,"%c", &Font_7x10, 1);//oled显示驱动程序oled_show_str(70,30,"%rh", &Font_7x10, 1);//oled显示驱动程序oled_show_str(70,45,"ug/m3" , &Font_7x10, 1);//oled显示驱动程序rec_buf[start_flag]=param->value.state_change.onoff_set.onoff;if(  rec_buf[0]==0xff){    start_flag++;if(start_flag==4){  start_flag=0;oled_show_num(50,15, rec_buf[1], &Font_7x10, 1);//oled显示驱动程序oled_show_num(50,30, rec_buf[2], &Font_7x10, 1);//oled显示驱动程序oled_show_num(50,45, rec_buf[3], &Font_7x10, 1);}//oled显示驱动程序} else start_flag=0;//   ESP_LOGI("测试", "%4.2f C \r\n", g_temp); //℃打印出来是乱码,所以用C}break;default:ESP_LOGE(TAG, "Unknown Generic Server event 0x%02x", event);break;}
}

还有一个超级重要的要点,就是mesh 里面onoff模型的验证

这个验证非常的耗费时,每发送一个字节都要耗费四五秒在验证上,在esp_idf>components>bt>esp_ble_mesh>mesh_models里面,按照下面代码更改,即可解除延时

static void gen_onoff_set(struct bt_mesh_model *model,struct bt_mesh_msg_ctx *ctx,struct net_buf_simple *buf)//状态设置命令
{struct bt_mesh_gen_onoff_srv *srv = model->user_data;u8_t tid, onoff, trans_time, delay;bool optional;s64_t now;if (srv == NULL) {BT_ERR("%s, Invalid model user_data", __func__);return;}onoff = net_buf_simple_pull_u8(buf);if (onoff > BLE_MESH_STATE_ON) {//BT_ERR("%s, Invalid OnOff value 0x%02x", __func__, onoff);//return;}tid = net_buf_simple_pull_u8(buf);if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {return;}/* Callback the received message to the application layer *//* if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {bt_mesh_gen_server_recv_set_msg_t set = {.onoff_set.op_en = optional,.onoff_set.onoff = onoff,.onoff_set.tid = tid,.onoff_set.trans_time = trans_time,.onoff_set.delay = delay,};bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));return;}*/if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {send_gen_onoff_status(model, ctx, false);}BT_ERR("%s, Invalid OnOff value 0x%02x", __func__, 0xf6);send_gen_onoff_status(model, NULL, true);/* In this condition, no event will be callback to application layer */return;}bt_mesh_generic_server_lock();bt_mesh_server_stop_transition(&srv->transition);//bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);//这一句超级重要,一定要删掉不然,传输超级慢srv->state.target_onoff = onoff;if (srv->state.target_onoff != srv->state.onoff) {generic_onoff_tt_values(srv, trans_time, delay);} else {bt_mesh_gen_server_state_change_t change = {.gen_onoff_set.onoff = srv->state.onoff,};bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {send_gen_onoff_status(model, ctx, false);}send_gen_onoff_status(model, NULL, true);bt_mesh_generic_server_unlock();return;}/* Copy the ctx of the received message */if (srv->transition.timer.work._reserved) {memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));}/* For Instantaneous Transition */if (srv->transition.counter == 0U) {srv->state.onoff = srv->state.target_onoff;}srv->transition.just_started = true;if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {send_gen_onoff_status(model, ctx, false);}send_gen_onoff_status(model, NULL, true);bt_mesh_generic_server_unlock();bt_mesh_server_start_transition(&srv->transition);return;
}

关于外设的驱动就不讲了,难度较低

最后贴出一个实物图

本人小白,不喜无喷,欢迎大家一起讨论,谢谢

利用mesh ble_mesh_provisioner和 onoff_server建立网络传输温湿度以及pm2.5等数据相关推荐

  1. iOS 网络传输数据安全以及常用的加密算法使用

    我们常说的数据安全:主要分为两种,数据本身的安全和数据防护安全. 数据本身的安全包括数据保密,数据完整性验证,数据双向认证等. 数据防护安全包括磁盘阵列,数据备份,异地容灾等. App安全问题主要包括 ...

  2. 论文阅读:基于区块链的一个车联网轻量级安全V2V通信特点:利用无线网络传输在V2V通信中的信道特性,生成特殊的LF(链路指纹)用于标识每个信道,区块链技术用于生成区块

    论文阅读:基于区块链的一个车联网轻量级安全V2V通信特点:利用无线网络传输在V2V通信中的信道特性,生成特殊的LF(链路指纹)用于标识每个信道,区块链技术用于生成区块. 系统模型: 汽车使用MICAz ...

  3. Android建立网络连接,利用JSON数据获取百度图片搜索结果及GSON的简单使用

    1.建立网络连接的基本方式 Android中建立网络连接最主要的方式是利用HttpURLConnection,示例如下: public class HttpUtil {public static by ...

  4. 如何构建全球实时音视频云及其海外网络传输优化

    点击上方"LiveVideoStack"关注我们 全球不同国家和地区的网络基建水平参差不齐,如何利用有限的网络资源提供更高质量的音视频通话体验是音视频服务商必须面对的挑战.在此次L ...

  5. python opencv 图像网络传输

    本代码主要实现的是利用网络传输图片,用在我的树莓派项目之上.该项目在PC上运行服务端,树莓派上运行客户端,两者连接到同一局域网中,修改代码中的IP地址,就可以实现将树莓派采集到的图像数据实时传输到PC ...

  6. Java DICOM 网络传输_DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store

    背景: 上一篇博文对DICOM中的网络传输进行了介绍,主要参照DCMTK Wiki中的英文原文.通过对比DCMTK与fo-dicom两个开源库对DICOM标准的具体实现,对理解DICOM标准有一个更直 ...

  7. Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platfrom))

    catalog 0.引言 1.Windows 2000网络结构和OSI模型 2.NDIS驱动 3.NDIS微端口驱动编程实例 4.NDIS中间层驱动编程实例 5.TDI驱动 6.TDI驱动 7.TDI ...

  8. Linux基础命令介绍七:网络传输与安全

    本篇接着介绍网络相关命令 1.wget 文件下载工具 wget [option]... [URL]... wget是一个非交互的下载器,支持HTTP, HTTPS和FTP协议,也可以使用代理.所谓'非 ...

  9. 网络传输层之TCP、UDP详解

    1.传输层存在的必要性 由于网络层的分组传输是不可靠的,无法了解数据到达终点的时间,无法了解数据未达终点的状态.因此有必要增强网络层提供服务的服务质量. 2.引入传输层的原因 面向连接的传输服务与面向 ...

最新文章

  1. 网络协议分层_接口测试之网络分层和数据
  2. 学 Win32 汇编[17]: 关于压栈(PUSH)与出栈(POP) 之一
  3. java对象的强引用,软引用,弱引用和虚引用
  4. 10分钟,快速使用VUE-VUEX
  5. leetcode47. 全排列 II(回溯)
  6. CentOS 7 搭建swagger Api文档管理系统
  7. Visual Studio调试技巧
  8. python接口测试第二期_Python接口测试实战2 - 使用Python发送请求
  9. 【TCP/IP】单播与组播
  10. JVM学习笔记(一)JDKJREJVM
  11. 微博爬虫 ----- 微博发布时间清洗
  12. VS2011可以下载了,VC++部分强大了很多
  13. 如何在windows上搭建DZ(Discuz!)论坛?
  14. 对训练集和测试集的PCA方法
  15. 为什么IT白领生命如此短暂--猝死!!! 让所谓的PMP和IT项目管理见鬼吧。
  16. 美化微信小程序的界面--微信小程序开发中使用vant的完整步骤
  17. 记录:前端js实现页面内简繁体切换
  18. 华为鸿蒙源自那句话,华为鸿蒙系统名字源自山海经它的很多自主专利都源于这本古籍,为什么?...
  19. ADS(Authenticated data structure)
  20. STM32的中断优先级说明(抢占式与响应式优先级)

热门文章

  1. 列举一个利用MATLAB进行仿真的案例,MATHCAD 和MATLAB建模与仿真-中国大学mooc-题库零氪...
  2. 教培机构如何实现长期主义知识变现?
  3. 计算机专业有纹身,“韩商言”身上也有纹身?得知背后的原因,无数粉丝暴风哭泣!...
  4. 【英宝通Unity4.0公开课学习 】(三)脚本使用
  5. 企业不可忽视的数据存储和数据安全问题!
  6. 帮91岁老兵圆64年终极愿望,看百度大脑的绝对实力和技术温情“DNA”
  7. 5g加鸿蒙概念股票,华为鸿蒙系统概念龙头股,无人驾驶最强龙头股
  8. “假若你一直和时间赛跑,你就可以成功”
  9. [系统安全] 二十八.WannaCry勒索病毒分析 (4)全网“最“详细的蠕虫传播机制解读
  10. 编写多格式音乐播放器(扫盲)