wifi适配

This commit is contained in:
“虞渠成” 2026-06-17 15:42:55 +08:00
parent 3d16c2bddc
commit 412184ef1b
20 changed files with 1486 additions and 404 deletions

View File

@ -0,0 +1,197 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.Collections.Generic;
using System.IO;
namespace Kill.Editor
{
/// <summary>
/// 批量字体替换工具
/// 一次性替换项目中所有 Text 组件的字体
/// </summary>
public class BatchFontReplacer : EditorWindow
{
private Font targetFont;
private bool includeInactive = true;
private bool includePrefabs = true;
private Vector2 scrollPosition;
private List<string> modifiedObjects = new List<string>();
[MenuItem("Tools/批量替换字体")]
static void OpenWindow()
{
GetWindow<BatchFontReplacer>("批量替换字体");
}
void OnGUI()
{
GUILayout.Label("批量替换字体工具", EditorStyles.boldLabel);
EditorGUILayout.Space();
// 选择目标字体
targetFont = (Font)EditorGUILayout.ObjectField(
"目标字体", targetFont, typeof(Font), false);
if (targetFont == null)
{
EditorGUILayout.HelpBox("请选择一个中文字体文件", MessageType.Warning);
return;
}
EditorGUILayout.Space();
// 选项
includeInactive = EditorGUILayout.Toggle("包含未激活的物体", includeInactive);
includePrefabs = EditorGUILayout.Toggle("包含预制体资源", includePrefabs);
EditorGUILayout.Space();
// 按钮
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("替换场景中的 Text", GUILayout.Height(30)))
{
ReplaceFontsInScene();
}
if (GUILayout.Button("替换预制体中的 Text", GUILayout.Height(30)))
{
ReplaceFontsInPrefabs();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
if (GUILayout.Button("一键替换全部", GUILayout.Height(40)))
{
ReplaceAllFonts();
}
EditorGUILayout.Space();
// 显示修改记录
if (modifiedObjects.Count > 0)
{
GUILayout.Label($"已修改 {modifiedObjects.Count} 个对象:", EditorStyles.boldLabel);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(200));
foreach (var obj in modifiedObjects)
{
EditorGUILayout.LabelField(obj);
}
EditorGUILayout.EndScrollView();
}
}
/// <summary>
/// 替换场景中的所有 Text
/// </summary>
private void ReplaceFontsInScene()
{
if (targetFont == null) return;
modifiedObjects.Clear();
int count = 0;
// 获取场景中的所有 Text
Text[] texts = Resources.FindObjectsOfTypeAll<Text>();
foreach (var text in texts)
{
// 只处理场景中的物体
if (!text.gameObject.scene.IsValid()) continue;
// 检查是否未激活
if (!includeInactive && !text.gameObject.activeInHierarchy) continue;
// 替换字体
if (text.font != targetFont)
{
Undo.RecordObject(text, "Replace Font");
text.font = targetFont;
EditorUtility.SetDirty(text);
modifiedObjects.Add($"[场景] {text.gameObject.name}");
count++;
}
}
Debug.Log($"[批量替换字体] 场景中共替换了 {count} 个 Text 组件");
}
/// <summary>
/// 替换所有预制体中的 Text
/// </summary>
private void ReplaceFontsInPrefabs()
{
if (targetFont == null) return;
modifiedObjects.Clear();
int count = 0;
// 查找所有预制体文件
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets" });
foreach (string guid in prefabGuids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab == null) continue;
// 获取预制体中的所有 Text
Text[] texts = prefab.GetComponentsInChildren<Text>(true);
bool modified = false;
foreach (var text in texts)
{
if (text.font != targetFont)
{
text.font = targetFont;
modified = true;
count++;
}
}
// 保存修改
if (modified)
{
EditorUtility.SetDirty(prefab);
modifiedObjects.Add($"[预制体] {path}");
}
}
// 保存所有修改
AssetDatabase.SaveAssets();
Debug.Log($"[批量替换字体] 预制体中共替换了 {count} 个 Text 组件");
}
/// <summary>
/// 一键替换全部
/// </summary>
private void ReplaceAllFonts()
{
if (targetFont == null)
{
EditorUtility.DisplayDialog("错误", "请先选择一个字体", "确定");
return;
}
if (EditorUtility.DisplayDialog("确认",
"这将替换项目中所有 Text 组件的字体,是否继续?",
"确定", "取消"))
{
ReplaceFontsInScene();
ReplaceFontsInPrefabs();
EditorUtility.DisplayDialog("完成",
$"共替换了 {modifiedObjects.Count} 个对象",
"确定");
}
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bbd63d6707c04ff43a80f5c18165add4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: f4c31d68e7cd3454685bb4c132a52f58
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- PingFang SC
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@ -226,7 +226,7 @@
}, },
{ {
"key": "100046", "key": "100046",
"zh": "Photon Matrix专为智能、高效的蚊虫控制而设计——我们不断优化的功能和操作模式旨在提供可靠、有效的害虫管理体验。\n\n然而安全仍然是所有设备操作的基本原则。为确保我们的产品得到正确且安全的使用我们要求所有用户在访问应用程序的核心功能之前必须完成强制性的安全培训和评估。本次培训将涵盖关键的设备操作流程、安全注意事项和使用指南成功完成培训后您将能够使用应用程序的全部功能。\n\n在我们努力实现有效的蚊虫控制时我们将把安全放在首位。", "zh": "Photon Matrix专为智能、高效的蚊虫控制而设计\n——我们不断优化的功能和操作模式旨在提供可靠、有效的害虫管理体验。\n\n然而安全仍然是所有设备操作的基本原则。为确保我们的产品得到正确且安全的使用我们要求所有用户在访问应用程序的核心功能之前必须完成强制性的安全培训和评估。本次培训将涵盖关键的设备操作流程、安全注意事项和使用指南成功完成培训后您将能够使用应用程序的全部功能。\n\n在我们努力实现有效的蚊虫控制时我们将把安全放在首位。",
"en": "Photon Matrix is designed for intelligent and efficient mosquito control. Our continuously optimized features and operation modes aim to deliver a reliable and effective pest management experience.\n\nNevertheless, safety remains the fundamental principle for all device operations. To ensure our products are used correctly and safely, we require all users to complete mandatory safety training and assessment before accessing the core functions of the application. This training will cover key device operation procedures, safety precautions, and usage guidelines. Upon successful completion of the training, you will gain full access to all features of the application.\n\nWhile we strive for effective mosquito control, we prioritize safety above all." "en": "Photon Matrix is designed for intelligent and efficient mosquito control. Our continuously optimized features and operation modes aim to deliver a reliable and effective pest management experience.\n\nNevertheless, safety remains the fundamental principle for all device operations. To ensure our products are used correctly and safely, we require all users to complete mandatory safety training and assessment before accessing the core functions of the application. This training will cover key device operation procedures, safety precautions, and usage guidelines. Upon successful completion of the training, you will gain full access to all features of the application.\n\nWhile we strive for effective mosquito control, we prioritize safety above all."
}, },
{ {
@ -1134,7 +1134,7 @@
"zh": "固件更新失败,请重试", "zh": "固件更新失败,请重试",
"en": "Firmware update failed. Please try again." "en": "Firmware update failed. Please try again."
}, },
{ {
"key": "100228", "key": "100228",
"zh": "温度错误:", "zh": "温度错误:",
"en": "Temperature error:" "en": "Temperature error:"
@ -1157,12 +1157,12 @@
{ {
"key": "100232", "key": "100232",
"zh": "温度异常", "zh": "温度异常",
"en": "Temperature exception" "en": "Temperature error"
}, },
{ {
"key": "100233", "key": "100233",
"zh": "反馈异常", "zh": "反馈异常",
"en": "Feedback exception" "en": "Feedback error"
}, },
{ {
"key": "100234", "key": "100234",
@ -1182,27 +1182,27 @@
{ {
"key": "100237", "key": "100237",
"zh": "视觉传感器异常:", "zh": "视觉传感器异常:",
"en": "Visual sensor exception:" "en": "Vision error:"
}, },
{ {
"key": "100238", "key": "100238",
"zh": "通信异常", "zh": "通信异常",
"en": "Communication exception" "en": "Communication error:"
}, },
{ {
"key": "100239", "key": "100239",
"zh": "加速度传感器异常:", "zh": "加速度传感器异常:",
"en": "Accelerationometer sensor exception:" "en": "Accelerometer error:"
}, },
{ {
"key": "100240", "key": "100240",
"zh": "毫米波雷达异常:", "zh": "毫米波雷达异常:",
"en": "Millimeter wave radar exception:" "en": "Millimeter-Wave Radar error:"
}, },
{ {
"key": "100241", "key": "100241",
"zh": "激光雷达异常:", "zh": "激光雷达异常:",
"en": "Laser radar exception:" "en": "LiDAR error:"
}, },
{ {
"key": "100242", "key": "100242",
@ -1443,6 +1443,26 @@
"key": "100289", "key": "100289",
"zh": "如需新增或修改指纹,可按设备端屏幕提示,录入指纹", "zh": "如需新增或修改指纹,可按设备端屏幕提示,录入指纹",
"en": "If you have any new or modified fingerprint requirements, please follow the instructions on the device screen to enter the fingerprint." "en": "If you have any new or modified fingerprint requirements, please follow the instructions on the device screen to enter the fingerprint."
},
{
"key": "100290",
"zh": "删除设备",
"en": "Delete Device"
},
{
"key": "100291",
"zh": "确认删除设备吗?",
"en": "Are you sure you want to delete the device?"
},
{
"key": "100292",
"zh": "设备当前不在线,请稍候,或连接蓝牙使用",
"en": "Device is not online, please wait or connect to Bluetooth to use."
},
{
"key": "100293",
"zh": "WiFi模式下暂不支持指纹设置请通过蓝牙连接操作",
"en": "Fingerprint settings are not supported in WiFi mode. Please connect via Bluetooth."
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 3fec09170d5c7164c8e83a43cef1221a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -555,6 +555,28 @@ namespace Kill.Managers
public bool? sound_enable; public bool? sound_enable;
public string sound_type; public string sound_type;
public byte? volume; public byte? volume;
/// <summary>
/// 将服务器配置字符串解析为枚举值
/// </summary>
public static T ParseServerEnum<T>(string serverValue, T defaultValue) where T : struct
{
if (string.IsNullOrEmpty(serverValue))
return defaultValue;
if (System.Enum.TryParse<T>(serverValue, true, out T result))
return result;
return defaultValue;
}
/// <summary>
/// 将枚举值转换为服务器配置字符串(小写)
/// </summary>
public static string ToServerString<T>(T enumValue) where T : struct
{
return enumValue.ToString().ToLower();
}
} }
/// <summary> /// <summary>

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kill.Network; using Kill.Network;
using Kill.Managers.ResponseModels;
using Kill.UI.Components; using Kill.UI.Components;
using UnityEngine; using UnityEngine;
namespace Kill.Managers namespace Kill.Managers
@ -16,6 +17,10 @@ namespace Kill.Managers
public List<DeviceInfo> SharedDevices = new List<DeviceInfo>(); public List<DeviceInfo> SharedDevices = new List<DeviceInfo>();
public bool isOwner; public bool isOwner;
public bool hasWifi; public bool hasWifi;
public bool hasBluetooth;
public FingerprintListResponseData fingerprintListData = new FingerprintListResponseData();
public List<FingerprintUserData> fingerprintUserDatas = new List<FingerprintUserData>();
public List<ScheduleTaskData> scheduleTaskDatas = new List<ScheduleTaskData>();
private void Awake() private void Awake()
{ {
@ -223,5 +228,128 @@ namespace Kill.Managers
} }
#endregion #endregion
/// <summary>
/// 通过WiFi获取指纹列表
/// </summary>
public async Task GetFingerprints(string deviceSn)
{
var response = await NetworkCtrl.Instance.Get<FingerprintListResponse>(
"/api/v1/device/fingerprints",
new Dictionary<string, string> { { "device_sn", deviceSn } }
);
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
fingerprintUserDatas.Clear();
if (data.data?.list != null)
{
fingerprintUserDatas.AddRange(data.data.list);
}
Debug.Log($"[DataManager] 获取到 {fingerprintUserDatas.Count} 条指纹记录");
},
onError: (code, msg) =>
{
Debug.LogError($"[DataManager] 获取指纹列表失败: {msg}");
}
);
}
/// <summary>
/// 通过WiFi获取定时任务列表
/// </summary>
public async Task GetScheduleTasks(string deviceSn)
{
var response = await NetworkCtrl.Instance.Get<ScheduleTaskListDataResponse>(
"/api/v1/device/schedule-tasks",
new Dictionary<string, string> { { "device_sn", deviceSn } }
);
ResponseCodeHandler.HandleResponse(response,
onSuccess: (data) =>
{
scheduleTaskDatas.Clear();
Debug.Log($"[DataManager] 定时任务API返回: total={data.data?.total}, list count={data.data?.list?.Count ?? 0}");
if (data.data?.list != null)
{
scheduleTaskDatas.AddRange(data.data.list);
foreach (var d in scheduleTaskDatas)
{
Debug.Log($"[DataManager] 任务 ID={d.task_id}, enabled={d.enabled}, start={d.start_hour}:{d.start_minute:D2}, end={d.end_hour}:{d.end_minute:D2}, mode={d.mode}, repeat={d.repeat_mask}");
}
}
Debug.Log($"[DataManager] 获取到 {scheduleTaskDatas.Count} 条定时任务");
},
onError: (code, msg) =>
{
Debug.LogError($"[DataManager] 获取定时任务列表失败: {msg}");
}
);
}
}
/// <summary>
/// 指纹用户数据(从服务器获取)
/// </summary>
[System.Serializable]
public class FingerprintUserData
{
public string username;
public int fingerprint_id;
public bool has_fingerprint;
}
}
// 响应模型
namespace Kill.Managers.ResponseModels
{
[System.Serializable]
public class FingerprintListResponse
{
public int code;
public string message;
public FingerprintListResponseData data;
}
[System.Serializable]
public class FingerprintListResponseData
{
public int total;
public int pages;
public int limit;
public int page;
public List<FingerprintUserData> list;
}
[System.Serializable]
public class ScheduleTaskListDataResponse
{
public int code;
public string message;
public ScheduleTaskListData data;
}
[System.Serializable]
public class ScheduleTaskListData
{
public int total;
public int pages;
public int limit;
public int page;
public List<ScheduleTaskData> list;
}
[System.Serializable]
public class ScheduleTaskData
{
public byte task_id;
public bool enabled;
public byte start_hour;
public byte start_minute;
public byte end_hour;
public byte end_minute;
public string mode;
public byte repeat_mask;
} }
} }

View File

@ -1085,7 +1085,16 @@ namespace Kill.Network
[System.Serializable] [System.Serializable]
public class DeviceControlResponse public class DeviceControlResponse
{ {
public string code; public int code;
public string message;
public DeviceControlResponseData data;
}
[System.Serializable]
public class DeviceControlResponseData
{
public int seq;
public bool success;
public string message; public string message;
} }

View File

@ -74,15 +74,28 @@ namespace Kill.UI.Pages
} }
bool isfingerOn = true; bool isfingerOn = true;
public void ReadFingerprint() public async void ReadFingerprint()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
Debug.Log("初始化指纹"); {
initActions.Remove(ReadFingerprint); // WiFi模式从服务器指纹列表读取
fingerprintSwitch.Init(true, (ison) => { Debug.Log($"指纹开关:{ison}"); }); await DataManager.Instance.GetFingerprints(DataManager.Instance.selectedDeviceMac);
InitData(); bool hasFp = false;
return; foreach (var user in DataManager.Instance.fingerprintUserDatas)
#endif {
if (user.username == nowUserid)
{
hasFp = user.has_fingerprint;
break;
}
}
isfingerOn = hasFp;
initActions.Remove(ReadFingerprint);
fingerprintSwitch.Init(isfingerOn, SetFingerprintSwicth);
InitData();
return;
}
BLECommunicationManager.Instance.QueryUserList((UserListResponse) => BLECommunicationManager.Instance.QueryUserList((UserListResponse) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
@ -104,9 +117,14 @@ namespace Kill.UI.Pages
} }
public void SetFingerprintSwicth(bool isOn) public void SetFingerprintSwicth(bool isOn)
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
return; {
#endif // WiFi模式下不能通过WiFi控制指纹开关仅展示状态
ToastUI.Show("100293");
fingerprintSwitch.isOn = !isOn;
return;
}
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.SetFingerprintEnable(nowUserid, isOn, (response) => BLECommunicationManager.Instance.SetFingerprintEnable(nowUserid, isOn, (response) =>
{ {
@ -152,16 +170,19 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadLightSettings() private void ReadLightSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
this.rGBControl = new RGBControl(); {
rGBControl.SetColor(new Color(0.1f, 0.2f, 0.3f)); var config = DataManager.Instance.deviceConfig;
rGBControl.Enable = true; this.rGBControl = new RGBControl();
rGBControl.Effect = 0; rGBControl.Enable = config?.rgb_enable ?? false;
rgbValue.text = GetOnOffValue(rGBControl.Enable); rGBControl.SetColor(new Color((config?.rgb_red ?? 0) / 255f, (config?.rgb_green ?? 0) / 255f, (config?.rgb_blue ?? 0) / 255f));
initActions.Remove(ReadLightSettings); rGBControl.Effect = DeviceConfig.ParseServerEnum(config?.rgb_effect, RGBEffectMode.Blinking);
InitData(); rgbValue.text = GetOnOffValue(rGBControl.Enable);
return; initActions.Remove(ReadLightSettings);
#endif InitData();
return;
}
// 读取rgb // 读取rgb
BLECommunicationManager.Instance.ReadRGBControl((setting) => BLECommunicationManager.Instance.ReadRGBControl((setting) =>
{ {

View File

@ -56,21 +56,23 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadLCDSettings() private void ReadLCDSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
// 编辑器模式下使用默认值
brightnessSetting = new LCDBrightnessSetting
{ {
AutoBrightness = false, var config = DataManager.Instance.deviceConfig;
Brightness = 80 brightnessSetting = new LCDBrightnessSetting
}; {
sleepSetting = new LCDSleepSetting AutoBrightness = config?.lcd_auto_brightness ?? false,
{ Brightness = config?.lcd_brightness ?? 80
Enable = true, };
SleepTime = 0x05 // 5分钟 sleepSetting = new LCDSleepSetting
}; {
UpdateUI(); Enable = config?.lcd_sleep_enable ?? true,
return; SleepTime = config?.lcd_sleep_time ?? 0x05
#endif };
UpdateUI();
return;
}
LoadingUI.Show(); LoadingUI.Show();
// 读取亮度设置 // 读取亮度设置
@ -95,12 +97,25 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 写入LCD亮度设置 /// 写入LCD亮度设置
/// </summary> /// </summary>
private void WriteBrightnessSetting() private async void WriteBrightnessSetting()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
UpdateUI(); {
return; LoadingUI.Show();
#endif bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_LCD_BRIGHTNESS_SETTING, brightnessSetting.ToBytes());
if (success)
{
SyncBrightnessConfig();
UpdateUI();
}
else
{
ReadLCDSettings();
}
return;
}
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.WriteLCDBrightnessSetting(brightnessSetting, (success) => BLECommunicationManager.Instance.WriteLCDBrightnessSetting(brightnessSetting, (success) =>
{ {
@ -119,15 +134,35 @@ namespace Kill.UI.Pages
}); });
} }
private void SyncBrightnessConfig()
{
var config = DataManager.Instance.deviceConfig;
config.lcd_auto_brightness = brightnessSetting.AutoBrightness;
config.lcd_brightness = brightnessSetting.Brightness;
}
/// <summary> /// <summary>
/// 写入LCD休眠设置 /// 写入LCD休眠设置
/// </summary> /// </summary>
private void WriteSleepSetting() private async void WriteSleepSetting()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
UpdateUI(); {
return; LoadingUI.Show();
#endif bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_LCD_SLEEP_SETTING, sleepSetting.ToBytes());
if (success)
{
SyncSleepConfig();
UpdateUI();
}
else
{
ReadLCDSettings();
}
return;
}
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.WriteLCDSleepSetting(sleepSetting, (success) => BLECommunicationManager.Instance.WriteLCDSleepSetting(sleepSetting, (success) =>
{ {
@ -135,6 +170,7 @@ namespace Kill.UI.Pages
{ {
if (success) if (success)
{ {
SyncSleepConfig();
UpdateUI(); UpdateUI();
} }
else else
@ -146,6 +182,13 @@ namespace Kill.UI.Pages
}); });
} }
private void SyncSleepConfig()
{
var config = DataManager.Instance.deviceConfig;
config.lcd_sleep_enable = sleepSetting.Enable;
config.lcd_sleep_time = sleepSetting.SleepTime;
}
/// <summary> /// <summary>
/// 更新UI显示 /// 更新UI显示
/// </summary> /// </summary>

View File

@ -46,14 +46,16 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadLightSettings() private void ReadLightSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
this.setting = new RGBControl(); {
setting.SetColor(new Color(0.1f,0.2f,0.3f)); var config = DataManager.Instance.deviceConfig;
setting.Enable = true; this.setting = new RGBControl();
setting.Effect = 0; setting.Enable = config?.rgb_enable ?? false;
UpdateUI(); setting.SetColor(new Color((config?.rgb_red ?? 0) / 255f, (config?.rgb_green ?? 0) / 255f, (config?.rgb_blue ?? 0) / 255f));
return; setting.Effect = DeviceConfig.ParseServerEnum(config?.rgb_effect, RGBEffectMode.Blinking);
#endif UpdateUI();
return;
}
// 显示Loading // 显示Loading
LoadingUI.Show(); LoadingUI.Show();
@ -68,17 +70,31 @@ namespace Kill.UI.Pages
}); });
}); });
} }
private void SetRGBSetting() private async void SetRGBSetting()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
UpdateUI(); {
return; LoadingUI.Show();
#endif bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_RGB_CONTROL, setting.ToBytes());
if (success)
{
SyncRGBConfig();
UpdateUI();
}
else
{
ReadLightSettings();
}
return;
}
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.WriteRGBControl(setting, (success) => BLECommunicationManager.Instance.WriteRGBControl(setting, (success) =>
{ {
if (success) if (success)
{ {
SyncRGBConfig();
UpdateUI(); UpdateUI();
} }
else else
@ -88,6 +104,17 @@ namespace Kill.UI.Pages
} }
); );
} }
private void SyncRGBConfig()
{
var config = DataManager.Instance.deviceConfig;
config.rgb_enable = setting.Enable;
config.rgb_red = (byte)(setting.GetColor().r * 255);
config.rgb_green = (byte)(setting.GetColor().g * 255);
config.rgb_blue = (byte)(setting.GetColor().b * 255);
config.rgb_effect = DeviceConfig.ToServerString(setting.Effect);
}
public Image lightColor; public Image lightColor;
public Text modeValue; public Text modeValue;
private void UpdateUI() private void UpdateUI()

View File

@ -76,19 +76,12 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadMultimediaSettings() private void ReadMultimediaSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
// 编辑器模式下使用默认值
multimediaSetting = new MultimediaControl
{ {
VideoRecordEnable = true, MultimediaConfigFromServer();
RecordDuration = 0x05, return;
SoundEnable = true, }
SoundType = SoundEffectType.Hello,
Volume = 10
};
UpdateUI();
return;
#endif
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.ReadMultimediaControl((setting) => BLECommunicationManager.Instance.ReadMultimediaControl((setting) =>
@ -104,12 +97,25 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 写入多媒体设置 /// 写入多媒体设置
/// </summary> /// </summary>
private void WriteMultimediaSetting() private async void WriteMultimediaSetting()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
UpdateUI(); {
return; LoadingUI.Show();
#endif bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_MULTIMEDIA_CONTROL, multimediaSetting.ToBytes());
if (success)
{
SyncMultimediaConfig();
UpdateUI();
}
else
{
ReadMultimediaSettings();
}
return;
}
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance.WriteMultimediaControl(multimediaSetting, (success) => BLECommunicationManager.Instance.WriteMultimediaControl(multimediaSetting, (success) =>
{ {
@ -117,6 +123,7 @@ namespace Kill.UI.Pages
{ {
if (success) if (success)
{ {
SyncMultimediaConfig();
UpdateUI(); UpdateUI();
} }
else else
@ -127,6 +134,30 @@ namespace Kill.UI.Pages
}); });
} }
private void MultimediaConfigFromServer()
{
var config = DataManager.Instance.deviceConfig;
multimediaSetting = new MultimediaControl
{
VideoRecordEnable = config?.video_record_enable ?? false,
RecordDuration = config?.record_duration ?? 0x05,
SoundEnable = config?.sound_enable ?? true,
SoundType = DeviceConfig.ParseServerEnum(config?.sound_type, SoundEffectType.Hello),
Volume = config?.volume ?? 10
};
UpdateUI();
}
private void SyncMultimediaConfig()
{
var config = DataManager.Instance.deviceConfig;
config.video_record_enable = multimediaSetting.VideoRecordEnable;
config.record_duration = multimediaSetting.RecordDuration;
config.sound_enable = multimediaSetting.SoundEnable;
config.sound_type = DeviceConfig.ToServerString(multimediaSetting.SoundType);
config.volume = multimediaSetting.Volume;
}
/// <summary> /// <summary>
/// 更新UI显示 /// 更新UI显示
/// </summary> /// </summary>

View File

@ -206,11 +206,11 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadAngleAndVllSettings() private void ReadAngleAndVllSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
// 编辑器模式下使用假数据 {
Editor_InitWithFakeData(); LoadSettingsFromConfig();
return; return;
#endif }
// 显示Loading // 显示Loading
LoadingUI.Show(); LoadingUI.Show();
@ -220,50 +220,20 @@ namespace Kill.UI.Pages
BLECommunicationManager.Instance?.ReadAngleControl(); BLECommunicationManager.Instance?.ReadAngleControl();
} }
#if UNITY_EDITOR private void LoadSettingsFromConfig()
/// <summary>
/// 编辑器模式下使用假数据初始化
/// </summary>
private void Editor_InitWithFakeData()
{ {
Debug.Log("[FovSettingPage] 编辑器模式:使用假数据初始化"); var config = DataManager.Instance.deviceConfig;
// 假数据:角度 60度可见激光开启 currentAngle = (int)((config?.fov_angle ?? 0) * 0.1f);
currentAngle = 60; selectedAngle = currentAngle;
selectedAngle = 60; originalAngle = currentAngle;
vllEnabled = true;
vllEnabled = config?.laser_visible_enable ?? false;
originalVllEnabled = vllEnabled;
// 更新UI显示
UpdateUI(); UpdateUI();
} }
/// <summary>
/// 编辑器模式切换测试数据可在Inspector中调用
/// </summary>
[ContextMenu("测试切换角度为30度")]
private void Editor_SetAngle30()
{
currentAngle = 30;
selectedAngle = 30;
UpdateUI();
}
[ContextMenu("测试切换角度为90度")]
private void Editor_SetAngle90()
{
currentAngle = 90;
selectedAngle = 90;
UpdateUI();
}
[ContextMenu("测试:切换可见激光开关")]
private void Editor_ToggleVll()
{
vllEnabled = !vllEnabled;
UpdateVllButton();
}
#endif
/// <summary> /// <summary>
@ -360,24 +330,38 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 角度按钮点击事件 - 立即发送到设备 /// 角度按钮点击事件 - 立即发送到设备
/// </summary> /// </summary>
private void OnAngleButtonClick(int angle) private async void OnAngleButtonClick(int angle)
{ {
Debug.Log($"[FovSettingPage] 选择角度: {angle}°"); Debug.Log($"[FovSettingPage] 选择角度: {angle}°");
selectedAngle = angle; selectedAngle = angle;
UpdateUI(); UpdateUI();
#if UNITY_EDITOR
Debug.Log("[FovSettingPage] 编辑器模式:模拟设置角度");
currentAngle = selectedAngle;
return;
#endif
// 立即发送角度设置到设备 // 立即发送角度设置到设备
AngleControl angleControl = new AngleControl AngleControl angleControl = new AngleControl
{ {
AngleRange = (ushort)(selectedAngle * 10) // 转换为0.1度单位 AngleRange = (ushort)(selectedAngle * 10) // 转换为0.1度单位
}; };
BLECommunicationManager.Instance?.WriteAngleControl(angleControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_ANGLE_CONTROL, angleControl.ToBytes());
if (success)
{
Debug.Log($"[FovSettingPage] 角度设置成功: {selectedAngle}°");
currentAngle = selectedAngle;
DataManager.Instance.deviceConfig.fov_angle = selectedAngle * 10;
}
else
{
Debug.LogError("[FovSettingPage] 角度设置失败");
selectedAngle = currentAngle;
UpdateUI();
}
}
else
{
BLECommunicationManager.Instance?.WriteAngleControl(angleControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -385,6 +369,7 @@ namespace Kill.UI.Pages
{ {
Debug.Log($"[FovSettingPage] 角度设置成功: {selectedAngle}°"); Debug.Log($"[FovSettingPage] 角度设置成功: {selectedAngle}°");
currentAngle = selectedAngle; currentAngle = selectedAngle;
DataManager.Instance.deviceConfig.fov_angle = selectedAngle * 10;
} }
else else
{ {
@ -395,29 +380,43 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
} }
/// <summary> /// <summary>
/// 可见激光开关按钮点击事件 - 立即发送到设备 /// 可见激光开关按钮点击事件 - 立即发送到设备
/// </summary> /// </summary>
private void OnVllButtonClick() private async void OnVllButtonClick()
{ {
bool newVllState = !vllEnabled; bool newVllState = !vllEnabled;
Debug.Log($"[FovSettingPage] 可见激光开关: {(newVllState ? "" : "")}"); Debug.Log($"[FovSettingPage] 可见激光开关: {(newVllState ? "" : "")}");
#if UNITY_EDITOR
Debug.Log("[FovSettingPage] 编辑器模式:模拟设置可见激光");
vllEnabled = newVllState;
UpdateVllButton();
return;
#endif
// 立即发送可见激光设置到设备 // 立即发送可见激光设置到设备
VisibleLaserControl vllControl = new VisibleLaserControl VisibleLaserControl vllControl = new VisibleLaserControl
{ {
Enable = newVllState Enable = newVllState
}; };
BLECommunicationManager.Instance?.WriteVisibleLaserControl(vllControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_VISIBLE_LASER_CONTROL, vllControl.ToBytes());
if (success)
{
Debug.Log($"[FovSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}");
vllEnabled = newVllState;
UpdateVllButton();
DataManager.Instance.deviceConfig.laser_visible_enable = newVllState;
}
else
{
Debug.LogError("[FovSettingPage] 可见激光设置失败");
}
}
else
{
BLECommunicationManager.Instance?.WriteVisibleLaserControl(vllControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -426,6 +425,7 @@ namespace Kill.UI.Pages
Debug.Log($"[FovSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}"); Debug.Log($"[FovSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}");
vllEnabled = newVllState; vllEnabled = newVllState;
UpdateVllButton(); UpdateVllButton();
DataManager.Instance.deviceConfig.laser_visible_enable = newVllState;
} }
else else
{ {
@ -434,6 +434,7 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
} }
/// <summary> /// <summary>
@ -455,16 +456,10 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 取消按钮点击事件 - 只恢复原始角度,可见激光不恢复 /// 取消按钮点击事件 - 只恢复原始角度,可见激光不恢复
/// </summary> /// </summary>
public void OnCancelButtonClick() public async void OnCancelButtonClick()
{ {
Debug.Log("[FovSettingPage] 取消设置,恢复原始角度"); Debug.Log("[FovSettingPage] 取消设置,恢复原始角度");
#if UNITY_EDITOR
Debug.Log("[FovSettingPage] 编辑器模式:模拟恢复原始角度");
ClosePage();
return;
#endif
// 如果角度没有变化,直接关闭页面 // 如果角度没有变化,直接关闭页面
if (selectedAngle == originalAngle) if (selectedAngle == originalAngle)
{ {
@ -482,7 +477,27 @@ namespace Kill.UI.Pages
AngleRange = (ushort)(originalAngle * 10) AngleRange = (ushort)(originalAngle * 10)
}; };
BLECommunicationManager.Instance?.WriteAngleControl(angleControl, (angleSuccess) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool angleSuccess = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_ANGLE_CONTROL, angleControl.ToBytes());
if (angleSuccess)
{
Debug.Log($"[FovSettingPage] 角度恢复成功: {originalAngle}°");
currentAngle = originalAngle;
selectedAngle = originalAngle;
DataManager.Instance.deviceConfig.fov_angle = originalAngle * 10;
}
else
{
Debug.LogError("[FovSettingPage] 角度恢复失败");
}
NotifyHomePageRefresh();
ClosePage();
}
else
{
BLECommunicationManager.Instance?.WriteAngleControl(angleControl, (angleSuccess) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -493,6 +508,7 @@ namespace Kill.UI.Pages
Debug.Log($"[FovSettingPage] 角度恢复成功: {originalAngle}°"); Debug.Log($"[FovSettingPage] 角度恢复成功: {originalAngle}°");
currentAngle = originalAngle; currentAngle = originalAngle;
selectedAngle = originalAngle; selectedAngle = originalAngle;
DataManager.Instance.deviceConfig.fov_angle = originalAngle * 10;
} }
else else
{ {
@ -506,8 +522,8 @@ namespace Kill.UI.Pages
ClosePage(); ClosePage();
}); });
}); });
}
} }
/// <summary> /// <summary>

View File

@ -31,6 +31,8 @@ namespace Kill.UI.Pages
public Kill.Managers.DeviceInfo selectedDevice; public Kill.Managers.DeviceInfo selectedDevice;
bool hasBluetooth = false; bool hasBluetooth = false;
bool hasWifi = false; bool hasWifi = false;
bool isPollingOnline = false;
bool stopPolling = false;
// UI 组件引用 // UI 组件引用
public HomePageDeviceState deviceState; public HomePageDeviceState deviceState;
@ -91,6 +93,7 @@ namespace Kill.UI.Pages
} }
void OnDestroy() void OnDestroy()
{ {
StopDeviceOnlineStatusPolling();
UnsubscribeBluetoothEvents(); UnsubscribeBluetoothEvents();
StopAllCoroutines(); StopAllCoroutines();
} }
@ -166,6 +169,10 @@ namespace Kill.UI.Pages
{ {
Debug.Log("[HomePageCtrl] 蓝牙连接成功"); Debug.Log("[HomePageCtrl] 蓝牙连接成功");
hasBluetooth = true; hasBluetooth = true;
DataManager.Instance.hasBluetooth = true;
// 启动WiFi在线状态轮询后台检测设备WiFi状态
StartDeviceOnlineStatusPolling();
// 更新连接状态UI // 更新连接状态UI
pendingUIUpdates.Add(() => pendingUIUpdates.Add(() =>
@ -181,6 +188,7 @@ namespace Kill.UI.Pages
{ {
Debug.Log("[HomePageCtrl] 设备已在线"); Debug.Log("[HomePageCtrl] 设备已在线");
hasWifi = true; hasWifi = true;
DataManager.Instance.hasWifi = true;
// 更新连接状态UI // 更新连接状态UI
pendingUIUpdates.Add(() => pendingUIUpdates.Add(() =>
@ -331,6 +339,7 @@ namespace Kill.UI.Pages
{ {
Debug.Log("[HomePageCtrl] 蓝牙断开连接"); Debug.Log("[HomePageCtrl] 蓝牙断开连接");
hasBluetooth = false; hasBluetooth = false;
DataManager.Instance.hasBluetooth = false;
isBluetoothUserLoggedIn = false; isBluetoothUserLoggedIn = false;
isQueryingStatus = false; isQueryingStatus = false;
statusQueryQueue?.Clear(); statusQueryQueue?.Clear();
@ -468,6 +477,22 @@ namespace Kill.UI.Pages
return; return;
} }
// WiFi模式
if (hasWifi && !hasBluetooth)
{
LoadingUI.Show();
SetWorkModeByWifiAsync(mode).ContinueWith(t =>
{
Loom.QueueOnMainThread(() =>
{
LoadingUI.Hide();
currentWorkMode = (WorkMode)mode;
deviceCtrl?.InitWrokMode(mode);
});
});
return;
}
// 检查蓝牙连接 // 检查蓝牙连接
if (!BluetoothManager.Instance.IsConnected) if (!BluetoothManager.Instance.IsConnected)
{ {
@ -531,17 +556,31 @@ namespace Kill.UI.Pages
Debug.Log(commandHex); Debug.Log(commandHex);
var requestData = new DeviceControlRequest var requestData = new DeviceControlRequest
{ {
device_sn =selectedDevice.ble_mac, device_sn = selectedDevice.ble_mac,
command = commandHex command = commandHex
}; };
var response = await NetworkCtrl.Instance.Post<DeviceControlResponse>("/api/v1/device/command",requestData); var response = await NetworkCtrl.Instance.Post<DeviceControlResponse>("/api/v1/device/command", requestData);
// 处理结果 ResponseCodeHandler.HandleResponse(response,
if (response.IsSuccess) onSuccess: (res) =>
{ {
ToastUI.Show(response.Data.message); if (res.data != null && res.data.success)
} {
Debug.Log($"[HomePageCtrl] WiFi工作模式设置成功: {(WorkMode)mode}");
}
else
{
Debug.LogError($"[HomePageCtrl] WiFi工作模式设置失败: {res.data?.message}");
ToastUI.Show("100292");
}
},
onError: (code, msg) =>
{
Debug.LogError($"[HomePageCtrl] WiFi工作模式设置失败: {msg}");
ToastUI.Show("100292");
}
);
} }
@ -636,6 +675,13 @@ namespace Kill.UI.Pages
public void RefreshAngleControl() public void RefreshAngleControl()
{ {
Debug.Log("[HomePageCtrl] 刷新角度控制设置"); 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(); BLECommunicationManager.Instance?.ReadAngleControl();
} }
@ -665,6 +711,13 @@ namespace Kill.UI.Pages
public void RefreshLensControl() public void RefreshLensControl()
{ {
Debug.Log("[HomePageCtrl] 刷新距离控制设置"); 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(); BLECommunicationManager.Instance?.ReadDistanceControl();
} }
private void OnFillLightControlReceived(FillLightControl control) private void OnFillLightControlReceived(FillLightControl control)
@ -686,6 +739,12 @@ namespace Kill.UI.Pages
public void RefreshLightControl() public void RefreshLightControl()
{ {
Debug.Log("[HomePageCtrl] 刷新补光灯控制设置"); Debug.Log("[HomePageCtrl] 刷新补光灯控制设置");
if (hasWifi && !hasBluetooth)
{
var config = DataManager.Instance.deviceConfig;
pendingUIUpdates.Add(() => deviceCtrl?.InitLightText(config?.fill_light_enable ?? false));
return;
}
BLECommunicationManager.Instance?.ReadFillLightControl(); BLECommunicationManager.Instance?.ReadFillLightControl();
} }
// private void OnMillimeterWaveReceived(MillimeterWaveSetting setting) // private void OnMillimeterWaveReceived(MillimeterWaveSetting setting)
@ -718,6 +777,75 @@ namespace Kill.UI.Pages
#endregion #endregion
/// <summary>
/// WiFi模式下从设备配置初始化首页UI
/// </summary>
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<ScheduleTask>();
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() public async Task Init()
{ {
if (DataManager.Instance.userInfo.device_count == 0) if (DataManager.Instance.userInfo.device_count == 0)
@ -783,22 +911,27 @@ namespace Kill.UI.Pages
InitDeviceState(); InitDeviceState();
deviceState?.UpdateDeviceState(hasBluetooth, hasWifi); deviceState?.UpdateDeviceState(hasBluetooth, hasWifi);
// 始终启动WiFi在线状态轮询
StartDeviceOnlineStatusPolling();
// 如果蓝牙已连接,立即查询状态 // 如果蓝牙已连接,立即查询状态
if (hasBluetooth) if (hasBluetooth)
{ {
deviceCtrl?.InitDeviceControl(true); deviceCtrl?.InitDeviceControl(false);
// 开始设备状态初始化显示Loading BLECommunicationManager.Instance.ReadDeviceLockControl();
StartDeviceStateInitialization();
StartCoroutine(QueryAllDeviceStatusSequential());
scheduleSettingButton.interactable = true; scheduleSettingButton.interactable = true;
moreSettingButton.interactable = true; moreSettingButton.interactable = true;
} }
else if(hasWifi) else if(hasWifi)
{ {
deviceCtrl?.InitDeviceControl(false);
await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac); await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac);
deviceCtrl?.InitDeviceControl(true); await DataManager.Instance.GetFingerprints(selectedDevice.device_sn);
await DataManager.Instance.GetScheduleTasks(selectedDevice.device_sn);
scheduleSettingButton.interactable = true; scheduleSettingButton.interactable = true;
moreSettingButton.interactable = true; moreSettingButton.interactable = true;
InitDeviceUIFromConfig();
} }
else else
{ {
@ -1034,7 +1167,14 @@ namespace Kill.UI.Pages
schedulePage.OnPageClosed = () => schedulePage.OnPageClosed = () =>
{ {
// 重新读取定时任务更新主页显示 // 重新读取定时任务更新主页显示
BLECommunicationManager.Instance?.ReadScheduleTasks(); if (hasWifi && !hasBluetooth)
{
_ = RefreshHomeScheduleFromWifi();
}
else
{
BLECommunicationManager.Instance?.ReadScheduleTasks();
}
}; };
} }
@ -1094,6 +1234,38 @@ namespace Kill.UI.Pages
}); });
}); });
} }
else if (hasWifi)
{
// WiFi模式下锁定/解锁设备
LoadingUI.Show();
var lockControl = new DeviceLockControl { IsLocked = !ison };
byte[] lockBytes = lockControl.ToBytes();
_ = SendBleCommandByWifiAsync(BLEConstants.CMD_DEVICE_LOCK, lockBytes).ContinueWith(t =>
{
Loom.QueueOnMainThread(() =>
{
LoadingUI.Hide();
if (t.Result)
{
Debug.Log($"[HomePageCtrl] WiFi锁定设置成功: {(lockControl.IsLocked ? "" : "")}");
if (lockControl.IsLocked)
{
deviceCtrl?.InitDeviceControl(false);
}
else
{
deviceCtrl?.InitDeviceControl(true);
// WiFi模式下从配置重新初始化UI
InitDeviceUIFromConfig();
}
}
else
{
Debug.LogError("[HomePageCtrl] WiFi设置锁定失败");
}
});
});
}
else else
{ {
LoadingUI.Hide(); LoadingUI.Hide();
@ -1440,6 +1612,211 @@ namespace Kill.UI.Pages
return await tcs.Task; return await tcs.Task;
} }
/// <summary>
/// 启动设备在线状态轮询始终运行后台检测WiFi状态变化
/// </summary>
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.GetFingerprints(selectedDevice.device_sn);
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;
}
/// <summary>
/// 停止设备在线状态轮询(切换设备或销毁时调用)
/// </summary>
private void StopDeviceOnlineStatusPolling()
{
stopPolling = true;
isPollingOnline = false;
}
private void ScheduleUIUpdate(Action action)
{
pendingUIUpdates.Add(action);
}
/// <summary>
/// 从WiFi刷新主页定时任务显示
/// </summary>
private async Task RefreshHomeScheduleFromWifi()
{
await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac);
var tasks = new List<ScheduleTask>();
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();
});
}
/// <summary>
/// 通过WiFi发送BLE指令到设备使用共通错误处理
/// </summary>
public async Task<bool> 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<DeviceControlResponse>(
"/api/v1/device/command", requestData);
var tcs = new TaskCompletionSource<bool>();
ResponseCodeHandler.HandleResponse(response,
onSuccess: (res) =>
{
if (res.data != null && res.data.success)
{
tcs.TrySetResult(true);
}
else
{
Debug.LogError($"[HomePageCtrl] WiFi命令发送失败(0x{command:X2}): {res.data?.message ?? ""}");
ToastUI.Show("100292");
tcs.TrySetResult(false);
}
},
onError: (code, msg) =>
{
Debug.LogError($"[HomePageCtrl] WiFi命令发送失败(0x{command:X2}): {msg}");
ToastUI.Show("100292");
tcs.TrySetResult(false);
}
);
return await tcs.Task;
}
/// <summary>
/// 刷新安全设置UI
/// </summary>
public void RefreshSafetyUI()
{
pendingUIUpdates.Add(() =>
{
deviceState?.UpdateDeviceState(hasBluetooth, hasWifi);
});
}
/// <summary>
/// 通过WiFi加载定时任务
/// </summary>
public async void LoadScheduleTasks()
{
await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac);
}
/// <summary>
/// 通过WiFi保存定时任务
/// </summary>
public async Task SaveScheduleTasksAsync(List<ScheduleTask> tasks)
{
if (tasks == null || tasks.Count == 0)
{
Debug.LogWarning("[HomePageCtrl] 定时任务列表为空");
return;
}
// 将List转为byte数组
byte[] data = new byte[tasks.Count * 8];
for (int i = 0; i < tasks.Count; i++)
{
byte[] taskBytes = tasks[i].ToBytes();
Array.Copy(taskBytes, 0, data, i * 8, 8);
}
bool success = await SendBleCommandByWifiAsync(
BLEConstants.CMD_SCHEDULE_TASK, data);
if (success)
{
Debug.Log($"[HomePageCtrl] WiFi定时任务保存成功共 {tasks.Count} 条");
}
// 失败时 SendBleCommandByWifiAsync 已显示 Toast "100292"
}
} }

View File

@ -232,11 +232,11 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadLensAndVllSettings() private void ReadLensAndVllSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
// 编辑器模式下使用假数据 {
Editor_InitWithFakeData(); LoadSettingsFromConfig();
return; return;
#endif }
// 显示Loading // 显示Loading
LoadingUI.Show(); LoadingUI.Show();
@ -247,23 +247,16 @@ namespace Kill.UI.Pages
} }
#if UNITY_EDITOR private void LoadSettingsFromConfig()
/// <summary>
/// 编辑器模式下使用假数据初始化
/// </summary>
private void Editor_InitWithFakeData()
{ {
Debug.Log("[LensSettingPage] 编辑器模式:使用假数据初始化"); var config = DataManager.Instance.deviceConfig;
currentLensValue = (config?.detection_distance ?? 0) * 0.1f;
// 假数据:距离 3m可见激光关闭 selectedLensValue = currentLensValue;
currentLensValue = 3f; originalLensValue = currentLensValue;
selectedLensValue = 3f; vllEnabled = config?.laser_visible_enable ?? false;
vllEnabled = false; originalVllEnabled = vllEnabled;
// 更新UI显示
UpdateUI(); UpdateUI();
} }
#endif
/// <summary> /// <summary>
/// 更新UI显示 /// 更新UI显示
@ -432,24 +425,15 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 滑动选择器选中值回调(滑动结束后) /// 滑动选择器选中值回调(滑动结束后)
/// </summary> /// </summary>
private void OnLensValueSelected(float value) private async void OnLensValueSelected(float value)
{ {
Debug.Log($"[LensSettingPage] 选中距离值: {value}"); Debug.Log($"[LensSettingPage] 选中距离值: {value}");
#if UNITY_EDITOR
Debug.Log("[LensSettingPage] 编辑器模式:模拟设置距离");
currentLensValue = selectedLensValue;
return;
#endif
// 发送距离设置到设备 // 发送距离设置到设备
SendLensSettingToDevice(); await SendLensSettingToDeviceAsync();
} }
/// <summary> private async Task SendLensSettingToDeviceAsync()
/// 发送距离设置到设备
/// </summary>
private void SendLensSettingToDevice()
{ {
// 设置检测距离和瞄准距离为同一个值 // 设置检测距离和瞄准距离为同一个值
ushort distanceValue = (ushort)Mathf.RoundToInt(selectedLensValue*10); ushort distanceValue = (ushort)Mathf.RoundToInt(selectedLensValue*10);
@ -459,7 +443,26 @@ namespace Kill.UI.Pages
AimDistance = distanceValue // 单位是0.1米 AimDistance = distanceValue // 单位是0.1米
}; };
BLECommunicationManager.Instance?.WriteDistanceControl(distanceControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_DISTANCE_CONTROL, distanceControl.ToBytes());
if (success)
{
Debug.Log($"[LensSettingPage] 距离设置成功: {selectedLensValue}m");
currentLensValue = selectedLensValue;
DataManager.Instance.deviceConfig.detection_distance = (int)(selectedLensValue * 10);
}
else
{
Debug.LogError("[LensSettingPage] 距离设置失败");
selectedLensValue = currentLensValue;
UpdateUI();
}
}
else
{
BLECommunicationManager.Instance?.WriteDistanceControl(distanceControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -467,6 +470,7 @@ namespace Kill.UI.Pages
{ {
Debug.Log($"[LensSettingPage] 距离设置成功: {selectedLensValue}m"); Debug.Log($"[LensSettingPage] 距离设置成功: {selectedLensValue}m");
currentLensValue = selectedLensValue; currentLensValue = selectedLensValue;
DataManager.Instance.deviceConfig.detection_distance = (int)(selectedLensValue * 10);
} }
else else
{ {
@ -477,30 +481,42 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
} }
/// <summary> /// <summary>
/// 可见激光开关按钮点击事件 /// 可见激光开关按钮点击事件
/// </summary> /// </summary>
private void OnVllButtonClick() private async void OnVllButtonClick()
{ {
bool newVllState = !vllEnabled; bool newVllState = !vllEnabled;
Debug.Log($"[LensSettingPage] 可见激光开关: {(newVllState ? "" : "")}"); Debug.Log($"[LensSettingPage] 可见激光开关: {(newVllState ? "" : "")}");
#if UNITY_EDITOR
Debug.Log("[LensSettingPage] 编辑器模式:模拟设置可见激光");
vllEnabled = newVllState;
UpdateVllButton();
return;
#endif
// 发送可见激光设置到设备 // 发送可见激光设置到设备
VisibleLaserControl vllControl = new VisibleLaserControl VisibleLaserControl vllControl = new VisibleLaserControl
{ {
Enable = newVllState Enable = newVllState
}; };
BLECommunicationManager.Instance?.WriteVisibleLaserControl(vllControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_VISIBLE_LASER_CONTROL, vllControl.ToBytes());
if (success)
{
Debug.Log($"[LensSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}");
vllEnabled = newVllState;
UpdateVllButton();
DataManager.Instance.deviceConfig.laser_visible_enable = newVllState;
}
else
{
Debug.LogError("[LensSettingPage] 可见激光设置失败");
}
}
else
{
BLECommunicationManager.Instance?.WriteVisibleLaserControl(vllControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -509,6 +525,7 @@ namespace Kill.UI.Pages
Debug.Log($"[LensSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}"); Debug.Log($"[LensSettingPage] 可见激光设置成功: {(newVllState ? "" : "")}");
vllEnabled = newVllState; vllEnabled = newVllState;
UpdateVllButton(); UpdateVllButton();
DataManager.Instance.deviceConfig.laser_visible_enable = newVllState;
} }
else else
{ {
@ -516,6 +533,7 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
} }
/// <summary> /// <summary>
@ -593,16 +611,10 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 取消按钮点击事件 - 恢复原始数值 /// 取消按钮点击事件 - 恢复原始数值
/// </summary> /// </summary>
public void OnCancelButtonClick() public async void OnCancelButtonClick()
{ {
Debug.Log("[LensSettingPage] 取消设置,恢复原始数值"); Debug.Log("[LensSettingPage] 取消设置,恢复原始数值");
#if UNITY_EDITOR
Debug.Log("[LensSettingPage] 编辑器模式:模拟恢复原始数值");
ClosePage();
return;
#endif
// 如果数值没有变化,直接关闭页面 // 如果数值没有变化,直接关闭页面
if (Mathf.Abs(selectedLensValue - originalLensValue) < 0.01f) if (Mathf.Abs(selectedLensValue - originalLensValue) < 0.01f)
{ {
@ -623,7 +635,27 @@ namespace Kill.UI.Pages
AimDistance = originalValue AimDistance = originalValue
}; };
BLECommunicationManager.Instance?.WriteDistanceControl(distanceControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_DISTANCE_CONTROL, distanceControl.ToBytes());
if (success)
{
Debug.Log($"[LensSettingPage] 距离恢复成功: {originalLensValue}m");
currentLensValue = originalLensValue;
selectedLensValue = originalLensValue;
DataManager.Instance.deviceConfig.detection_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10);
}
else
{
Debug.LogError("[LensSettingPage] 距离恢复失败");
}
NotifyHomePageRefresh();
ClosePage();
}
else
{
BLECommunicationManager.Instance?.WriteDistanceControl(distanceControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
@ -634,6 +666,7 @@ namespace Kill.UI.Pages
Debug.Log($"[LensSettingPage] 距离恢复成功: {originalLensValue}m"); Debug.Log($"[LensSettingPage] 距离恢复成功: {originalLensValue}m");
currentLensValue = originalLensValue; currentLensValue = originalLensValue;
selectedLensValue = originalLensValue; selectedLensValue = originalLensValue;
DataManager.Instance.deviceConfig.detection_distance = (ushort)Mathf.RoundToInt(originalLensValue * 10);
} }
else else
{ {
@ -647,6 +680,7 @@ namespace Kill.UI.Pages
ClosePage(); ClosePage();
}); });
}); });
}
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Threading.Tasks;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Kill.Bluetooth; using Kill.Bluetooth;
@ -194,11 +195,11 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadLightSettings() private void ReadLightSettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
// 编辑器模式下使用假数据 {
Editor_InitWithFakeData(); LoadSettingsFromConfig();
return; return;
#endif }
// 显示Loading // 显示Loading
LoadingUI.Show(); LoadingUI.Show();
@ -208,24 +209,20 @@ namespace Kill.UI.Pages
} }
#if UNITY_EDITOR private void LoadSettingsFromConfig()
/// <summary>
/// 编辑器模式下使用假数据初始化
/// </summary>
private void Editor_InitWithFakeData()
{ {
Debug.Log("[LightSettingPage] 编辑器模式:使用假数据初始化"); var config = DataManager.Instance.deviceConfig;
currentLightEnabled = config?.fill_light_enable ?? false;
currentLightEnabled = true; selectedLightEnabled = currentLightEnabled;
selectedLightEnabled = true; originalLightEnabled = currentLightEnabled;
currentLightType = FillLightType.White; currentLightType = DeviceConfig.ParseServerEnum(config?.fill_light_type, FillLightType.Infrared);
selectedLightType = FillLightType.White; selectedLightType = currentLightType;
currentIntensity = LightIntensity.High; originalLightType = currentLightType;
selectedIntensity = LightIntensity.High; currentIntensity = DeviceConfig.ParseServerEnum(config?.fill_light_intensity, LightIntensity.Medium);
selectedIntensity = currentIntensity;
originalIntensity = currentIntensity;
UpdateUI(); UpdateUI();
} }
#endif
@ -283,19 +280,13 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 灯光开关状态改变回调 /// 灯光开关状态改变回调
/// </summary> /// </summary>
private void OnLightSwitchChanged(bool isOn) private async void OnLightSwitchChanged(bool isOn)
{ {
Debug.Log($"[LightSettingPage] 灯光开关: {(isOn ? "" : "")}"); Debug.Log($"[LightSettingPage] 灯光开关: {(isOn ? "" : "")}");
selectedLightEnabled = isOn; selectedLightEnabled = isOn;
#if UNITY_EDITOR
Debug.Log("[LightSettingPage] 编辑器模式:模拟设置灯光开关");
currentLightEnabled = selectedLightEnabled;
return;
#endif
// 发送设置到设备 // 发送设置到设备
SendLightSettingToDevice(); await SendLightSettingToDeviceAsync();
} }
/// <summary> /// <summary>
@ -319,20 +310,14 @@ namespace Kill.UI.Pages
} }
} }
selectPage.Init(currentIndex, (selectedIndex) => selectPage.Init(currentIndex, async (selectedIndex) =>
{ {
Debug.Log($"[LightSettingPage] 选择类型: {selectedIndex}"); Debug.Log($"[LightSettingPage] 选择类型: {selectedIndex}");
selectedLightType = (FillLightType)selectedIndex; selectedLightType = (FillLightType)selectedIndex;
UpdateTypeText(); UpdateTypeText();
#if UNITY_EDITOR
Debug.Log("[LightSettingPage] 编辑器模式:模拟设置灯光类型");
currentLightType = selectedLightType;
return;
#endif
// 发送设置到设备 // 发送设置到设备
SendLightSettingToDevice(); await SendLightSettingToDeviceAsync();
}); });
selectPage.gameObject.SetActive(true); selectPage.gameObject.SetActive(true);
} }
@ -358,20 +343,14 @@ namespace Kill.UI.Pages
} }
} }
selectPage.Init(currentIndex, (selectedIndex) => selectPage.Init(currentIndex, async (selectedIndex) =>
{ {
Debug.Log($"[LightSettingPage] 选择功率: {selectedIndex}"); Debug.Log($"[LightSettingPage] 选择功率: {selectedIndex}");
selectedIntensity = (LightIntensity)selectedIndex; selectedIntensity = (LightIntensity)selectedIndex;
UpdatePowerText(); UpdatePowerText();
#if UNITY_EDITOR
Debug.Log("[LightSettingPage] 编辑器模式:模拟设置灯光强度");
currentIntensity = selectedIntensity;
return;
#endif
// 发送设置到设备 // 发送设置到设备
SendLightSettingToDevice(); await SendLightSettingToDeviceAsync();
}); });
selectPage.gameObject.SetActive(true); selectPage.gameObject.SetActive(true);
} }
@ -379,7 +358,7 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 发送灯光设置到设备 /// 发送灯光设置到设备
/// </summary> /// </summary>
private void SendLightSettingToDevice() private async Task SendLightSettingToDeviceAsync()
{ {
FillLightControl lightControl = new FillLightControl FillLightControl lightControl = new FillLightControl
{ {
@ -388,16 +367,29 @@ namespace Kill.UI.Pages
Intensity = selectedIntensity Intensity = selectedIntensity
}; };
BLECommunicationManager.Instance?.WriteFillLightControl(lightControl, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_FILL_LIGHT_CONTROL, lightControl.ToBytes());
if (success)
{
SyncLightConfigFromCurrent();
}
else
{
Debug.LogError("[LightSettingPage] 灯光设置失败");
}
}
else
{
BLECommunicationManager.Instance?.WriteFillLightControl(lightControl, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
if (success) if (success)
{ {
Debug.Log($"[LightSettingPage] 灯光设置成功: 开关={selectedLightEnabled}, 类型={selectedLightType}, 强度={selectedIntensity}"); Debug.Log($"[LightSettingPage] 灯光设置成功: 开关={selectedLightEnabled}, 类型={selectedLightType}, 强度={selectedIntensity}");
currentLightEnabled = selectedLightEnabled; SyncLightConfigFromCurrent();
currentLightType = selectedLightType;
currentIntensity = selectedIntensity;
} }
else else
{ {
@ -409,8 +401,16 @@ namespace Kill.UI.Pages
UpdateUI(); UpdateUI();
} }
}); });
}); });
}
}
private void SyncLightConfigFromCurrent()
{
var config = DataManager.Instance.deviceConfig;
config.fill_light_enable = selectedLightEnabled;
config.fill_light_type = DeviceConfig.ToServerString(selectedLightType);
config.fill_light_intensity = DeviceConfig.ToServerString(selectedIntensity);
} }
/// <summary> /// <summary>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Kill.Bluetooth; using Kill.Bluetooth;
using Kill.Bluetooth.Protocol; using Kill.Bluetooth.Protocol;
using Kill.Core; using Kill.Core;
@ -208,10 +209,11 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void ReadSafetySettings() private void ReadSafetySettings()
{ {
#if UNITY_EDITOR if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
Editor_InitWithFakeData(); {
return; LoadSettingsFromConfig();
#endif return;
}
LoadingUI.Show(); LoadingUI.Show();
@ -219,24 +221,17 @@ namespace Kill.UI.Pages
BLECommunicationManager.Instance?.ReadVisualDetectionSetting(); BLECommunicationManager.Instance?.ReadVisualDetectionSetting();
} }
#if UNITY_EDITOR private void LoadSettingsFromConfig()
/// <summary>
/// 编辑器模式下使用假数据初始化
/// </summary>
private void Editor_InitWithFakeData()
{ {
Debug.Log("[SafetySettingPage] 编辑器模式:使用假数据初始化"); var config = DataManager.Instance.deviceConfig;
currentVisualEnabled = config?.visual_detect_enable ?? false;
currentVisualEnabled = true; selectedVisualEnabled = currentVisualEnabled;
selectedVisualEnabled = true; currentVisualSensitivity = DeviceConfig.ParseServerEnum(config?.visual_sensitivity, SensitivityLevel.Medium);
currentVisualSensitivity = SensitivityLevel.High; selectedVisualSensitivity = currentVisualSensitivity;
selectedVisualSensitivity = SensitivityLevel.High; currentWaveSensitivity = DeviceConfig.ParseServerEnum(config?.radar_sensitivity, SensitivityLevel.Medium);
currentWaveSensitivity = SensitivityLevel.Medium; selectedWaveSensitivity = currentWaveSensitivity;
selectedWaveSensitivity = SensitivityLevel.Medium;
UpdateUI(); UpdateUI();
} }
#endif
/// <summary> /// <summary>
@ -293,19 +288,13 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 视觉检测开关状态改变回调 /// 视觉检测开关状态改变回调
/// </summary> /// </summary>
private void OnVisualSwitchChanged(bool isOn) private async void OnVisualSwitchChanged(bool isOn)
{ {
Debug.Log($"[SafetySettingPage] 视觉检测开关: {(isOn ? "" : "")}"); Debug.Log($"[SafetySettingPage] 视觉检测开关: {(isOn ? "" : "")}");
selectedVisualEnabled = isOn; selectedVisualEnabled = isOn;
#if UNITY_EDITOR
Debug.Log("[SafetySettingPage] 编辑器模式:模拟设置视觉检测开关");
currentVisualEnabled = selectedVisualEnabled;
return;
#endif
// 发送设置到设备 // 发送设置到设备
SendVisualDetectionSettingToDevice(); await SendVisualDetectionSettingToDeviceAsync();
} }
/// <summary> /// <summary>
@ -328,19 +317,13 @@ namespace Kill.UI.Pages
} }
} }
selectPage.Init(currentIndex, (selectedIndex) => selectPage.Init(currentIndex, async (selectedIndex) =>
{ {
Debug.Log($"[SafetySettingPage] 选择视觉检测灵敏度: {selectedIndex}"); Debug.Log($"[SafetySettingPage] 选择视觉检测灵敏度: {selectedIndex}");
selectedVisualSensitivity = (SensitivityLevel)selectedIndex; selectedVisualSensitivity = (SensitivityLevel)selectedIndex;
UpdateVisualDetectionSensitivityText(); UpdateVisualDetectionSensitivityText();
#if UNITY_EDITOR await SendVisualDetectionSettingToDeviceAsync();
Debug.Log("[SafetySettingPage] 编辑器模式:模拟设置视觉检测灵敏度");
currentVisualSensitivity = selectedVisualSensitivity;
return;
#endif
SendVisualDetectionSettingToDevice();
}); });
selectPage.gameObject.SetActive(true); selectPage.gameObject.SetActive(true);
} }
@ -365,19 +348,13 @@ namespace Kill.UI.Pages
} }
} }
selectPage.Init(currentIndex, (selectedIndex) => selectPage.Init(currentIndex, async (selectedIndex) =>
{ {
Debug.Log($"[SafetySettingPage] 选择毫米波雷达灵敏度: {selectedIndex}"); Debug.Log($"[SafetySettingPage] 选择毫米波雷达灵敏度: {selectedIndex}");
selectedWaveSensitivity = (SensitivityLevel)selectedIndex; selectedWaveSensitivity = (SensitivityLevel)selectedIndex;
UpdateMillimeterWaveSensitivityText(); UpdateMillimeterWaveSensitivityText();
#if UNITY_EDITOR await SendMillimeterWaveSettingToDeviceAsync();
Debug.Log("[SafetySettingPage] 编辑器模式:模拟设置毫米波雷达灵敏度");
currentWaveSensitivity = selectedWaveSensitivity;
return;
#endif
SendMillimeterWaveSettingToDevice();
}); });
selectPage.gameObject.SetActive(true); selectPage.gameObject.SetActive(true);
} }
@ -389,11 +366,6 @@ namespace Kill.UI.Pages
{ {
Debug.Log("[SafetySettingPage] 点击试射测试按钮"); Debug.Log("[SafetySettingPage] 点击试射测试按钮");
#if UNITY_EDITOR
Debug.Log("[SafetySettingPage] 编辑器模式:模拟试射测试");
return;
#endif
LoadingUI.Show(); LoadingUI.Show();
BLECommunicationManager.Instance?.TriggerLaserTest((success) => BLECommunicationManager.Instance?.TriggerLaserTest((success) =>
{ {
@ -413,7 +385,7 @@ namespace Kill.UI.Pages
/// <summary> /// <summary>
/// 发送视觉检测设置到设备 /// 发送视觉检测设置到设备
/// </summary> /// </summary>
private void SendVisualDetectionSettingToDevice() private async Task SendVisualDetectionSettingToDeviceAsync()
{ {
VisualDetectionSetting setting = new VisualDetectionSetting VisualDetectionSetting setting = new VisualDetectionSetting
{ {
@ -421,15 +393,32 @@ namespace Kill.UI.Pages
Sensitivity = selectedVisualSensitivity Sensitivity = selectedVisualSensitivity
}; };
BLECommunicationManager.Instance?.WriteVisualDetectionSetting(setting, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_VISUAL_DETECTION_SETTING, setting.ToBytes());
if (success)
{
SyncVisualConfig();
}
else
{
Debug.LogError("[SafetySettingPage] 视觉检测设置失败");
selectedVisualEnabled = currentVisualEnabled;
selectedVisualSensitivity = currentVisualSensitivity;
UpdateVisualDetectionSensitivityText();
}
}
else
{
BLECommunicationManager.Instance?.WriteVisualDetectionSetting(setting, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
if (success) if (success)
{ {
Debug.Log($"[SafetySettingPage] 视觉检测设置成功: 开关={selectedVisualEnabled}, 灵敏度={selectedVisualSensitivity}"); Debug.Log($"[SafetySettingPage] 视觉检测设置成功: 开关={selectedVisualEnabled}, 灵敏度={selectedVisualSensitivity}");
currentVisualEnabled = selectedVisualEnabled; SyncVisualConfig();
currentVisualSensitivity = selectedVisualSensitivity;
} }
else else
{ {
@ -440,12 +429,20 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
}
private void SyncVisualConfig()
{
var config = DataManager.Instance.deviceConfig;
config.visual_detect_enable = selectedVisualEnabled;
config.visual_sensitivity = DeviceConfig.ToServerString(selectedVisualSensitivity);
} }
/// <summary> /// <summary>
/// 发送毫米波雷达设置到设备(保持开启,只设置灵敏度) /// 发送毫米波雷达设置到设备(保持开启,只设置灵敏度)
/// </summary> /// </summary>
private void SendMillimeterWaveSettingToDevice() private async Task SendMillimeterWaveSettingToDeviceAsync()
{ {
// 毫米波雷达保持开启,只修改灵敏度 // 毫米波雷达保持开启,只修改灵敏度
MillimeterWaveSetting setting = new MillimeterWaveSetting MillimeterWaveSetting setting = new MillimeterWaveSetting
@ -455,14 +452,31 @@ namespace Kill.UI.Pages
SafeDistance = 10 // 默认安全距离1米单位0.1米) SafeDistance = 10 // 默认安全距离1米单位0.1米)
}; };
BLECommunicationManager.Instance?.WriteMillimeterWaveSetting(setting, (success) => if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
bool success = await HomePageCtrl.Instance.SendBleCommandByWifiAsync(
BLEConstants.CMD_MILLIMETER_WAVE_SETTING, setting.ToBytes());
if (success)
{
SyncRadarConfig();
}
else
{
Debug.LogError("[SafetySettingPage] 毫米波雷达设置失败");
selectedWaveSensitivity = currentWaveSensitivity;
UpdateMillimeterWaveSensitivityText();
}
}
else
{
BLECommunicationManager.Instance?.WriteMillimeterWaveSetting(setting, (success) =>
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
if (success) if (success)
{ {
Debug.Log($"[SafetySettingPage] 毫米波雷达设置成功: 灵敏度={selectedWaveSensitivity}"); Debug.Log($"[SafetySettingPage] 毫米波雷达设置成功: 灵敏度={selectedWaveSensitivity}");
currentWaveSensitivity = selectedWaveSensitivity; SyncRadarConfig();
} }
else else
{ {
@ -472,6 +486,13 @@ namespace Kill.UI.Pages
} }
}); });
}); });
}
}
private void SyncRadarConfig()
{
var config = DataManager.Instance.deviceConfig;
config.radar_sensitivity = DeviceConfig.ToServerString(selectedWaveSensitivity);
} }
/// <summary> /// <summary>
@ -503,6 +524,11 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void NotifyHomePageRefresh() private void NotifyHomePageRefresh()
{ {
if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
HomePageCtrl.Instance?.RefreshSafetyUI();
return;
}
// 通知主页刷新安全设置显示 // 通知主页刷新安全设置显示
BLECommunicationManager.Instance?.ReadVisualDetectionSetting(); BLECommunicationManager.Instance?.ReadVisualDetectionSetting();
BLECommunicationManager.Instance?.ReadMillimeterWaveSetting(); BLECommunicationManager.Instance?.ReadMillimeterWaveSetting();

View File

@ -40,8 +40,6 @@ namespace Kill.UI.Pages
// 静态标志:是否有设置页面正在处理回调 // 静态标志:是否有设置页面正在处理回调
private static bool _isSettingPageActive = false; private static bool _isSettingPageActive = false;
// 编辑器模式使用假数据
public bool useFakeDataInEditor = true;
public GameObject noTip; public GameObject noTip;
private void OnEnable() private void OnEnable()
{ {
@ -60,18 +58,8 @@ namespace Kill.UI.Pages
// 绑定新增按钮事件 // 绑定新增按钮事件
BindAddButton(); BindAddButton();
#if UNITY_EDITOR
// 编辑器模式下使用假数据
if (useFakeDataInEditor)
{
Debug.Log("[ScheduleSettingPage] 编辑器模式:使用假数据");
LoadFakeData();
return;
}
#endif
// 读取定时任务 // 读取定时任务
ReadScheduleTasksFromBluetooth(); ReadScheduleTasks();
} }
private void OnDisable() private void OnDisable()
@ -116,83 +104,45 @@ namespace Kill.UI.Pages
} }
/// <summary> /// <summary>
/// 加载假数据(用于编辑器测试) /// 读取定时任务
/// </summary> /// </summary>
private void LoadFakeData() public async void ReadScheduleTasks()
{ {
var fakeTasks = new ScheduleTask[] if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{ {
new ScheduleTask Debug.Log("[ScheduleSettingPage] WiFi模式读取定时任务...");
await DataManager.Instance.GetScheduleTasks(DataManager.Instance.selectedDevice.device_sn);
Debug.Log($"[ScheduleSettingPage] WiFi获取到 {DataManager.Instance.scheduleTaskDatas.Count} 条原始数据");
// 将API数据转换为ScheduleTask过滤全0无效任务
var tasks = new List<ScheduleTask>();
foreach (var d in DataManager.Instance.scheduleTaskDatas)
{ {
TaskId = 0, // 过滤开始时间和结束时间都为0的无效任务与BLE过滤规则一致
Enabled = true, bool isInvalid = d.start_hour == 0 && d.start_minute == 0 &&
StartHour = 8, d.end_hour == 0 && d.end_minute == 0;
StartMinute = 0, if (isInvalid)
EndHour = 12, {
EndMinute = 0, Debug.Log($"[ScheduleSettingPage] WiFi过滤无效任务 ID={d.task_id}");
Mode = ScheduleTaskMode.Scan, continue;
Repeat = ScheduleTask.REPEAT_MONDAY | ScheduleTask.REPEAT_TUESDAY | ScheduleTask.REPEAT_THURSDAY }
}, tasks.Add(new ScheduleTask
new ScheduleTask {
{ TaskId = d.task_id,
TaskId = 1, Enabled = d.enabled,
Enabled = true, StartHour = d.start_hour,
StartHour = 14, StartMinute = d.start_minute,
StartMinute = 30, EndHour = d.end_hour,
EndHour = 18, EndMinute = d.end_minute,
EndMinute = 0, Mode = (ScheduleTaskMode)System.Enum.Parse(typeof(ScheduleTaskMode), d.mode, true),
Mode = ScheduleTaskMode.Sterilize, Repeat = d.repeat_mask
Repeat = ScheduleTask.REPEAT_WEDNESDAY | ScheduleTask.REPEAT_FRIDAY });
},
new ScheduleTask
{
TaskId = 2,
Enabled = false,
StartHour = 20,
StartMinute = 0,
EndHour = 22,
EndMinute = 30,
Mode = ScheduleTaskMode.Standby,
Repeat = ScheduleTask.REPEAT_SATURDAY | ScheduleTask.REPEAT_SUNDAY
},
new ScheduleTask
{
TaskId = 3,
Enabled = true,
StartHour = 6,
StartMinute = 30,
EndHour = 9,
EndMinute = 0,
Mode = ScheduleTaskMode.Scan,
Repeat = ScheduleTask.REPEAT_MONDAY | ScheduleTask.REPEAT_TUESDAY | ScheduleTask.REPEAT_WEDNESDAY |
ScheduleTask.REPEAT_THURSDAY | ScheduleTask.REPEAT_FRIDAY
},
// 这个任务的开始和结束时间都是0应该被过滤掉
new ScheduleTask
{
TaskId = 4,
Enabled = false,
StartHour = 0,
StartMinute = 0,
EndHour = 0,
EndMinute = 0,
Mode = ScheduleTaskMode.Standby,
Repeat = 0
} }
}; Debug.Log($"[ScheduleSettingPage] WiFi有效任务数: {tasks.Count}");
UpdateScheduleUI(tasks.ToArray());
return;
}
// 过滤有效任务
var validTasks = FilterValidTasks(fakeTasks);
UpdateScheduleUI(validTasks);
Debug.Log($"[ScheduleSettingPage] 假数据加载完成,有效任务数: {validTasks.Length}");
}
/// <summary>
/// 从蓝牙读取定时任务
/// </summary>
public void ReadScheduleTasksFromBluetooth()
{
if (BLECommunicationManager.Instance != null && BluetoothManager.Instance.IsConnected) if (BLECommunicationManager.Instance != null && BluetoothManager.Instance.IsConnected)
{ {
Debug.Log("[ScheduleSettingPage] 开始读取定时任务..."); Debug.Log("[ScheduleSettingPage] 开始读取定时任务...");
@ -213,6 +163,13 @@ namespace Kill.UI.Pages
/// </summary> /// </summary>
private void OnScheduleTaskListReceived(ScheduleTaskListResponse response) private void OnScheduleTaskListReceived(ScheduleTaskListResponse response)
{ {
// WiFi模式下忽略BLE回调
if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
Debug.Log("[ScheduleSettingPage] WiFi模式下忽略BLE定时任务回调");
return;
}
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
Debug.Log($"[ScheduleSettingPage] 收到定时任务列表,状态: {response.Status}"); Debug.Log($"[ScheduleSettingPage] 收到定时任务列表,状态: {response.Status}");
@ -582,8 +539,23 @@ namespace Kill.UI.Pages
/// 保存定时任务到设备 /// 保存定时任务到设备
/// 有效数据放在前面后面补全0数据 /// 有效数据放在前面后面补全0数据
/// </summary> /// </summary>
public void SaveScheduleTasks() public async void SaveScheduleTasks()
{ {
if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth)
{
LoadingUI.Show();
var tasksToSave = new List<ScheduleTask>();
for (int i = 0; i < _scheduleTasks.Count; i++)
{
var task = _scheduleTasks[i];
task.TaskId = (byte)i;
tasksToSave.Add(task);
}
await HomePageCtrl.Instance?.SaveScheduleTasksAsync(tasksToSave);
LoadingUI.Hide();
return;
}
if (BLECommunicationManager.Instance != null && BluetoothManager.Instance.IsConnected) if (BLECommunicationManager.Instance != null && BluetoothManager.Instance.IsConnected)
{ {
// 显示Loading // 显示Loading