You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP-IDF NimBLE:将接收的BLE数据转为整数/十六进制并存储

解决方案:修改BLE写入回调存储数据为整数/十六进制格式

首先明确:ctxt->om->om_data 是指向接收到的BLE字节数据的指针,ctxt->om->om_len 是数据长度。以下提供两种适配不同需求的实现方式:

方式1:存储为十六进制字节数组(保留原始数据)

适合需要保留BLE原始字节数据的场景,每个字节对应十六进制的两位。我们可以定义全局缓冲区存储数据(新手场景下先简化处理,多连接场景可后续加锁优化)。

修改后的核心代码

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include <stdio.h>
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sdkconfig.h"
#include "string.h"

char *TAG = "BLE-Server";
uint8_t ble_addr_type;
void ble_app_advertise(void);

// 定义全局缓冲区,适配BLE单包最大20字节的常规场景
#define MAX_RECV_BUF_LEN 20
uint8_t ble_recv_buf[MAX_RECV_BUF_LEN];
size_t ble_recv_len = 0; // 记录实际接收数据长度

// Write data to ESP32 defined as server
static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    // 校验数据长度,避免缓冲区溢出
    if (ctxt->om->om_len > MAX_RECV_BUF_LEN) {
        ESP_LOGE(TAG, "Data too long, max support %d bytes", MAX_RECV_BUF_LEN);
        return BLE_HS_EINVAL;
    }

    // 将BLE接收数据复制到全局缓冲区
    memcpy(ble_recv_buf, ctxt->om->om_data, ctxt->om->om_len);
    ble_recv_len = ctxt->om->om_len;

    // 以十六进制格式打印(替换原printf)
    ESP_LOGI(TAG, "Received BLE data (hex): ");
    for (size_t i = 0; i < ble_recv_len; i++) {
        printf("%02X ", ble_recv_buf[i]);
    }
    printf("\n");

    return 0;
}

// 其余代码保持不变...

方式2:解析为整数类型(如uint16_t/uint32_t)

如果客户端发送固定长度的整数数据(比如2字节表示16位整数),可直接解析为对应整数类型。注意BLE通信通常采用小端字节序,需做字节序转换适配主机端。

修改后的核心代码(以解析16位无符号整数为例)

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include <stdio.h>
#include "esp_log.h"
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sdkconfig.h"
#include "string.h"
#include "endian.h" // 用于字节序转换

char *TAG = "BLE-Server";
uint8_t ble_addr_type;
void ble_app_advertise(void);

// 全局变量存储解析后的16位整数
uint16_t ble_recv_uint16 = 0;

// Write data to ESP32 defined as server
static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    // 校验数据长度是否匹配16位整数要求
    if (ctxt->om->om_len != sizeof(uint16_t)) {
        ESP_LOGE(TAG, "Invalid length for uint16_t, expected %d bytes", sizeof(uint16_t));
        return BLE_HS_EINVAL;
    }

    // 小端字节序转主机字节序并存储
    ble_recv_uint16 = le16toh(*(uint16_t *)ctxt->om->om_data);

    // 打印解析结果(十进制/十六进制可选)
    ESP_LOGI(TAG, "Received BLE data (uint16): %u", ble_recv_uint16);
    // ESP_LOGI(TAG, "Received BLE data (hex uint16): 0x%04X", ble_recv_uint16);

    return 0;
}

// 其余代码保持不变...

关键注意事项

  • 直接强转ctxt->om->om_data时,必须确保数据长度和目标类型匹配,否则会引发内存越界问题。
  • 全局变量是新手场景下最便捷的存储方式,多连接场景可改用连接句柄关联的数组或哈希表存储。
  • 字节序转换:遵循BLE规范用le16toh/le32toh转换,即使主机本身是小端(如ESP32),保持规范写法也能提升代码兼容性。

内容的提问来源于stack exchange,提问作者o-ozdemir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:24:45