`
SoC-温度计客户端
此示例应用程序演示了在多从BLE拓扑中客户端设备的操作。Silicon Labs蓝牙协议栈支持同时连接最多8个从设备。这个示例应用程序演示了如何同时连接到四个温度计外围设备。
需要一个运行SoC温度计客户端示例应用程序的EFR32/BGM设备,以及至少一个(但不超过四个)运行SoC温度计应用程序的外围设备。下图显示了测试此示例应用程序的拓扑设置。
网络拓扑
当客户端启动时,它开始搜索/发现广告设备。它启动与那些在其广告包中包含健康温度计服务的设备的连接。
建立连接后,客户机从远程GATT数据库中发现健康温度计服务。服务发现完成后,客户机发现温度计特性并启用从远程GATT服务器发送的指示。
对设备进行编程后,打开终端 仿真器并通过其串行端口连接到客户端设备。将波特率设置为115200。打开从属温度计设备的 电源,观察终端上的输出读数。
四个外围设备的温度读数
- void sl_bt_on_event(sl_bt_msg_t* evt)
- {
- sl_status_t sc;
- uint8_t *char_value;
- uint16_t addr_value;
- uint8_t table_index;
- // Handle stack events
- 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:
- // Print boot message.
- app_log_info("Bluetooth stack booted: v%d.%d.%d-b%d
- ",
- evt->data.evt_system_boot.major,
- evt->data.evt_system_boot.minor,
- evt->data.evt_system_boot.patch,
- evt->data.evt_system_boot.build);
- // Print bluetooth address.
- print_bluetooth_address();
- // Set passive scanning on 1Mb PHY
- sc = sl_bt_scanner_set_mode(sl_bt_gap_1m_phy, SCAN_PASSIVE);
- app_assert_status(sc);
- // Set scan interval and scan window
- sc = sl_bt_scanner_set_timing(sl_bt_gap_1m_phy, SCAN_INTERVAL, SCAN_WINDOW);
- app_assert_status(sc);
- // Set the default connection parameters for subsequent connections
- sc = sl_bt_connection_set_default_parameters(CONN_INTERVAL_MIN,
- CONN_INTERVAL_MAX,
- CONN_RESPONDER_LATENCY,
- CONN_TIMEOUT,
- CONN_MIN_CE_LENGTH,
- CONN_MAX_CE_LENGTH);
- app_assert_status(sc);
- // Start scanning - looking for thermometer devices
- sc = sl_bt_scanner_start(sl_bt_gap_1m_phy, sl_bt_scanner_discover_generic);
- app_assert_status_f(sc,
- "Failed to start discovery #1
- ");
- conn_state = scanning;
- break;
- // -------------------------------
- // This event is generated when an advertisement packet or a scan response
- // is received from a responder
- case sl_bt_evt_scanner_scan_report_id:
- // Parse advertisement packets
- if (evt->data.evt_scanner_scan_report.packet_type == 0) {
- // If a thermometer advertisement is found...
- if (find_service_in_advertisement(&(evt->data.evt_scanner_scan_report.data.data[0]),
- evt->data.evt_scanner_scan_report.data.len) != 0) {
- // then stop scanning for a while
- sc = sl_bt_scanner_stop();
- app_assert_status(sc);
- // and connect to that device
- if (active_connections_num < SL_BT_CONFIG_MAX_CONNECTIONS) {
- sc = sl_bt_connection_open(evt->data.evt_scanner_scan_report.address,
- evt->data.evt_scanner_scan_report.address_type,
- sl_bt_gap_1m_phy,
- NULL);
- app_assert_status(sc);
- conn_state = opening;
- }
- }
- }
- break;
- // -------------------------------
- // This event is generated when a new connection is established
- case sl_bt_evt_connection_opened_id:
- // Get last two bytes of sender address
- addr_value = (uint16_t)(evt->data.evt_connection_opened.address.addr[1] << 8) + evt->data.evt_connection_opened.address.addr[0];
- // Add connection to the connection_properties array
- add_connection(evt->data.evt_connection_opened.connection, addr_value);
- // Discover Health Thermometer service on the responder device
- sc = sl_bt_gatt_discover_primary_services_by_uuid(evt->data.evt_connection_opened.connection,
- sizeof(thermo_service),
- (const uint8_t*)thermo_service);
- app_assert_status(sc);
- // Set remote connection power reporting - needed for Power Control
- sc = sl_bt_connection_set_remote_power_reporting(
- evt->data.evt_connection_opened.connection,
- sl_bt_connection_power_reporting_enable);
- app_assert_status(sc);
- conn_state = discover_services;
- break;
- // -------------------------------
- // This event is generated when a new service is discovered
- case sl_bt_evt_gatt_service_id:
- table_index = find_index_by_connection_handle(evt->data.evt_gatt_service.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- // Save service handle for future reference
- conn_properties[table_index].thermometer_service_handle = evt->data.evt_gatt_service.service;
- }
- break;
- // -------------------------------
- // This event is generated when a new characteristic is discovered
- case sl_bt_evt_gatt_characteristic_id:
- table_index = find_index_by_connection_handle(evt->data.evt_gatt_characteristic.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- // Save characteristic handle for future reference
- conn_properties[table_index].thermometer_characteristic_handle = evt->data.evt_gatt_characteristic.characteristic;
- }
- break;
- // -------------------------------
- // This event is generated for various procedure completions, e.g. when a
- // write procedure is completed, or service discovery is completed
- case sl_bt_evt_gatt_procedure_completed_id:
- table_index = find_index_by_connection_handle(evt->data.evt_gatt_procedure_completed.connection);
- if (table_index == TABLE_INDEX_INVALID) {
- break;
- }
- // If service discovery finished
- if (conn_state == discover_services && conn_properties[table_index].thermometer_service_handle != SERVICE_HANDLE_INVALID) {
- // Discover thermometer characteristic on the responder device
- sc = sl_bt_gatt_discover_characteristics_by_uuid(evt->data.evt_gatt_procedure_completed.connection,
- conn_properties[table_index].thermometer_service_handle,
- sizeof(thermo_char),
- (const uint8_t*)thermo_char);
- app_assert_status(sc);
- conn_state = discover_characteristics;
- break;
- }
- // If characteristic discovery finished
- if (conn_state == discover_characteristics && conn_properties[table_index].thermometer_characteristic_handle != CHARACTERISTIC_HANDLE_INVALID) {
- // stop discovering
- sl_bt_scanner_stop();
- // enable indications
- sc = sl_bt_gatt_set_characteristic_notification(evt->data.evt_gatt_procedure_completed.connection,
- conn_properties[table_index].thermometer_characteristic_handle,
- sl_bt_gatt_indication);
- app_assert_status(sc);
- conn_state = enable_indication;
- break;
- }
- // If indication enable process finished
- if (conn_state == enable_indication) {
- // and we can connect to more devices
- if (active_connections_num < SL_BT_CONFIG_MAX_CONNECTIONS) {
- // start scanning again to find new devices
- sc = sl_bt_scanner_start(sl_bt_gap_1m_phy, sl_bt_scanner_discover_generic);
- app_assert_status_f(sc,
- "Failed to start discovery #2
- ");
- conn_state = scanning;
- } else {
- conn_state = running;
- }
- break;
- }
- break;
- // -------------------------------
- // This event is generated when a connection is dropped
- case sl_bt_evt_connection_closed_id:
- // remove connection from active connections
- remove_connection(evt->data.evt_connection_closed.connection);
- if (conn_state != scanning) {
- // start scanning again to find new devices
- sc = sl_bt_scanner_start(sl_bt_gap_1m_phy, sl_bt_scanner_discover_generic);
- app_assert_status_f(sc,
- "Failed to start discovery #3
- ");
- conn_state = scanning;
- }
- break;
- // -------------------------------
- // This event is generated when a characteristic value was received e.g. an indication
- case sl_bt_evt_gatt_characteristic_value_id:
- if (evt->data.evt_gatt_characteristic_value.value.len >= 5) {
- char_value = &(evt->data.evt_gatt_characteristic_value.value.data[0]);
- table_index = find_index_by_connection_handle(evt->data.evt_gatt_characteristic_value.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- conn_properties[table_index].temperature = translate_IEEE_11073_temperature_to_float((IEEE_11073_float *)(char_value + 1));
- conn_properties[table_index].unit = translate_flags_to_temperature_unit(char_value[0]);
- }
- } else {
- app_log_warning("Characteristic value too short: %d
- ",
- evt->data.evt_gatt_characteristic_value.value.len);
- }
- // Send confirmation for the indication
- sc = sl_bt_gatt_send_characteristic_confirmation(evt->data.evt_gatt_characteristic_value.connection);
- app_assert_status(sc);
- // Trigger RSSI measurement on the connection
- sc = sl_bt_connection_get_rssi(evt->data.evt_gatt_characteristic_value.connection);
- app_assert_status(sc);
- break;
- // -------------------------------
- // This event is generated when RSSI value was measured
- case sl_bt_evt_connection_rssi_id:
- table_index = find_index_by_connection_handle(evt->data.evt_connection_rssi.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- conn_properties[table_index].rssi = evt->data.evt_connection_rssi.rssi;
- }
- print_values();
- break;
- // -------------------------------
- // TX Power is updated
- case sl_bt_evt_connection_tx_power_id:
- table_index = find_index_by_connection_handle(
- evt->data.evt_connection_tx_power.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- conn_properties[table_index].tx_power =
- evt->data.evt_connection_tx_power.power_level;
- }
- // TX Power reporting is enabled on the other side.
- conn_properties[table_index].power_control_active =
- TX_POWER_CONTROL_ACTIVE;
- break;
- // -------------------------------
- // Remote TX Power is updated
- case sl_bt_evt_connection_remote_tx_power_id:
- table_index = find_index_by_connection_handle(
- evt->data.evt_connection_remote_tx_power.connection);
- if (table_index != TABLE_INDEX_INVALID) {
- conn_properties[table_index].remote_tx_power =
- evt->data.evt_connection_remote_tx_power.power_level;
- }
- break;
- default:
- break;
- }
- }
复制代码
`
|