From e69d3e4cbb7fcaa6be21fedf139dd24ce728f848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9C=E8=99=9E=E6=B8=A0=E6=88=90=E2=80=9D?= <“yuqucheng2006@qq.com”> Date: Wed, 24 Jun 2026 10:20:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=93=9D=E7=89=99=E8=AE=BE=E7=BD=AE=E9=80=9A?= =?UTF-8?q?=E8=BF=87wifi=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Plugins/iOS/BluetoothHelper.mm | 3 +- Assets/Scripts/Bluetooth/BluetoothManager.cs | 12 +-- Assets/Scripts/Managers/DataManager.cs | 81 +++++++++++++++++++ .../ConnectDevice/ConnectDevicePageCtrl.cs | 4 + .../UI/Pages/DeviceInfoPage/DeviceInfoPage.cs | 18 ++++- .../UI/Pages/DeviceInfoPage/LCDSetting.cs | 1 + .../Pages/DeviceInfoPage/RGBlightSetting.cs | 1 + .../DeviceInfoPage/VideoAndSoundSetting.cs | 1 + .../UI/Pages/HomePage/FovSettingPage.cs | 3 + .../Scripts/UI/Pages/HomePage/HomePageCtrl.cs | 15 +++- .../UI/Pages/HomePage/LensSettingPage.cs | 7 ++ .../UI/Pages/HomePage/LightSettingPage.cs | 1 + .../UI/Pages/HomePage/SafetySettingPage.cs | 4 + .../ScheduleSetting/ScheduleSettingPage.cs | 38 ++++++++- ProjectSettings/ProjectSettings.asset | 12 ++- 15 files changed, 186 insertions(+), 15 deletions(-) diff --git a/Assets/Plugins/iOS/BluetoothHelper.mm b/Assets/Plugins/iOS/BluetoothHelper.mm index 0a8b5cb..0a12da3 100644 --- a/Assets/Plugins/iOS/BluetoothHelper.mm +++ b/Assets/Plugins/iOS/BluetoothHelper.mm @@ -9,7 +9,8 @@ extern "C" { // 0 = Unknown, 1 = Resetting, 2 = Unsupported, 3 = Unauthorized, 4 = PoweredOff, 5 = PoweredOn int GetBluetoothStateIOS() { if (centralManager == nil) { - centralManager = [[CBCentralManager alloc] initWithDelegate:nil queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey: @NO}]; + // 使用 @YES 允许 iOS 系统在蓝牙关闭时自动弹出"打开蓝牙"对话框 + centralManager = [[CBCentralManager alloc] initWithDelegate:nil queue:nil options:@{CBCentralManagerOptionShowPowerAlertKey: @YES}]; } switch (centralManager.state) { diff --git a/Assets/Scripts/Bluetooth/BluetoothManager.cs b/Assets/Scripts/Bluetooth/BluetoothManager.cs index d1034c6..2b1a9a5 100644 --- a/Assets/Scripts/Bluetooth/BluetoothManager.cs +++ b/Assets/Scripts/Bluetooth/BluetoothManager.cs @@ -339,18 +339,18 @@ namespace Kill.Bluetooth Log("iOS 蓝牙已开启"); onBluetoothReady?.Invoke(); } - // 4 = PoweredOff (蓝牙关闭) + // 4 = PoweredOff (蓝牙关闭) — iOS 系统会自动弹出蓝牙开启对话框,无需手动跳转设置 else if (state == 4) { - Log("iOS 蓝牙未开启,跳转到系统设置..."); - ShowIOSTurnOnBluetoothPrompt(); - // 等待用户从设置返回(检测焦点变化 + 轮询蓝牙状态) + Log("iOS 蓝牙未开启,等待系统弹出蓝牙开启提示..."); + // 不调用 ShowIOSTurnOnBluetoothPrompt(),让 iOS 原生弹窗处理 + // 等待蓝牙状态变化(检测焦点变化 + 轮询蓝牙状态) _enableBtCoroutine = StartCoroutine(WaitForIOSBluetoothEnabled(onBluetoothReady)); } - // 3 = Unauthorized (未授权) + // 3 = Unauthorized (未授权) — 需要跳转到应用设置页面让用户开启蓝牙权限 else if (state == 3) { - Log("iOS 蓝牙未授权,跳转到系统设置..."); + Log("iOS 蓝牙未授权,跳转到应用设置页..."); ShowIOSTurnOnBluetoothPrompt(); _enableBtCoroutine = StartCoroutine(WaitForIOSBluetoothEnabled(onBluetoothReady)); } diff --git a/Assets/Scripts/Managers/DataManager.cs b/Assets/Scripts/Managers/DataManager.cs index fb332e5..c7a29c9 100644 --- a/Assets/Scripts/Managers/DataManager.cs +++ b/Assets/Scripts/Managers/DataManager.cs @@ -229,6 +229,73 @@ namespace Kill.Managers #endregion + /// + /// 同步设备配置到服务器(WiFi在线时调用,由各设置页面Sync方法调用) + /// + public async void SyncDeviceConfigToServer() + { + if (!hasWifi) return; + await UpdateDeviceConfig(selectedDevice.ble_mac, deviceConfig); + } + + /// + /// 更新定时任务到服务器 + /// + public async Task UpdateScheduleTasksToServer(string deviceSn, List tasks) + { + var requestData = new ScheduleTasksUploadRequest + { + device_sn = deviceSn, + tasks = tasks + }; + + var response = await NetworkCtrl.Instance.Post( + "/api/v1/device/schedule-tasks", JsonUtility.ToJson(requestData)); + + bool success = false; + ResponseCodeHandler.HandleResponse(response, + onSuccess: (data) => + { + success = true; + Debug.Log($"[DataManager] 定时任务已同步到服务器,共 {tasks.Count} 条"); + }, + onError: (code, msg) => + { + Debug.LogError($"[DataManager] 同步定时任务失败: {msg}"); + } + ); + return success; + } + + /// + /// 更新指纹列表到服务器 + /// + public async Task UpdateFingerprintsToServer(string deviceSn, List fingerprints) + { + var requestData = new FingerprintsUploadRequest + { + device_sn = deviceSn, + fingerprints = fingerprints + }; + + var response = await NetworkCtrl.Instance.Post( + "/api/v1/device/fingerprints", JsonUtility.ToJson(requestData)); + + bool success = false; + ResponseCodeHandler.HandleResponse(response, + onSuccess: (data) => + { + success = true; + Debug.Log($"[DataManager] 指纹列表已同步到服务器,共 {fingerprints.Count} 条"); + }, + onError: (code, msg) => + { + Debug.LogError($"[DataManager] 同步指纹列表失败: {msg}"); + } + ); + return success; + } + /// /// 通过WiFi获取指纹列表 /// @@ -352,4 +419,18 @@ namespace Kill.Managers.ResponseModels public string mode; public byte repeat_mask; } + + [System.Serializable] + public class ScheduleTasksUploadRequest + { + public string device_sn; + public List tasks; + } + + [System.Serializable] + public class FingerprintsUploadRequest + { + public string device_sn; + public List fingerprints; + } } diff --git a/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs b/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs index 6cd6e8e..136f48b 100644 --- a/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs +++ b/Assets/Scripts/UI/Pages/ConnectDevice/ConnectDevicePageCtrl.cs @@ -173,6 +173,10 @@ public class ConnectDevicePageCtrl : MonoBehaviour 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 diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs index 008af57..c9ca9bf 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs @@ -128,14 +128,18 @@ namespace Kill.UI.Pages LoadingUI.Show(); BLECommunicationManager.Instance.SetFingerprintEnable(nowUserid, isOn, (response) => { - Loom.QueueOnMainThread(() => + Loom.QueueOnMainThread(async () => { if (response.IsSuccess) { if (isOn) SetFingerprint(); else + { + // 禁用指纹成功,同步到服务器 + await SyncFingerprintsToServerAsync(); LoadingUI.Hide(); + } } else { @@ -150,11 +154,13 @@ namespace Kill.UI.Pages { BLECommunicationManager.Instance.StartFingerprintRecord(nowUserid, (response) => { - Loom.QueueOnMainThread(() => + Loom.QueueOnMainThread(async () => { if (response.IsSuccess) { fingerTip.SetActive(true); + // 录制成功,同步到服务器 + await SyncFingerprintsToServerAsync(); LoadingUI.Hide(); } else @@ -165,6 +171,14 @@ namespace Kill.UI.Pages }); } + private async Task SyncFingerprintsToServerAsync() + { + if (!DataManager.Instance.hasWifi) return; + await DataManager.Instance.UpdateFingerprintsToServer( + DataManager.Instance.selectedDevice.device_sn, + DataManager.Instance.fingerprintUserDatas); + } + /// /// 读取RGB设置 /// diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs index baf1833..d213951 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs @@ -171,6 +171,7 @@ namespace Kill.UI.Pages if (success) { SyncSleepConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); UpdateUI(); } else diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/RGBlightSetting.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/RGBlightSetting.cs index 1fdf7db..dcb75bc 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/RGBlightSetting.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/RGBlightSetting.cs @@ -80,6 +80,7 @@ namespace Kill.UI.Pages if (success) { SyncRGBConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); UpdateUI(); } else diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/VideoAndSoundSetting.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/VideoAndSoundSetting.cs index 5675c71..7d635d5 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/VideoAndSoundSetting.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/VideoAndSoundSetting.cs @@ -124,6 +124,7 @@ namespace Kill.UI.Pages if (success) { SyncMultimediaConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); UpdateUI(); } else diff --git a/Assets/Scripts/UI/Pages/HomePage/FovSettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/FovSettingPage.cs index cfa5ad7..bee0277 100644 --- a/Assets/Scripts/UI/Pages/HomePage/FovSettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/FovSettingPage.cs @@ -372,6 +372,7 @@ namespace Kill.UI.Pages Debug.Log($"[FovSettingPage] 角度设置成功: {selectedAngle}°"); currentAngle = selectedAngle; DataManager.Instance.deviceConfig.fov_angle = selectedAngle * 10; + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -431,6 +432,7 @@ namespace Kill.UI.Pages vllEnabled = newVllState; UpdateVllButton(); DataManager.Instance.deviceConfig.laser_visible_enable = newVllState; + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -515,6 +517,7 @@ namespace Kill.UI.Pages currentAngle = originalAngle; selectedAngle = originalAngle; DataManager.Instance.deviceConfig.fov_angle = originalAngle * 10; + DataManager.Instance.SyncDeviceConfigToServer(); } else { diff --git a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs index e3b1ac3..4425413 100644 --- a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs +++ b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs @@ -471,6 +471,7 @@ namespace Kill.UI.Pages { currentWorkMode = (WorkMode)mode; deviceCtrl?.InitWrokMode(mode); + DataManager.Instance.deviceConfig.work_mode = DeviceConfig.ToServerString((WorkMode)mode); } return; } @@ -511,6 +512,9 @@ namespace Kill.UI.Pages { deviceCtrl?.InitWrokMode(mode); }); + + DataManager.Instance.deviceConfig.work_mode = DeviceConfig.ToServerString(setting.Mode); + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -1175,11 +1179,15 @@ namespace Kill.UI.Pages DeviceLockControl deviceLockControl = new DeviceLockControl(); deviceLockControl.IsLocked = false; OnLockReceived(deviceLockControl); + DataManager.Instance.deviceConfig.is_locked = false; + DataManager.Instance.SyncDeviceConfigToServer(); LoadingUI.Hide(); } else { deviceCtrl.InitDeviceControl(false); + DataManager.Instance.deviceConfig.is_locked = true; + DataManager.Instance.SyncDeviceConfigToServer(); LoadingUI.Hide(); } @@ -1197,6 +1205,7 @@ namespace Kill.UI.Pages if (success) { Debug.Log($"[HomePageCtrl] WiFi锁定设置成功: {(lockControl.IsLocked ? "锁定" : "解锁")}"); + DataManager.Instance.deviceConfig.is_locked = lockControl.IsLocked; if (lockControl.IsLocked) { deviceCtrl?.InitDeviceControl(false); @@ -1486,7 +1495,11 @@ namespace Kill.UI.Pages { Loom.QueueOnMainThread(() => { - + if (success) + { + DataManager.Instance.deviceConfig.language = isChinese ? 1 : 0; + DataManager.Instance.SyncDeviceConfigToServer(); + } ReceiveStatus(); }); diff --git a/Assets/Scripts/UI/Pages/HomePage/LensSettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/LensSettingPage.cs index d2d7f9d..9a84389 100644 --- a/Assets/Scripts/UI/Pages/HomePage/LensSettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/LensSettingPage.cs @@ -454,6 +454,7 @@ namespace Kill.UI.Pages Debug.Log($"[LensSettingPage] 距离设置成功: {selectedLensValue}m"); currentLensValue = selectedLensValue; DataManager.Instance.deviceConfig.detection_distance = (int)(selectedLensValue * 10); + DataManager.Instance.deviceConfig.aim_distance = (int)(selectedLensValue * 10); } else { @@ -473,6 +474,8 @@ namespace Kill.UI.Pages Debug.Log($"[LensSettingPage] 距离设置成功: {selectedLensValue}m"); currentLensValue = selectedLensValue; DataManager.Instance.deviceConfig.detection_distance = (int)(selectedLensValue * 10); + DataManager.Instance.deviceConfig.aim_distance = (int)(selectedLensValue * 10); + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -531,6 +534,7 @@ namespace Kill.UI.Pages vllEnabled = newVllState; UpdateVllButton(); DataManager.Instance.deviceConfig.laser_visible_enable = newVllState; + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -650,6 +654,7 @@ namespace Kill.UI.Pages currentLensValue = originalLensValue; selectedLensValue = originalLensValue; DataManager.Instance.deviceConfig.detection_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10); + DataManager.Instance.deviceConfig.aim_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10); } else { @@ -673,6 +678,8 @@ namespace Kill.UI.Pages currentLensValue = originalLensValue; selectedLensValue = originalLensValue; DataManager.Instance.deviceConfig.detection_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10); + DataManager.Instance.deviceConfig.aim_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10); + DataManager.Instance.SyncDeviceConfigToServer(); } else { diff --git a/Assets/Scripts/UI/Pages/HomePage/LightSettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/LightSettingPage.cs index 949dba7..f3786c5 100644 --- a/Assets/Scripts/UI/Pages/HomePage/LightSettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/LightSettingPage.cs @@ -396,6 +396,7 @@ namespace Kill.UI.Pages { Debug.Log($"[LightSettingPage] 灯光设置成功: 开关={selectedLightEnabled}, 类型={selectedLightType}, 强度={selectedIntensity}"); SyncLightConfigFromCurrent(); + DataManager.Instance.SyncDeviceConfigToServer(); } else { diff --git a/Assets/Scripts/UI/Pages/HomePage/SafetySettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/SafetySettingPage.cs index 3c765e6..1cc3882 100644 --- a/Assets/Scripts/UI/Pages/HomePage/SafetySettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/SafetySettingPage.cs @@ -438,6 +438,7 @@ namespace Kill.UI.Pages { Debug.Log($"[SafetySettingPage] 视觉检测设置成功: 开关={selectedVisualEnabled}, 灵敏度={selectedVisualSensitivity}"); SyncVisualConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -498,6 +499,7 @@ namespace Kill.UI.Pages { Debug.Log($"[SafetySettingPage] 毫米波雷达设置成功: 灵敏度={selectedWaveSensitivity}"); SyncRadarConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); } else { @@ -513,7 +515,9 @@ namespace Kill.UI.Pages private void SyncRadarConfig() { var config = DataManager.Instance.deviceConfig; + config.radar_enable = true; config.radar_sensitivity = DeviceConfig.ToServerString(selectedWaveSensitivity); + config.radar_safe_distance = 10; } /// diff --git a/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs index da708b2..dfb4be9 100644 --- a/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs @@ -5,6 +5,7 @@ using Kill.Bluetooth; using Kill.Bluetooth.Protocol; using Kill.Core; using Kill.Managers; +using Kill.Managers.ResponseModels; using Kill.UI.Components; using UnityEngine; using UnityEngine.UI; @@ -607,7 +608,7 @@ namespace Kill.UI.Pages BLECommunicationManager.Instance.WriteScheduleTasks(tasksToSave.ToArray(), (success) => { - Loom.QueueOnMainThread(() => + Loom.QueueOnMainThread(async () => { // 隐藏Loading LoadingUI.Hide(); @@ -615,6 +616,28 @@ namespace Kill.UI.Pages if (success) { Debug.Log("[ScheduleSettingPage] 定时任务保存成功"); + + // WiFi在线时同步到服务器 + if (DataManager.Instance.hasWifi) + { + var tasksData = new List(); + foreach (var t in tasksToSave) + { + tasksData.Add(new ScheduleTaskData + { + task_id = t.TaskId, + enabled = t.Enabled, + start_hour = t.StartHour, + start_minute = t.StartMinute, + end_hour = t.EndHour, + end_minute = t.EndMinute, + mode = ToModeString(t.Mode), + repeat_mask = t.Repeat + }); + } + await DataManager.Instance.UpdateScheduleTasksToServer( + DataManager.Instance.selectedDevice.device_sn, tasksData); + } } else { @@ -636,6 +659,19 @@ namespace Kill.UI.Pages LoadingUI.Hide(); Destroy(gameObject); } + + private static string ToModeString(ScheduleTaskMode mode) + { + switch (mode) + { + case ScheduleTaskMode.Scan: + return "SCAN"; + case ScheduleTaskMode.Sterilize: + return "STERILIZE"; + default: + return "STANDBY"; + } + } } } diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index a6a25a5..2c55106 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -18,9 +18,9 @@ PlayerSettings: cursorHotspot: {x: 0, y: 0} m_SplashScreenBackgroundColor: {r: 0.12156863, g: 0.12156863, b: 0.1254902, a: 1} m_ShowUnitySplashScreen: 0 - m_ShowUnitySplashLogo: 1 + m_ShowUnitySplashLogo: 0 m_SplashScreenOverlayOpacity: 1 - m_SplashScreenAnimation: 1 + m_SplashScreenAnimation: 2 m_SplashScreenLogoStyle: 1 m_SplashScreenDrawMode: 0 m_SplashScreenBackgroundAnimationZoom: 1 @@ -39,7 +39,11 @@ PlayerSettings: y: 0 width: 1 height: 1 - m_SplashScreenLogos: [] + m_SplashScreenLogos: + - logo: {fileID: 21300000, guid: 0ddd579c89aad104fba3a316bd6c82fa, type: 3} + duration: 2 + - logo: {fileID: 21300000, guid: ca5bf37fb627d9e4690c05d832243763, type: 3} + duration: 2 m_VirtualRealitySplashScreen: {fileID: 0} m_HolographicTrackingLossScreen: {fileID: 0} defaultScreenWidth: 1920 @@ -269,7 +273,7 @@ PlayerSettings: AndroidTargetArchitectures: 2 AndroidTargetDevices: 1 AndroidSplashScreenScale: 0 - androidSplashScreen: {fileID: 0} + androidSplashScreen: {fileID: 2800000, guid: 0ddd579c89aad104fba3a316bd6c82fa, type: 3} AndroidKeystoreName: AndroidKeyaliasName: AndroidEnableArmv9SecurityFeatures: 0