ln:蓝牙设备ui逻辑添加 2800/target/3 2807/1 2807/head 2808/target/1
authorluozheng <1732036298@qq.com>
Wed, 26 Nov 2025 13:30:42 +0000 (21:30 +0800)
committerluozheng <1732036298@qq.com>
Wed, 26 Nov 2025 13:30:42 +0000 (21:30 +0800)
13 files changed:
code/sdk/application/wearable/ln/nativeapp/nativelauncher/src/NativeLauncher.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/BluetoothModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp [new file with mode: 0644]
code/sdk/application/wearable/ln/nativeapp/nativeui/include/bluetooth/BluetoothModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/include/bluetooth/Ln_Bluetooth_apiC.h [new file with mode: 0644]
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdBlueView.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdPresenter.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdBlueView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdMainView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp
code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_bluetooth_api.c

index 1f01e4a..ad5b0b6 100644 (file)
@@ -58,6 +58,7 @@ void NativeLauncher::InitNativeLauncher()
   
     //初始化slice
     NativeRegisterManager::GetInstance().InitAllNativesSlices();
+    BluetoothModel::GetInstance()->Init();
 
     //初始化屏幕亮度
     cm_initScreenBrightness();
index cf54e84..5f08874 100644 (file)
 #if defined(SUPPORT_LWIP) && defined(SUPPORT_BREDR)\r
 #include "lwip_driver_adapter.h"\r
 #endif\r
+#include <bluetooth/BluetoothHeadsetEvent.h>\r
+#include "ln_api.h"\r
+#include "phoneservice/PhoneService.h"\r
+#include "thunderbird/include/ThunderBirdMainView.h"\r
+#include <custom_utils.h>\r
 namespace OHOS {\r
 \r
 #define BT_SPP_TASK_STACK_SIZE 2048\r
@@ -141,20 +146,22 @@ void BluetoothModel::Init()
     BtInitCallBacksEx();\r
     BtInitGatts();\r
     BtInitSpp();\r
+    // InitBtHeadsetEvent(); // 蓝牙ct和tg适配初始化\r
+    // PhoneServiceInit();\r
 \r
     /* 实验室测试需要,开机开广播 */\r
     BleAdvStart();\r
 \r
-    SetUpListCase();\r
-    SetUpConnedDevicesList();\r
 #endif\r
 }\r
 \r
 void BluetoothModel::SetCaseListClear()\r
 {\r
     btScansDevicesList_.clear();\r
+    SetUpConnedDevicesList();\r
 }\r
 \r
+// 检查扫描列表是否存在该设备\r
 bool BluetoothModel::CheckExistScanList(BluetoothCaseInfo caseInfo)\r
 {\r
     std::list<BluetoothCaseInfo>::iterator node = btScansDevicesList_.begin();\r
@@ -278,13 +285,14 @@ void BluetoothModel::SetUpConnedDevicesList()
     }\r
 }\r
 \r
+// 已连接设备队列\r
 void BluetoothModel::AddConnedDevicesCase(BluetoothCaseInfo caseInfo)\r
 {\r
     if (btConnedDevicesList_ == nullptr) {\r
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "btConnedDevicesList_ nullptr");\r
         return;\r
     }\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AddConnedDevicesCase::caseInfo addr: %02x%02x%02x%02x%02x%02x",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AddConnedDevicesCase::caseInfo addr: %02x%02x%02x%02x%02x%02x",\r
         caseInfo.addr[5], caseInfo.addr[4], caseInfo.addr[3], /* mac下标 0 1 2 3 4 5 */\r
         caseInfo.addr[2], caseInfo.addr[1], caseInfo.addr[0]);\r
     if (btConnedDevicesList_->Size() >= BLUETOOTH_MAX_NUM) {\r
@@ -330,14 +338,23 @@ BluetoothCaseInfo *BluetoothModel::GetTempMacValue(void)
     return &tempMacValue;\r
 }\r
 \r
+// 设置最后连接的蓝牙设备地址\r
 void BluetoothModel::SetLastConnedAddr(const bd_addr_t *addr)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetLastConnedAddr: %02x%02x%02x%02x%02x%02x",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置最后连接的蓝牙设备地址: %02X:%02X:%02X:%02X:%02X:%02X",\r
                   addr->addr[5], addr->addr[4], addr->addr[3], /* macϱê 0 1 2 3 4 5 */\r
                   addr->addr[2], addr->addr[1], addr->addr[0]); /* macϱê 0 1 2 3 4 5 */\r
     (void)memcpy_s(lastConnedAddr.addr, BD_ADDR_LEN, addr->addr, BD_ADDR_LEN);\r
+    if (addr != nullptr) {\r
+        char lastConnedDeviceName[BD_NAME_LEN] = {0};\r
+        snprintf(lastConnedDeviceName, BD_NAME_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",\r
+            addr->addr[5], addr->addr[4], addr->addr[3], /* macϱê 0 1 2 3 4 5 */\r
+            addr->addr[2], addr->addr[1], addr->addr[0]); /* macϱê 0 1 2 3 4 5 */\r
+        SetBoundDeviceMac(lastConnedDeviceName);\r
+    }\r
 }\r
 \r
+// 获取最后连接的蓝牙设备地址\r
 bd_addr_t *BluetoothModel::GetLastConnedAddr(void)\r
 {\r
     return &lastConnedAddr;\r
@@ -510,6 +527,7 @@ void BluetoothModel::SetAdvStartState(bool state)
     advStartState = state;\r
 }\r
 \r
+// 连接远程设备\r
 int BluetoothModel::ConnectRemoteDevice(const bd_addr_t *addr)\r
 {\r
     /* 恢厂后耳机连接要开启BT广播否则会导致AVRCP无法音量控制 */\r
@@ -518,14 +536,100 @@ int BluetoothModel::ConnectRemoteDevice(const bd_addr_t *addr)
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice gap_br_set_bt_scan_mode ret = 0x%x", ret);\r
     }\r
     errcode_t retVal = gap_connect_remote_device(addr);\r
-    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "ConnectRemoteDevice gap_connect_remote_device ret = 0x%x", retVal);\r
+    WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "连接远程设备 ret = 0x%x", retVal);\r
     (void)memcpy_s(&remoteConnectAddr, sizeof(bd_addr_t), addr, sizeof(bd_addr_t));\r
     return retVal;\r
 }\r
 \r
+// 断开远程设备\r
+int BluetoothModel::DisconnectRemoteDevice(void)\r
+{\r
+    bd_addr_t *lastAddr = BluetoothModel::GetInstance()->GetLastConnedAddr();\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "断开远程设备 Addr: %02X:%02X:%02X:%02X:%02X:%02X",\r
+        lastAddr->addr[5], lastAddr->addr[4], lastAddr->addr[3], /* mac下标 0 1 2 3 4 5 */\r
+        lastAddr->addr[2], lastAddr->addr[1], lastAddr->addr[0]); /* mac下标 0 1 2 3 4 5 */\r
+    errcode_t retVal  = gap_disconnect_remote_device(lastAddr);\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "gap_disconnect_remote_device %d", retVal);\r
+    // 清空正在连接的设备地址,避免影响后续连接\r
+    (void)memset_s(&remoteConnectAddr, sizeof(bd_addr_t), 0, sizeof(bd_addr_t));\r
+    return retVal;\r
+}\r
+\r
+// 解绑本地设备\r
+int BluetoothModel::UnBindLocalDevice(void)\r
+{\r
+    bd_addr_t *lastAddr = BluetoothModel::GetInstance()->GetLastConnedAddr();\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "解绑蓝牙设备 Addr: %02X:%02X:%02X:%02X:%02X:%02X",\r
+        lastAddr->addr[5], lastAddr->addr[4], lastAddr->addr[3], /* mac下标 0 1 2 3 4 5 */\r
+        lastAddr->addr[2], lastAddr->addr[1], lastAddr->addr[0]); /* mac下标 0 1 2 3 4 5 */\r
+    bool ret = gap_remove_pair(lastAddr);\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "gap_remove_pair %d", ret);\r
+    return ret;\r
+}\r
+\r
+// 设置绑定的本地设备MAC地址\r
+void BluetoothModel::SetBoundDeviceMac(const char *mac)\r
+{\r
+    if (mac != nullptr) {\r
+        (void)strcpy_s(boundDeviceMac, BD_NAME_LEN, mac);\r
+    }\r
+}\r
+\r
+// 获取绑定的本地设备MAC地址\r
+char *BluetoothModel::GetBoundDeviceMac(void)\r
+{\r
+    return boundDeviceMac;\r
+}\r
+\r
+// 设置最后连接的设备名称\r
+void BluetoothModel::SetLastConnedDeviceName(const char *name)\r
+{\r
+    if (name != nullptr) {\r
+        (void)strcpy_s(lastConnedDeviceName, BD_NAME_LEN, name);\r
+    }\r
+}\r
+\r
+// 获取最后连接的设备名称\r
+char *BluetoothModel::GetLastConnedDeviceName(void)\r
+{\r
+    return lastConnedDeviceName;\r
+}\r
+\r
+// 设置最后连接的设备电池电量\r
+void BluetoothModel::SetLastConnedDeviceBatteryLevel(int level)\r
+{\r
+    lastConnedDeviceBatteryLevel = level;\r
+}\r
+\r
+// 获取最后连接的设备电池电量\r
+int BluetoothModel::GetLastConnedDeviceBatteryLevel(void)\r
+{\r
+    return lastConnedDeviceBatteryLevel;\r
+}\r
+\r
+// 设置扫描状态\r
+void BluetoothModel::SetScanStatus(bool value)\r
+{\r
+    scanStart = value;\r
+}\r
+\r
+// 获取扫描状态\r
+bool BluetoothModel::GetScanStatus(void)\r
+{\r
+    return scanStart;\r
+}\r
+\r
+// 检查是否是正在连接的设备\r
 bool BluetoothModel::ConnectRemoteCheck(const bd_addr_t *addr)\r
 {\r
     bool ret;\r
+    // 如果remoteConnectAddr为空(全0),说明没有明确的连接目标,允许A2DP连接\r
+    if ((remoteConnectAddr.addr[0] == 0) && (remoteConnectAddr.addr[1] == 0) &&\r
+        (remoteConnectAddr.addr[2] == 0) && (remoteConnectAddr.addr[3] == 0) &&\r
+        (remoteConnectAddr.addr[4] == 0) && (remoteConnectAddr.addr[5] == 0)) {\r
+        return true;\r
+    }\r
+    // 检查地址是否匹配\r
     if ((remoteConnectAddr.addr[0] == addr->addr[0]) && (remoteConnectAddr.addr[1] == addr->addr[1]) &&\r
         (remoteConnectAddr.addr[2] == addr->addr[2]) && (remoteConnectAddr.addr[3] == addr->addr[3]) &&\r
         (remoteConnectAddr.addr[4] == addr->addr[4]) && (remoteConnectAddr.addr[5] == addr->addr[5])) {\r
@@ -559,110 +663,96 @@ void BtGapDiscoveryStateChangedCallback(int status)
     WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "bt BtGapDiscoveryStateChangedCallback %d", status);\r
 }\r
 \r
-static void ChangeScanView()\r
-{\r
-    BluetoothEarPhoneView *bluetoothEarPhoneView = BluetoothEarPhoneView::GetInstance();\r
-    if (bluetoothEarPhoneView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "bluetoothEarPhoneView nullptr");\r
-        return;\r
-    }\r
-    bluetoothEarPhoneView->setScanStatus(false);\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Bt scan one jumpView");\r
-    if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERPLAYERS) {\r
-        JumpView *jumpView = JumpView::GetInstance();\r
-        if (jumpView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jumpView GetInstance fail");\r
-            return;\r
-        }\r
-        jumpView->ChangeView(JumpView::BluetoothJumpViewNum::BLUETOOTHEARPHONEVIEW,\r
-                             JumpView::BluetoothJumpViewNum::BLUETOOTHEARLISTVIEW);\r
-    } else if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERSETTING) {\r
-        MainBluetoothView *mainBluetoothView = MainBluetoothView::GetInstance();\r
-        if (mainBluetoothView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mainBluetoothView GetInstance fail");\r
-            return;\r
-        }\r
-        mainBluetoothView->ChangeView(BLUETOOTHEARPHONEVIEW, BLUETOOTHEARLISTVIEW);\r
-    }\r
-    // 暂停动画\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtAnimatorStop bk");\r
-    bluetoothEarPhoneView->BtAnimatorStop();\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtAnimatorStop");\r
-}\r
-\r
+// 回调:发现设备上报处理\r
 void BluetoothModel::BtGapDiscoveryResultCallbakHandle(const bd_addr_t &bdAddr)\r
 {\r
     BluetoothCaseInfo caseInfo{};\r
     (void)memcpy_s(caseInfo.addr, BD_ADDR_LEN, bdAddr.addr, BD_ADDR_LEN);\r
-\r
     unsigned char nameLen = BD_NAME_LEN;\r
     bool getNameRet = gap_get_device_name(&bdAddr, caseInfo.deviceName, &nameLen);\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "gap_discovery_result_callback getNameRet(bool): %d nameLen: %d name:%s",\r
-                  getNameRet, nameLen, caseInfo.deviceName);\r
-\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发现蓝牙设备 : %d nameLen: %d name:%s",getNameRet, nameLen, caseInfo.deviceName);\r
     if (nameLen == 0) { // 过滤未扫描到名字的设备\r
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "nameLen == 0 return");\r
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "过滤未扫描到名字的设备");\r
         return;\r
     }\r
     // 去重操作\r
     bool tag = BluetoothModel::GetInstance()->CheckExistScanList(caseInfo);\r
-    if (!tag) {\r
+    if (!tag) \r
+    {\r
         BluetoothModel::GetInstance()->AddCase(caseInfo); // 增加扫描设备信息\r
     }\r
+    else\r
+    {\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CheckExistScanList true");\r
+    }\r
+\r
     bool ret = gap_read_remote_rssi_value(&bdAddr); // 获取rssi\r
     WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "gap_read_remote_rssi_value ret = %d", ret);\r
-    BluetoothEarPhoneView *bluetoothEarPhoneView = BluetoothEarPhoneView::GetInstance();\r
-    if (bluetoothEarPhoneView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "bluetoothEarPhoneView nullptr");\r
+\r
+    ThunderBirdMainView *thunderBirdMainView = ThunderBirdMainView::GetInstance();\r
+    if (thunderBirdMainView == nullptr) {\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "thunderBirdMainView nullptr");\r
         return;\r
     }\r
-    tag = bluetoothEarPhoneView->getScanStatus();\r
-    if (tag) { // 跳转\r
-        ChangeScanView();\r
+    int currentView = thunderBirdMainView->GetCurrentView();\r
+    tag = GetScanStatus();\r
+    if (tag) { \r
+        // 跳转\r
+        SetScanStatus(false);\r
+        thunderBirdMainView->ChangeView(\r
+                currentView, \r
+                THUNDERBIRD_BLUEVIEW, \r
+                ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST);\r
     } else {\r
-        BluetoothEarListView *bluetoothEarListView = BluetoothEarListView::GetInstance();\r
-        if (bluetoothEarListView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "bluetoothEarListView nullptr");\r
+        ThunderBirdBlueView *thunderBirdBlueView = ThunderBirdBlueView::GetInstance();\r
+        if (thunderBirdBlueView == nullptr) {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "thunderBirdBlueView nullptr");\r
             return;\r
         }\r
-        if (bluetoothEarListView->GetScanUIList() == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetScanUIList nullptr");\r
-            return;\r
-        } // 刷新\r
-        bluetoothEarListView->GetScanUIList()->RefreshList();\r
+        thunderBirdBlueView->RefreshDeviceList();\r
     }\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "bt BtGapDiscoveryResultCallback end");\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BtGapDiscoveryResultCallback end");\r
 }\r
 \r
 void BtGapPairStatusChangedCallback(const bd_addr_t *bdAddr, int status)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtGapPairStatusChangedCallback addr: ****%02x%02x%02x%02x status: %d\n",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "配对状态变化 addr: ****%02x%02x%02x%02x status: %d\n",\r
         bdAddr->addr[3], bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], status); /* addr下标 0 1 2 3 */\r
-    if (status == GAP_PAIR_PAIRED) {\r
-        if (ConnectPhonePresenter::GetInstance() != nullptr) {\r
-            NativeAbility::GetInstance().ChangeSlice(VIEW_SETTING);\r
-        }\r
+    if(status == GAP_PAIR_NONE){\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "取消配对");\r
+        char *bluetoothStatus = "UNBIND_SUCCESS";\r
+        do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus));\r
+    } else if(status == GAP_PAIR_PAIRING){\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "正在配对");\r
+    } else if(status == GAP_PAIR_PAIRED){\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "配对成功");\r
     }\r
 }\r
 \r
 void BtGapPairRequestedCallback(const bd_addr_t *bdAddr)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtGapPairRequestedCallback addr: ****%02x%02x%02x%02x\n",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "配对请求 addr: ****%02x%02x%02x%02x\n",\r
         bdAddr->addr[3], bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0]); /* addr下标 0 1 2 3 */\r
 }\r
 \r
 void BtGapPairConfirmedCallback(const bd_addr_t *bdAddr, int req_type, int number)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtGapPairConfirmedCallback addr: ****%02x%02x%02x%02x req_type: %d number: %d\n",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "配对确认 addr: ****%02x%02x%02x%02x req_type: %d number: %d\n",\r
         bdAddr->addr[3], bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], /* addr下标 0 1 2 3 */\r
         req_type, number);\r
 }\r
+// 回调:远程电池等级变化上报\r
+void BtGapRemoteBatteryLevelChangedCallback(const bd_addr_t *bdAddr, int level)\r
+{\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "远程电池等级变化 addr: ****%02x%02x%02x%02x level: %d\n",\r
+        bdAddr->addr[3], bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], level); /* addr下标 0 1 2 3 */\r
+}\r
 \r
 // 回调:扫描结果处理/发现结果上报\r
 void BtGapDiscoveryResultCallback(const bd_addr_t *bdAddr)\r
 {\r
     if ((gap_get_device_class(bdAddr) & DEVICE_MAJOR_CLASS_PHONE) != 0) {\r
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "BtGapDiscoveryResultCallback: Mobile Phone Device");\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发现结果: Mobile Phone Device");\r
         return;\r
     }\r
 \r
@@ -670,7 +760,7 @@ void BtGapDiscoveryResultCallback(const bd_addr_t *bdAddr)
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "addr nullptr");\r
         return;\r
     }\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "gap_discovery_result_callback addr: %02x%02x%02x%02x%02x%02x",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发现结果 addr: %02x:%02x:%02x:%02x:%02x:%02x",\r
         bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* mac下标 0 1 2 3 4 5 */\r
         bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0]); /* mac下标 0 1 2 3 4 5 */\r
     GraphicService::GetInstance()->PostGraphicEvent(std::bind(&BluetoothModel::BtGapDiscoveryResultCallbakHandle,\r
@@ -715,108 +805,75 @@ void HandleBeforeChangeView()
     }\r
 }\r
 \r
+// 回调:ACL连接成功\r
 static void ACLConnectionSuss(const bd_addr_t &bdAddr)\r
 {\r
-    // 判断是否已退出蓝牙模块(无需跳转)\r
-    bool tagConnectView = BluetoothModel::GetInstance()->IsTagConnectView();\r
-    if (!tagConnectView) {\r
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback tagConnectView fail");\r
-        return;\r
-    }\r
-    // 成功提示\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "GAP_ACL_STATE_CONNECTED");\r
-    HandleBeforeChangeView();\r
-    if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERPLAYERS) {\r
-        JumpView *jumpView = JumpView::GetInstance();\r
-        if (jumpView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jumpView GetInstance fail");\r
-            return;\r
-        }\r
-        jumpView->ChangeView(BluetoothModel::GetInstance()->GetCurView(),\r
-                             JumpView::BluetoothJumpViewNum::TIPSSUCCMESSAGEVIEW);\r
-    } else if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERSETTING) {\r
-        MainBluetoothView *mainBluetoothView = MainBluetoothView::GetInstance();\r
-        if (mainBluetoothView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mainBluetoothView GetInstance fail");\r
+    BluetoothCaseInfo caseInfo;\r
+    (void)memcpy_s(caseInfo.addr, BD_ADDR_LEN, bdAddr.addr, BD_ADDR_LEN);\r
+    unsigned char nameLen = BD_NAME_LEN;\r
+    bool getNameRet = gap_get_device_name(&bdAddr, caseInfo.deviceName, &nameLen);\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "连接成功 deviceName: %s", caseInfo.deviceName);\r
+    BluetoothModel::GetInstance()->SetLastConnedDeviceName((const char *)caseInfo.deviceName);\r
+    if(strcmp((const char *)caseInfo.deviceName, BluetoothModel::GetInstance()->GetLastConnedDeviceName()) == 0){\r
+        \r
+        //亮屏操作\r
+        uapi_set_screen_on_api();\r
+        \r
+        //蓝牙已连接,上报蓝牙状态\r
+        char *bluetoothStatus = "CONNECTED";\r
+        do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus));\r
+    \r
+        ThunderBirdMainView *thunderBirdMainView = ThunderBirdMainView::GetInstance();\r
+        if (thunderBirdMainView == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "thunderBirdMainView nullptr");\r
             return;\r
         }\r
-        mainBluetoothView->ChangeView(BluetoothModel::GetInstance()->GetCurView(), TIPSSUCCMESSAGEVIEW);\r
+        int currentView = thunderBirdMainView->GetCurrentView();\r
+        thunderBirdMainView->ChangeView(\r
+            currentView,\r
+            THUNDERBIRD_BLUEVIEW,\r
+            ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS);\r
     }\r
-    TipsSuccMessageView *tipsSuccMessageView = TipsSuccMessageView::GetInstance();\r
-    if (tipsSuccMessageView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ACLConnectionSuss tipsSuccMessageView GetInstance fail");\r
-        return;\r
-    }\r
-    tipsSuccMessageView->RefreshNameLabel(bdAddr);\r
 }\r
 \r
+// 回调:ACL连接失败\r
 static void ACLConnectionFail(const bd_addr_t &bdAddr)\r
 {\r
-    // 判断是否已退出蓝牙模块(无需跳转)\r
-    bool tagConnectView = BluetoothModel::GetInstance()->IsTagConnectView();\r
-    // 判断是否无需跳转到失败界面\r
-    bool tagDisconnectView = BluetoothModel::GetInstance()->IsTagDisconnectView();\r
-    if ((!tagConnectView) || (!tagDisconnectView)) {\r
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "GapAclStateChangedCallback tagDisconnectView fail");\r
-        return;\r
-    }\r
-    // 失败提示页\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "conn fail");\r
-    HandleBeforeChangeView();\r
-    if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERPLAYERS) {\r
-        JumpView *jumpView = JumpView::GetInstance();\r
-        if (jumpView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jumpView GetInstance fail");\r
-            return;\r
-        }\r
-        jumpView->ChangeView(BluetoothModel::GetInstance()->GetCurView(),\r
-                             JumpView::BluetoothJumpViewNum::TIPSCONNFAILMESSAGEVIEW);\r
-    } else if (BluetoothModel::GetInstance()->GetBluetoothCalleridStatus() == CALLERSETTING) {\r
-        MainBluetoothView *mainBluetoothView = MainBluetoothView::GetInstance();\r
-        if (mainBluetoothView == nullptr) {\r
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mainBluetoothView GetInstance fail");\r
+    BluetoothCaseInfo caseInfo;\r
+    (void)memcpy_s(caseInfo.addr, BD_ADDR_LEN, bdAddr.addr, BD_ADDR_LEN);\r
+    unsigned char nameLen = BD_NAME_LEN;\r
+    bool getNameRet = gap_get_device_name(&bdAddr, caseInfo.deviceName, &nameLen);\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "连接断开 deviceName: %s", caseInfo.deviceName);\r
+    if(strcmp((const char *)caseInfo.deviceName, BluetoothModel::GetInstance()->GetLastConnedDeviceName()) == 0){\r
+        \r
+        //亮屏操作\r
+        uapi_set_screen_on_api();\r
+\r
+        //蓝牙已断开,上报蓝牙状态\r
+        char *bluetoothStatus = "DISCONNECTED";\r
+        do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus));\r
+\r
+        ThunderBirdMainView *thunderBirdMainView = ThunderBirdMainView::GetInstance();\r
+        if (thunderBirdMainView == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "thunderBirdMainView nullptr");\r
             return;\r
         }\r
-        mainBluetoothView->ChangeView(BluetoothModel::GetInstance()->GetCurView(), TIPSCONNFAILMESSAGEVIEW);\r
+        int currentView = thunderBirdMainView->GetCurrentView();\r
+        thunderBirdMainView->ChangeView(\r
+            currentView,\r
+            THUNDERBIRD_BLUEVIEW,\r
+            ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_SUCCESS);\r
     }\r
-    TipsConnFailMessageView *tipsConnFailMessageView = TipsConnFailMessageView::GetInstance();\r
-    if (tipsConnFailMessageView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ACLConnectionFail tipsConnFailMessageView GetInstance fail");\r
-        return;\r
-    }\r
-    tipsConnFailMessageView->RefreshNameLabel(bdAddr);\r
 }\r
-\r
-static void DisconnectedHandle()\r
-{\r
-    BluetoothModel::GetInstance()->SetTagDisconnectView(false);\r
-    BluetoothDeviceListView *bluetoothDeviceListView = BluetoothDeviceListView::GetInstance();\r
-    if (bluetoothDeviceListView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AclStateChangedCallback bluetoothDeviceListView  == nullptr");\r
-        return;\r
-    }\r
-    UIList *deviceList = bluetoothDeviceListView->GetDeviceUIList();\r
-    if (deviceList == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "DisconnectedHandle deviceList nullptr");\r
-        return;\r
-    }\r
-    deviceList->RefreshList();\r
-    BluetoothOptionsView *bluetoothOptionsView = BluetoothOptionsView::GetInstance();\r
-    if (bluetoothOptionsView == nullptr) {\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AclStateChangedCallback bluetoothOptionsView  == nullptr");\r
-        return;\r
-    }\r
-    bluetoothOptionsView->RefreshText();\r
-}\r
-\r
 void BluetoothModel::BtGapAclStateChangedHandle(gap_acl_state_t state, unsigned int reason, const bd_addr_t &bdAddr)\r
 {\r
     bool tag = BluetoothModel::GetInstance()->IsTagScanDeviceClicked();\r
     if ((reason == 0x13) || (reason == 0x14) || (reason == 0x15) || (reason == 0x3D) || (reason == 0x08 && (!tag))) { // 连接断开\r
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "The peer end is disconnected.");\r
-        DisconnectedHandle();\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "蓝牙设备主动断开连接 reason is %x", reason);\r
     } else if (reason == 0x16) { // 主动断开连接\r
-        DisconnectedHandle();\r
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "主动断开与蓝牙设备连接,reason is%x", reason);\r
         BluetoothCaseInfo *onClickBtCaseInfo = BluetoothModel::GetInstance()->GetTempMacValue();\r
         if (BluetoothModel::GetInstance()->IsTagConnectNew()) {\r
             errcode_t retVal = ConnectRemoteDevice((const bd_addr_t *)&onClickBtCaseInfo->addr);\r
@@ -842,12 +899,9 @@ void BluetoothModel::BtGapAclStateChangedHandle(gap_acl_state_t state, unsigned
     if ((state == GAP_ACL_STATE_CONNECTED) || (state == GAP_ACL_STATE_LE_CONNECTED)) {\r
         if (BluetoothModel::GetInstance()->ConnectRemoteCheck(&bdAddr)) {\r
             int32_t retA2dp = a2dp_src_connect(&bdAddr);\r
-            if (retA2dp) {\r
-                ACLConnectionFail(bdAddr);\r
-            }\r
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "a2dp_src_connect result 0x%x", retA2dp);\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "a2dp连接结果 result 0x%x", retA2dp);\r
         } else {\r
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ingore a2dp_src_connect");\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "忽略a2dp连接");\r
         }\r
     }\r
 }\r
@@ -952,7 +1006,7 @@ void BtIsAcceptConnOnSafeModeCallback(const bd_addr_t *bdAddr, bool *res)
 \r
 static void A2dpSrcConnectstateChanged(bd_addr_t *bdAddr, int connState)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "a2dp_src_connectStateChangedCallback addr: %02x%02x%02x%02x%02x%02x connState: %x",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "a2dp_src_connectStateChangedCallback addr: %02x%02x%02x%02x%02x%02x connState: %x",\r
         bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* 5 4 3 idx */\r
         bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], connState); /* 2 1 0 idx */\r
     if ((gap_get_device_class(bdAddr) & 0x200) != 0) {\r
@@ -979,7 +1033,7 @@ static void A2dpSrcConnectstateChanged(bd_addr_t *bdAddr, int connState)
 \r
 static void A2dpSrcPlayingStateChanged(bd_addr_t *bdAddr, int playState)\r
 {\r
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "A2dpSrcPlayingStateChangedCallback addr: %02x%02x%02x%02x%02x%02x playState: %x",\r
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "A2dpSrcPlayingStateChangedCallback addr: %02x%02x%02x%02x%02x%02x playState: %x",\r
         bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* 5 4 3 idx */\r
         bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], playState); /* 2 1 0 idx */\r
 }\r
@@ -1351,6 +1405,7 @@ void BtInitCallBacks()
     g_btGapCallBacks.pair_status_changed_callback = BtGapPairStatusChangedCallback;\r
     g_btGapCallBacks.pair_requested_callback = BtGapPairRequestedCallback;\r
     g_btGapCallBacks.pair_confiremed_callback = BtGapPairConfirmedCallback;\r
+    g_btGapCallBacks.remote_battery_level_changed_callback = BtGapRemoteBatteryLevelChangedCallback;\r
     gap_register_callbacks(&g_btGapCallBacks);\r
 \r
     g_a2dpSrcCallbacks.connectstate_changed_cb = A2dpSrcConnectstateChanged;\r
diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/bluetooth/src/Ln_Bluetooth_apiC.cpp
new file mode 100644 (file)
index 0000000..7d0617a
--- /dev/null
@@ -0,0 +1,207 @@
+#include "bluetooth/Ln_Bluetooth_apiC.h"
+#include "bluetooth/BluetoothModel.h"
+#include "thunderbird/include/ThunderBirdMainView.h"
+#include "graphic_service.h"
+#include "ohos_timer.h"
+#include "graphic_timer.h"
+#include "wearable_log.h"
+#include <custom_utils.h>
+
+namespace OHOS
+{
+
+    GraphicTimer *g_stopScanHandle_ln = nullptr;
+    static constexpr uint64_t MS_SCAN_TIME = 25 * 1000;
+
+    // 取消蓝牙扫描
+    void LN_CancelBrScanHandle(void)
+    {
+        if (g_stopScanHandle_ln != nullptr)
+        {
+            g_stopScanHandle_ln->Stop();
+            delete g_stopScanHandle_ln;
+            g_stopScanHandle_ln = nullptr;
+            bool results = gap_br_cancel_discovery();
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "取消扫描 results %d", results);
+        }
+    }
+
+    // 扫描结束处理
+    void LN_EndScanHandle(void)
+    {
+        if (BluetoothModel::GetInstance()->GetCase().size() == 0)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "扫描结果为空");
+            if (BluetoothModel::GetInstance()->GetScanStatus() == true) // 如果是扫描状态
+            {
+                BluetoothModel::GetInstance()->SetScanStatus(false);
+                ThunderBirdMainView *thunderBirdMainView = ThunderBirdMainView::GetInstance();
+                if (thunderBirdMainView == nullptr)
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "thunderBirdMainView nullptr");
+                    return;
+                }
+                int currentView = thunderBirdMainView->GetCurrentView();
+                thunderBirdMainView->ChangeView(
+                    currentView,
+                    THUNDERBIRD_BLUEVIEW,
+                    ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING_FAILED);
+            }
+        }
+        // 扫描结束后关闭屏幕常亮
+        ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
+        return;
+    }
+
+    // 定时器回调函数
+    static void LnBluetoothScanTimerCallbackProc(void *data)
+    {
+        (void)data;
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "扫描结束");
+        LN_CancelBrScanHandle();
+        LN_EndScanHandle();
+    }
+    void LN_BluetoothScanTimerCallback(void *data)
+    {
+        GraphicService::GetInstance()->PostGraphicEvent(std::bind(LnBluetoothScanTimerCallbackProc, data));
+    }
+
+    void LN_BluetoothScanStart(void)
+    {
+        bool ret;
+        bool results;
+        // 经典蓝牙扫描
+        BluetoothModel::GetInstance()->SetScanStatus(true);
+        BluetoothModel::GetInstance()->SetCaseListClear(); // 扫描list清空
+        ret = is_bt_discovering(BT_TRANSPORT_BR_EDR);
+        if (ret)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "经典蓝牙正在扫描中");
+            return;
+        }
+        else
+        {
+            results = gap_br_set_inquiry_paramters(DEVICE_MAJOR_CLASS_AUDIO_VIDEO, 10);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "设置扫描参数 results %d", results);
+            results = gap_br_start_discovery();
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "启动扫描 results %d", results);
+        }
+        if (g_stopScanHandle_ln != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_stopScanHandle_ln != nullptr");
+            return;
+        }
+        // 扫描的时候保持屏幕常亮
+        /* -------------------------------------------------------------------------- */
+        ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
+        /* -------------------------------------------------------------------------- */
+        uint32_t tick = GetOSTick(MS_SCAN_TIME);
+        g_stopScanHandle_ln = new GraphicTimer(tick, LN_BluetoothScanTimerCallback, nullptr, true);
+        if (g_stopScanHandle_ln == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BluetoothEarPhoneView::BtEnable new GraphicTimer failed!!");
+            return;
+        }
+        bool retTimer = g_stopScanHandle_ln->Start();
+        if (!retTimer)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "启动扫描定时器失败");
+            if (g_stopScanHandle_ln != nullptr)
+            {
+                delete g_stopScanHandle_ln;
+                g_stopScanHandle_ln = nullptr;
+            }
+            return;
+        }
+        return;
+    }
+
+    void LN_BluetoothScanStop(void)
+    {
+        LN_CancelBrScanHandle();
+    }
+
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    // 初始化蓝牙
+    int ln_bt_init(void)
+    {
+        OHOS::BluetoothModel::GetInstance()->Init();
+        return 0;
+    }
+
+    int ln_bt_scan_start(void)
+    {
+        OHOS::LN_BluetoothScanStart();
+        return 0;
+    }
+
+    int ln_bt_scan_stop(void)
+    {
+        OHOS::LN_BluetoothScanStop();
+        return 0;
+    }
+    // 连接远程设备
+    int ln_bt_connect(const char *addr)
+    {
+        if (addr == NULL)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_connect addr is NULL");
+            return -1;
+        }
+        OHOS::BluetoothModel *bluetoothMode_ = OHOS::BluetoothModel::GetInstance();
+        // 判断是否已有连接
+        bd_addr_t *lastAddr = bluetoothMode_->GetLastConnedAddr();
+        if (bt_is_acl_connected(lastAddr))
+        {
+            WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "LastDevice addr: %02x%02x%02x%02x%02x%02x is connected",
+                          lastAddr->addr[5], lastAddr->addr[4], lastAddr->addr[3],
+                          lastAddr->addr[2], lastAddr->addr[1], lastAddr->addr[0]);
+            bluetoothMode_->DisconnectRemoteDevice();
+            bluetoothMode_->SetTagConnectNew(true);
+        }
+        errcode_t retVal = OHOS::BluetoothModel::GetInstance()->ConnectRemoteDevice((bd_addr_t *)addr);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ln_bt_connect ConnectRemoteDevice retVal = %d", retVal);
+        return 0;
+    }
+    // 断开远程设备连接
+    int ln_bt_disconnect(void)
+    {
+        OHOS::BluetoothModel *bluetoothMode_ = OHOS::BluetoothModel::GetInstance();
+        bluetoothMode_->SetTagConnectNew(false);
+        bluetoothMode_->DisconnectRemoteDevice();
+        return 0;
+    }
+    // 解绑本地设备
+    int ln_bt_unbind(void)
+    {
+        OHOS::BluetoothModel::GetInstance()->UnBindLocalDevice();
+        return 0;
+    }
+
+    // 获取绑定的本地设备MAC地址
+    char *ln_bt_get_bound_device_mac(void)
+    {
+        return OHOS::BluetoothModel::GetInstance()->GetBoundDeviceMac();
+    }
+
+    // 获取最后连接的蓝牙设备MAC地址
+    char *ln_bt_get_last_conned_device_name(void)
+    {
+        return OHOS::BluetoothModel::GetInstance()->GetLastConnedDeviceName();
+    }
+
+    // 获取最后连接的蓝牙设备电池电量
+    int ln_bt_get_last_conned_device_battery_level(void)
+    {
+        return OHOS::BluetoothModel::GetInstance()->GetLastConnedDeviceBatteryLevel();
+    }
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
index 632af7b..cee1db3 100644 (file)
@@ -29,12 +29,13 @@ typedef enum : uint16_t {
     CALLERPLAYERS,\r
 } CallerFactor;\r
 \r
-typedef struct {\r
+typedef struct\r
+{\r
     unsigned char deviceName[BD_NAME_LEN]; /* Name of the device record, must be in UTF-8 */\r
-    unsigned char addr[BD_ADDR_LEN];\r
-    int16_t index;\r
-    int16_t connIndex;\r
-    int16_t temp;\r
+    unsigned char addr[BD_ADDR_LEN];       // 设备地址\r
+    int16_t index;                         // 设备在列表中的索引\r
+    int16_t connIndex;                     // 已连接设备在列表中的索引\r
+    int16_t temp;                          // 设备信号强度\r
 } BluetoothCaseInfo;\r
 \r
 class BluetoothItemView;\r
@@ -87,10 +88,18 @@ public:
     bool GetAdvStartState(void);\r
     void SetAdvStartState(bool state);\r
     int ConnectRemoteDevice(const bd_addr_t *addr);\r
+    int DisconnectRemoteDevice(void);\r
+    int UnBindLocalDevice(void);\r
+    void SetBoundDeviceMac(const char *mac);\r
+    void SetLastConnedDeviceName(const char *name);\r
+    char *GetBoundDeviceMac(void);\r
+    char *GetLastConnedDeviceName(void);\r
+    void SetLastConnedDeviceBatteryLevel(int level);\r
+    int GetLastConnedDeviceBatteryLevel(void);\r
+    void SetScanStatus(bool value);\r
+    bool GetScanStatus(void);\r
     bool ConnectRemoteCheck(const bd_addr_t *addr);\r
     char* getWatchName(void);\r
-    void ChangeBleConnectToMax();\r
-    void ChangeBleConnectToDefault();\r
        \r
 private:\r
     BluetoothModel();\r
@@ -101,11 +110,11 @@ private:
     void InitBluetoothInfo(void);\r
     bool aclConnected{false};\r
     BluetoothCaseInfo tempMacValue{};\r
-    bd_addr_t lastConnedAddr{0};\r
-    bd_addr_t remoteConnectAddr{0};\r
+    bd_addr_t lastConnedAddr{0};   // 最后连接的设备地址\r
+    bd_addr_t remoteConnectAddr{0};// 正在连接的远程设备地址\r
     BluetoothItemView *selectItemView{nullptr};\r
-    std::list<BluetoothCaseInfo> btScansDevicesList_{};\r
-    List<BluetoothCaseInfo> *btConnedDevicesList_{nullptr};\r
+    std::list<BluetoothCaseInfo> btScansDevicesList_{};     // 扫描到的设备列表\r
+    List<BluetoothCaseInfo> *btConnedDevicesList_{nullptr}; // 已连接设备列表\r
     bool tagReconnectJump{0};\r
     int16_t curView{0};\r
     bool tagConnectView{true};\r
@@ -115,6 +124,11 @@ private:
     bool tagScanDeviceClicked{false};\r
     bool advStartState{false};\r
     char watchName[BD_NAME_LEN] = { 0 };\r
+\r
+    char boundDeviceMac[BD_NAME_LEN] = { 0 }; // 绑定的本地设备MAC地址\r
+    char lastConnedDeviceName[BD_NAME_LEN] = { 0 }; // 最后连接的设备名称\r
+    int lastConnedDeviceBatteryLevel{0}; // 最后连接的设备电池电量\r
+    bool scanStart{false}; // 扫描状态\r
 };\r
 \r
 #ifdef __cplusplus\r
diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/include/bluetooth/Ln_Bluetooth_apiC.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/include/bluetooth/Ln_Bluetooth_apiC.h
new file mode 100644 (file)
index 0000000..5751ec6
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _LN_BLUETOOTH_API_C_H_
+#define _LN_BLUETOOTH_API_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ln_bt_init(void);
+//开启蓝牙扫描
+int ln_bt_scan_start(void);
+
+//停止蓝牙扫描
+int ln_bt_scan_stop(void);
+
+// 连接远程设备
+int ln_bt_connect(const char *addr);
+
+// 断开远程设备连接
+int ln_bt_disconnect(void);
+
+// 解绑本地设备
+int ln_bt_unbind(void);
+
+// 获取绑定的本地设备MAC地址
+char *ln_bt_get_bound_device_mac(void);
+
+// 获取最后连接的蓝牙设备名称
+char *ln_bt_get_last_conned_device_name(void);
+
+// 获取最后连接的蓝牙设备电池电量
+int ln_bt_get_last_conned_device_battery_level(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
index 0248641..306ead8 100644 (file)
@@ -22,14 +22,17 @@ namespace OHOS
         void ClearAll(void);
         void Show(int16_t showView);
         void UpdateTaskReminderText(const char* text);
+        void RefreshDeviceList(void);
+        void HandleBluetoothViewOperation(int16_t view);
+        void ExecuteDisconnect(void);
         enum : int16_t {
-            THUNDERBIRD_BULEVIEW_ENTER = 0,          // 进入配对
+            THUNDERBIRD_BULEVIEW_ENTER = 0,          // 配对准备中页面
             THUNDERBIRD_BULEVIEW_SREACHING,          // 寻找设备
             THUNDERBIRD_BULEVIEW_SREACHING_FAILED,   // 搜索失败(原变量名修正拼写:v→VIEW)
             THUNDERBIRD_BULEVIEW_CONNECT_FAILED,     // 连接失败
             THUNDERBIRD_BULEVIEW_DEVICE_LIST,        // 蓝牙列表
             THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS,    // 连接成功
-            THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM, // 断连确认
+            THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM, // 断连询问
             THUNDERBIRD_BULEVIEW_DISCONNECT_SUCCESS, // 断连成功
             THUNDERBIRD_BULEVIEW_DISCONNECT_FAILED   // 断连失败
         };
index 11fb99c..48f4d1e 100644 (file)
@@ -77,6 +77,7 @@ namespace OHOS
         bool HandleLullabyViewNavigation(int16_t currentSubView, KeyType keyType);
         bool HandleReminderViewNavigation(int16_t currentSubView, KeyType keyType);
         bool HandleAdjustViewNavigation(int16_t currentSubView, KeyType keyType);
+        bool HandleBlueViewNavigation(int16_t currentSubView, KeyType keyType);
         bool CheckOtaConditionsAndProceed();
         
        
index dfcbd8f..c3af0eb 100644 (file)
@@ -4,6 +4,7 @@
 #include "common/image_cache_manager.h"
 #include "custom_utils.h"
 #include "vibrator_service.h"
+#include "bluetooth/Ln_Bluetooth_apiC.h"
 
 
 namespace OHOS
@@ -401,7 +402,10 @@ namespace OHOS
             if (TextLabel_2)//已连接到
             {
                 TextLabel_2->SetPosition(0, 184, 360, 28);
-                TextLabel_2->SetText("已连接到");
+                std::string str1 = "已连接到";
+                std::string str2 = ln_bt_get_last_conned_device_name();
+                std::string deviceName = str1 + str2;
+                TextLabel_2->SetText(deviceName.c_str());
                 TextLabel_2->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
                 TextLabel_2->SetVisible(true);
             } 
@@ -454,7 +458,10 @@ namespace OHOS
             if (TextLabel_2)//已连接到
             {
                 TextLabel_2->SetPosition(0, 184, 360, 28);
-                TextLabel_2->SetText("已连接到");
+                std::string str1 = "已连接到";
+                std::string str2 = ln_bt_get_last_conned_device_name();
+                std::string deviceName = str1 + str2;
+                TextLabel_2->SetText(deviceName.c_str());
                 TextLabel_2->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
                 TextLabel_2->SetVisible(true);
             } 
@@ -567,11 +574,40 @@ namespace OHOS
         default:
             break;
         }
+        HandleBluetoothViewOperation(showView);
+        return;
     }
     void ThunderBirdBlueView::UpdateTaskReminderText(const char* text)
     {
         if (TextLabel) { TextLabel->SetText(text); }
     }
+    
+    void ThunderBirdBlueView::RefreshDeviceList(void)
+    {
+        if (DeviceList == nullptr) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BluetoothEarListView nullptr");
+            return;
+        }
+        DeviceList->RefreshList();
+    }
+    // 处理蓝牙视图操作
+    void ThunderBirdBlueView::HandleBluetoothViewOperation(int16_t view)
+    {
+        if(view == THUNDERBIRD_BULEVIEW_SREACHING)
+        {
+            // 开启蓝牙扫描
+            ln_bt_scan_start();
+        }
+        else
+        {
+            // 关闭蓝牙扫描
+            ln_bt_scan_stop();
+        }
+    }
+    
+    // 执行蓝牙断开连接操作
+    void ThunderBirdBlueView::ExecuteDisconnect(void)
+    {
+        ln_bt_disconnect();
+    }
 }
-
-
index 05ba7db..b2d327b 100644 (file)
@@ -192,6 +192,11 @@ namespace OHOS
             delete g_pThunderBirdShutdownView;
             g_pThunderBirdShutdownView = nullptr;
         }
+        if (g_pThunderBirdBlueView)
+        {
+            delete g_pThunderBirdBlueView;
+            g_pThunderBirdBlueView = nullptr;
+        }
 
         // 不再持有旧 View 实例,全部使用聚合组件
         // 先停止视频播放
@@ -584,6 +589,22 @@ namespace OHOS
         }
         return true;
     }
+    bool ThunderBirdMainView::ChangeThunderBirdBlueView(int16_t thisView) // 切换蓝牙耳机界面接口
+    {
+        if (group[thisView] == nullptr)
+        {
+            g_pThunderBirdBlueView = new ThunderBirdBlueView();
+            if (g_pThunderBirdBlueView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdBlueView new fail %d", thisView);
+                return false;
+            }
+            group[thisView] = g_pThunderBirdBlueView->ThunderBirdBlueViewInit();
+            ScrollView_->Add(group[thisView]);
+        }
+        return true;
+    }
+
 
     /**
      * 视图映射结构体 - 将视图ID映射到对应的视图切换函数
@@ -601,6 +622,7 @@ namespace OHOS
         {THUNDERBIRD_REMINDERVIEW, &ThunderBirdMainView::ChangeThunderBirdReminderView},
         {THUNDERBIRD_ADJUSTVIEW, &ThunderBirdMainView::ChangeThunderBirdAdjustView},
         {THUNDERBIRD_SHUTDOWNVIEW, &ThunderBirdMainView::ChangeThunderBirdShutdownView},
+        {THUNDERBIRD_BLUEVIEW, &ThunderBirdMainView::ChangeThunderBirdBlueView},
     };
 
     bool ThunderBirdMainView::ClickFunc(int16_t interface)
@@ -703,6 +725,12 @@ namespace OHOS
                     g_pThunderBirdAdjustView->Show(subView);
                 }
                 break;
+            case THUNDERBIRD_BLUEVIEW:
+                if (g_pThunderBirdBlueView)
+                {
+                    g_pThunderBirdBlueView->Show(subView);
+                }
+                break;
             default:
                 break;
             }
index ad8dca3..d202ccd 100644 (file)
@@ -18,6 +18,7 @@
  #include "thunderbird/include/ThunderBirdReminderView.h"
  #include "thunderbird/include/ThunderBirdLullabyView.h"
  #include "thunderbird/include/ThunderBirdMainView.h"
+ #include "thunderbird/include/ThunderBirdBlueView.h"
  #include "thunderbird/include/ThunderBirdPresenter.h"
  #include "wearable_log.h"
  #include <sys/time.h>
@@ -2551,6 +2552,12 @@ extern "C" {
     {
         // bluetoothAddress//保留字段,暂时无用
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleBluetoothConnect: 收到蓝牙耳机连接通知,bluetoothAddress=%s", bluetoothAddress);
+        if(ThunderBirdMainView::GetInstance()){
+            //亮屏
+            uapi_set_screen_on_api();
+            int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); //获取当前视图
+            ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_ENTER);
+        }
     }
 
     void ThunderBirdModel::HandleBindAndUnbind(int is_bind)
index c5df130..5578435 100644 (file)
@@ -561,6 +561,9 @@ namespace OHOS
                 
             case THUNDERBIRD_ADJUSTVIEW://提示界面
                 return HandleAdjustViewNavigation(currentSubView, keyType);
+            
+            case THUNDERBIRD_BLUEVIEW://蓝牙界面
+                return HandleBlueViewNavigation(currentSubView, keyType);
                 
             default:
                 return true;
@@ -782,6 +785,78 @@ namespace OHOS
         return true;
     }
 
+     /**
+     * @brief 处理蓝牙界面导航
+     */
+    bool ThunderBirdPresenter::HandleBlueViewNavigation(int16_t currentSubView, KeyType keyType)
+    {
+        WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "HandleBlueViewNavigation: currentSubView = %d, keyType = %d", currentSubView, keyType);
+        int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView();
+        if(ThunderBirdBlueView::GetInstance() == nullptr)
+        {
+            return false;
+        }
+        if(keyType == KEY_TYPE_VENDOR_UP)
+        {
+            switch (currentSubView) {
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_ENTER:
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING_FAILED: 
+                    //无设备搜索失败,返回搜索界面,提示用户重新搜索
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_SUCCESS: 
+                    //蓝牙已断开,返回搜索界面,提示用户重新搜索
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS:
+                    //跳转到断连询问界面
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM:
+                    //执行断连操作
+                    ThunderBirdBlueView::GetInstance()->ExecuteDisconnect();
+                    break;
+            }
+        }
+        else if(keyType == KEY_TYPE_VENDOR_DOWN)
+        {
+            switch (currentSubView) {
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING:
+                    //搜索中,中途退出,返回配对准备中页面
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_ENTER);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_ENTER:
+                    //配对中,中途退出,返回配对准备中页面
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW);
+                    break;
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS:
+                    //返回设备列表
+                    ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST);
+                    break;
+            }
+        }
+        else if(keyType == KEY_TYPE_FUNC)
+        {
+            switch (currentSubView) {
+                case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST:
+                    //搜索中,点击确认,返回配对准备中页面
+                    // ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_ENTER);
+                    break;
+                // case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS:
+                //     //跳转到断连询问界面
+                //     ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_BLUEVIEW, ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM);
+                //     break;
+                // case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM:
+                //     //执行断连操作
+                //     ThunderBirdBlueView::GetInstance()->ExecuteDisconnect();
+                //     break;
+            }
+        }
+        return true;
+    }
+
     // 更新二维码
     void ThunderBirdPresenter::UpdateQrcodeIfValid()
     {
@@ -947,6 +1022,27 @@ namespace OHOS
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdPresenter::HandleFuncKeyLongPress");
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_LULLABYVIEW, ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_5);
             }
+            //当前为蓝牙配对界面
+            else if(currentView == THUNDERBIRD_BLUEVIEW)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdPresenter::HandleFuncKeyLongPress");
+                switch(currentSubView)
+                {
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING: 
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_SREACHING_FAILED:
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_FAILED:
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DEVICE_LIST:
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_CONNECT_SUCCESS:
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_CONFIRM:
+                    case ThunderBirdBlueView::THUNDERBIRD_BULEVIEW_DISCONNECT_FAILED:
+                    //搜索中页面长按对话按键退出到主页面
+                    ThunderBirdMainView::GetInstance()->ChangeView(
+                        currentView, 
+                        THUNDERBIRD_DIALOGUEVIEW, 
+                        ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_STATUS_SHOW);
+                    break;
+                }
+            }
         }
     }
 
index b28cb23..2c5bb2b 100644 (file)
@@ -13,6 +13,9 @@
 #include "ln_api_interface.h"
 #include "cJSON.h"
 #include "broadcast_feature.h"
+#include "bts_br_gap.h"
+#include "bts_def.h"
+#include "bluetooth/Ln_Bluetooth_apiC.h"
 
 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
 #define LN_MAX_ARGC 8
@@ -1657,9 +1660,176 @@ static uint32_t ln_bluetooth_status_report_at(uint8_t *para, uint32_t paraLen, c
     }
     printf("+LN_BLUETOOTH_STATUS_REPORT: OK\n");
     printf("[LN][BLUETOOTH_STATUS_REPORT] bluetoothStatus=%s\n", bluetoothStatus);
-    do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus));
+    // do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_BLUETOOTH_STATUS_REPORT, bluetoothStatus, strlen(bluetoothStatus));
+    push_bluetooth_connect_notification(bluetoothStatus);
     return ERRCODE_SUCC;
 }
+/* 格式化打印蓝牙地址 */
+static void print_bt_address(const bd_addr_t *addr)
+{
+    if (addr == NULL) {
+        return;
+    }
+    printf("%02X:%02X:%02X:%02X:%02X:%02X",
+           addr->addr[5], addr->addr[4], addr->addr[3],
+           addr->addr[2], addr->addr[1], addr->addr[0]);
+}
+
+/* AT^LN_BT_SCAN - 搜索附近蓝牙设备 */
+static uint32_t ln_bt_scan_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(para);
+    LN_UNUSED(paraLen);
+    LN_UNUSED(strCommonCmd);
+    ln_bt_scan_start();
+    return ERRCODE_SUCC;
+}
+
+/* AT^LN_BT_SCAN_STOP - 停止搜索蓝牙设备 */
+static uint32_t ln_bt_scan_stop_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(para);
+    LN_UNUSED(paraLen);
+    LN_UNUSED(strCommonCmd);
+    ln_bt_scan_stop();
+    return ERRCODE_SUCC;
+}
+
+/* 解析蓝牙地址字符串为 bd_addr_t 结构 */
+static int parse_bt_address(const char *addr_str, bd_addr_t *addr)
+{
+    if (addr_str == NULL || addr == NULL) {
+        return LN_FAILED;
+    }
+    
+    // 支持格式: "AA:BB:CC:DD:EE:FF" 或 "AABBCCDDEEFF"
+    unsigned int addr_bytes[6] = {0};
+    int count = sscanf(addr_str, "%02X:%02X:%02X:%02X:%02X:%02X",
+                       &addr_bytes[0], &addr_bytes[1], &addr_bytes[2],
+                       &addr_bytes[3], &addr_bytes[4], &addr_bytes[5]);
+    
+    if (count != 6) {
+        // 尝试无冒号格式
+        count = sscanf(addr_str, "%02X%02X%02X%02X%02X%02X",
+                       &addr_bytes[0], &addr_bytes[1], &addr_bytes[2],
+                       &addr_bytes[3], &addr_bytes[4], &addr_bytes[5]);
+        if (count != 6) {
+            return LN_FAILED;
+        }
+    }
+    
+    // 蓝牙地址是反向存储的
+    addr->addr[0] = (unsigned char)addr_bytes[5];
+    addr->addr[1] = (unsigned char)addr_bytes[4];
+    addr->addr[2] = (unsigned char)addr_bytes[3];
+    addr->addr[3] = (unsigned char)addr_bytes[2];
+    addr->addr[4] = (unsigned char)addr_bytes[1];
+    addr->addr[5] = (unsigned char)addr_bytes[0];
+    
+    return LN_SUCCESS;
+}
+
+/* AT^LN_BT_PAIR=AA:BB:CC:DD:EE:FF - 绑定指定蓝牙设备 */
+static uint32_t ln_bt_pair_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(strCommonCmd);
+    
+    if (para == NULL || paraLen == 0) {
+        printf("ERROR: Missing Bluetooth address parameter\n");
+        printf("Usage: AT^LN_BT_PAIR=AA:BB:CC:DD:EE:FF\n");
+        return ERRCODE_FAIL;
+    }
+    
+    uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
+    uint32_t argc = 0;
+    if (ConvertCmdToParam(para, paraLen, argv, &argc) != LN_SUCCESS || argc < 1) {
+        printf("ERROR: Failed to parse Bluetooth address\n");
+        return ERRCODE_FAIL;
+    }
+    
+    bd_addr_t addr = {0};
+    if (parse_bt_address((char*)argv[0], &addr) != LN_SUCCESS) {
+        printf("ERROR: Invalid Bluetooth address format\n");
+        printf("Usage: AT^LN_BT_PAIR=AA:BB:CC:DD:EE:FF\n");
+        return ERRCODE_FAIL;
+    }
+    
+    printf("[LN][BT_PAIR] Pairing with device: ");
+    print_bt_address(&addr);
+    printf("\n");
+    
+    // 先连接设备(连接后会自动配对)
+    errcode_t ret = gap_connect_remote_device(&addr);
+    if (ret == ERRCODE_SUCC) {
+        printf("+LN_BT_PAIR: OK\n");
+        printf("[LN][BT_PAIR] Connection initiated, pairing will occur automatically\n");
+    } else {
+        printf("+LN_BT_PAIR: FAIL\n");
+        printf("[LN][BT_PAIR] Failed to connect device, ret=0x%X\n", ret);
+        return ERRCODE_FAIL;
+    }
+    
+    return ERRCODE_SUCC;
+}
+
+/* AT^LN_BT_UNPAIR=AA:BB:CC:DD:EE:FF - 解绑指定蓝牙设备 */
+static uint32_t ln_bt_unpair_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(strCommonCmd);
+    ln_bt_unbind();
+    return ERRCODE_SUCC;
+}
+
+/* AT^LN_BT_CONNECT=AA:BB:CC:DD:EE:FF - 连接蓝牙设备 */
+static uint32_t ln_bt_connect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(strCommonCmd);
+    
+    if (para == NULL || paraLen == 0) {
+        printf("ERROR: Missing Bluetooth address parameter\n");
+        printf("Usage: AT^LN_BT_CONNECT=AA:BB:CC:DD:EE:FF\n");
+        return ERRCODE_FAIL;
+    }
+    
+    uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
+    uint32_t argc = 0;
+    if (ConvertCmdToParam(para, paraLen, argv, &argc) != LN_SUCCESS || argc < 1) {
+        printf("ERROR: Failed to parse Bluetooth address\n");
+        return ERRCODE_FAIL;
+    }
+    
+    bd_addr_t addr = {0};
+    if (parse_bt_address((char*)argv[0], &addr) != LN_SUCCESS) {
+        printf("ERROR: Invalid Bluetooth address format\n");
+        printf("Usage: AT^LN_BT_CONNECT=AA:BB:CC:DD:EE:FF\n");
+        return ERRCODE_FAIL;
+    }
+    
+    printf("[LN][BT_CONNECT] Connecting to device: ");
+    print_bt_address(&addr);
+    printf("\n");
+    
+    int ret = ln_bt_connect(&addr);
+    if (ret != LN_SUCCESS) {
+        printf("+LN_BT_CONNECT: FAIL\n");
+        printf("[LN][BT_CONNECT] Failed to connect device, ret=0x%X\n", ret);
+        return ERRCODE_FAIL;
+    }
+    
+    return ERRCODE_SUCC;
+}
+
+/* AT^LN_BT_DISCONNECT=AA:BB:CC:DD:EE:FF - 断开蓝牙设备 */
+static uint32_t ln_bt_disconnect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(strCommonCmd);
+    LN_UNUSED(para);
+    LN_UNUSED(paraLen);
+    // 先断开连接
+    ln_bt_disconnect();
+    return ERRCODE_SUCC;
+}
+
 static const at_cmd_table_t g_ln_api_cmd[] = {
     /* ---------------------------------- 雷鸟API --------------------------------- */
     {(char *)"AT^LN_GET_TOKEN", ln_get_device_token_at, (char *)"获取雷鸟设备Token: AT^LN_GET_TOKEN[=deviceId,deviceIccid,deviceModel,deviceVersion]"},
@@ -1749,6 +1919,12 @@ static const at_cmd_table_t g_ln_api_cmd[] = {
 
     //蓝牙相关
     {(char *)"AT^LN_BLUETOOTH_STATUS_REPORT", ln_bluetooth_status_report_at, (char *)"蓝牙状态上报: AT^LN_BLUETOOTH_STATUS_REPORT[=bluetoothStatus]"},
+    {(char *)"AT^LN_BT_SCAN", ln_bt_scan_at, (char *)"搜索附近蓝牙设备: AT^LN_BT_SCAN"},
+    {(char *)"AT^LN_BT_SCAN_STOP", ln_bt_scan_stop_at, (char *)"停止搜索蓝牙设备: AT^LN_BT_SCAN_STOP"},
+    {(char *)"AT^LN_BT_PAIR", ln_bt_pair_at, (char *)"绑定指定蓝牙设备: AT^LN_BT_PAIR=AA:BB:CC:DD:EE:FF"},
+    {(char *)"AT^LN_BT_UNPAIR", ln_bt_unpair_at, (char *)"解绑指定蓝牙设备: AT^LN_BT_UNPAIR=AA:BB:CC:DD:EE:FF"},
+    {(char *)"AT^LN_BT_CONNECT", ln_bt_connect_at, (char *)"连接蓝牙设备: AT^LN_BT_CONNECT=AA:BB:CC:DD:EE:FF"},
+    {(char *)"AT^LN_BT_DISCONNECT", ln_bt_disconnect_at, (char *)"断开蓝牙设备: AT^LN_BT_DISCONNECT=AA:BB:CC:DD:EE:FF"},
 };
 
 
index f90ea0c..ed637ae 100644 (file)
@@ -2,6 +2,7 @@
 #include "cJSON.h"
 #include "custom_utils.h"
 #include <string.h>
+#include "bluetooth/Ln_Bluetooth_apiC.h"
 
 /* 蓝牙状态枚举值常量 */
 #define BT_STATUS_CONNECTED "CONNECTED"           /* 蓝牙已连接 */
@@ -23,15 +24,9 @@ static int battery_level;          /* 电池电量百分比,范围0-100 */
 char *ln_get_bluetooth_device_mac(void)
 {
     bluetooth_address[0] = '\0';
-    // errcode_t res = bluetooth_get_bound_device_mac(bluetooth_address, sizeof(bluetooth_address));
-    // if (res != ERRCODE_SUCCESS)
-    // {
-    //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备MAC地址失败");
-    //     return NULL;
-    // }
-    // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备MAC地址成功:%s", bluetooth_address);
-    strncpy(bluetooth_address, "AA:BB:CC:DD:EE:FF", sizeof(bluetooth_address) - 1);
+    strncpy(bluetooth_address, ln_bt_get_bound_device_mac(), sizeof(bluetooth_address) - 1);
     bluetooth_address[sizeof(bluetooth_address) - 1] = '\0';
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备MAC地址成功:%s", bluetooth_address);
     return bluetooth_address;
 }
 
@@ -39,15 +34,9 @@ char *ln_get_bluetooth_device_mac(void)
 char *ln_get_bluetooth_device_name(void)
 {
     bluetooth_name[0] = '\0';
-    // errcode_t res = bluetooth_get_bound_device_name(bluetooth_name, sizeof(bluetooth_name));
-    // if (res != ERRCODE_SUCCESS)
-    // {
-    //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备名称失败");
-    //     return NULL;
-    // }
-    // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备名称成功:%s", bluetooth_name);
-    strncpy(bluetooth_name, "AirPods Pro", sizeof(bluetooth_name) - 1);
+    strncpy(bluetooth_name, ln_bt_get_last_conned_device_name(), sizeof(bluetooth_name) - 1);
     bluetooth_name[sizeof(bluetooth_name) - 1] = '\0';
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[BT] 获取已绑定的耳机蓝牙设备名称成功:%s", bluetooth_name);
     return bluetooth_name;
 }
 
@@ -123,7 +112,7 @@ static int ln_ws_send_bluetooth_status_report(const char *bluetooth_address, con
     }
 
     int ret = uapi_ws_send_text(json_string);
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Sent BluetoothStatusReport: %s\n", json_string);
+    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Sent BluetoothStatusReport: %s\n", json_string);
     cJSON_free(json_string);
     cJSON_Delete(json);
     return ret;