源码:
https://download.csdn.net/download/hxkrrzq/88353283
以上源码都是官方资源,可以自行gitbub下载(参见之前笔记)
蓝牙广播格式化
之前的笔记中广播数据是直接使用的十六进制字符串,关于这32bytes数据的格式化在这个例程中,有实例代码。
同时这些例程的readme十分完善。
// Advertising flags (common)
#define ADVERTISE_FLAGS_LENGTH 2
#define ADVERTISE_FLAGS_TYPE 0x01
// Bit mask for flags advertising data type
#define ADVERTISE_FLAGS_LE_LIMITED_DISCOVERABLE 0x01
#define ADVERTISE_FLAGS_LE_GENERAL_DISCOVERABLE 0x02
#define ADVERTISE_FLAGS_BR_EDR_NOT_SUPPORTED 0x04
// Scan Response
#define ADVERTISE_MANDATORY_DATA_LENGTH 5
#define ADVERTISE_MANDATORY_DATA_TYPE_MANUFACTURER 0xFF
// Advertise ID
#define ADVERTISE_COMPANY_ID 0x0047
#define ADVERTISE_FIRMWARE_ID 0x0000
// Complete local name
#define ADVERTISE_TYPE_LOCAL_NAME 0x09
#define ADVERTISE_DEVICE_NAME_LEN 10
#define ADVERTISE_DEVICE_NAME "Thermostat"
// Helper macro
#define UINT16_TO_BYTES(x) { (uint8_t)(x), (uint8_t)((x) >> 8) }
// Default advertising scan response parameters
#define ADVERTISE_SCAN_RESPONSE_DEFAULT \
{ \
.flags_length = ADVERTISE_FLAGS_LENGTH, \
.flags_type = ADVERTISE_FLAGS_TYPE, \
.flags = ADVERTISE_FLAGS_LE_GENERAL_DISCOVERABLE \
| ADVERTISE_FLAGS_BR_EDR_NOT_SUPPORTED, \
.mandatory_data_length = ADVERTISE_MANDATORY_DATA_LENGTH, \
.mandatory_data_type = ADVERTISE_MANDATORY_DATA_TYPE_MANUFACTURER, \
.company_id = UINT16_TO_BYTES(ADVERTISE_COMPANY_ID), \
.firmware_id = UINT16_TO_BYTES(ADVERTISE_FIRMWARE_ID), \
.local_name_length = ADVERTISE_DEVICE_NAME_LEN + 1, \
.local_name_type = ADVERTISE_TYPE_LOCAL_NAME, \
.local_name = ADVERTISE_DEVICE_NAME \
}
/***************************************************************************//**
* @brief
* Structure that holds Scan Response data
******************************************************************************/
typedef struct {
uint8_t flags_length; /**< Length of the Flags field. */
uint8_t flags_type; /**< Type of the Flags field. */
uint8_t flags; /**< Flags field. */
uint8_t mandatory_data_length; /**< Length of the mandata field. */
uint8_t mandatory_data_type; /**< Type of the mandata field. */
uint8_t company_id[2]; /**< Company ID. */
uint8_t firmware_id[2]; /**< Firmware ID */
uint8_t local_name_length; /**< Length of the local name field. */
uint8_t local_name_type; /**< Type of the local name field. */
uint8_t local_name[ADVERTISE_DEVICE_NAME_LEN]; /**< Local name field. */
} advertise_scan_response_t;
// The advertising set handle allocated from Bluetooth stack.
static uint8_t advertising_set_handle = 0xff;
static const advertise_scan_response_t adv_scan_response
= ADVERTISE_SCAN_RESPONSE_DEFAULT;
...
...
...
[设置广播数据]
sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle,
0, // 类型是广播,而不是广播回包
sizeof(adv_scan_response),
(uint8_t *)&adv_scan_response);
蓝牙事件
void sl_bt_on_event(sl_bt_msg_t *evt)
{
sl_status_t sc;
bd_addr address;
uint8_t address_type;
uint8_t system_id[8];
switch (SL_BT_MSG_ID(evt->header)) {
case sl_bt_evt_system_boot_id:
...
case sl_bt_evt_connection_opened_id:
...
case sl_bt_evt_connection_closed_id:
...
///
// Add additional event handlers here as your application requires! //
///
// -------------------------------
// Handle configuration characteristics.
case sl_bt_evt_gatt_server_attribute_value_id:
break;
case sl_bt_evt_gatt_server_user_write_request_id:
thermostat_process_evt_gatt_server_user_write_request(
&(evt->data.evt_gatt_server_user_write_request));
break;
case sl_bt_evt_gatt_server_user_read_request_id:
thermostat_process_evt_gatt_server_user_read_request(
&(evt->data.evt_gatt_server_user_read_request));
break;
case sl_bt_evt_system_external_signal_id:
thermostat_process_evt_external_signal(
evt->data.evt_system_external_signal.extsignals);
break;
case sl_bt_evt_system_soft_timer_id:
break;
// -------------------------------
// Default event handler.
default:
break;
}
}
代码中添加了几个蓝牙协议栈的事件,需要搞清楚如何使用:
sl_bt_evt_gatt_server_attribute_value_id
最常见的,手机侧写数据后,会进入此事件,识别写入的value,做出相应动作;
sl_bt_evt_gatt_server_user_write_request_id
简单阅读api.h函数说明后还是不清楚;
参考:
GATT Server and Client Roles,文档中有一段较详细的对比说明:
这个user的意思是,只上报写事件,不直接处理接收到的数据,这个操作粒度比“sl_bt_evt_gatt_server_attribute_value”事件更细。
sl_bt_evt_gatt_server_user_read_request_id
同上
sl_bt_evt_system_soft_timer_id
api文档中:
提示了,此函数超时后会发出此事件。
sl_bt_evt_system_external_signal_id
外部信号是什么?关键的是何时会产生此事件?
同样的搜索api.h和官方帮助文档,都不能获得有效信息,只是说这是外部信号,没找到怎么使用,猜测它是可以自定义的。
继续寻找……
根据api.h文档可以找到“sl_bt_evt_system_external_signal_t”结构体,在接口文档中公开,必然有些地方会使用它。
检索整个蓝牙例程包,发现有多个例程用到了:
具体可以参考例程:bluetooth_ethernet_gateway
最后找到发送信号的函数:
/**
* @brief Signal the Bluetooth stack that an external event has happened.
*
* Signals can be used to report status changes from interrupt context or from
* other threads to application. Signals are bits that are automatically cleared
* after application has been notified.
*
* If the Platform Core Interrupt API has been configured to use the
* CORE_ATOMIC_METHOD_BASEPRI as the implementation method of atomic sections,
* this function must not be called from an interrupt handler with a priority
* higher than CORE_ATOMIC_BASE_PRIORITY_LEVEL.
*
* @param signals is a bitmask defining active signals that are reported back to
* the application by system_external_signal-event.
* @return SL_STATUS_OK if the operation is successful,
* SL_STATUS_NO_MORE_RESOURCE indicating the request could not be processed
* due to resource limitation at the moment, or SL_STATUS_INVALID_STATE when
* the on-demand start feature is used and the stack is currently stopped.
*/
sl_status_t sl_bt_external_signal(uint32_t signals);
反过来,检索sl_bt_external_signal,看看那些地方用到了,怎么使用的。
结果是很多例程使用到了。选“bluetooth_air_quality_monitor”看看:
产生信号的地方:
/***************************************************************************//**
* Simple Button
* Button state changed callback
* @param[in] handle
* Button event handle
******************************************************************************/
void sl_button_on_change(const sl_button_t *handle)
{
// Button released.
if (sl_button_get_state(handle) == SL_SIMPLE_BUTTON_RELEASED) {
if (&sl_button_btn0 == handle) {
sl_bt_external_signal(AIR_QUALITY_MONITOR_BUTTON_EVENT);
}
}
}
接收信号:
/***************************************************************************//**
* Bluetooth stack event handler.
* This overrides the dummy weak implementation.
*
* @param[in] evt Event coming from the Bluetooth stack.
******************************************************************************/
void sl_bt_on_event(sl_bt_msg_t *evt)
{
sl_status_t sc;
bd_addr address;
uint8_t address_type;
uint8_t system_id[8];
switch (SL_BT_MSG_ID(evt->header)) {
// -------------------------------
// This event indicates the device has started and the radio is ready.
// Do not call any stack command before receiving this boot event!
case sl_bt_evt_system_boot_id:
.....
break;
// -------------------------------
// This event indicates that a new connection was opened.
case sl_bt_evt_connection_opened_id:
connection_opened_handler(evt);
break;
// -------------------------------
// This event indicates that a connection was closed.
case sl_bt_evt_connection_closed_id:
connection_closed_handler(evt);
break;
// -------------------------------
// The parameters event
case sl_bt_evt_connection_parameters_id:
connection_parameters_handler(evt);
break;
// -------------------------------
// The confirm_bonding event
case sl_bt_evt_sm_confirm_bonding_id:
sm_confirm_bonding_handler(evt);
break;
// -------------------------------
// This event triggered after the pairing or bonding procedure is
// successfully completed.
case sl_bt_evt_sm_bonded_id:
app_log("Bluetooth Stack Event : BONDED\r\n");
break;
// -------------------------------
// This event is triggered if the pairing or bonding procedure fails.
case sl_bt_evt_sm_bonding_failed_id:
sm_bonding_failed_handler(evt);
break;
// Service the gatt server user write request event
case sl_bt_evt_gatt_server_user_write_request_id:
// Service write handlers
air_quality_user_write_callback(evt);
break;
// Service the gatt server user read request event
case sl_bt_evt_gatt_server_user_read_request_id:
air_quality_user_read_callback(evt);
break;
// -------------------------------
// External signal indication (comes from the interrupt handler)
case sl_bt_evt_system_external_signal_id:
air_quality_process_event(evt->data.evt_system_external_signal.extsignals);
break;
///
// Add additional event handlers here as your application requires! //
///
// -------------------------------
// Default event handler.
default:
break;
}
}