killapp/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs
“虞渠成” 1e1fd209f9 fix(connectDevice): 修复跨平台蓝牙设备连接逻辑
适配iOS和Android不同的蓝牙地址规则,通过有效地址匹配设备后再发起连接
2026-07-23 16:21:24 +08:00

571 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Kill.Bluetooth;
using Kill.Core;
using Kill.Managers;
using Kill.Network;
using Kill.UI;
using Kill.UI.Components;
using Kill.UI.Pages;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class ConnectDevicePageCtrl : MonoBehaviour
{
/// <summary>
/// 0连接 1 失败 2 成功 3 选择wifi
/// </summary>
public GameObject[] sonPages;
public GameObject topBar;
public string blueToothNameKeyWord;
private List<BluetoothDevice> deviceList = new List<BluetoothDevice>();
public Button backButton;
public Button skipButton;
public GameObject titleText;
public GameObject scanningIcon;
void Start()
{
BluetoothManager.Instance.OnDeviceFound += OnDeviceFound;
BluetoothManager.Instance.OnConnectedSuccess += OnDeviceConnected;
BluetoothManager.Instance.OnConnectFailed += OnConnectFailed;
BluetoothManager.Instance.OnDisconnected += OnDeviceDisconnected;
EnterConnectPage();
}
void OnDestroy()
{
BluetoothManager.Instance.OnDeviceFound -= OnDeviceFound;
BluetoothManager.Instance.OnConnectedSuccess -= OnDeviceConnected;
BluetoothManager.Instance.OnConnectFailed -= OnConnectFailed;
BluetoothManager.Instance.OnDisconnected -= OnDeviceDisconnected;
}
IEnumerator WaitToScan()
{
yield return new WaitForSeconds(1);
EnterConnectPage();
}
public void EnterConnectPage()
{
if(BluetoothManager.Instance.IsConnected)
{
BluetoothManager.Instance.Disconnect();
StartCoroutine(WaitToScan());
}
OnStopScanClick();
BluetoothManager.Instance.ChangeAimMac("");
topBar.SetActive(true);
titleText.SetActive(false);
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(BackToHomePage);
backButton.gameObject.SetActive(true);
skipButton.gameObject.SetActive(false);
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[0].SetActive(true);
UIManager.Instance.RegisterBackAction(BackToHomePage);
OnScanClick();
}
public GameObject qrCodePlane;
public void ScanQrCode()
{
qrCodePlane.SetActive(true);
qrCodePlane.GetComponent<ScanQRcode>().OnQRCodeScanned+=GetQrResult;
}
public void GetQrResult(string result)
{
qrCodePlane.GetComponent<ScanQRcode>().Close();
foreach(var d in DataManager.Instance.OwnedDevices)
{
if (d.ble_mac == result)
{
ToastUI.Show("100287");
qrCodePlane.GetComponent<ScanQRcode>().OnQRCodeScanned += GetQrResult;
return;
}
}
foreach(var d in DataManager.Instance.SharedDevices)
{
if (d.ble_mac == result)
{
ToastUI.Show("100287");
qrCodePlane.GetComponent<ScanQRcode>().OnQRCodeScanned += GetQrResult;
return;
}
}
isconnecting=true;
// 根据 MAC 在已扫描到的设备列表中查找对应设备
// iOS: Address 是 UUID, MacFromBroadcast 是真实 MAC
// Android: Address 本身就是 MAC
string targetMac = result.ToUpper();
var foundDevice = BluetoothManager.Instance.DiscoveredDevices.Find(
d => d.GetEffectiveAddress().ToUpper() == targetMac
);
if (foundDevice != null)
{
// 找到设备用正确的地址连接iOS 用 UUIDAndroid 用 MAC
BluetoothManager.Instance.Connect(foundDevice.Address);
}
else
{
// 未找到,设置 aimMac 让扫描到设备时自动连接
BluetoothManager.Instance.ChangeAimMac(result);
}
LoadingUI.Show();
qrCodePlane.SetActive(false);
nowDeviceMac=result;
}
string errorTip="";
private void ShowErrorPage()
{
if(BluetoothManager.Instance.IsConnected)
{
BluetoothManager.Instance.Disconnect();
}
topBar.SetActive(false);
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[1].SetActive(true);
Text errorText=sonPages[1].transform.Find("提示").GetComponent<Text>();
if(errorTip!="")
{
errorText.text=LanguageManager.Instance.GetLanguage(errorTip);
}
else
{
errorText.text=LanguageManager.Instance.GetLanguage("100069");
}
UIManager.Instance.RegisterBackAction(EnterConnectPage);
LoadingUI.Hide();
}
public InputField wifiNameInput;
public InputField wifiPasswordInput;
public void ShowWifiPage()
{
topBar.SetActive(true);
titleText.SetActive(true);
backButton.gameObject.SetActive(false);
UIManager.Instance.ClearBackAction();
skipButton.gameObject.SetActive(true);
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[3].SetActive(true);
// 获取当前 WiFi 名称
string wifiName = GetCurrentWiFiName();
wifiNameInput.text = wifiName ?? "";
wifiPasswordInput.text="";
}
/// <summary>
/// 确认配置 WiFi
/// </summary>
public void OnWifiConfirmClick()
{
string ssid = wifiNameInput.text.Trim();
string password = wifiPasswordInput.text;
if (string.IsNullOrEmpty(ssid))
{
ToastUI.Show("100082");
return;
}
// 创建 WiFi 配置
var wifiControl = new Kill.Bluetooth.Protocol.WIFIControl
{
Enable = true,
SSID = ssid,
Password = password
};
LoadingUI.Show();
// 发送 WiFi 配置到设备
BLECommunicationManager.Instance.WriteWIFIControl(wifiControl, (success) =>
{
Loom.QueueOnMainThread(() =>
{
LoadingUI.Hide();
if (success)
{
UnityEngine.Debug.Log("WiFi 配置成功");
DataManager.Instance.deviceConfig.wifi_enable = true;
DataManager.Instance.deviceConfig.wifi_ssid = ssid;
DataManager.Instance.deviceConfig.wifi_password = password;
DataManager.Instance.SyncDeviceConfigToServer();
ShowSuccessPage();
}
else
{
ToastUI.Show("100083");;
}
});
});
}
/// <summary>
/// 0不可点击 1可点击
/// </summary>
public GameObject[] wifiConfirmButtons;
public void CheckWifiNameAndPassword()
{
string ssid = wifiNameInput.text.Trim();
string password = wifiPasswordInput.text;
if(string.IsNullOrEmpty(ssid) || string.IsNullOrEmpty(password))
{
wifiConfirmButtons[0].SetActive(true);
wifiConfirmButtons[1].SetActive(false);
}
else
{
wifiConfirmButtons[0].SetActive(false);
wifiConfirmButtons[1].SetActive(true);
}
}
/// <summary>
/// 获取当前连接的 WiFi 名称
/// </summary>
private string GetCurrentWiFiName()
{
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
using (AndroidJavaObject wifiManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "wifi"))
{
if (wifiManager == null) return null;
using (AndroidJavaObject wifiInfo = wifiManager.Call<AndroidJavaObject>("getConnectionInfo"))
{
if (wifiInfo == null) return null;
string ssid = wifiInfo.Call<string>("getSSID");
if (!string.IsNullOrEmpty(ssid) && ssid != "<unknown ssid>")
{
return ssid.Trim('"');
}
}
}
}
catch (System.Exception ex)
{
Debug.LogError($"获取 WiFi 名称失败: {ex.Message}");
}
return null;
#elif UNITY_IOS && !UNITY_EDITOR
// iOS 调用原生插件
return GetWiFiNameIOS();
#else
return "Editor_WiFi"; // 编辑器返回模拟值
#endif
}
#if UNITY_IOS && !UNITY_EDITOR
[System.Runtime.InteropServices.DllImport("__Internal")]
private static extern System.IntPtr GetWiFiSSID();
/// <summary>
/// iOS 获取 WiFi 名称
/// </summary>
private string GetWiFiNameIOS()
{
try
{
System.IntPtr ptr = GetWiFiSSID();
if (ptr == System.IntPtr.Zero)
{
return null;
}
string ssid = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptr);
// 释放内存
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
return ssid;
}
catch (System.Exception ex)
{
Debug.LogError($"iOS 获取 WiFi 名称失败: {ex.Message}");
return null;
}
}
#endif
public void ShowSuccessPage()
{
topBar.SetActive(false);
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[2].SetActive(true);
UIManager.Instance.RegisterBackAction(EnterConnectPage);
}
private void OnDeviceFound(BluetoothDevice device)
{
if(string.IsNullOrEmpty(device.Name))
return;
Debug.Log($"[发现新设备] {device.Name} Address={device.Address} MAC={device.GetEffectiveAddress()} RSSI={device.Rssi} 广播数据(Hex)={BitConverter.ToString(device.info)}");
foreach(var d in DataManager.Instance.OwnedDevices)
{
if(d.ble_mac==device.GetEffectiveAddress())
return;
}
foreach(var d in DataManager.Instance.SharedDevices)
{
if(d.ble_mac==device.GetEffectiveAddress())
return;
}
AddOneDevice(device);
}
private void OnDeviceConnected()
{
if (selectedIndex >= 0 && selectedIndex < deviceObjects.Count)
{
deviceObjects[selectedIndex].transform.Find("状态").Find("loading").gameObject.SetActive(false);
deviceObjects[selectedIndex].transform.Find("状态").Find("成功").gameObject.SetActive(true);
}
// 延迟 500ms 再查询,确保 BLE 连接完全就绪
StartCoroutine(DelayedQueryRegistration());
isconnecting =false;
}
/// <summary>
/// 延迟查询注册状态
/// </summary>
private System.Collections.IEnumerator DelayedQueryRegistration()
{
yield return new WaitForSeconds(0.5f);
//OnQueryRegistrationClick();
BandDevice();
}
private void OnConnectFailed(string address)
{
if(!isconnecting)
return;
errorTip="100069";
ShowErrorPage();
isconnecting=false;
}
private void OnDeviceDisconnected(string address)
{
// UpdateStatus($"已断开连接: {address}");
// if (deviceStatusText != null)
// deviceStatusText.text = "未连接";
}
public List<GameObject> deviceObjects;
/// <summary>
/// 开始扫描
/// </summary>
public void OnScanClick()
{
scanningIcon.SetActive(true);
devicePrefab.SetActive(false);
if (BluetoothManager.Instance != null)
{
// 清空列表
deviceList.Clear();
if (deviceObjects != null && deviceObjects.Count > 0)
{
foreach (var item in deviceObjects)
{
Destroy(item);
}
deviceObjects.Clear();
}
deviceObjects = new List<GameObject>();
// 用户进入配网页面,强制初始化以触发蓝牙开启提示
BluetoothManager.Instance.ForceInitialize();
BluetoothManager.Instance.StartScan(999f); // 扫描999秒
}
}
public GameObject deviceListParent;
public GameObject devicePrefab;
public GameObject deviceListUi;
bool isconnecting=false;
public void AddOneDevice(BluetoothDevice device)
{
if (deviceList.Contains(device))
return;
if(!device.Name.Contains(blueToothNameKeyWord))
return;
if(!deviceListUi.activeSelf)
deviceListUi.SetActive(true);
deviceList.Add(device);
GameObject deviceObject = Instantiate(devicePrefab, deviceListParent.transform);
deviceObject.transform.Find("name").GetComponent<Text>().text=device.Name;
deviceObject.transform.Find("mac").GetComponent<Text>().text=device.GetEffectiveAddress();
deviceObject.SetActive(true);
deviceObjects.Add(deviceObject);
int index = deviceObjects.Count-1;
deviceObject.GetComponent<Button>().onClick.AddListener(() =>ClickOneDevice(index));
isconnecting=true;
}
int selectedIndex=-1;
string nowDeviceMac="";
public void ClickOneDevice(int index)
{
if (BluetoothManager.Instance == null) return;
OnStopScanClick();
selectedIndex = index;
if (selectedIndex >= 0 && selectedIndex < deviceList.Count)
{
var device = deviceList[selectedIndex];
Debug.Log("设备mac:"+device.GetEffectiveAddress());
nowDeviceMac=device.GetEffectiveAddress();
BluetoothManager.Instance.Connect(device.Address);
LoadingUI.Show();
deviceObjects[index].transform.Find("状态").Find("loading").gameObject.SetActive(true);
}
}
/// <summary>
/// 停止扫描
/// </summary>
public void OnStopScanClick()
{
scanningIcon.SetActive(false);
if (BluetoothManager.Instance != null)
{
BluetoothManager.Instance.StopScan();
}
}
/// <summary>
/// 查询设备注册状态
/// </summary>
private void OnQueryRegistrationClick()
{
BLECommunicationManager.Instance.QueryRegistrationStatus((success,status) =>
{
Loom.QueueOnMainThread(() =>
{
if (success)
{
bool IsRegistered = status.IsRegistered;
if (IsRegistered)
{
errorTip = "100070";
ShowErrorPage();
}
else
{
BandDevice();
}
}
else
{
errorTip = "100069";
ShowErrorPage();
}
});
});
}
/// <summary>
/// 注册设备
/// </summary>
private void OnRegisterDeviceClick()
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.RegisterDevice(username, (success, message) =>
{
Loom.QueueOnMainThread(() =>
{
LoadingUI.Hide();
ShowWifiPage();
DataManager.Instance.SavaSelectedDeviceMac(nowDeviceMac);
// if (success)
// {
// ShowWifiPage();
// DataManager.Instance.SavaSelectedDeviceMac(nowDeviceMac);
// }
// else
// {
// errorTip = "100070";
// ShowErrorPage();
// }
});
});
}
/// <summary>
/// 注销用户
/// </summary>
private void OnUnregisterUserClick()
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.UnregisterUser(username, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
Debug.Log($"用户 {username} 注销成功!");
}
else
{
OnUnregisterUserClick();
}
});
});
}
public void BackToHomePage()
{
OnStopScanClick();
UIManager.Instance.OpenPage(UIManager.PageName.homePage, null, true);
}
/// <summary>
/// 绑定设备
/// </summary>
public async void BandDevice()
{
LoadingUI.Show();
try
{
BandDeviceRequest request = new BandDeviceRequest
{
device_sn = nowDeviceMac,
user_id = DataManager.Instance.userInfo.id,
};
Debug.Log($"绑定设备请求: deviceSn={request.device_sn}, userId={request.user_id}");
var response = await NetworkCtrl.Instance.Post<NoDataResponse>("/api/v1/device/bind", request);
LoadingUI.Hide();
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
Debug.Log($"绑定设备成功");
OnRegisterDeviceClick();
}
,
onError: (code,message) =>
{
Debug.Log($"绑定设备失败:{code},{message}");
errorTip = "100070";
ShowErrorPage();
}
);
}
catch (Exception ex)
{
LoadingUI.Hide();
Debug.LogError($"绑定设备异常: {ex.Message}");
}
}
public void ConnectError()
{
errorTip = "100069";
ShowErrorPage();
}
}