diff --git a/Assets/Scripts/Bluetooth/BLECommunicationManager.cs b/Assets/Scripts/Bluetooth/BLECommunicationManager.cs
index 2d9d4a7..216b7d1 100644
--- a/Assets/Scripts/Bluetooth/BLECommunicationManager.cs
+++ b/Assets/Scripts/Bluetooth/BLECommunicationManager.cs
@@ -128,7 +128,7 @@ namespace Kill.Bluetooth
///
/// 更新当前设备状态,并仅在值发生变化时广播状态事件。
///
- private bool UpdateDeviceState(string deviceMac, BLEDeviceStateField field, Action update)
+ private bool UpdateDeviceState(string deviceMac, BLEDeviceStateField field, Func update)
{
if (update == null)
{
@@ -162,10 +162,9 @@ namespace Kill.Bluetooth
return changed;
}
- private bool UpdateStateFromResponse(BLEResponse response, BLEDeviceStateField field, Action update)
+ private bool UpdateStateFromResponse(BLEResponse response, BLEDeviceStateField field, Func update)
{
- return response != null && response.IsSuccess &&
- UpdateDeviceState(GetCurrentDeviceMac(), field, update);
+ return response.IsSuccess && UpdateDeviceState(GetStateMac(), field, update);
}
private static string NormalizeDeviceMac(string deviceMac)
@@ -295,11 +294,13 @@ namespace Kill.Bluetooth
{
Log($"蓝牙已断开: {address}");
- // 使用断开参数作为设备状态键;部分平台会在清空地址前触发事件。
- string stateMac = NormalizeDeviceMac(address);
+ // 断开参数通常是 BLE 地址,优先使用已记录的真实 MAC 作为状态键。
+ string stateMac = string.IsNullOrEmpty(_lastStateMac)
+ ? NormalizeDeviceMac(address)
+ : _lastStateMac;
if (string.IsNullOrEmpty(stateMac))
{
- stateMac = string.IsNullOrEmpty(_lastStateMac) ? GetCurrentDeviceMac() : _lastStateMac;
+ stateMac = GetCurrentDeviceMac();
}
_lastStateMac = string.IsNullOrEmpty(stateMac) ? _lastStateMac : stateMac;
UpdateDeviceState(
@@ -881,6 +882,15 @@ namespace Kill.Bluetooth
Log($"定时任务设置成功: {tasks[0]}");
else
Log($"定时任务批量设置成功,共 {tasks.Length} 条任务");
+
+ ScheduleTask[] normalizedTasks = new ScheduleTask[tasks.Length];
+ for (int i = 0; i < tasks.Length; i++)
+ {
+ normalizedTasks[i] = tasks[i];
+ normalizedTasks[i].TaskId = (byte)i;
+ }
+ UpdateStateFromResponse(response, BLEDeviceStateField.ScheduleTasks,
+ state => state.SetScheduleTasks(normalizedTasks));
}
else
{
@@ -1601,6 +1611,8 @@ namespace Kill.Bluetooth
SendFrame(frame, (response) =>
{
var setting = MillimeterWaveSetting.FromBytes(response.Data);
+ UpdateStateFromResponse(response, BLEDeviceStateField.MillimeterWave,
+ state => state.SetMillimeterWave(setting));
callback?.Invoke(setting);
OnMillimeterWaveSettingReceived?.Invoke(setting);
Log($"读取毫米波雷达设置: {setting}");
@@ -1630,9 +1642,15 @@ namespace Kill.Bluetooth
{
bool success = response.IsSuccess;
if (success)
- Log($"毫米波雷达设置成功: {setting}");
+ {
+ Log($"毫米波设置成功: {setting}");
+ UpdateStateFromResponse(response, BLEDeviceStateField.MillimeterWave,
+ state => state.SetMillimeterWave(setting));
+ }
else
- LogError($"毫米波雷达设置失败, 状态码={response.Status:X2}");
+ {
+ LogError($"毫米波设置失败, 状态码={response.Status:X2}");
+ }
callback?.Invoke(success);
});
}
@@ -2612,7 +2630,7 @@ namespace Kill.Bluetooth
// 通知帧优先处理,并且绝对不影响命令队列(IsWaitingResponse / _pendingCallback / _responseTimer)
// 设备主动通知是异步旁路通道,与当前等待响应的命令是两条独立链路
- if (frame.ReadWrite == BLEConstants.RW_NOTIFY || frame.Command == BLEConstants.NOTIFY_COMMAND_CODE)
+ if (frame.ReadWrite == BLEConstants.RW_NOTIFY && frame.Command == BLEConstants.NOTIFY_COMMAND_CODE)
{
HandleNotification(frame.Data);
return;
@@ -2728,6 +2746,12 @@ namespace Kill.Bluetooth
private void HandleDeviceStateChangeNotification(byte[] data)
{
+ if (data == null || data.Length < 2)
+ {
+ LogWarning("设备状态变化通知数据长度不足");
+ return;
+ }
+
var notify = DeviceStateChangeNotification.FromBytes(data);
if (notify.WorkMode > (byte)WorkMode.Eliminate)
{
@@ -2737,7 +2761,7 @@ namespace Kill.Bluetooth
Log($"设备状态变化通知: 工作模式=0x{notify.WorkMode:X2}");
UpdateDeviceState(
- GetCurrentDeviceMac(),
+ GetStateMac(),
BLEDeviceStateField.WorkMode,
state => state.SetWorkMode((WorkMode)notify.WorkMode));
try
@@ -2752,11 +2776,17 @@ namespace Kill.Bluetooth
private void HandleErrorStatusNotification(byte[] data)
{
+ if (data == null || data.Length < 8)
+ {
+ LogWarning("错误状态通知数据长度不足");
+ return;
+ }
+
var notify = ErrorStatusNotification.FromBytes(data);
if (data != null && data.Length >= 8)
{
UpdateDeviceState(
- GetCurrentDeviceMac(),
+ GetStateMac(),
BLEDeviceStateField.HardwareStatus,
state => state.SetHardwareStatus(notify.Status));
}
@@ -2773,6 +2803,12 @@ namespace Kill.Bluetooth
private void HandleParameterChangeNotification(byte[] data)
{
+ if (data == null || data.Length < 3)
+ {
+ LogWarning("参数变化通知数据长度不足");
+ return;
+ }
+
var notify = ParameterChangeNotification.FromBytes(data);
Log($"参数变化通知: 命令=0x{notify.CommandCode:X2}, 数据长度={(notify.Payload?.Length ?? 0)}");
@@ -2794,7 +2830,7 @@ namespace Kill.Bluetooth
///
private void ApplyParameterChangeToDeviceState(ParameterChangeNotification notify)
{
- string deviceMac = GetCurrentDeviceMac();
+ string deviceMac = GetStateMac();
if (string.IsNullOrEmpty(deviceMac) || notify.Payload == null)
{
return;
@@ -2805,35 +2841,52 @@ namespace Kill.Bluetooth
switch (notify.CommandCode)
{
case BLEConstants.CMD_LANGUAGE_SETTING:
+ if (notify.Payload.Length < 1) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.Language,
state => state.SetLanguage(LanguageSetting.FromBytes(notify.Payload)));
break;
case BLEConstants.CMD_SCHEDULE_TASK:
+ if (notify.Payload.Length < 7) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.ScheduleTasks,
state => state.SetScheduleTasks(ScheduleTaskListResponse.FromBytes(0x00, notify.Payload).Tasks));
break;
+ case BLEConstants.CMD_DEVICE_LOCK:
+ if (notify.Payload.Length < 1) return;
+ UpdateDeviceState(deviceMac, BLEDeviceStateField.LockState,
+ state => state.SetLockState(DeviceLockControl.FromBytes(notify.Payload)));
+ break;
case BLEConstants.CMD_FILL_LIGHT_CONTROL:
+ if (notify.Payload.Length < 3) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.FillLight,
state => state.SetFillLight(FillLightControl.FromBytes(notify.Payload)));
break;
case BLEConstants.CMD_ANGLE_CONTROL:
+ if (notify.Payload.Length < 2) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.Angle,
state => state.SetAngle(AngleControl.FromBytes(notify.Payload)));
break;
case BLEConstants.CMD_DISTANCE_CONTROL:
+ if (notify.Payload.Length < 4) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.Distance,
state => state.SetDistance(DistanceControl.FromBytes(notify.Payload)));
break;
case BLEConstants.CMD_VISUAL_DETECTION_SETTING:
+ if (notify.Payload.Length < 2) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.VisualDetection,
state => state.SetVisualDetection(VisualDetectionSetting.FromBytes(notify.Payload)));
break;
+ case BLEConstants.CMD_MILLIMETER_WAVE_SETTING:
+ if (notify.Payload.Length < 4) return;
+ UpdateDeviceState(deviceMac, BLEDeviceStateField.MillimeterWave,
+ state => state.SetMillimeterWave(MillimeterWaveSetting.FromBytes(notify.Payload)));
+ break;
case BLEConstants.CMD_FILL_LIGHT_CONNECTION_STATUS:
+ if (notify.Payload.Length < 1) return;
UpdateDeviceState(deviceMac, BLEDeviceStateField.FillLightConnection,
state => state.SetFillLightConnection(FillLightConnectionStatus.FromBytes(notify.Payload)));
break;
default:
- // 未映射的字段:不写仓库,避免误覆盖
+ // 暂不写入本地状态,避免异常参数覆盖正确值
break;
}
}
@@ -2845,11 +2898,17 @@ namespace Kill.Bluetooth
private void HandleCapacitorStateNotification(byte[] data)
{
+ if (data == null || data.Length < 2)
+ {
+ LogWarning("蓄能状态通知数据长度不足");
+ return;
+ }
+
var notify = CapacitorStateNotification.FromBytes(data);
if (data != null && data.Length >= 2)
{
UpdateDeviceState(
- GetCurrentDeviceMac(),
+ GetStateMac(),
BLEDeviceStateField.CapacitorState,
state => state.SetCapacitorState(notify));
}
@@ -2866,12 +2925,18 @@ namespace Kill.Bluetooth
private void HandleFillLightConnectionNotification(byte[] data)
{
+ if (data == null || data.Length < 2)
+ {
+ LogWarning("补光灯连接状态通知数据长度不足");
+ return;
+ }
+
var notify = FillLightConnectionNotification.FromBytes(data);
if (data != null && data.Length >= 2)
{
var status = new FillLightConnectionStatus { IsConnected = notify.IsConnected };
UpdateDeviceState(
- GetCurrentDeviceMac(),
+ GetStateMac(),
BLEDeviceStateField.FillLightConnection,
state => state.SetFillLightConnection(status));
}
diff --git a/Assets/Scripts/Bluetooth/BLEDeviceState.cs b/Assets/Scripts/Bluetooth/BLEDeviceState.cs
index 8a0212e..2bf209d 100644
--- a/Assets/Scripts/Bluetooth/BLEDeviceState.cs
+++ b/Assets/Scripts/Bluetooth/BLEDeviceState.cs
@@ -52,6 +52,8 @@ namespace Kill.Bluetooth
public VisualDetectionSetting? VisualDetection { get; private set; }
+ public MillimeterWaveSetting? MillimeterWave { get; private set; }
+
public LanguageSetting? Language { get; private set; }
public HardwareStatus? HardwareStatus { get; private set; }
@@ -183,6 +185,21 @@ namespace Kill.Bluetooth
return true;
}
+ internal bool SetMillimeterWave(MillimeterWaveSetting setting)
+ {
+ if (MillimeterWave.HasValue &&
+ MillimeterWave.Value.Enable == setting.Enable &&
+ MillimeterWave.Value.Sensitivity == setting.Sensitivity &&
+ MillimeterWave.Value.ActualSafeDistance == setting.ActualSafeDistance)
+ {
+ return false;
+ }
+
+ MillimeterWave = setting;
+ MarkUpdated();
+ return true;
+ }
+
internal bool SetLanguage(LanguageSetting language)
{
if (Language.HasValue && Language.Value.Language == language.Language)
diff --git a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
index 998b267..5fb591a 100644
--- a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
+++ b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
@@ -60,6 +60,7 @@ namespace Kill.UI.Pages
private int TOTAL_STATUS_COUNT = 8; // 总共需要查询的状态数量
private float statusQueryTimeout = 15f; // 状态查询超时时间(秒)
private Coroutine statusQueryTimeoutCoroutine; // 超时协程
+ private Coroutine deviceStatusQueryCoroutine; // 首次状态全量查询协程
// 串行查询相关
private Queue statusQueryQueue = new Queue(); // 状态查询队列
@@ -286,6 +287,12 @@ namespace Kill.UI.Pages
///
private void StartDeviceStateInitialization()
{
+ if (deviceStatusQueryCoroutine != null)
+ {
+ StopCoroutine(deviceStatusQueryCoroutine);
+ deviceStatusQueryCoroutine = null;
+ }
+
isDeviceStateInitializing = true;
pendingStatusCount = TOTAL_STATUS_COUNT;
@@ -334,6 +341,11 @@ namespace Kill.UI.Pages
StopCoroutine(statusQueryTimeoutCoroutine);
statusQueryTimeoutCoroutine = null;
}
+ if (deviceStatusQueryCoroutine != null)
+ {
+ StopCoroutine(deviceStatusQueryCoroutine);
+ deviceStatusQueryCoroutine = null;
+ }
bluetoothDeviceInfoCoroutine=StartCoroutine(CheckDeviceError());
Debug.Log("[HomePageCtrl] 设备状态初始化完成");
}
@@ -363,6 +375,11 @@ namespace Kill.UI.Pages
isBluetoothUserLoggedIn = false;
isQueryingStatus = false;
statusQueryQueue?.Clear();
+ if (deviceStatusQueryCoroutine != null)
+ {
+ StopCoroutine(deviceStatusQueryCoroutine);
+ deviceStatusQueryCoroutine = null;
+ }
UIManager.Instance?.ClearBackAction();
// 刷新首页设备连接状态UI(延迟到主循环执行,与连接成功时保持一致)
pendingUIUpdates.Add(() =>
@@ -398,7 +415,7 @@ namespace Kill.UI.Pages
StartDeviceStateInitialization();
// 串行查询设备状态
- StartCoroutine(QueryAllDeviceStatusSequential());
+ deviceStatusQueryCoroutine = StartCoroutine(QueryAllDeviceStatusSequential());
}
///
@@ -493,9 +510,13 @@ namespace Kill.UI.Pages
///
/// 按 MAC 隔离:当前设备不匹配(已切换/未连接/选中设备不同)则丢弃通知
///
- private bool IsNotificationForCurrentDevice()
+ private bool IsNotificationForCurrentDevice(BLEDeviceState state = null)
{
- string mac = BLECommunicationManager.Instance?.GetCurrentDeviceMac();
+ string mac = state?.DeviceMac;
+ if (string.IsNullOrEmpty(mac))
+ {
+ mac = BLECommunicationManager.Instance?.GetCurrentDeviceMac();
+ }
string selectedMac = selectedDevice?.ble_mac;
if (string.IsNullOrEmpty(mac) || string.IsNullOrEmpty(selectedMac)) return false;
return string.Equals(mac, selectedMac, StringComparison.OrdinalIgnoreCase);
@@ -509,7 +530,7 @@ namespace Kill.UI.Pages
private void OnDeviceStateChanged(BLEDeviceState state, BLEDeviceStateField field)
{
if (state == null) return;
- if (!IsNotificationForCurrentDevice()) return;
+ if (!IsNotificationForCurrentDevice(state)) return;
if (isDeviceStateInitializing) return;
switch (field)
@@ -519,7 +540,10 @@ namespace Kill.UI.Pages
{
int mode = (int)state.WorkMode.Value;
currentWorkMode = state.WorkMode.Value;
- DataManager.Instance.deviceConfig.work_mode = DeviceConfig.ToServerString(state.WorkMode.Value);
+ if (DataManager.Instance.deviceConfig != null)
+ {
+ DataManager.Instance.deviceConfig.work_mode = DeviceConfig.ToServerString(state.WorkMode.Value);
+ }
pendingUIUpdates.Add(() => deviceCtrl?.InitWrokMode(mode));
}
break;
@@ -576,12 +600,15 @@ namespace Kill.UI.Pages
case BLEDeviceStateField.Language:
if (state.Language.HasValue)
{
- DataManager.Instance.deviceConfig.language = state.Language.Value.IsChinese ? 1 : 0;
- DataManager.Instance.SyncDeviceConfigToServer();
+ if (DataManager.Instance.deviceConfig != null)
+ {
+ DataManager.Instance.deviceConfig.language = state.Language.Value.IsChinese ? 1 : 0;
+ DataManager.Instance.SyncDeviceConfigToServer();
+ }
}
break;
default:
- // 其他字段(Connection / LockState / HardwareStatus / CapacitorState / FillLightConnection)暂不在主页直接刷新
+ // 其他字段(Connection / HardwareStatus / CapacitorState / FillLightConnection)暂不在主页直接刷新
break;
}
}