using System.Collections; using System.Collections.Generic; using Kill.Managers; using UnityEngine; using UnityEngine.UI; using System; using System.Threading.Tasks; using Kill.Network; using Kill.UI.Components; using Kill.Bluetooth; using Kill.Bluetooth.Protocol; using Kill.Core; using Unity.VisualScripting; namespace Kill.UI.Pages { public class HomePageCtrl : MonoBehaviour { public static HomePageCtrl Instance { get; private set; } public GameObject noDevicePage; public GameObject normalPage; // 存储待执行的UI更新操作 private List pendingUIUpdates = new List(); public Button selectDeviceButton; public GameObject selectDevicePage; // 设备列表数据 (使用 Kill.Managers.DeviceInfo) public List OwnedDevices { get; private set; } = new List(); public List SharedDevices { get; private set; } = new List(); public Kill.Managers.DeviceInfo selectedDevice; bool hasBluetooth = false; bool hasWifi = false; bool isPollingOnline = false; bool stopPolling = false; // UI 组件引用 public HomePageDeviceState deviceState; public HomePageDeviceCtrl deviceCtrl; public HomePageSchedule deviceSchedule; public Button scheduleSettingButton; public GameObject scheduleSettingPrefab; /// /// 触发密码验证按钮 /// public GameObject LockButtonPlane; // 状态初始化相关 private bool isDeviceStateInitializing = false; // 是否正在初始化设备状态 private int pendingStatusCount = 0; // 待接收的状态数量 private int TOTAL_STATUS_COUNT = 8; // 总共需要查询的状态数量 private float statusQueryTimeout = 15f; // 状态查询超时时间(秒) private Coroutine statusQueryTimeoutCoroutine; // 超时协程 // 串行查询相关 private Queue statusQueryQueue = new Queue(); // 状态查询队列 private bool isQueryingStatus = false; // 是否正在查询状态 // 工作模式设置后查询相关 private bool isWaitingForWorkModeQuery = false; // 是否正在等待工作模式查询响应 void Awake() { Instance = this; } async Task Start() { // 订阅蓝牙事件 SubscribeBluetoothEvents(); // 获取设备列表 await FetchDeviceList(); Init(); } float waitLockTime=0; void FixedUpdate() { if(!LockButtonPlane.activeSelf) { waitLockTime+=Time.deltaTime; } else { waitLockTime=0; } if(waitLockTime>=60) LockButtonPlane.SetActive(true); } void OnApplicationPause(bool pause) { LockButtonPlane.SetActive(true); } void OnDestroy() { StopDeviceOnlineStatusPolling(); UnsubscribeBluetoothEvents(); StopAllCoroutines(); } #region 蓝牙事件订阅 private void SubscribeBluetoothEvents() { if (BluetoothManager.Instance != null) { BluetoothManager.Instance.OnConnectedSuccess += OnBluetoothConnected; BluetoothManager.Instance.OnDisconnected += OnBluetoothDisconnected; BluetoothManager.Instance.OnError += OnBluetoothError; BluetoothManager.Instance.OnStopScan+=deviceState.StopScan; BluetoothManager.Instance.OnStartScan+=deviceState.OnStartScan; } if (BLECommunicationManager.Instance != null) { // 订阅用户登录结果事件 BLECommunicationManager.Instance.OnUserLoginResult += OnUserLoginResult; // 订阅设备状态事件 BLECommunicationManager.Instance.OnWorkModeSettingReceived += OnWorkModeReceived; BLECommunicationManager.Instance.OnDeviceLockControlReceived += OnLockReceived; BLECommunicationManager.Instance.OnScheduleTaskListReceived += OnScheduleTaskListReceived; BLECommunicationManager.Instance.OnAngleControlReceived += OnAngleControlReceived; BLECommunicationManager.Instance.OnDistanceControlReceived += OnDistanceControlReceived; BLECommunicationManager.Instance.OnFillLightControlReceived += OnFillLightControlReceived; //BLECommunicationManager.Instance.OnMillimeterWaveSettingReceived += OnMillimeterWaveReceived; BLECommunicationManager.Instance.OnVisualDetectionSettingReceived += OnVisualDetectionReceived; // 订阅蚊虫数据事件 BLECommunicationManager.Instance.OnMosquitoDataReceived += OnMosquitoDataReceived; } } private void UnsubscribeBluetoothEvents() { if (BluetoothManager.Instance != null) { BluetoothManager.Instance.OnConnectedSuccess -= OnBluetoothConnected; BluetoothManager.Instance.OnDisconnected -= OnBluetoothDisconnected; BluetoothManager.Instance.OnError -= OnBluetoothError; BluetoothManager.Instance.OnStopScan-=deviceState.StopScan; BluetoothManager.Instance.OnStartScan-=deviceState.OnStartScan; } if (BLECommunicationManager.Instance != null) { // 取消订阅用户登录结果事件 BLECommunicationManager.Instance.OnUserLoginResult -= OnUserLoginResult; BLECommunicationManager.Instance.OnDeviceLockControlReceived -= OnLockReceived; BLECommunicationManager.Instance.OnWorkModeSettingReceived -= OnWorkModeReceived; BLECommunicationManager.Instance.OnScheduleTaskListReceived -= OnScheduleTaskListReceived; BLECommunicationManager.Instance.OnAngleControlReceived -= OnAngleControlReceived; BLECommunicationManager.Instance.OnDistanceControlReceived -= OnDistanceControlReceived; BLECommunicationManager.Instance.OnFillLightControlReceived -= OnFillLightControlReceived; // BLECommunicationManager.Instance.OnMillimeterWaveSettingReceived -= OnMillimeterWaveReceived; BLECommunicationManager.Instance.OnVisualDetectionSettingReceived -= OnVisualDetectionReceived; // 取消订阅蚊虫数据事件 BLECommunicationManager.Instance.OnMosquitoDataReceived -= OnMosquitoDataReceived; } } #endregion #region 蓝牙事件处理 // 标记是否已完成蓝牙用户登录 private bool isBluetoothUserLoggedIn = false; private void OnBluetoothConnected() { Debug.Log("[HomePageCtrl] 蓝牙连接成功"); hasBluetooth = true; DataManager.Instance.hasBluetooth = true; // 更新连接状态UI pendingUIUpdates.Add(() => { deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); // 先进行蓝牙用户登录,登录成功后再获取设备状态 StartCoroutine(BluetoothUserLoginThenQueryStatus()); }); } /// /// 蓝牙用户登录,登录成功后查询设备状态 /// private IEnumerator BluetoothUserLoginThenQueryStatus() { LoadingUI.Show(); yield return new WaitForSeconds(0.5f); // 获取用户ID string username = DataManager.Instance?.userInfo?.id; if (string.IsNullOrEmpty(username)) { Debug.LogError("[HomePageCtrl] 蓝牙用户登录失败:用户未登录"); yield break; } Debug.Log($"[HomePageCtrl] 开始进行蓝牙用户登录,用户名: {username}"); isBluetoothUserLoggedIn = false; // 调用蓝牙用户登录 BLECommunicationManager.Instance?.UserLogin(username, (response) => { if (response.IsSuccess) { Debug.Log("[HomePageCtrl] 蓝牙用户登录成功"); isBluetoothUserLoggedIn = true; } else { Debug.LogError($"[HomePageCtrl] 蓝牙用户登录失败: {response.Status}"); } }); // 等待登录结果(最多3秒) float timeout = 3f; float elapsed = 0f; while (!isBluetoothUserLoggedIn && elapsed < timeout) { yield return new WaitForSeconds(0.1f); elapsed += 0.1f; } if (isBluetoothUserLoggedIn) { Debug.Log("[HomePageCtrl] 蓝牙用户登录成功,获取锁定状态"); BLECommunicationManager.Instance.ReadDeviceLockControl(); } else { Debug.LogWarning("[HomePageCtrl] 蓝牙用户登录超时,3s重试"); yield return new WaitForSeconds(3); StartCoroutine(BluetoothUserLoginThenQueryStatus()); } } /// /// 用户登录结果回调 /// private void OnUserLoginResult(UserLoginResponse response) { Debug.Log($"[HomePageCtrl] 收到用户登录结果: {response.Status}"); // 登录结果在 UserLogin 回调中处理,这里仅作日志记录 } /// /// 开始设备状态初始化 /// private void StartDeviceStateInitialization() { isDeviceStateInitializing = true; pendingStatusCount = TOTAL_STATUS_COUNT; // 显示Loading,阻止操作 LoadingUI.Show(); // 启动超时检测 if (statusQueryTimeoutCoroutine != null) { StopCoroutine(statusQueryTimeoutCoroutine); } statusQueryTimeoutCoroutine = StartCoroutine(StatusQueryTimeoutCoroutine()); Debug.Log($"[HomePageCtrl] 开始设备状态初始化,待接收状态数: {pendingStatusCount}"); } /// /// 状态查询超时协程 /// private IEnumerator StatusQueryTimeoutCoroutine() { yield return new WaitForSeconds(statusQueryTimeout); if (isDeviceStateInitializing) { Debug.LogWarning($"[HomePageCtrl] 设备状态查询超时,已接收 {TOTAL_STATUS_COUNT - pendingStatusCount}/{TOTAL_STATUS_COUNT} 个状态"); FinishDeviceStateInitialization(); } } Coroutine bluetoothDeviceInfoCoroutine = null; /// /// 完成设备状态初始化 /// private void FinishDeviceStateInitialization() { isDeviceStateInitializing = false; pendingStatusCount = 0; // 隐藏Loading LoadingUI.Hide(); // 停止超时协程 if (statusQueryTimeoutCoroutine != null) { StopCoroutine(statusQueryTimeoutCoroutine); statusQueryTimeoutCoroutine = null; } bluetoothDeviceInfoCoroutine=StartCoroutine(CheckDeviceError()); Debug.Log("[HomePageCtrl] 设备状态初始化完成"); } /// /// 接收一个状态,减少待接收计数 /// private void ReceiveStatus() { if (!isDeviceStateInitializing) return; pendingStatusCount--; Debug.Log($"[HomePageCtrl] 接收到状态,剩余: {pendingStatusCount}/{TOTAL_STATUS_COUNT}"); // 所有状态都接收完成 if (pendingStatusCount <= 0) { FinishDeviceStateInitialization(); } } private void OnBluetoothDisconnected(string address) { Debug.Log("[HomePageCtrl] 蓝牙断开连接"); hasBluetooth = false; DataManager.Instance.hasBluetooth = false; isBluetoothUserLoggedIn = false; isQueryingStatus = false; statusQueryQueue?.Clear(); UIManager.Instance?.ClearBackAction(); UIManager.Instance.OpenPage(UIManager.PageName.homePage, null, true); if(bluetoothDeviceInfoCoroutine!=null) { StopCoroutine(bluetoothDeviceInfoCoroutine); } } private void OnBluetoothError(string error) { Debug.LogError($"[HomePageCtrl] 蓝牙错误: {error}"); } /// /// 延迟查询设备状态 /// private IEnumerator QueryDeviceStatusDelayed() { // 等待 500ms 确保连接稳定 yield return new WaitForSeconds(0.1f); // 开始设备状态初始化(显示Loading) StartDeviceStateInitialization(); // 串行查询设备状态 StartCoroutine(QueryAllDeviceStatusSequential()); } /// /// 串行查询所有设备状态(收到返回后再发送下一个) /// private IEnumerator QueryAllDeviceStatusSequential() { Debug.Log("[HomePageCtrl] 开始串行查询设备状态..."); // 清空队列 statusQueryQueue.Clear(); isQueryingStatus = true; // 将查询请求加入队列 statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 工作模式"); BLECommunicationManager.Instance?.ReadWorkMode(); }); statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 定时任务"); BLECommunicationManager.Instance?.ReadScheduleTasks(); }); statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 角度控制"); BLECommunicationManager.Instance?.ReadAngleControl(); }); statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 距离控制"); BLECommunicationManager.Instance?.ReadDistanceControl(); }); statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 补光灯控制"); BLECommunicationManager.Instance?.ReadFillLightControl(); }); statusQueryQueue.Enqueue(() => { Debug.Log("[HomePageCtrl] 查询: 视觉检测"); BLECommunicationManager.Instance?.ReadVisualDetectionSetting(); }); statusQueryQueue.Enqueue(OnWriteLanguageClick); statusQueryQueue.Enqueue(OnWriteTimeClick); // 依次执行查询 while (statusQueryQueue.Count > 0 && isQueryingStatus) { int pendingCountBefore = pendingStatusCount; var query = statusQueryQueue.Dequeue(); query?.Invoke(); // 等待 200ms 确保请求发送完成 yield return new WaitForSeconds(0.2f); // 等待响应(最多2秒) float waitTime = 0f; float maxWaitTime = 2f; while (waitTime < maxWaitTime) { // 检查是否已接收到状态(通过 pendingStatusCount 减少来判断) if (pendingStatusCount < pendingCountBefore) { Debug.Log($"[HomePageCtrl] 收到响应,继续下一个查询"); break; } yield return new WaitForSeconds(0.05f); waitTime += 0.05f; } } isQueryingStatus = false; Debug.Log("[HomePageCtrl] 串行查询设备状态完成"); OnGetAllMosquitoDataClick(); } /// /// 查询所有设备状态(旧方法,已废弃) /// private void QueryAllDeviceStatus() { Debug.Log("[HomePageCtrl] 开始查询设备状态..."); // 查询工作模式 BLECommunicationManager.Instance?.ReadWorkMode(); // 查询硬件状态 BLECommunicationManager.Instance?.ReadHardwareStatus(); // 查询定时任务 BLECommunicationManager.Instance?.ReadScheduleTasks(); // 查询角度控制 BLECommunicationManager.Instance?.ReadAngleControl(); // 查询距离控制 BLECommunicationManager.Instance?.ReadDistanceControl(); // 查询补光灯控制 BLECommunicationManager.Instance?.ReadFillLightControl(); // 查询毫米波雷达设置 BLECommunicationManager.Instance?.ReadMillimeterWaveSetting(); // 查询视觉检测设置 BLECommunicationManager.Instance?.ReadVisualDetectionSetting(); } #endregion #region 设备状态回调 // 当前工作模式 private WorkMode currentWorkMode = WorkMode.Standby; /// /// 设置工作模式 /// /// 0:待机 1:扫描 2:消杀 public async void SetWorkMode(int mode) { waitLockTime=0; // 检查是否与当前模式相同 if ((int)currentWorkMode == mode) { Debug.Log($"[HomePageCtrl] 目标模式 {mode} 与当前模式相同,不执行切换"); return; } // WiFi模式 if (hasWifi && !hasBluetooth) { LoadingUI.Show(); bool success = await SetWorkModeByWifiAsync(mode); LoadingUI.Hide(); if (success) { currentWorkMode = (WorkMode)mode; deviceCtrl?.InitWrokMode(mode); } return; } // 检查蓝牙连接 if (!BluetoothManager.Instance.IsConnected) { Debug.LogWarning("[HomePageCtrl] 蓝牙未连接,无法切换工作模式"); LoadingUI.Hide(); return; } // 显示 Loading LoadingUI.Show(); // 构建工作模式设置 WorkModeSetting setting = new WorkModeSetting { Mode = (WorkMode)mode }; Debug.Log($"[HomePageCtrl] 正在设置工作模式: {setting.Mode}"); // 发送设置命令 BLECommunicationManager.Instance?.WriteWorkMode(setting, (success) => { Loom.QueueOnMainThread(() => { LoadingUI.Hide(); if (success) { Debug.Log($"[HomePageCtrl] 工作模式设置成功: {setting.Mode}"); // 更新当前模式 currentWorkMode = setting.Mode; // 更新 UI pendingUIUpdates.Add(() => { deviceCtrl?.InitWrokMode(mode); }); } else { Debug.LogError("[HomePageCtrl] 工作模式设置失败"); } }); }); } public async Task SetWorkModeByWifiAsync(int mode) { var setting = new WorkModeSetting { Mode = (WorkMode)mode }; bool success = await SendBleCommandByWifiAsync( BLEConstants.CMD_WORK_MODE_SETTING, setting.ToBytes()); if (success) { Debug.Log($"[HomePageCtrl] WiFi工作模式设置成功: {(WorkMode)mode}"); } return success; } private void OnLockReceived(DeviceLockControl setting) { Debug.Log($"[HomePageCtrl] 锁定状态: {setting.IsLocked}"); pendingUIUpdates.Add(() => { LoadingUI.Hide(); if (setting.IsLocked) { deviceCtrl.InitDeviceControl(false); BLECommunicationManager.Instance.ReadScheduleTasks(); } else { deviceCtrl.InitDeviceControl(true); StartCoroutine(QueryDeviceStatusDelayed()); } }); } private void OnWorkModeReceived(WorkModeSetting setting) { Debug.Log($"[HomePageCtrl] 收到工作模式: {setting.Mode}"); ReceiveStatus(); // 更新当前工作模式 currentWorkMode = setting.Mode; // 如果是工作模式设置后的查询响应,重置等待标志 if (isWaitingForWorkModeQuery) { isWaitingForWorkModeQuery = false; Debug.Log("[HomePageCtrl] 工作模式查询响应已处理"); } pendingUIUpdates.Add(() => { deviceCtrl?.InitWrokMode((int)setting.Mode); }); } private void OnScheduleTaskListReceived(ScheduleTaskListResponse response) { // 如果设置页面正在处理,跳过主页处理 if (ScheduleSettingPage.IsSettingPageActive()) { Debug.Log("[HomePageCtrl] 设置页面正在处理定时任务列表,跳过主页更新"); return; } if (response.IsSuccess) { Debug.Log($"[HomePageCtrl] 收到定时任务列表: {response.Tasks.Length} 个任务"); ReceiveStatus(); pendingUIUpdates.Add(() => { deviceSchedule?.Init(response.Tasks); }); } else { ReceiveStatus(); } scheduleSettingButton.interactable = true; } private void OnAngleControlReceived(AngleControl control) { // 如果设置页面正在处理,跳过主页处理 if (FovSettingPage.IsSettingPageActive()) { Debug.Log("[HomePageCtrl] 设置页面正在处理角度控制,跳过主页更新"); return; } Debug.Log($"[HomePageCtrl] 收到角度控制: {control.ActualAngle}°"); ReceiveStatus(); pendingUIUpdates.Add(() => { // 使用实际角度值 int fov = (int)control.ActualAngle; deviceCtrl?.InitFovText(fov); }); } /// /// 刷新角度控制设置(供FovSettingPage调用) /// public void RefreshAngleControl() { Debug.Log("[HomePageCtrl] 刷新角度控制设置"); if (hasWifi && !hasBluetooth) { var config = DataManager.Instance.deviceConfig; float fov = (config?.fov_angle ?? 0) * 0.1f; pendingUIUpdates.Add(() => deviceCtrl?.InitFovText((int)fov)); return; } BLECommunicationManager.Instance?.ReadAngleControl(); } private void OnDistanceControlReceived(DistanceControl control) { // 如果设置页面正在处理,跳过主页处理 if (LensSettingPage.IsSettingPageActive()) { Debug.Log("[HomePageCtrl] 设置页面正在处理距离控制,跳过主页更新"); return; } // 单位是 0.1m,需要除以 10 转换为实际米数 float detectionDistance = control.DetectionDistance / 10f; float aimDistance = control.AimDistance / 10f; Debug.Log($"[HomePageCtrl] 收到距离控制: 检测={detectionDistance}m, 瞄准={aimDistance}m"); ReceiveStatus(); pendingUIUpdates.Add(() => { // 使用检测距离,单位 0.1m 转实际米数,保留1位小数 deviceCtrl?.InitLensText(detectionDistance, DataManager.Instance.userInfo.unit_system); // 0 = 米 }); } /// /// 刷新lens设置 /// public void RefreshLensControl() { Debug.Log("[HomePageCtrl] 刷新距离控制设置"); if (hasWifi && !hasBluetooth) { var config = DataManager.Instance.deviceConfig; float distance = (config?.detection_distance ?? 0) * 0.1f; pendingUIUpdates.Add(() => deviceCtrl?.InitLensText(distance, DataManager.Instance.userInfo.unit_system)); return; } BLECommunicationManager.Instance?.ReadDistanceControl(); } private void OnFillLightControlReceived(FillLightControl control) { // 如果设置页面正在处理,跳过主页处理 if (LightSettingPage.IsSettingPageActive()) { Debug.Log("[HomePageCtrl] 设置页面正在处理补光灯控制,跳过主页更新"); return; } Debug.Log($"[HomePageCtrl] 收到补光灯控制: {control.Enable}"); ReceiveStatus(); pendingUIUpdates.Add(() => { deviceCtrl?.InitLightText(control.Enable); }); } public void RefreshLightControl() { Debug.Log("[HomePageCtrl] 刷新补光灯控制设置"); if (hasWifi && !hasBluetooth) { var config = DataManager.Instance.deviceConfig; pendingUIUpdates.Add(() => deviceCtrl?.InitLightText(config?.fill_light_enable ?? false)); return; } BLECommunicationManager.Instance?.ReadFillLightControl(); } // private void OnMillimeterWaveReceived(MillimeterWaveSetting setting) // { // Debug.Log($"[HomePageCtrl] 收到毫米波设置: {setting.Enable}"); // ReceiveStatus(); // pendingUIUpdates.Add(() => // { // // 更新安全状态 - 毫米波 // // 注意:需要结合 VisualDetectionSetting 一起判断 // }); // } private void OnVisualDetectionReceived(VisualDetectionSetting setting) { // 如果设置页面正在处理,跳过主页处理 if (SafetySettingPage.IsSettingPageActive()) { Debug.Log("[HomePageCtrl] 设置页面正在处理视觉检测设置,跳过主页更新"); return; } Debug.Log($"[HomePageCtrl] 收到视觉检测设置: {setting.Enable}"); ReceiveStatus(); pendingUIUpdates.Add(() => { deviceCtrl?.InitSafeText(setting.Enable); }); } #endregion /// /// WiFi模式下从设备配置初始化首页UI /// private void InitDeviceUIFromConfig() { var config = DataManager.Instance.deviceConfig; if (config == null) return; bool isLocked = config.is_locked ?? false; Debug.Log($"[HomePageCtrl] WiFi初始化:设备锁定状态={isLocked}"); if (isLocked) { deviceCtrl?.InitDeviceControl(false); } else { deviceCtrl?.InitDeviceControl(true); // 初始化工作模式 WorkMode workMode = DeviceConfig.ParseServerEnum(config.work_mode, WorkMode.Standby); currentWorkMode = workMode; deviceCtrl?.InitWrokMode((int)workMode); // 初始化FOV float fov = (config.fov_angle ?? 0) * 0.1f; deviceCtrl?.InitFovText((int)fov); // 初始化距离 float distance = (config.detection_distance ?? 0) * 0.1f; deviceCtrl?.InitLensText(distance, DataManager.Instance.userInfo.unit_system); // 初始化补光灯 deviceCtrl?.InitLightText(config.fill_light_enable ?? false); // 初始化安全设置 deviceCtrl?.InitSafeText(config.visual_detect_enable ?? false); } // 初始化定时任务 var scheduleTasks = new List(); foreach (var d in DataManager.Instance.scheduleTaskDatas) { // 过滤开始时间和结束时间都为0的无效任务 bool isInvalid = d.start_hour == 0 && d.start_minute == 0 && d.end_hour == 0 && d.end_minute == 0; if (isInvalid) continue; scheduleTasks.Add(new ScheduleTask { TaskId = d.task_id, Enabled = d.enabled, StartHour = d.start_hour, StartMinute = d.start_minute, EndHour = d.end_hour, EndMinute = d.end_minute, Mode = (ScheduleTaskMode)System.Enum.Parse(typeof(ScheduleTaskMode), d.mode, true), Repeat = d.repeat_mask }); } if (scheduleTasks.Count > 0) { deviceSchedule?.Init(scheduleTasks.ToArray()); } else { deviceSchedule?.DisplayNoSchedule(); } } public async Task Init() { if (DataManager.Instance.userInfo.device_count == 0) { noDevicePage.SetActive(true); normalPage.SetActive(false); selectedDevice = null; selectDeviceButton.gameObject.SetActive(false); return; } else { if (DataManager.Instance.userInfo.exam_completed == false) { UIManager.Instance.OpenMainPage(UIManager.PageName.safetylearningPage); } noDevicePage.SetActive(false); normalPage.SetActive(true); } if (DataManager.Instance.selectedDeviceMac == "") { if(OwnedDevices.Count>0) { selectedDevice = OwnedDevices[0]; } else { selectedDevice=SharedDevices[0]; } DataManager.Instance.selectedDeviceMac = selectedDevice.ble_mac; DataManager.Instance.SavaSelectedDeviceMac(selectedDevice.ble_mac); } else { selectedDevice = OwnedDevices.Find(x => x.ble_mac == DataManager.Instance.selectedDeviceMac); if (selectedDevice == null) { selectedDevice = SharedDevices.Find(x => x.ble_mac == DataManager.Instance.selectedDeviceMac); if (selectedDevice == null) { if (OwnedDevices.Count > 0) { selectedDevice = OwnedDevices[0]; } else { selectedDevice = SharedDevices[0]; } DataManager.Instance.selectedDeviceMac = selectedDevice.ble_mac; DataManager.Instance.SavaSelectedDeviceMac(selectedDevice.ble_mac); } Debug.Log("当前选中设备:" + DataManager.Instance.selectedDeviceMac); } } hasWifi=await GetDeviceOnlineStatus(); hasBluetooth = BluetoothManager.Instance.ChangeAimMac(selectedDevice.ble_mac); selectDeviceButton.GetComponentInChildren().text = selectedDevice.device_name; selectDeviceButton.gameObject.SetActive(true); // 先初始化所有 UI 为未连接状态 ResetAllDeviceUI(); InitDeviceState(); deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); // 始终启动WiFi在线状态轮询 StartDeviceOnlineStatusPolling(); // 如果蓝牙已连接,立即查询状态 if (hasBluetooth) { deviceCtrl?.InitDeviceControl(false); BLECommunicationManager.Instance.ReadDeviceLockControl(); scheduleSettingButton.interactable = true; moreSettingButton.interactable = true; } else if(hasWifi) { deviceCtrl?.InitDeviceControl(false); await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac); await DataManager.Instance.GetScheduleTasks(selectedDevice.device_sn); scheduleSettingButton.interactable = true; moreSettingButton.interactable = true; InitDeviceUIFromConfig(); } else { deviceCtrl?.InitDeviceControl(false); scheduleSettingButton.interactable = false; moreSettingButton.interactable = false; } GetLastRecords(); ShowCharts(); GetMessageTypeList(); // StartCoroutine(GetLastMosquitoData()); DataManager.Instance.selectedDevice = selectedDevice; DataManager.Instance.OwnedDevices=OwnedDevices; DataManager.Instance.SharedDevices=SharedDevices; } /// /// 重置所有设备 UI 为未连接状态 /// private void ResetAllDeviceUI() { Debug.Log("[HomePageCtrl] 重置所有 UI 为未连接状态"); // 重置工作模式为未连接 deviceCtrl?.InitWrokMode(-1); // 重置 FOV deviceCtrl?.InitFovText(0); // 重置距离 deviceCtrl?.InitLensText(0f, 0); // 重置补光灯 deviceCtrl?.InitLightText(false); // 重置安全状态 deviceCtrl?.InitSafeText(false); // 重置定时任务显示 deviceSchedule?.DisplayNoSchedule(); scheduleSettingButton.onClick.RemoveAllListeners(); scheduleSettingButton.onClick.AddListener(() => { ShowScheduleSettingPage(); }); scheduleSettingButton.interactable = false; } /// /// 获取用户设备列表 /// public async Task FetchDeviceList() { LoadingUI.Show(); try { Debug.Log("[HomePageCtrl] 开始获取设备列表..."); // 构建带 user_id 参数的 URL string userId = DataManager.Instance?.userInfo?.id; if (string.IsNullOrEmpty(userId)) { Debug.LogError("[HomePageCtrl] 获取设备列表失败: 用户未登录"); LoadingUI.Hide(); return; } string url = $"/api/v1/device/user/list?user_id={userId}"; var response = await NetworkCtrl.Instance.Get(url); LoadingUI.Hide(); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { // 更新设备列表 OwnedDevices = data.data.owned_devices ?? new List(); foreach (var device in OwnedDevices) { device.owner_id = DataManager.Instance.userInfo.id; if(string.IsNullOrEmpty(device.ble_mac)) { device.ble_mac = device.device_sn; } } SharedDevices = data.data.shared_devices ?? new List(); foreach (var device in SharedDevices) { if(string.IsNullOrEmpty(device.ble_mac)) { device.ble_mac = device.device_sn; } } Debug.Log($"[HomePageCtrl] 获取设备列表成功: 自有设备={OwnedDevices.Count}, 共享设备={SharedDevices.Count}"); DataManager.Instance.userInfo.device_count = OwnedDevices.Count + SharedDevices.Count; }, onError: null ); } catch (Exception ex) { LoadingUI.Hide(); Debug.LogError($"[HomePageCtrl] 获取设备列表异常: {ex.Message}"); } } void Update() { // 执行所有挂起的UI更新 if (pendingUIUpdates.Count > 0) { foreach (var update in pendingUIUpdates) { update?.Invoke(); } pendingUIUpdates.Clear(); } } public void ConnectDevice() { if (!CheckSafetylearning()) { UIManager.Instance.OpenPage(UIManager.PageName.safetylearningPage); return; } UIManager.Instance.OpenPage(UIManager.PageName.connectDevicePage); } public bool CheckSafetylearning() { bool isPassed = false; isPassed = DataManager.Instance.userInfo.exam_completed; return isPassed; } public void InitDeviceState() { // 初始化设备状态UI deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); } public void ShowDeviceList() { selectDevicePage.SetActive(true); selectDevicePage.GetComponent().InitDeviceList(OwnedDevices, SharedDevices, selectedDevice); UIManager.Instance.RegisterBackAction(() => { selectDevicePage.GetComponent().ClosePage(); }); } public GameObject fovSettingPagePrefab; public void ShowFovSettingPage() { waitLockTime=0; if (fovSettingPagePrefab == null) { Debug.LogError("[HomePageCtrl] 未设置FOV设置页面预制体"); return; } GameObject fovSettingPage = Instantiate(fovSettingPagePrefab, transform); fovSettingPage.SetActive(true); UIManager.Instance.RegisterBackAction(() => { fovSettingPage.GetComponent().OnCancelButtonClick(); }); } public GameObject lensSettingPagePrefab; public void ShowLensSettingPage() { waitLockTime=0; if (lensSettingPagePrefab == null) { Debug.LogError("[HomePageCtrl] 未设置lens设置页面预制体"); return; } GameObject lensSettingPage = Instantiate(lensSettingPagePrefab, transform); lensSettingPage.SetActive(true); UIManager.Instance.RegisterBackAction(() => { lensSettingPage.GetComponent().OnCancelButtonClick(); }); } public GameObject lightSettingPagePrefab; public void ShowLightSettingPage() { waitLockTime=0; if (lightSettingPagePrefab == null) { Debug.LogError("[HomePageCtrl] 未设置light设置页面预制体"); return; } GameObject lightSettingPage = Instantiate(lightSettingPagePrefab, transform); lightSettingPage.SetActive(true); UIManager.Instance.RegisterBackAction(() => { lightSettingPage.GetComponent().ClosePage(); }); } public GameObject safetySettingPagePrefab; public void ShowSafetySettingPage() { waitLockTime=0; if (safetySettingPagePrefab == null) { Debug.LogError("[HomePageCtrl] 未设置safetySettingPage预制体"); return; } GameObject safetySettingPage = Instantiate(safetySettingPagePrefab, transform); safetySettingPage.SetActive(true); UIManager.Instance.RegisterBackAction(() => { safetySettingPage.GetComponent().ClosePage(); }); } public void ShowScheduleSettingPage() { waitLockTime=0; if (scheduleSettingPrefab == null) { Debug.LogError("[HomePageCtrl] 未设置scheduleSettingPage预制体"); return; } GameObject scheduleSettingPage = Instantiate(scheduleSettingPrefab, transform); scheduleSettingPage.SetActive(true); // 注册页面关闭回调,更新主页定时任务显示 var schedulePage = scheduleSettingPage.GetComponent(); if (schedulePage != null) { schedulePage.OnPageClosed = () => { // 重新读取定时任务更新主页显示 if (hasWifi && !hasBluetooth) { _ = RefreshHomeScheduleFromWifi(); } else { BLECommunicationManager.Instance?.ReadScheduleTasks(); } }; } UIManager.Instance.RegisterBackAction(() => { scheduleSettingPage.GetComponent().ClosePage(); }); } public Button moreSettingButton; public void EnterMoreSettingPage() { waitLockTime=0; DataManager.Instance.selectedDevice = selectedDevice; UIManager.Instance.OpenPage(UIManager.PageName.deviceInfoPage); } public void EnterRankingPage() { UIManager.Instance.OpenPage(UIManager.PageName.rankPage); } public void EnterSelfPage() { UIManager.Instance.OpenPage(UIManager.PageName.selfPage); } public MessageTypeListPage messagePagePrefab; public void EnterMessagePage() { waitLockTime=0; Instantiate(messagePagePrefab,transform); } public void EnterVideoPage() { waitLockTime=0; UIManager.Instance.OpenPage(UIManager.PageName.videoPage); } public async void SetLock(bool ison) { waitLockTime=0; if (hasBluetooth) { BLECommunicationManager.Instance.WriteDeviceLockControl(!ison, (success) => { Loom.QueueOnMainThread(() => { if (ison) { DeviceLockControl deviceLockControl = new DeviceLockControl(); deviceLockControl.IsLocked = false; OnLockReceived(deviceLockControl); LoadingUI.Hide(); } else { deviceCtrl.InitDeviceControl(false); LoadingUI.Hide(); } }); }); } else if (hasWifi) { // WiFi模式下锁定/解锁设备 try { var lockControl = new DeviceLockControl { IsLocked = !ison }; byte[] lockBytes = lockControl.ToBytes(); bool success = await SendBleCommandByWifiAsync(BLEConstants.CMD_DEVICE_LOCK, lockBytes); if (success) { Debug.Log($"[HomePageCtrl] WiFi锁定设置成功: {(lockControl.IsLocked ? "锁定" : "解锁")}"); if (lockControl.IsLocked) { deviceCtrl?.InitDeviceControl(false); } else { deviceCtrl?.InitDeviceControl(true); InitDeviceUIFromConfig(); } } } finally { LoadingUI.Hide(); } } else { LoadingUI.Hide(); ToastUI.Show("100081"); } } IEnumerator CheckDeviceError() { while(hasBluetooth) { GetDeviceStatus(); yield return new WaitForSeconds(30); } } int waitTime = 0; IEnumerator GetLastMosquitoData() { while (true) { yield return new WaitForSeconds(1); waitTime++; if (waitTime==50) { OnGetAllMosquitoDataClick(); } if(waitTime==100) { waitTime=0; GetLastRecords(); ShowCharts(); GetMessageTypeList(); } } } public Button errorTipButton; public GameObject deiviceErrorTip; public void GetDeviceStatus() { List errorlist = new List(); BLECommunicationManager.Instance.ReadHardwareStatus((status) => { Loom.QueueOnMainThread(() => { bool hasError = false; if (status.TemperatureError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100228"); if (status.TemperatureError == 1) { error += LanguageManager.Instance.GetLanguage("100229"); } else { error += LanguageManager.Instance.GetLanguage("100230"); } } if (status.MotorError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100231"); if (status.MotorError == 1) { error += LanguageManager.Instance.GetLanguage("100232"); } else { error += LanguageManager.Instance.GetLanguage("100233"); } errorlist.Add(error); } if (status.LaserError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100234"); if (status.LaserError == 1) { error += LanguageManager.Instance.GetLanguage("100232"); } else if (status.LaserError == 2) { error += LanguageManager.Instance.GetLanguage("100236"); } else { error += LanguageManager.Instance.GetLanguage("100235"); } errorlist.Add(error); } if (status.VisionError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100237"); error += LanguageManager.Instance.GetLanguage("100232"); errorlist.Add(error); } if (status.AccelerometerError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100239"); error += LanguageManager.Instance.GetLanguage("100232"); errorlist.Add(error); } if (status.MillimeterWaveError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100240"); error += LanguageManager.Instance.GetLanguage("100232"); errorlist.Add(error); } if (status.LidarError != 0) { hasError = true; string error = LanguageManager.Instance.GetLanguage("100241"); error += LanguageManager.Instance.GetLanguage("100232"); errorlist.Add(error); } errorTipButton.gameObject.SetActive(hasError); string fullerror = ""; int index = 1; foreach (string e in errorlist) { fullerror += $"{index}.{e}/n"; } deiviceErrorTip.GetComponentInChildren().text=fullerror; }); }); } public Text lastRecordTimeTexts; public async void GetLastRecords() { waitTime=0; LoadingUI.Show(); string url = $"/api/v1/stats/device/records?device_sn={selectedDevice.ble_mac}&type=1&page=1&page_size=1"; var response = await NetworkCtrl.Instance.Get(url); LoadingUI.Hide(); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { if (data.data.records != null && data.data.records.Count > 0) { RecordData record = data.data.records[0]; lastRecordTimeTexts.text=$"{record.time:HH:mm} {record.time:yyyy/MM/dd}"; } else { lastRecordTimeTexts.text = "--"; } }, onError: null ); } public HomePageChartsCtrl homePageChartsCtrl; public void ShowCharts() { waitTime = 0; homePageChartsCtrl.Init(); } List mosquitoDatas; int aimMosquitoDataCount=0; Coroutine waitToPostMosquitoDatas=null; private void OnMosquitoDataReceived(MosquitoData mosquitoData) { DateTime now=DateTime.Now; mosquitoDatas.Add(mosquitoData); if(waitToPostMosquitoDatas!=null) StopCoroutine(waitToPostMosquitoDatas); if(mosquitoDatas.Count>=aimMosquitoDataCount&&aimMosquitoDataCount>0) { LoadingUI.Hide(); PostMosquitoDatas(); aimMosquitoDataCount=0; waitToPostMosquitoDatas=null; } else if(mosquitoDatas.Count>0) { waitToPostMosquitoDatas=StartCoroutine(WaitToPostMosquitoDatas()); } } IEnumerator WaitToPostMosquitoDatas() { yield return new WaitForSeconds(2); PostMosquitoDatas(); LoadingUI.Hide(); } async void PostMosquitoDatas() { List postRecordDatas=new List(); foreach(var a in mosquitoDatas) { var b=new PostRecordData { device_sn=selectedDevice.ble_mac, record_time=a.GetTimeString(), angle=a.GetActualAngle(), distance=a.GetActualDis() }; postRecordDatas.Add(b); } Debug.Log("发送灭蚊数据:"+JsonUtility.ToJson(postRecordDatas)); var response = await NetworkCtrl.Instance.Post("/api/v1/stats/device/records", postRecordDatas); ResponseCodeHandler.HandleResponse(response, null, null); } /// /// 获取所有蚊虫数据 (0xA4) /// 流程:1.查询数量 -> 2.请求数据 -> 3.接收通知 /// private void OnGetAllMosquitoDataClick() { LoadingUI.Show(); // 步骤1: 查询蚊虫数据数量 BLECommunicationManager.Instance.ReadMosquitoDataCount((count) => { Loom.QueueOnMainThread(() => { if (count.Count == 0) { Debug.Log("设备中没有蚊虫数据"); LoadingUI.Hide(); return; } Debug.Log($"检测到 {count.Count} 条蚊虫数据,正在请求..."); // 步骤2: 请求所有蚊虫数据 BLECommunicationManager.Instance.RequestMosquitoData(count.Count, (success) => { Loom.QueueOnMainThread(() => { if (success) { Debug.Log($"已请求 {count.Count} 条蚊虫数据,等待接收..."); mosquitoDatas=new List(); aimMosquitoDataCount=(int)count.Count; } else { Debug.Log("蚊虫数据请求失败"); LoadingUI.Hide(); } }); }); }); }); } /// /// 写入语言设置 /// private void OnWriteLanguageClick() { bool isChinese = LanguageManager.Instance.languageType == LanguageManager.LanguageType.Chinese; BLECommunicationManager.Instance.WriteLanguageSetting(isChinese, (success) => { Loom.QueueOnMainThread(() => { ReceiveStatus(); }); }); } /// /// 写入时间设置 /// private void OnWriteTimeClick() { TimeSetting timeSetting = new TimeSetting(); timeSetting.SetTime(DateTime.Now); BLECommunicationManager.Instance.WriteTimeSetting(timeSetting, (success) => { Loom.QueueOnMainThread(() => { ReceiveStatus(); }); }); } public GameObject tipPoint; public async Task GetMessageTypeList() { LoadingUI.Show(); var response = await NetworkCtrl.Instance.Get("/api/v1/notifications/unread-count"); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { if(data.data.announcement>0||data.data.device>0||data.data.warning>0) { tipPoint.SetActive(true); } else { tipPoint.SetActive(false); } },(code,message)=>{tipPoint.SetActive(false);} ); LoadingUI.Hide(); } /// /// 查询设备在线状态 /// public async Task GetDeviceOnlineStatus() { if (selectedDevice == null || string.IsNullOrEmpty(selectedDevice.ble_mac)) { Debug.LogWarning("[HomePageCtrl] 未选中设备"); return false; } var tcs = new TaskCompletionSource(); var response = await NetworkCtrl.Instance.Get( "/api/v1/device/online", new Dictionary { { "mac", selectedDevice.ble_mac } } ); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { Debug.Log($"[HomePageCtrl] 设备在线状态: {data.data}"); tcs.TrySetResult(data.data); DataManager.Instance.hasWifi=data.data; }, onError: (code, msg) => { Debug.LogError($"[HomePageCtrl] 查询设备在线状态失败: {msg}"); tcs.TrySetResult(false); } ); return await tcs.Task; } /// /// 启动设备在线状态轮询(始终运行,后台检测WiFi状态变化) /// private async void StartDeviceOnlineStatusPolling() { if (isPollingOnline) return; isPollingOnline = true; stopPolling = false; while (!stopPolling && selectedDevice != null) { await System.Threading.Tasks.Task.Delay(30000); if (stopPolling || selectedDevice == null) break; // 查询WiFi在线状态 bool wasOnline = hasWifi; bool online = await GetDeviceOnlineStatus(); if (stopPolling) break; hasWifi = online; DataManager.Instance.hasWifi = online; if (!online && !hasBluetooth) { // WiFi和蓝牙都断开 if (wasOnline) { Debug.Log("[HomePageCtrl] 设备WiFi离线"); pendingUIUpdates.Add(() => { deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); }); } } else if (online && !wasOnline && !hasBluetooth) { // WiFi刚上线,且没有蓝牙连接 → 初始化UI Debug.Log("[HomePageCtrl] 设备WiFi上线,初始化UI"); await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac); if (stopPolling) break; await DataManager.Instance.GetScheduleTasks(selectedDevice.device_sn); if (stopPolling) break; ScheduleUIUpdate(() => { scheduleSettingButton.interactable = true; moreSettingButton.interactable = true; deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); InitDeviceUIFromConfig(); }); } else if (online && wasOnline) { // WiFi持续在线,正常更新UI pendingUIUpdates.Add(() => { deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); }); } } isPollingOnline = false; } /// /// 停止设备在线状态轮询(切换设备或销毁时调用) /// private void StopDeviceOnlineStatusPolling() { stopPolling = true; isPollingOnline = false; } private void ScheduleUIUpdate(Action action) { pendingUIUpdates.Add(action); } /// /// 从WiFi刷新主页定时任务显示 /// private async Task RefreshHomeScheduleFromWifi() { await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac); var tasks = new List(); foreach (var d in DataManager.Instance.scheduleTaskDatas) { // 过滤开始时间和结束时间都为0的无效任务 bool isInvalid = d.start_hour == 0 && d.start_minute == 0 && d.end_hour == 0 && d.end_minute == 0; if (isInvalid) continue; tasks.Add(new ScheduleTask { TaskId = d.task_id, Enabled = d.enabled, StartHour = d.start_hour, StartMinute = d.start_minute, EndHour = d.end_hour, EndMinute = d.end_minute, Mode = (ScheduleTaskMode)System.Enum.Parse(typeof(ScheduleTaskMode), d.mode, true), Repeat = d.repeat_mask }); } pendingUIUpdates.Add(() => { if (tasks.Count > 0) deviceSchedule?.Init(tasks.ToArray()); else deviceSchedule?.DisplayNoSchedule(); }); } /// /// 通过WiFi发送BLE指令到设备(使用共通错误处理) /// public async Task SendBleCommandByWifiAsync(byte command, byte[] data) { byte[] commandBytes = BLECommunicationManager.Instance.GetCommandBytes( command, BLEConstants.RW_WRITE, data); string commandHex = BitConverter.ToString(commandBytes).Replace("-", ""); var requestData = new DeviceControlRequest { device_sn = selectedDevice.ble_mac, command = commandHex }; var response = await NetworkCtrl.Instance.Post( "/api/v1/device/command", requestData); if (response == null || !response.IsSuccess) { Debug.LogError($"[HomePageCtrl] WiFi命令发送失败(0x{command:X2}): 网络错误"); ToastUI.Show("100292"); return false; } var resData = response.Data?.data; if (resData != null && resData.success) { return true; } Debug.LogError($"[HomePageCtrl] WiFi命令发送失败(0x{command:X2}): {resData?.message ?? "未知错误"}"); ToastUI.Show("100292"); return false; } /// /// 刷新安全设置UI /// public void RefreshSafetyUI() { pendingUIUpdates.Add(() => { deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); }); } /// /// 通过WiFi加载定时任务 /// public async void LoadScheduleTasks() { await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac); } /// /// 通过WiFi保存定时任务(与BLE WriteScheduleTasks协议一致:每任务7字节,不含TaskId) /// public async Task SaveScheduleTasksAsync(List tasks) { if (tasks == null || tasks.Count == 0) { Debug.LogWarning("[HomePageCtrl] 定时任务列表为空"); return; } // 每条任务7字节(不含TaskId),与BLE WriteScheduleTasks保持一致 byte[] data = new byte[tasks.Count * 7]; for (int i = 0; i < tasks.Count; i++) { byte[] taskBytes = tasks[i].ToBytesWithoutTaskId(); Array.Copy(taskBytes, 0, data, i * 7, 7); } bool success = await SendBleCommandByWifiAsync( BLEConstants.CMD_SCHEDULE_TASK, data); if (success) { Debug.Log($"[HomePageCtrl] WiFi定时任务保存成功,共 {tasks.Count} 条"); } // 失败时 SendBleCommandByWifiAsync 已显示 Toast "100292" } } }