蓝牙Mesh系统开发四 ble mesh网关节点管理

前言

当配网器配置了多个节点设备后,需要对各个节点状态信息进行更新管理,如何将设备与其订阅地址、单播地址信息关联,对节点的功能定义进行分类

BLE Mesh组件配置

esp32 ble mesh组件源码位于esp-idf_old\components\bt\esp_ble_mesh,使用命令make menuconfig启动配置工具,进入ble mesh组件的配置页面,路径Component config-->ESP BLE Mesh Support-->

  • 使能配网器,可以配置最大支持的配网数,默认为10个
    在这里插入图片描述
  • 配置PB-ADV与PB-GATT同时支持的配网数量
    在这里插入图片描述
节点管理
节点状态信息

参考配网器工程,路径idf\examples\bluetooth\esp_ble_mesh\ble_mesh_provisioner下,定义了上层应用的节点信息,与协议栈中保存的节点信息一一对应

typedef struct {
    uint8_t  uuid[16];//uuid
    uint16_t unicast;//单播地址
    uint8_t  elem_num;//元素个数
    uint8_t  onoff;//开关状态
} esp_ble_mesh_node_info_t;
//默认十个节点信息缓存
static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
    [0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
        .unicast = ESP_BLE_MESH_ADDR_UNASSIGNED,
        .elem_num = 0,
        .onoff = LED_OFF,
    }
};
更新与保持节点信息
  • 当配网完成后,系统触发事件ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT,调用接口prov_complete更新与保持节点信息,同时给节点设置一个名称保存
static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
                               uint16_t unicast, uint8_t elem_num, uint16_t net_idx)
{
    esp_ble_mesh_client_common_param_t common = {0};
    esp_ble_mesh_cfg_client_get_state_t get_state = {0};
    esp_ble_mesh_node_info_t *node = NULL;
    char name[11] = {0};
    int err;
    ESP_LOGI(TAG, "node index: 0x%x, unicast address: 0x%02x, element num: %d, netkey index: 0x%02x",
             node_idx, unicast, elem_num, net_idx);
    ESP_LOGI(TAG, "device uuid: %s", bt_hex(uuid, 16));
    sprintf(name, "%s%d", "NODE-", node_idx); // NODE-x(0 1 2..)
    err = esp_ble_mesh_provisioner_set_node_name(node_idx, name); //设置一个名称;底层栈写入nvs
    if (err) {
        ESP_LOGE(TAG, "%s: Set node name failed", __func__);
        return ESP_FAIL;
    }
    err = example_ble_mesh_store_node_info(uuid, unicast, elem_num, LED_OFF);//同步保存到上层应用
    if (err) {
        ESP_LOGE(TAG, "%s: Store node info failed", __func__);
        return ESP_FAIL;
    }
    node = example_ble_mesh_get_node_info(unicast);//重新读取节点信息
    if (!node) {
        ESP_LOGE(TAG, "%s: Get node info failed", __func__);
        return ESP_FAIL;
    }
    example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
    get_state.comp_data_get.page = COMP_DATA_PAGE_0;
    err = esp_ble_mesh_config_client_get_state(&common, &get_state);//发起模型配置
    if (err) {
        ESP_LOGE(TAG, "%s: Send config comp data get failed", __func__);
        return ESP_FAIL;
    }
    return ESP_OK;
}
  • 单节点状态发生改变时,上层应用也会同步更新状态(对于节点状态有掉电保存要求的,可以写到flash中)
static esp_err_t example_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t unicast,
                                                  uint8_t elem_num, uint8_t onoff_state)
{
    int i;
    if (!uuid || !ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
        return ESP_ERR_INVALID_ARG;
    }
    /* Judge if the device has been provisioned before */
    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (!memcmp(nodes[i].uuid, uuid, 16)) { //匹配uuid
            ESP_LOGW(TAG, "%s: reprovisioned device 0x%04x", __func__, unicast);
            nodes[i].unicast = unicast;//更新地址
            nodes[i].elem_num = elem_num;//更新元素
            nodes[i].onoff = onoff_state;//更新开关状态
            return ESP_OK;
        }
    }
    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (nodes[i].unicast == ESP_BLE_MESH_ADDR_UNASSIGNED) {//新增节点
            memcpy(nodes[i].uuid, uuid, 16);
            nodes[i].unicast = unicast;
            nodes[i].elem_num = elem_num;
            nodes[i].onoff = onoff_state;
            return ESP_OK;
        }
    }
    return ESP_FAIL;
}
获取节点信息
  • 应用层中的nodes获取节点,通过匹配地址是否在节点元素中
static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)//通过地址获取
{
    int i;
    if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
        return NULL;
    }
    for (i = 0; i < ARRAY_SIZE(nodes); i++) {
        if (nodes[i].unicast <= unicast && /*匹配地址在节点元素中*/
                nodes[i].unicast + nodes[i].elem_num > unicast) {
            return &nodes[i];
        }
    }
    return NULL;
}
  • 通过协议栈的接口获取节点信息,可以通过节点uuid、节点命名、节点地址
esp_err_t err = ESP_OK;
esp_ble_mesh_node_t *node_info = NULL;

if(type == UUID_GET)//通过uuid获取
    node_info = esp_ble_mesh_provisioner_get_node_with_uuid(uuid);
else if(type == NAME_GET)//通过名称获取
    node_info = esp_ble_mesh_provisioner_get_node_with_name(name);
else if(type == UNICASE_GET)  //通过单播地址获取
    node_info = esp_ble_mesh_provisioner_get_node_with_addr(unicast);
if (node_info == NULL) 
{
    ESP_LOGE(TAG, "can't get node info");
    return;
} 
总结
  • 上层的节点信息与协议栈中的需要保持同步
  • 使用vendor模型,由于帧数据自定义,将节点的信息插入到数据帧中,考究设计上省略上层的数据存储,开发更多样;
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS蓝牙Mesh开发是指在iOS系统中使用蓝牙Mesh技术进行开发蓝牙Mesh是一种用于无线络通信的技术,它基于蓝牙低功耗(Bluetooth Low Energy,BLE)标准,并支持多对多的络连接。通过使用蓝牙Mesh,可以实现设备间的直接通信,而无需通过传统的中心设备来中转数据。 在iOS蓝牙Mesh开发中,开发者可以利用iOS系统提供的CoreBluetooth框架来实现蓝牙Mesh的功能。CoreBluetooth框架提供了一系列API,可以用于扫描、连接和通信等操作。开发者可以使用这些API与蓝牙Mesh设备进行通信,并实现各种功能,如设备发现、数据传输、络配置等。 在进行iOS蓝牙Mesh开发时,需要特别注意以下几点: 1. 版本要求:要使用蓝牙Mesh功能,需要iOS 11及以上的版本。 2. 硬件支持:要使用蓝牙Mesh功能,需要确保设备支持蓝牙4.0及以上版本。 3. 学习Mesh协议:蓝牙Mesh开发需要了解蓝牙Mesh协议的相关知识,如络拓扑结构、节点之间的通信方式等。 4. 设备兼容性:不同厂商的设备对蓝牙Mesh的支持程度可能有所不同,需要考虑设备的兼容性。 总体来说,iOS蓝牙Mesh开发可以用于构建无线传感器络、智能家居和物联等应用。开发者可以根据具体需求,利用iOS系统提供的CoreBluetooth框架实现各种功能,并通过蓝牙Mesh技术实现设备间的直接通信。这将为用户带来更好的体验和更广泛的应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值