在智能家居系统中,BLE(蓝牙低功耗,Bluetooth Low Energy)因低功耗、短距离、易部署等特点,被广泛用于设备间通信(如传感器、智能开关、灯具、门锁等)。BLE 的通用协议可分为基础核心协议 (蓝牙 SIG 定义的底层规范)和行业通用应用协议(适配智能家居场景的高层规范),程序实现需基于 BLE 芯片和协议栈,结合具体场景设计服务与数据交互逻辑。
一、智能家居中 BLE 的通用协议
BLE 的通信基于蓝牙核心规范(Bluetooth Core Specification),其通用协议可分为底层核心协议 和高层应用协议,前者确保设备互联基础,后者定义智能家居场景的标准化数据交互。
1. 底层核心协议(蓝牙 SIG 标准)
所有 BLE 设备必须遵循的基础协议,确保设备发现、连接和数据传输的兼容性:
-
**GAP(Generic Access Profile,通用访问规范)**负责设备发现、连接管理、广播 / 扫描、安全配对等。在智能家居中,设备可通过两种方式交互:
- 广播模式:设备周期性广播数据(如温湿度传感器每秒广播一次数据,网关被动接收,无需建立连接,功耗极低)。
- 连接模式:设备建立点对点连接(如手机 APP 控制智能灯,需先连接再发送指令)。
-
**GATT(Generic Attribute Profile,通用属性规范)**是 BLE 数据传输的核心框架,定义了 "服务(Service)- 特性(Characteristic)" 的数据组织结构:
- 服务(Service):一组相关特性的集合(如 "灯光控制服务" 包含 "开关特性""亮度特性")。
- 特性(Characteristic):具体的数据单元,包含 "值(Value)" 和 "描述符(Descriptor)"(如 "开关特性" 的值为 0/1,代表关 / 开)。GATT 通过 "客户端 - 服务器" 模型通信:控制端(如手机、网关)作为客户端,读取 / 写入设备(服务器)的特性值。
-
ATT(Attribute Protocol,属性协议) GATT 的底层支撑协议,定义了特性的编码格式(16 位 / 32 位 / 128 位 UUID)和交互指令(读、写、通知等)。蓝牙 SIG 定义了大量标准 UUID(如 0x180A 为设备信息服务,0x2A05 为电池电量特性),方便不同厂商设备兼容。
2. 行业通用应用协议(智能家居场景)
基于底层协议,针对智能家居设备的功能(如控制、状态上报、组网)制定的标准化规范,确保跨厂商设备兼容:
-
BLE Mesh(蓝牙 Mesh 网络) 由蓝牙 SIG 定义的 Mesh 组网协议,解决传统 BLE 点对点通信的局限,支持多设备互联 (最多 32767 个节点)和多跳转发(数据通过中间设备中继),适合大规模智能家居场景(如全屋灯光、传感器组网)。
- 核心特点:支持广播转发(Relay)、低功耗节点(Sleepy Node)、分组控制(多设备同时接收指令)。
- 应用场景:全屋灯光同步控制、传感器网络数据汇总(如温湿度、门窗传感器)。
-
**HomeKit(苹果智能家居协议)**苹果定义的智能家居协议,支持 BLE 作为通信方式之一,需遵循严格的服务和特性规范(基于 GATT),并通过 MFi 认证。
- 核心规范:设备需实现 "HomeKit Accessory Protocol(HAP)",定义了标准化服务(如 "灯光服务" UUID:0x00000043-0000-1000-8000-0026BB765291),特性包含开关、亮度、色温等。
- 优势:无缝对接 iPhone、HomePod 等苹果设备,支持 Siri 语音控制。
-
**Google Weave(谷歌智能家居协议)**谷歌针对物联网设备的通用协议,支持 BLE、Wi-Fi 等多种传输方式,定义了标准化的设备模型和数据交互格式(基于 Protocol Buffers)。
- 核心特点:设备通过 "Trait" 定义功能(如 "OnOff" Trait 对应开关功能),数据格式统一,方便接入 Google Home 生态。
-
**自定义 GATT 服务(厂商通用方案)**中小厂商常基于 GATT 自定义服务和特性(使用 128 位 UUID),实现设备功能(如智能开关定义 "开关服务 UUID + 开关特性 UUID")。虽兼容性弱于标准协议,但开发灵活,适合专用场景(如自有品牌设备组网)。
二、BLE 智能家居设备的程序实现方法
以 "智能灯(BLE 控制,支持开关和亮度调节)" 为例,基于nRF52840(BLE 芯片) 和nRF5 SDK,详解程序实现步骤(通用流程适用于 ESP32 等其他 BLE 芯片)。
1. 硬件与开发环境
- 硬件:nRF52840 开发板(内置 BLE 射频,支持 GATT 和 BLE Mesh)、LED(模拟灯光)、电位器(模拟亮度调节)。
- 开发环境:nRF5 SDK 17.0(含 BLE 协议栈)、Segger Embedded Studio(IDE)、nRF Connect(手机 APP,用于调试)。
2. 核心实现步骤
(1)初始化 BLE 协议栈(GAP/GATT 配置)
初始化 BLE 射频、GAP(设备名称、广播参数)、GATT 服务器,定义设备的基本身份和通信规则。
#include "nrf.h"
#include "ble.h"
#include "ble_gap.h"
#include "ble_gatt.h"
// 设备名称(广播时可见)
#define DEVICE_NAME "SmartLight"
// BLE UUID(自定义服务和特性,128位UUID)
#define LIGHT_SERVICE_UUID 0x0001 // 简化表示,实际为128位:00000001-...
#define SWITCH_CHAR_UUID 0x0002 // 开关特性
#define BRIGHTNESS_CHAR_UUID 0x0003 // 亮度特性
// GAP初始化(设备身份与广播配置)
void gap_init() {
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // 无安全模式(可被任意设备发现)
// 设置设备名称
sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)DEVICE_NAME, strlen(DEVICE_NAME));
// 配置广播数据(包含设备名称和服务UUID)
ble_gap_adv_data_t adv_data = {
.len = 1 + 1 + strlen(DEVICE_NAME) + 2 + 1, // 长度=标志+名称+服务UUID
.p_data = (uint8_t[]){
0x02, 0x01, 0x06, // 标志:LE General Discoverable Mode
0x09, 0x09, // 完整设备名称类型
DEVICE_NAME, // 设备名称
0x03, 0x03, LIGHT_SERVICE_UUID // 服务UUID列表(简化)
}
};
sd_ble_gap_adv_data_set(&adv_data, NULL); // 设置广播数据
// 配置广播参数(间隔100ms,覆盖范围约10米)
ble_gap_adv_params_t adv_params = {
.type = BLE_GAP_ADV_TYPE_ADV_IND, // 可连接的广播
.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), // 广播间隔
.channel_mask = {0, 0, 0, 0, 0x07}, // 使用37、38、39频道
.adv_filter_policy = BLE_GAP_ADV_FP_ANY // 允许任何设备扫描和连接
};
sd_ble_gap_adv_start(&adv_params, BLE_CONN_CFG_TAG_DEFAULT); // 开始广播
}
// GATT服务器初始化(注册服务和特性)
void gatt_init() {
// 注册GATT事件回调(处理读写请求)
NRF_SDH_GATT_DEFAULT_CONFIG();
sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &LIGHT_SERVICE_UUID, &service_handle);
// 添加"开关特性"(可读写,支持通知)
ble_gatts_char_md_t switch_char_md = {
.char_props.read = 1, // 允许读
.char_props.write = 1, // 允许写
.char_props.notify = 1 // 允许通知(状态变化时主动上报)
};
ble_uuid_t switch_uuid = {.uuid = SWITCH_CHAR_UUID, .type = BLE_UUID_TYPE_VENDOR_BEGIN};
ble_gatts_attr_md_t switch_attr_md = {
.read_perm = BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode), // 读权限:公开
.write_perm = BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode) // 写权限:公开
};
ble_gatts_attr_t switch_attr = {
.p_uuid = &switch_uuid,
.p_attr_md = &switch_attr_md,
.init_len = 1, // 数据长度1字节(0=关,1=开)
.max_len = 1,
.p_value = (uint8_t[]){0} // 初始值:关
};
sd_ble_gatts_characteristic_add(service_handle, &switch_char_md, &switch_attr, &switch_char_handle);
// 类似添加"亮度特性"(0-255,1字节)
// ...(代码略,与开关特性类似,UUID为BRIGHTNESS_CHAR_UUID)
}
(2)实现 GATT 数据交互(处理读写与通知)
通过 GATT 事件回调,处理客户端(如手机 APP)的读写请求,并在设备状态变化时主动通知客户端(如灯光被物理开关改变时,通知 APP)。
// BLE事件处理回调
void ble_evt_handler(ble_evt_t const *p_evt, void *p_context) {
switch(p_evt->header.evt_id) {
case BLE_GATTS_EVT_WRITE: { // 客户端写入数据(如APP控制灯光)
ble_gatts_evt_write_t const *p_write = &p_evt->evt.gatts_evt.params.write;
if(p_write->handle == switch_char_handle.value_handle) { // 写入开关特性
uint8_t switch_state = p_write->data[0];
if(switch_state == 1) {
LED_ON(); // 开灯
} else {
LED_OFF(); // 关灯
}
// 通知客户端:状态已更新
ble_gatts_hvx_params_t hvx_params = {
.handle = switch_char_handle.value_handle,
.type = BLE_GATT_HVX_NOTIFICATION,
.p_data = &switch_state,
.len = 1
};
sd_ble_gatts_hvx(p_evt->evt.gap_evt.conn_handle, &hvx_params);
} else if(p_write->handle == brightness_char_handle.value_handle) { // 写入亮度
uint8_t brightness = p_write->data[0];
set_led_brightness(brightness); // 调节PWM亮度
}
break;
}
case BLE_GATTS_EVT_READ_REQUEST: { // 客户端读取数据(如APP获取当前状态)
ble_gatts_evt_read_t const *p_read = &p_evt->evt.gatts_evt.params.read;
if(p_read->handle == switch_char_handle.value_handle) {
uint8_t current_state = (LED_IS_ON()) ? 1 : 0;
sd_ble_gatts_value_set(p_read->handle, 0, ¤t_state, 1); // 返回当前状态
}
break;
}
// 其他事件:连接、断开等(略)
}
}
(3)BLE Mesh 组网实现(可选,多设备场景)
若需多设备协同(如全屋灯光同步),需基于 BLE Mesh 协议栈实现节点功能(以 nRF5 SDK 的 Mesh 库为例):
#include "nrf_mesh.h"
#include "nrf_mesh_config_core.h"
// Mesh节点初始化(作为灯光节点,支持开关模型)
void mesh_init() {
nrf_mesh_init_params_t init_params = NRF_MESH_INIT_PARAMS_DEFAULT();
nrf_mesh_init(&init_params); // 初始化Mesh协议栈
// 配置节点地址(16位,如0x0001)
nrf_mesh_address_t addr = {.type = NRF_MESH_ADDRESS_TYPE_UNICAST, .value = 0x0001};
nrf_mesh_address_add(&addr);
// 注册Generic OnOff模型(Mesh标准模型,用于开关控制)
generic_onoff_server_init_t onoff_init = {
.p_vendor_model_op = NULL,
.set_cb = onoff_set_cb, // 处理开关指令的回调
.get_cb = onoff_get_cb // 处理状态查询的回调
};
generic_onoff_server_init(&m_onoff_server, &onoff_init);
// 启动Mesh网络(加入已有的Mesh网络或创建新网络)
nrf_mesh_network_start();
}
// Mesh开关指令回调(接收其他节点或网关的指令)
static void onoff_set_cb(generic_onoff_server_t *p_server, const access_message_rx_t *p_msg,
const generic_onoff_set_params_t *p_params) {
if(p_params->on_off) {
LED_ON(); // 收到开灯指令
} else {
LED_OFF(); // 收到关灯指令
}
// 回复状态确认
generic_onoff_server_publish(p_server, NULL);
}
(4)接入主流智能家居平台(以 HomeKit 为例)
若需接入 HomeKit,需遵循 HAP 规范,实现标准化服务和特性,并通过认证:
- 使用苹果提供的
HomeKit Accessory Protocol Specification定义服务(如Lightbulb服务 UUID:00000043-0000-1000-8000-0026BB765291)。 - 实现配对安全(SRP 加密)和数据签名,确保通信安全。
- 通过 MFi 认证(需向苹果申请),获取认证芯片(如 nRF52840 + 认证 IC)。
3. 调试与验证
- 用nRF Connect (手机 APP)扫描设备 "SmartLight",连接后可查看服务和特性,写入
0x01到开关特性,验证灯光是否开启。 - 多设备组网时,用 Mesh 网关(如 nRF52840 网关)发送广播指令,验证所有灯是否同步响应。
三、注意事项
-
功耗优化:
- 非活跃时进入低功耗模式(nRF52840 的 System Off 模式,电流 < 1μA),通过外部中断(如按键)唤醒。
- 广播间隔设为 1-10 秒(传感器)或按需广播(控制类设备连接时关闭广播)。
-
安全机制:
- 敏感设备(如门锁)需启用 BLE 配对加密(BLE Security Levels 2+),防止数据被窃听。
- 接入平台时(如 HomeKit),严格遵循平台的安全规范(如证书认证)。
-
兼容性:
- 优先使用蓝牙 SIG 标准服务 / 特性(如电池服务 0x180F),确保第三方 APP 可识别。
- 自定义服务需文档化 UUID 和数据格式,方便网关或 APP 集成。
总结
BLE 在智能家居中以 GAP/GATT 为基础,通过 BLE Mesh 实现多设备组网,通过 HomeKit 等平台协议实现跨生态兼容。程序实现需围绕 "服务 - 特性" 模型设计数据交互,结合硬件特性优化功耗和安全,最终实现设备的便捷控制与状态同步。对于中小规模场景,自定义 GATT 服务足够灵活;大规模场景则需基于 BLE Mesh 或平台协议开发。