killapp/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs
“虞渠成” 3a335e60a2 chore: 重构DOTween插件路径并更新相关代码
1. 将DOTween从原Plugins/DOTween迁移到Plugins/Demigiant/DOTween
2. 更新版本号解析逻辑,适配设备端压缩编码格式
3. 新增UI动画组件UIAnimator及其编辑器脚本
4. 优化主页设备列表项滑动菜单功能
5. 移除无用的VSCode编辑器包配置
6. 更新多语言文案修正末尾标点
7. 调整主页锁定超时配置为可配置项
2026-08-19 09:47:44 +08:00

732 lines
24 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);
//OnQueryRegistrationClick();
OnRegisterDeviceClick();
}
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
{
OnRegisterDeviceClick();
}
}
else
{
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();
// 蓝牙注册成功后,再调用服务器绑定接口
BandDevice();
}
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();
// 登录成功后,再调用服务器绑定接口
BandDevice();
}
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>
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($"绑定设备成功");
ShowWifiPage();
DataManager.Instance.SavaSelectedDeviceMac(nowDeviceMac);
}
,
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();
}
}