最近项目使用了国民技术的N32WB03X芯片,做了一个温度计。代码是基于国民技术的heart rate例程进行改写的,官方SDK给出了底层代码,这里直接贴上服务端应用层的代码。
头文件:app_htps.h代码
#ifndef APP_HTPS_H_
#define APP_HTPS_H_
/* Includes ------------------------------------------------------------------*/
#include "rwip_config.h" // SW Configuration
#if (BLE_APP_HTPT)
#include <stdint.h>
#include <htp_common.h>
/* Define ------------------------------------------------------------*/
#define APP_HTPT_FEATURES (0x04) //
#define HEALTH_THERMOMETER_SEND_DELAY 1000
enum htpt_cfg
{
HTPT_CFG_NTF_EN = 1, // 启用温度测量通知(Notification)的配置标志
};
//// 温度单位定义
//typedef enum {
// TEMP_UNIT_CELSIUS = 0, // 摄氏度
// TEMP_UNIT_FAHRENHEIT = 1 // 华氏度
//} temp_unit_t;
/// health thermometer Application Module Environment Structure
#define MAX_SENSOR_NUM 8 // 最大支持8个传感器,按需调整
struct app_htpt_env_tag {
uint8_t conidx;
float htpt_values[MAX_SENSOR_NUM]; // 存储多个传感器的温度
uint8_t sensor_count; // 当前检测到的传感器数量
};
/// Health Thermometer Application environment
extern struct app_htpt_env_tag app_htpt_env;
//定时器 ID heart_rate_timer_id。用于周期性发送心率数据的定时器。
extern uint16_t health_thermometer_timer_id;
/* Public variables ---------------------------------------------------------*/
/// 消息处理列表,注册心率服务相关的消息处理函数,
///用于响应 BLE 协议栈的事件(如连接、断连、写入请求等)。
extern const struct app_subtask_handlers app_htpt_handlers;
/* Public function prototypes -----------------------------------------------*/
/**
* @brief Initialize health thermometer Service Application
**/
void app_htpt_init(void);
void app_htpt_send(float temp, uint8_t sensor_idx);
/**
* @brief Add a health thermometer Service in the DB
**/
void app_htpt_add_htpt(void);
/**
* @brief Enable the health thermometer profile
**/
void app_htpt_enable_prf(uint8_t conidx, uint8_t cfg);
/**
* @brief Send health thermometer value
*/
//void app_htpt_send(float temp);
/**
* @brief Send health thermometer value periodically
*/
void app_htpt_timeout_handler(void);
#endif //BLE_APP_HTPS
/// @} APP
#endif //APP_HTPS_H_
说明:
- APP_HTPT_FEATURES:需要根据自身需求来决定,参考蓝牙联盟相关定义。
- MAX_SENSOR_NUM:本人使用多个温度传感器,兼容单一和多个传感器使用情况。
源代码:app_htps.c
#include "rwip_config.h" // SW configuration
#if (BLE_APP_HTPT)
/* Includes ------------------------------------------------------------------*/
#include "ns_ble.h" // Application Manager Definitions
#include "app_htps.h" // Device Information Service Application Definitions
#include "htpt_task.h" // Device Information Profile Functions
#include "prf_types.h" // Profile Common Types Definitions
#include "ke_task.h" // Kernel
#include "gapm_task.h" // GAP Manager Task API
#include "ns_ble_task.h"
#include <string.h>
#include "co_utils.h"
#include "htpt.h"
#include "stdio.h"
#include "ns_delay.h"
#include "ns_timer.h"
#include "T117_MTS4_OW.h"
#include "owmy.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/// health thermometer Application environment
/// 温度计应用环境变量
struct app_htpt_env_tag app_htpt_env;
/// 温度发送定时器ID
uint16_t health_thermometer_timer_id;
/**
* @brief 初始化温度计应用环境
*/
void app_htpt_init(void)
{
app_htpt_env.sensor_count = OW_SearchROM(ID_Buff);
// 注册HTPT任务到应用任务
struct prf_task_t prf;
prf.prf_task_id = TASK_ID_HTPT;
prf.prf_task_handler = &app_htpt_handlers;
ns_ble_prf_task_register(&prf);
// 注册Profile接口获取函数
struct prf_get_func_t get_func;
get_func.task_id = TASK_ID_HTPT;
get_func.prf_itf_get_func = htpt_prf_itf_get;
prf_get_itf_func_register(&get_func);
}
/**
* @brief 添加HTPT服务到GATT数据库
*/
void app_htpt_add_htpt(void)
{
struct htpt_db_cfg* db_cfg;
// 创建GAPM消息
struct gapm_profile_task_add_cmd *req = KE_MSG_ALLOC_DYN(
GAPM_PROFILE_TASK_ADD_CMD,
TASK_GAPM,
TASK_APP,
gapm_profile_task_add_cmd,
sizeof(struct htpt_db_cfg)
);
// 配置服务参数
req->operation = GAPM_PROFILE_TASK_ADD;
req->sec_lvl = PERM(SVC_AUTH, NO_AUTH); // 安全级别
req->prf_task_id = TASK_ID_HTPT;
req->app_task = TASK_APP;
req->start_hdl = 0; // 动态分配句柄
// 配置数据库特性
db_cfg = (struct htpt_db_cfg *)req->param;
db_cfg->features = 0;
// db_cfg->temp_type = HTP_TYPE_BODY; // 默认测量位置:腋下
// db_cfg->meas_intv = 0; // 默认间隔5秒
// db_cfg->valid_range_min = 0; // 最小间隔1秒
// db_cfg->valid_range_max = 0; // 最大间隔60秒
// 发送消息
ke_msg_send(req);
// 初始化应用环境
app_htpt_init();
}
/**
* @brief 启用HTPT服务配置
* @param conidx 连接索引
* @param cfg 通知/指示配置
*/
void app_htpt_enable_prf(uint8_t conidx, uint8_t cfg)
{
app_htpt_env.conidx = conidx;
struct htpt_enable_req *req = KE_MSG_ALLOC(
HTPT_ENABLE_REQ,
prf_get_task_from_id(TASK_ID_HTPT),
TASK_APP,
htpt_enable_req
);
req->conidx = conidx;
req->ntf_ind_cfg = cfg;
ke_msg_send(req);
}
/**
* @brief 发送温度测量值
* @param temp 温度值(单位:0.01°C)
* @param stable 是否为稳定测量
*/
static uint8_t current_sensor_idx = 0;
// 改进后的发送函数
void app_htpt_send_next_sensor(void)
{
if (current_sensor_idx >= app_htpt_env.sensor_count)
{
current_sensor_idx = 0; // 重置索引,等待下个周期
return;
}
float temp = app_htpt_env.htpt_values[current_sensor_idx];
struct htpt_temp_send_req *req = KE_MSG_ALLOC(
HTPT_TEMP_SEND_REQ,
prf_get_task_from_id(TASK_ID_HTPT),
TASK_APP,
htpt_temp_send_req
);
int32_t mantissa = (int32_t)(temp * 100 + 0.5f);
int8_t exponent = -2;
req->temp_meas.temp = ((uint32_t)(mantissa & 0x00FFFFFF)) | (((uint8_t)exponent) << 24);
req->temp_meas.flags = HTP_FLAG_TYPE_BIT;
req->temp_meas.type = current_sensor_idx + 1;
req->stable_meas = TRUE;
ke_msg_send(req);
current_sensor_idx++;
// 设定定时器调用自身,500ms发送下一个传感器的数据
ns_timer_create(HEALTH_THERMOMETER_SEND_DELAY, app_htpt_send_next_sensor);
}
void app_htpt_temp_timeout_handler(void)
{
GetTemp();
for (uint8_t i = 0; i < app_htpt_env.sensor_count; i++)
{
app_htpt_env.htpt_values[i] = g_TempValue[i];
}
// 启动发送第一个传感器数据,其他的延迟依次发送
current_sensor_idx = 0; // 复位发送索引,开始新一轮发送
ns_timer_cancel(health_thermometer_timer_id);
app_htpt_send_next_sensor(); // 触发首次发送
health_thermometer_timer_id = ns_timer_create(HEALTH_THERMOMETER_SEND_DELAY * app_htpt_env.sensor_count, app_htpt_temp_timeout_handler);
}
/**
* @brief 处理配置变更事件
*/
static int htpt_cfg_indntf_ind_handler(ke_msg_id_t const msgid,
struct htpt_cfg_indntf_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
if((param->ntf_ind_cfg & HTPT_CFG_NTF_EN) != 0)
{
app_htpt_enable_prf(0, PRF_CLI_START_NTF);
health_thermometer_timer_id = ns_timer_create(HEALTH_THERMOMETER_SEND_DELAY,app_htpt_temp_timeout_handler);
}
else
{
app_htpt_enable_prf(0, PRF_CLI_STOP_NTFIND);
ns_timer_cancel(health_thermometer_timer_id);
}
return KE_MSG_CONSUMED;
}
/* Public variables ---------------------------------------------------------*/
/// 消息处理列表
const struct ke_msg_handler app_htpt_msg_handler_list[] = {
{HTPT_CFG_INDNTF_IND, (ke_msg_func_t)htpt_cfg_indntf_ind_handler},
};
/// 应用子任务处理器
const struct app_subtask_handlers app_htpt_handlers = APP_HANDLERS(app_htpt);
#endif //
/// @} APP
说明:
- #include "T117_MTS4_OW.h"和#include "owmy.h"是本人所使用的传感器相关代码。
- 在app_htpt_init函数种调用了app_htpt_env.sensor_count = OW_SearchROM(ID_Buff);为了获取传感器数量,请删除。
- app_htpt_send_next_sensor和app_htpt_temp_timeout_handler函数中改成自己的温度数据进行发送。
其他说明:
记得在app_ble.c中的app_ble_prf_init函数注册htps服务。