killapp/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs
“虞渠成” 0f14d60f2f feat: 完善设备连接流程与多资源更新
1.  新增视频加载中的提示文案与图标资源
2.  调整服务器API地址为正式环境
3.  重构连接设备页面逻辑,优化设备注册绑定流程
4.  更新教学视频与文案为中文版本
5.  增加视频播放前的就绪校验逻辑
2026-08-21 09:49:21 +08:00

823 lines
27 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 System.Threading.Tasks;
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 4 指纹初始化
/// </summary>
public GameObject[] sonPages;
public string blueToothNameKeyWord;
private List<BluetoothDevice> deviceList = new List<BluetoothDevice>();
public GameObject scanningIcon;
/// <summary>设置指纹按钮</summary>
public Button fingerprintSetupButton;
/// <summary>跳过按钮</summary>
public Button fingerprintSkipButton;
/// <summary>引导录入指纹的提示框(用户制作,默认隐藏,设置指纹成功后显示)</summary>
public GameObject fingerInitTip;
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("");
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();
}
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()
{
//无法返回设备注册流程,清空返回操作
UIManager.Instance.ClearBackAction();
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[3].SetActive(true);
#if UNITY_IOS && !UNITY_EDITOR
// iOS异步请求位置权限授权后自动填入 WiFi 名称
wifiNameInput.text = "";
iOSWiFiHelper.RequestWiFiSSID((ssid) =>
{
if (!string.IsNullOrEmpty(ssid))
{
wifiNameInput.text = ssid;
}
});
#else
// 获取当前 WiFi 名称
string wifiName = GetCurrentWiFiName();
wifiNameInput.text = wifiName ?? "";
#endif
wifiPasswordInput.text="";
UIManager.Instance.ClearBackAction();
}
/// <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();
ShowFingerprintPage();
}
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()
{
foreach(GameObject g in sonPages)
g.gameObject.SetActive(false);
sonPages[2].SetActive(true);
UIManager.Instance.RegisterBackAction(BackToHomePage);
}
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);
// 抵消连接设备时的Loading点击设备/扫码时Show过后续由BandDevice自行管理Loading
LoadingUI.Hide();
// 连接成功后:先调用服务器绑定接口,绑定成功后再走蓝牙流程
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)
{
if (status.IsRegistered)
{
// 已注册:查询设备端用户列表,挨个注销
OnQueryUserListClick();
}
else
{
// 未注册:蓝牙注册当前用户
OnRegisterDeviceClick();
}
}
else
{
LoadingUI.Hide();
errorTip = "100069";
ShowErrorPage();
}
});
});
}
/// <summary>
/// 查询设备端用户列表
/// 有用户挨个注销注销完注册当前用户无用户固件bug直接登录当前用户
/// </summary>
private void OnQueryUserListClick()
{
BLECommunicationManager.Instance.QueryUserList((userList) =>
{
Loom.QueueOnMainThread(() =>
{
if (userList.Status != 0)
{
LoadingUI.Hide();
errorTip = "100069";
ShowErrorPage();
return;
}
if (userList.UserCount > 0 && userList.Users != null && userList.Users.Length > 0)
{
// 打印用户列表,方便排查注销失败原因
StringBuilder sb = new StringBuilder();
sb.Append($"用户列表: UserCount={userList.UserCount}, Users.Length={userList.Users.Length}");
for (int i = 0; i < userList.Users.Length; i++)
{
var u = userList.Users[i];
sb.Append($" [{i}] Username={u.Username}, FingerprintId={u.FingerprintId}, HasFingerprint={u.HasFingerprint}");
}
Debug.Log(sb.ToString());
// 挨个注销设备端用户
UnregisterAllUsers(userList.Users, 0);
}
else
{
// 设备端已注册但用户列表为空固件bug直接登录当前用户
Debug.Log("设备已注册但用户列表为空,直接登录当前用户");
UserLoginAndContinue();
}
});
});
}
/// <summary>
/// 挨个注销设备端用户,全部注销完后注册当前用户
/// </summary>
private void UnregisterAllUsers(Kill.Bluetooth.Protocol.UserInfo[] users, int index)
{
if (index >= users.Length)
{
// 全部注销完成,注册当前用户
OnRegisterDeviceClick();
return;
}
string username = users[index].Username;
BLECommunicationManager.Instance.UnregisterUser(username, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
Debug.Log($"用户 {username} 注销成功");
}
else
{
// 注销失败不阻塞,继续注销下一个
Debug.LogWarning($"用户 {username} 注销失败, 状态码={response.Status:X2},继续注销下一个");
}
UnregisterAllUsers(users, index + 1);
});
});
}
/// <summary>
/// 登录当前用户并进入 WiFi 配置流程
/// </summary>
private void UserLoginAndContinue()
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.UserLogin(username, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
Debug.Log($"用户登录成功,继续设备配置流程: {username}");
LoadingUI.Hide();
ShowWifiPage();
}
else
{
Debug.LogError($"用户登录失败: {response.Status}");
LoadingUI.Hide();
errorTip = "100069";
ShowErrorPage();
}
});
});
}
/// <summary>
/// 注册设备
/// </summary>
private void OnRegisterDeviceClick()
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.RegisterDevice(username, (success, message) =>
{
Loom.QueueOnMainThread(() =>
{
if (success)
{
LoadingUI.Hide();
// 蓝牙注册成功后,进入 WiFi 配置流程(服务器绑定已在前面完成)
ShowWifiPage();
}
else
{
// 固件bug规避恢复出厂后注册状态仍为已注册0x02注册会失败
// 导致无法设置指纹改用0x03用户登录流程
Debug.Log($"设备注册失败: {message},尝试用户登录(0x03)");
TryUserLoginAfterRegisterFailed(username);
}
});
});
}
/// <summary>
/// 注册失败后尝试用户登录(0x03),规避固件恢复出厂后注册状态异常的问题
/// </summary>
private void TryUserLoginAfterRegisterFailed(string username)
{
// 连接设备时的Loading仍在显示无需重复Show避免计数不平衡导致Loading不消失
BLECommunicationManager.Instance.UserLogin(username, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
Debug.Log($"用户登录成功,继续设备配置流程: {username}");
LoadingUI.Hide();
// 登录成功后,进入 WiFi 配置流程(服务器绑定已在前面完成)
ShowWifiPage();
}
else
{
Debug.LogError($"设备注册及用户登录均失败: {response.Status}");
LoadingUI.Hide();
errorTip = "100069";
ShowErrorPage();
}
});
});
}
/// <summary>
/// 显示指纹初始化页面(sonPages[4])
/// 注册设备成功后展示,引导用户设置或跳过指纹
/// </summary>
public void ShowFingerprintPage()
{
// 未配置指纹页则直接进入WiFi配置避免阻塞流程
if (sonPages == null || sonPages.Length <= 4 || sonPages[4] == null)
{
ShowSuccessPage();
return;
}
foreach (GameObject g in sonPages)
g.gameObject.SetActive(false);
if (fingerInitTip != null) fingerInitTip.SetActive(false);
sonPages[4].SetActive(true);
// 绑定按钮(每次进入页面重新绑定,避免重复订阅)
if (fingerprintSetupButton != null)
{
fingerprintSetupButton.onClick.RemoveAllListeners();
fingerprintSetupButton.onClick.AddListener(OnSetupFingerprintClick);
}
if (fingerprintSkipButton != null)
{
fingerprintSkipButton.onClick.RemoveAllListeners();
fingerprintSkipButton.onClick.AddListener(OnSkipFingerprintClick);
}
// 返回键=返回上一步wifi设置
UIManager.Instance.RegisterBackAction(ShowWifiPage);
}
/// <summary>
/// 设置指纹按钮开启该用户指纹并发起录入逻辑与DeviceInfoPage一致
/// </summary>
public void OnSetupFingerprintClick()
{
string username = DataManager.Instance.userInfo.id;
LoadingUI.Show();
BLECommunicationManager.Instance.SetFingerprintEnable(username, true, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (!response.IsSuccess)
{
LoadingUI.Hide();
ToastUI.Show("100321");
return;
}
SetFingerprint();
});
});
}
/// <summary>
/// 发起指纹录入与DeviceInfoPage.SetFingerprint一致失败自动重试
/// </summary>
private void SetFingerprint()
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.StartFingerprintRecord(username, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
// 弹出提示框,引导用户去设备端录入指纹
if (fingerInitTip != null)
fingerInitTip.SetActive(true);
LoadingUI.Hide();
}
else
{
SetFingerprint();
}
});
});
}
/// <summary>
/// 跳过按钮关闭该用户指纹进入WiFi配置失败最多重试2次
/// </summary>
public void OnSkipFingerprintClick()
{
string username = DataManager.Instance.userInfo.id;
if (string.IsNullOrEmpty(username))
{
ToastUI.Show("100321");
return;
}
LoadingUI.Show();
TryDisableFingerprint(0);
}
/// <summary>
/// 尝试关闭指纹失败自动重试最多2次共3次尝试之后无论结果如何都进入WiFi配置
/// </summary>
private void TryDisableFingerprint(int attempt)
{
string username = DataManager.Instance.userInfo.id;
BLECommunicationManager.Instance.SetFingerprintEnable(username, false, (response) =>
{
Loom.QueueOnMainThread(() =>
{
if (response.IsSuccess)
{
LoadingUI.Hide();
ShowSuccessPage();
}
else if (attempt < 2)
{
Debug.Log($"指纹关闭失败,准备第{attempt + 1}次重试");
TryDisableFingerprint(attempt + 1);
}
else
{
ToastUI.Show("100321");
LoadingUI.Hide();
ShowSuccessPage();
}
});
});
}
/// <summary>
/// 返回主页
/// </summary>
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($"绑定设备成功");
DataManager.Instance.SavaSelectedDeviceMac(nowDeviceMac);
// 服务器绑定成功后,蓝牙查询设备注册状态
LoadingUI.Show();
OnQueryRegistrationClick();
}
,
onError: (code,message) =>
{
Debug.Log($"绑定设备失败:{code},{message}");
if(code==404)
{
errorTip="100331";
}
else
errorTip = "100070";
ShowErrorPage();
}
);
}
catch (Exception ex)
{
LoadingUI.Hide();
Debug.LogError($"绑定设备异常: {ex.Message}");
}
}
public void ConnectError()
{
errorTip = "100069";
ShowErrorPage();
}
}