killapp/Assets/Scripts/Bluetooth/BLECommunicationManager.cs
“虞渠成” ed4a57b29d 0611
2026-06-11 11:17:27 +08:00

2756 lines
98 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using System;
using System.Collections.Generic;
using Kill.Bluetooth.Protocol;
using Kill.UI.Components;
using Kill.Core;
namespace Kill.Bluetooth
{
/// <summary>
/// BLE通信管理器 - 处理协议层通信
/// 基于 BluetoothManager 进行协议通信
/// </summary>
public class BLECommunicationManager : MonoBehaviour
{
public static BLECommunicationManager Instance { get; private set; }
// 事件定义
public event Action<DeviceRegistrationStatus> OnRegistrationStatusReceived; // 收到注册状态
public event Action<bool, string> OnRegisterResult; // 注册结果 (成功/失败, 消息)
public event Action<UserListResponse> OnUserListReceived; // 收到用户列表
public event Action<UnregisterUserResponse> OnUnregisterUserResult; // 注销用户结果
public event Action<UserLoginResponse> OnUserLoginResult; // 用户登录结果
public event Action<FingerprintEnableResponse> OnFingerprintEnableResult; // 指纹使能设置结果
public event Action<FingerprintRecordResponse> OnFingerprintRecordResult; // 指纹录制结果
public event Action<LanguageSetting> OnLanguageSettingReceived; // 收到语言设置
public event Action<TimeSetting> OnTimeSettingReceived; // 收到时间设置
public event Action<ScheduleTaskListResponse> OnScheduleTaskListReceived; // 收到定时任务列表
public event Action<LCDSleepSetting> OnLCDSleepSettingReceived; // 收到LCD休眠设置
public event Action<LCDBrightnessSetting> OnLCDBrightnessSettingReceived; // 收到LCD亮度设置
public event Action<RGBControl> OnRGBControlReceived; // 收到RGB控制设置
public event Action<WIFIControl> OnWIFIControlReceived; // 收到WIFI控制设置
public event Action<BLEControl> OnBLEControlReceived; // 收到BLE控制设置
public event Action<MultimediaControl> OnMultimediaControlReceived; // 收到多媒体控制设置
public event Action<FillLightControl> OnFillLightControlReceived; // 收到补光灯控制设置
public event Action<FillLightConnectionStatus> OnFillLightConnectionStatusReceived; // 收到补光灯连接状态
public event Action<VisibleLaserControl> OnVisibleLaserControlReceived; // 收到可见光激光器控制设置
public event Action<DeviceLockControl> OnDeviceLockControlReceived; // 收到设备锁定/解锁设置
public event Action<AngleControl> OnAngleControlReceived; // 收到角度控制设置
public event Action<DistanceControl> OnDistanceControlReceived; // 收到距离控制设置
public event Action<MillimeterWaveSetting> OnMillimeterWaveSettingReceived; // 收到毫米波雷达设置
public event Action<VisualDetectionSetting> OnVisualDetectionSettingReceived; // 收到视觉检测设置
public event Action<AccelerometerSetting> OnAccelerometerSettingReceived; // 收到加速度传感器设置
public event Action<AccelerometerData> OnAccelerometerDataReceived; // 收到加速度传感器数据
public event Action<TemperatureMonitorSetting> OnTemperatureMonitorSettingReceived; // 收到温度监控设置
public event Action<EnvironmentChangeTest> OnEnvironmentChangeStatusReceived; // 收到环境变化状态
public event Action<WorkModeSetting> OnWorkModeSettingReceived; // 收到工作模式设置
public event Action<HardwareStatus> OnHardwareStatusReceived; // 收到硬件状态
public event Action<DeviceInfo> OnDeviceInfoReceived; // 收到设备信息
public event Action<StatisticsData> OnStatisticsDataReceived; // 收到统计数据
public event Action<SensorData> OnSensorDataReceived; // 收到传感器数据
public event Action<MosquitoData> OnMosquitoDataReceived; // 收到蚊虫数据通知
public event Action<byte[]> OnDataReceived; // 收到原始数据
public event Action<string> OnRawDataReceived; // 收到原始数据(十六进制字符串)
public event Action<string> OnRawDataSent; // 发送原始数据(十六进制字符串)
public event Action<string> OnCommunicationError; // 通信错误
// 状态
public bool IsWaitingResponse { get; private set; }
public byte LastCommand { get; private set; }
// 响应超时设置 (OTA传输需要更长时间增加到10秒)
public float ResponseTimeout = 10f;
// 数据接收缓冲区
private List<byte> _receiveBuffer = new List<byte>();
private readonly object _bufferLock = new object(); // 缓冲区锁
private float _responseTimer;
private Action<BLEResponse> _pendingCallback;
// 指令队列
private Queue<CommandTask> _commandQueue = new Queue<CommandTask>();
private bool _isProcessingQueue = false;
private readonly object _queueLock = new object();
/// <summary>
/// 指令任务
/// </summary>
private class CommandTask
{
public BLEFrame Frame;
public Action<BLEResponse> Callback;
public string Description;
public CommandTask(BLEFrame frame, Action<BLEResponse> callback, string description)
{
Frame = frame;
Callback = callback;
Description = description;
}
}
// 服务和特征UUID (根据实际设备配置)
public string ServiceUUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
public string WriteCharacteristicUUID = "0000ffe1-0000-1000-8000-00805f9b34fb";
public string NotifyCharacteristicUUID = "0000ffe1-0000-1000-8000-00805f9b34fb";
// 是否自动初始化通信
public bool AutoInitialize = true;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
Log("[BLECommunicationManager.Start] 开始执行...");
// 订阅蓝牙连接事件
if (BluetoothManager.Instance != null)
{
Log($"[BLECommunicationManager.Start] BluetoothManager.Instance 存在IsConnected={BluetoothManager.Instance.IsConnected}");
BluetoothManager.Instance.OnConnectedSuccess += OnBluetoothConnected;
BluetoothManager.Instance.OnDisconnected += OnBluetoothDisconnected;
BluetoothManager.Instance.OnError += OnBluetoothError;
Log("[BLECommunicationManager.Start] 事件订阅完成");
// 如果已经连接(可能是自动连接已完成),立即初始化
if (BluetoothManager.Instance.IsConnected)
{
Log("[BLECommunicationManager.Start] 检测到蓝牙已连接,立即初始化通信...");
OnBluetoothConnected();
}
else
{
Log("[BLECommunicationManager.Start] 蓝牙未连接,等待连接事件...");
}
}
else
{
LogError("[BLECommunicationManager.Start] BluetoothManager.Instance 为 null");
}
}
/// <summary>
/// 蓝牙错误回调
/// </summary>
private void OnBluetoothError(string error)
{
// 忽略 "Service not found" 错误,因为这是正常的(还没连接设备)
if (error.Contains("Service not found"))
{
Log("蓝牙服务未找到(正常:尚未连接设备)");
return;
}
LogError($"蓝牙错误: {error}");
}
private void OnDestroy()
{
// 取消订阅事件
if (BluetoothManager.Instance != null)
{
BluetoothManager.Instance.OnConnectedSuccess -= OnBluetoothConnected;
BluetoothManager.Instance.OnDisconnected -= OnBluetoothDisconnected;
BluetoothManager.Instance.OnError -= OnBluetoothError;
}
if (Instance == this)
{
Instance = null;
}
}
private void Update()
{
// 响应超时检测
if (IsWaitingResponse)
{
_responseTimer -= Time.deltaTime;
if (_responseTimer <= 0)
{
OnResponseTimeout();
}
}
}
#region
/// <summary>
/// 蓝牙连接成功回调(特征发现完成后调用)
/// </summary>
private void OnBluetoothConnected()
{
if (AutoInitialize)
InitializeCommunication();
}
/// <summary>
/// 蓝牙断开连接回调
/// </summary>
private void OnBluetoothDisconnected(string address)
{
Log($"蓝牙已断开: {address}");
// 清理状态
IsWaitingResponse = false;
_responseTimer = 0;
_pendingCallback = null;
lock (_bufferLock)
{
_receiveBuffer.Clear();
}
// 清空指令队列
ClearCommandQueue();
}
/// <summary>
/// 初始化BLE通信 (连接成功后自动调用,也可手动调用)
/// </summary>
public void InitializeCommunication()
{
if (BluetoothManager.Instance == null || !BluetoothManager.Instance.IsConnected) return;
ServiceUUID = ServiceUUID.ToLower();
WriteCharacteristicUUID = WriteCharacteristicUUID.ToLower();
NotifyCharacteristicUUID = NotifyCharacteristicUUID.ToLower();
SubscribeToNotifications();
}
/// <summary>
/// 订阅设备通知
/// </summary>
private void SubscribeToNotifications()
{
string deviceAddress = BluetoothManager.Instance.ConnectedDeviceAddress;
ServiceUUID = ServiceUUID.ToLower();
WriteCharacteristicUUID = WriteCharacteristicUUID.ToLower();
NotifyCharacteristicUUID = NotifyCharacteristicUUID.ToLower();
Log($"[BLE-DEBUG] 订阅通知: 地址={deviceAddress}");
try
{
BluetoothLEHardwareInterface.SubscribeCharacteristicWithDeviceAddress(
deviceAddress,
ServiceUUID,
NotifyCharacteristicUUID,
(notifyAddress, notifyCharacteristic) =>
{
Log($"[BLE-DEBUG] 订阅成功: {notifyCharacteristic}");
},
(address, characteristicUUID, bytes) =>
{
OnNotificationReceived(bytes);
}
);
}
catch (System.Exception ex)
{
LogError($"[BLE-DEBUG] 订阅异常: {ex.Message}");
}
}
/// <summary>
/// 取消订阅通知
/// </summary>
public void UnsubscribeNotifications()
{
if (BluetoothManager.Instance == null || !BluetoothManager.Instance.IsConnected)
return;
string deviceAddress = BluetoothManager.Instance.ConnectedDeviceAddress;
BluetoothLEHardwareInterface.UnSubscribeCharacteristic(
deviceAddress,
ServiceUUID,
NotifyCharacteristicUUID,
null
);
}
#endregion
#region
/// <summary>
/// 查询设备注册状态 (命令 0x01)
/// </summary>
public void QueryRegistrationStatus(Action<bool,DeviceRegistrationStatus> callback = null)
{
if (!CheckConnection()) return;
// 构建查询帧
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_QUERY_REGISTRATION,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
if (response.IsSuccess && response.Data != null)
{
var status = DeviceRegistrationStatus.FromBytes(response.Data);
callback?.Invoke(true,status);
OnRegistrationStatusReceived?.Invoke(status);
}
else
{
LogError($"查询注册状态失败: 状态码={response.Status:X2}");
callback?.Invoke(false,new DeviceRegistrationStatus());
}
});
}
/// <summary>
/// 设备注册绑定 (命令 0x02)
/// 注意:根据协议,只发送用户名,不发送密码
/// </summary>
/// <param name="username">用户名</param>
/// <param name="callback">回调 (成功/失败, 消息)</param>
public void RegisterDevice(string username, Action<bool, string> callback = null)
{
if (!CheckConnection()) return;
// 验证输入
if (string.IsNullOrEmpty(username) || username.Length > BLEConstants.MAX_USERNAME_LENGTH)
{
callback?.Invoke(false, $"用户名长度必须在1-{BLEConstants.MAX_USERNAME_LENGTH}之间");
return;
}
// 构建注册请求(只发送用户名)
var request = new DeviceRegisterRequest
{
Username = username
};
byte[] requestData = request.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DEVICE_REGISTER,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)requestData.Length,
Data = requestData
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
string message = GetStatusMessage(response.Status);
if (success)
{
Log($"设备注册成功: 用户={username}");
if (response.Data != null && response.Data.Length > 0)
{
Log($"注册响应数据: {BitConverter.ToString(response.Data)}");
}
}
else
{
LogError($"设备注册失败: {message}");
}
callback?.Invoke(success, message);
OnRegisterResult?.Invoke(success, message);
});
}
/// <summary>
/// 用户登录 (命令 0x03)
/// 数据格式:用户名(16字节) + 解锁状态(1字节)解锁状态固定为1
/// </summary>
/// <param name="username">用户名</param>
/// <param name="callback">回调 (响应结果)</param>
public void UserLogin(string username, Action<UserLoginResponse> callback = null)
{
if (!CheckConnection()) return;
// 验证输入
if (string.IsNullOrEmpty(username) || username.Length > BLEConstants.MAX_USERNAME_LENGTH)
{
LogError($"用户名长度必须在1-{BLEConstants.MAX_USERNAME_LENGTH}之间");
callback?.Invoke(new UserLoginResponse { Status = BLEConstants.STATUS_PARAM_ERROR });
return;
}
// 构建登录请求
var request = new UserLoginRequest
{
Username = username,
UnlockStatus = 0x01 // 解锁状态固定为1
};
byte[] requestData = request.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_USER_LOGIN,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)requestData.Length,
Data = requestData
};
SendFrame(frame, (response) =>
{
var loginResponse = UserLoginResponse.FromBytes(response.Status);
if (loginResponse.IsSuccess)
{
Log($"用户登录成功: {username}");
}
else
{
LogError($"用户登录失败: {username}, 状态码={response.Status:X2}");
}
callback?.Invoke(loginResponse);
OnUserLoginResult?.Invoke(loginResponse);
});
}
/// <summary>
/// 指纹登录使能设置 (命令 0x04)
/// 数据格式:用户名(16字节) + 使能状态(1字节)
/// </summary>
/// <param name="username">用户名</param>
/// <param name="enable">使能状态true=使能, false=禁用</param>
/// <param name="callback">回调 (响应结果)</param>
public void SetFingerprintEnable(string username, bool enable, Action<FingerprintEnableResponse> callback = null)
{
if (!CheckConnection()) return;
// 验证输入
if (string.IsNullOrEmpty(username) || username.Length > BLEConstants.MAX_USERNAME_LENGTH)
{
LogError($"用户名长度必须在1-{BLEConstants.MAX_USERNAME_LENGTH}之间");
callback?.Invoke(new FingerprintEnableResponse { Status = BLEConstants.STATUS_PARAM_ERROR });
return;
}
// 构建请求
var request = new FingerprintEnableRequest
{
Username = username,
Enable = enable
};
byte[] requestData = request.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FINGERPRINT_ENABLE,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)requestData.Length,
Data = requestData
};
SendFrame(frame, (response) =>
{
var enableResponse = FingerprintEnableResponse.FromBytes(response.Status);
if (enableResponse.IsSuccess)
{
Log($"指纹登录使能设置成功: {username}, 状态={(enable ? "使" : "")}");
}
else
{
LogError($"指纹登录使能设置失败: {username}, 状态码={response.Status:X2}");
}
callback?.Invoke(enableResponse);
OnFingerprintEnableResult?.Invoke(enableResponse);
});
}
/// <summary>
/// 指纹录制请求 (命令 0x05)
/// 启动指纹注册流程
/// </summary>
/// <param name="username">用户名</param>
/// <param name="callback">回调 (响应结果)</param>
public void StartFingerprintRecord(string username, Action<FingerprintRecordResponse> callback = null)
{
if (!CheckConnection()) return;
// 验证输入
if (string.IsNullOrEmpty(username) || username.Length > BLEConstants.MAX_USERNAME_LENGTH)
{
LogError($"用户名长度必须在1-{BLEConstants.MAX_USERNAME_LENGTH}之间");
callback?.Invoke(new FingerprintRecordResponse { Status = BLEConstants.STATUS_PARAM_ERROR });
return;
}
// 构建请求
var request = new FingerprintRecordRequest
{
Username = username
};
byte[] requestData = request.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FINGERPRINT_RECORD,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)requestData.Length,
Data = requestData
};
SendFrame(frame, (response) =>
{
var recordResponse = FingerprintRecordResponse.FromBytes(response.Status);
if (recordResponse.IsSuccess)
{
Log($"指纹录制请求成功: {username}");
}
else
{
LogError($"指纹录制请求失败: {username}, 状态码={response.Status:X2}");
}
callback?.Invoke(recordResponse);
OnFingerprintRecordResult?.Invoke(recordResponse);
});
}
#region (0x10-0x1F)
/// <summary>
/// 读取语言设置 (命令 0x10)
/// </summary>
public void ReadLanguageSetting(Action<LanguageSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LANGUAGE_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = LanguageSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnLanguageSettingReceived?.Invoke(setting);
});
}
/// <summary>
/// 写入语言设置 (命令 0x10)
/// </summary>
/// <param name="isChinese">true=中文, false=英文</param>
public void WriteLanguageSetting(bool isChinese, Action<bool> callback = null)
{
if (!CheckConnection()) return;
var setting = new LanguageSetting { Language = isChinese ? (byte)0x01 : (byte)0x00 };
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LANGUAGE_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"语言设置成功: {(isChinese ? "" : "")}");
else
LogError($"语言设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取时间设置 (命令 0x11)
/// </summary>
public void ReadTimeSetting(Action<TimeSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_TIME_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = TimeSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnTimeSettingReceived?.Invoke(setting);
});
}
/// <summary>
/// 写入时间设置 (命令 0x11)
/// </summary>
public void WriteTimeSetting(TimeSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_TIME_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"时间设置成功: {setting}");
else
LogError($"时间设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取定时任务列表 (命令 0x12)
/// </summary>
public void ReadScheduleTasks(Action<ScheduleTaskListResponse> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_SCHEDULE_TASK,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var taskList = ScheduleTaskListResponse.FromBytes(response.Status, response.Data);
callback?.Invoke(taskList);
OnScheduleTaskListReceived?.Invoke(taskList);
});
}
/// <summary>
/// 写入定时任务 (命令 0x12)
/// 支持一次写入单条或多条定时任务最多5条
/// </summary>
/// <param name="task">单条定时任务</param>
/// <param name="callback">回调 (成功/失败)</param>
public void WriteScheduleTask(ScheduleTask task, Action<bool> callback = null)
{
WriteScheduleTasks(new ScheduleTask[] { task }, callback);
}
/// <summary>
/// 写入多条定时任务 (命令 0x12)
/// 支持一次写入最多5组定时任务硬件已支持批量写入
/// </summary>
/// <param name="tasks">定时任务数组最多5条每条8字节</param>
/// <param name="callback">回调 (成功/失败)</param>
public void WriteScheduleTasks(ScheduleTask[] tasks, Action<bool> callback = null)
{
if (!CheckConnection()) return;
if (tasks == null || tasks.Length == 0)
{
LogError("定时任务数组为空");
callback?.Invoke(false);
return;
}
if (tasks.Length > 5)
{
LogError("定时任务数量不能超过5条");
callback?.Invoke(false);
return;
}
// 计算总数据长度每条任务7字节不包含TaskId与读取格式一致
int totalLength = tasks.Length * 7;
byte[] data = new byte[totalLength];
// 将所有任务序列化到字节数组
for (int i = 0; i < tasks.Length; i++)
{
byte[] taskBytes = tasks[i].ToBytesWithoutTaskId();
Buffer.BlockCopy(taskBytes, 0, data, i * 7, 7);
// 调试:打印每个任务的详细信息
Debug.Log($"[WriteScheduleTasks] Task[{i}]: Enabled={tasks[i].Enabled} (0x{taskBytes[0]:X2}), " +
$"Time={tasks[i].StartHour:D2}:{tasks[i].StartMinute:D2}-{tasks[i].EndHour:D2}:{tasks[i].EndMinute:D2}, " +
$"Mode={(byte)tasks[i].Mode}, Repeat=0x{tasks[i].Repeat:X2}");
}
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_SCHEDULE_TASK,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
Debug.Log($"[WriteScheduleTasks] 发送数据: {BitConverter.ToString(data)}");
Debug.Log("定时任务:"+frame.ToString());
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
{
if (tasks.Length == 1)
Log($"定时任务设置成功: {tasks[0]}");
else
Log($"定时任务批量设置成功,共 {tasks.Length} 条任务");
}
else
{
LogError($"定时任务设置失败, 状态码={response.Status:X2}");
}
callback?.Invoke(success);
});
}
#endregion
#region (0x20-0x3F)
/// <summary>
/// 读取LCD休眠设置 (命令 0x20)
/// </summary>
public void ReadLCDSleepSetting(Action<LCDSleepSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LCD_SLEEP_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = LCDSleepSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnLCDSleepSettingReceived?.Invoke(setting);
});
}
/// <summary>
/// 写入LCD休眠设置 (命令 0x20)
/// </summary>
public void WriteLCDSleepSetting(LCDSleepSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LCD_SLEEP_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"LCD休眠设置成功: 开关={(setting.Enable ? "" : "")}, 时间={setting.GetSleepTimeString()}");
else
LogError($"LCD休眠设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取LCD亮度设置 (命令 0x21)
/// </summary>
public void ReadLCDBrightnessSetting(Action<LCDBrightnessSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LCD_BRIGHTNESS_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = LCDBrightnessSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnLCDBrightnessSettingReceived?.Invoke(setting);
});
}
/// <summary>
/// 写入LCD亮度设置 (命令 0x21)
/// </summary>
public void WriteLCDBrightnessSetting(LCDBrightnessSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_LCD_BRIGHTNESS_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
Log($"LCD亮度设置响应: 状态码={response.Status:X2}, 成功={success}");
if (success)
Log($"LCD亮度设置成功: 自适应={(setting.AutoBrightness ? "" : "")}, 亮度={setting.Brightness}%");
else
LogError($"LCD亮度设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取RGB指示灯控制 (命令 0x22)
/// </summary>
public void ReadRGBControl(Action<RGBControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_RGB_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = RGBControl.FromBytes(response.Data);
callback?.Invoke(control);
OnRGBControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入RGB指示灯控制 (命令 0x22)
/// </summary>
public void WriteRGBControl(RGBControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_RGB_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"RGB控制设置成功: 开关={(control.Enable ? "" : "")}, 颜色={control.Red},{control.Green},{control.Blue}");
else
LogError($"RGB控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取WIFI控制 (命令 0x23)
/// </summary>
public void ReadWIFIControl(Action<WIFIControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_WIFI_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = WIFIControl.FromBytes(response.Data);
callback?.Invoke(control);
OnWIFIControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入WIFI控制 (命令 0x23)
/// </summary>
public void WriteWIFIControl(WIFIControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_WIFI_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"WIFI控制设置成功: 开关={(control.Enable ? "" : "")}, SSID={control.SSID}");
else
LogError($"WIFI控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取BLE控制 (命令 0x24)
/// </summary>
public void ReadBLEControl(Action<BLEControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_BLE_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = BLEControl.FromBytes(response.Data);
callback?.Invoke(control);
OnBLEControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入BLE控制 (命令 0x24)
/// </summary>
public void WriteBLEControl(BLEControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_BLE_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"BLE控制设置成功: 设备名称={control.DeviceName}");
else
LogError($"BLE控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取多媒体控制 (命令 0x25)
/// </summary>
public void ReadMultimediaControl(Action<MultimediaControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MULTIMEDIA_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = MultimediaControl.FromBytes(response.Data);
callback?.Invoke(control);
OnMultimediaControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入多媒体控制 (命令 0x25)
/// </summary>
public void WriteMultimediaControl(MultimediaControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MULTIMEDIA_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"多媒体控制设置成功: 视频录制={(control.VideoRecordEnable ? "" : "")}, 音效={(control.SoundEnable ? "" : "")}");
else
LogError($"多媒体控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取补光灯控制 (命令 0x26)
/// </summary>
public void ReadFillLightControl(Action<FillLightControl> callback = null)
{
Loom.QueueOnMainThread(() =>
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FILL_LIGHT_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = FillLightControl.FromBytes(response.Data);
callback?.Invoke(control);
OnFillLightControlReceived?.Invoke(control);
});
});
}
/// <summary>
/// 写入补光灯控制 (命令 0x26)
/// </summary>
public void WriteFillLightControl(FillLightControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FILL_LIGHT_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"补光灯控制设置成功: 开关={(control.Enable ? "" : "")}, 类型={control.GetLightTypeString()}, 强度={control.GetIntensityString()}");
else
LogError($"补光灯控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取补光灯连接状态 (命令 0x27)
/// </summary>
public void ReadFillLightConnectionStatus(Action<FillLightConnectionStatus> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FILL_LIGHT_CONNECTION_STATUS,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var status = FillLightConnectionStatus.FromBytes(response.Data);
callback?.Invoke(status);
OnFillLightConnectionStatusReceived?.Invoke(status);
});
}
/// <summary>
/// 读取可见光激光器控制 (命令 0x28)
/// </summary>
public void ReadVisibleLaserControl(Action<VisibleLaserControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_VISIBLE_LASER_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = VisibleLaserControl.FromBytes(response.Data);
callback?.Invoke(control);
OnVisibleLaserControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入可见光激光器控制 (命令 0x28)
/// </summary>
public void WriteVisibleLaserControl(VisibleLaserControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_VISIBLE_LASER_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"可见光激光器控制设置成功: 开关={(control.Enable ? "" : "")}");
else
LogError($"可见光激光器控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取设备锁定状态 (命令 0x29)
/// </summary>
public void ReadDeviceLockControl(Action<DeviceLockControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DEVICE_LOCK,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
Debug.Log($"[ReadDeviceLockControl] 收到响应: Status={response.Status:X2}, Data={BitConverter.ToString(response.Data)}");
var control = DeviceLockControl.FromBytes(response.Data);
Debug.Log($"[ReadDeviceLockControl] 解析结果: IsLocked={control.IsLocked}");
callback?.Invoke(control);
OnDeviceLockControlReceived?.Invoke(control);
});
}
/// <summary>
/// 写入设备锁定状态 (命令 0x29)
/// </summary>
/// <param name="isLocked">true=锁定, false=解锁</param>
public void WriteDeviceLockControl(bool isLocked, Action<bool> callback = null)
{
if (!CheckConnection()) return;
var control = new DeviceLockControl { IsLocked = isLocked };
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DEVICE_LOCK,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
Debug.Log($"[WriteDeviceLockControl] 发送: IsLocked={isLocked}, Data={BitConverter.ToString(data)}");
SendFrame(frame, (response) =>
{
Debug.Log($"[WriteDeviceLockControl] 收到响应: Status={response.Status:X2}");
bool success = response.IsSuccess;
if (success)
Log($"设备{(isLocked ? "" : "")}成功");
else
LogError($"设备{(isLocked ? "" : "")}失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
#endregion
#region (0x40-0x4F)
/// <summary>
/// 读取角度控制设置 (命令 0x40)
/// </summary>
public void ReadAngleControl(Action<AngleControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ANGLE_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = AngleControl.FromBytes(response.Data);
callback?.Invoke(control);
OnAngleControlReceived?.Invoke(control);
Log($"读取角度控制: {control}");
});
}
/// <summary>
/// 写入角度控制设置 (命令 0x40)
/// </summary>
/// <param name="control">角度控制设置</param>
public void WriteAngleControl(AngleControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ANGLE_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"角度控制设置成功: {control}");
else
LogError($"角度控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取距离控制设置 (命令 0x41)
/// </summary>
public void ReadDistanceControl(Action<DistanceControl> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DISTANCE_CONTROL,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var control = DistanceControl.FromBytes(response.Data);
callback?.Invoke(control);
OnDistanceControlReceived?.Invoke(control);
Log($"读取距离控制: {control}");
});
}
/// <summary>
/// 写入距离控制设置 (命令 0x41)
/// </summary>
/// <param name="control">距离控制设置</param>
public void WriteDistanceControl(DistanceControl control, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = control.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DISTANCE_CONTROL,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"距离控制设置成功: {control}");
else
LogError($"距离控制设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
#endregion
#region (0x50-0x5F)
/// <summary>
/// 读取毫米波雷达设置 (命令 0x50)
/// </summary>
public void ReadMillimeterWaveSetting(Action<MillimeterWaveSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MILLIMETER_WAVE_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = MillimeterWaveSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnMillimeterWaveSettingReceived?.Invoke(setting);
Log($"读取毫米波雷达设置: {setting}");
});
}
/// <summary>
/// 写入毫米波雷达设置 (命令 0x50)
/// </summary>
public void WriteMillimeterWaveSetting(MillimeterWaveSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MILLIMETER_WAVE_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"毫米波雷达设置成功: {setting}");
else
LogError($"毫米波雷达设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取视觉检测设置 (命令 0x51)
/// </summary>
public void ReadVisualDetectionSetting(Action<VisualDetectionSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_VISUAL_DETECTION_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = VisualDetectionSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnVisualDetectionSettingReceived?.Invoke(setting);
Log($"读取视觉检测设置: {setting}");
});
}
/// <summary>
/// 写入视觉检测设置 (命令 0x51)
/// </summary>
public void WriteVisualDetectionSetting(VisualDetectionSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_VISUAL_DETECTION_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"视觉检测设置成功: {setting}");
else
LogError($"视觉检测设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 读取加速度传感器设置 (命令 0x52)
/// </summary>
public void ReadAccelerometerSetting(Action<AccelerometerSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ACCELEROMETER_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = AccelerometerSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnAccelerometerSettingReceived?.Invoke(setting);
Log($"读取加速度传感器设置: {setting}");
});
}
/// <summary>
/// 写入加速度传感器设置 (命令 0x52)
/// </summary>
public void WriteAccelerometerSetting(AccelerometerSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ACCELEROMETER_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"加速度传感器设置成功: {setting}");
else
LogError($"加速度传感器设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 查询加速度传感器数据 (命令 0x53)
/// </summary>
public void ReadAccelerometerData(Action<AccelerometerData> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ACCELEROMETER_DATA,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var data = AccelerometerData.FromBytes(response.Data);
callback?.Invoke(data);
OnAccelerometerDataReceived?.Invoke(data);
Log($"读取加速度传感器数据: {data}");
});
}
/// <summary>
/// 读取温度监控设置 (命令 0x55)
/// </summary>
public void ReadTemperatureMonitorSetting(Action<TemperatureMonitorSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_TEMPERATURE_MONITOR_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = TemperatureMonitorSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnTemperatureMonitorSettingReceived?.Invoke(setting);
Log($"读取温度监控设置: {setting}");
});
}
/// <summary>
/// 写入温度监控设置 (命令 0x55)
/// </summary>
public void WriteTemperatureMonitorSetting(TemperatureMonitorSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_TEMPERATURE_MONITOR_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"温度监控设置成功: {setting}");
else
LogError($"温度监控设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
#endregion
#region (0xA0-0xBF)
/// <summary>
/// 读取工作模式 (命令 0xA0)
/// </summary>
public void ReadWorkMode(Action<WorkModeSetting> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_WORK_MODE_SETTING,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var setting = WorkModeSetting.FromBytes(response.Data);
callback?.Invoke(setting);
OnWorkModeSettingReceived?.Invoke(setting);
Log($"读取工作模式: {setting}");
});
}
/// <summary>
/// 写入工作模式 (命令 0xA0)
/// </summary>
public void WriteWorkMode(WorkModeSetting setting, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = setting.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_WORK_MODE_SETTING,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"工作模式设置成功: {setting}");
else
LogError($"工作模式设置失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 查询硬件状态 (命令 0xA1)
/// </summary>
public void ReadHardwareStatus(Action<HardwareStatus> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_HARDWARE_STATUS,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var status = HardwareStatus.FromBytes(response.Data);
callback?.Invoke(status);
OnHardwareStatusReceived?.Invoke(status);
Log($"查询硬件状态: {status}");
});
}
/// <summary>
/// 查询设备信息 (命令 0xA2)
/// </summary>
public void ReadDeviceInfo(Action<DeviceInfo> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DEVICE_INFO,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var info = DeviceInfo.FromBytes(response.Data);
callback?.Invoke(info);
OnDeviceInfoReceived?.Invoke(info);
Log($"查询设备信息: {info}");
});
}
/// <summary>
/// 写入设备信息 (命令 0xA2 写操作)
/// 写操作接收56字节设备信息
/// </summary>
public void WriteDeviceInfo(DeviceInfoWrite deviceInfo, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = deviceInfo.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DEVICE_INFO,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"设备信息写入成功: {deviceInfo}");
else
LogError($"设备信息写入失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 查询统计数据 (命令 0xA3)
/// </summary>
public void ReadStatisticsData(Action<StatisticsData> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_STATISTICS_DATA,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var stats = StatisticsData.FromBytes(response.Data);
callback?.Invoke(stats);
OnStatisticsDataReceived?.Invoke(stats);
Log($"查询统计数据: {stats}");
});
}
/// <summary>
/// 查询蚊虫数据 (命令 0xA4)
/// </summary>
public void QueryMosquitoData(MosquitoDataQuery query, Action<bool> callback = null)
{
if (!CheckConnection()) return;
byte[] data = query.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MOSQUITO_DATA_QUERY,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log($"蚊虫数据查询成功: {query}");
else
LogError($"蚊虫数据查询失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 查询传感器数据 (命令 0xA5)
/// </summary>
public void ReadSensorData(Action<SensorData> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_SENSOR_DATA,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var data = SensorData.FromBytes(response.Data);
callback?.Invoke(data);
OnSensorDataReceived?.Invoke(data);
Log($"查询传感器数据: {data}");
});
}
#endregion
#region (0xA4 + 0x0B)
/// <summary>
/// 查询蚊虫数据数量 (命令 0xA4 读操作)
/// </summary>
public void ReadMosquitoDataCount(Action<MosquitoDataCount> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MOSQUITO_DATA_QUERY,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var count = MosquitoDataCount.FromBytes(response.Data);
callback?.Invoke(count);
Log($"查询蚊虫数据数量: {count}");
});
}
/// <summary>
/// 请求蚊虫数据 (命令 0xA4 写操作)
/// 写操作成功后,设备通过通知机制发送数据
/// </summary>
public void RequestMosquitoData(uint count, Action<bool> callback = null)
{
if (!CheckConnection()) return;
// 构建4字节数据读取数量小端序
byte[] data = new byte[]
{
(byte)(count & 0xFF),
(byte)((count >> 8) & 0xFF),
(byte)((count >> 16) & 0xFF),
(byte)((count >> 24) & 0xFF)
};
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_MOSQUITO_DATA_QUERY,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
{
mosquitoDataCount=(int)count;
OnDataReceived+=HandleMosquitoDataNotification;
Log($"蚊虫数据请求成功,期望接收 {count} 条数据");
}
else
LogError($"蚊虫数据请求失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
public int mosquitoDataCount=0;
/// <summary>
/// 处理蚊虫数据通知 (通知类型 0x0B)
/// </summary>
public void HandleMosquitoDataNotification(byte[] notifyData)
{
if(mosquitoDataCount<=0)
{
OnDataReceived-=HandleMosquitoDataNotification;
return;
}
if (notifyData == null || notifyData.Length < 20)
{
LogError("蚊虫数据通知格式错误数据长度不足20字节");
return;
}
mosquitoDataCount--;
var mosquitoData = MosquitoData.FromBytes(notifyData);
Log($"收到蚊虫数据通知: {mosquitoData} 剩余{mosquitoDataCount}");
OnMosquitoDataReceived?.Invoke(mosquitoData);
}
/// <summary>
/// 读取环境变化状态 (命令 0x56 读操作)
/// </summary>
public void ReadEnvironmentChangeStatus(Action<EnvironmentChangeTest> callback = null)
{
if (!CheckConnection()) return;
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ENVIRONMENT_CHANGE_TEST,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
var status = EnvironmentChangeTest.FromBytes(response.Data);
callback?.Invoke(status);
OnEnvironmentChangeStatusReceived?.Invoke(status);
Log($"读取环境变化状态: {status}");
});
}
/// <summary>
/// 触发激光试射测试 (命令 0x56 写操作)
/// 触发激光进行3次试射测试每次间隔1秒每次持续10ms
/// </summary>
public void TriggerLaserTest(Action<bool> callback = null)
{
if (!CheckConnection()) return;
var test = new EnvironmentChangeTest { TriggerTest = true };
byte[] data = test.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_ENVIRONMENT_CHANGE_TEST,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)data.Length,
Data = data
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log("激光试射测试已触发将进行3次试射每次间隔1秒每次持续10ms");
else
LogError($"激光试射测试触发失败, 状态码={response.Status:X2}");
callback?.Invoke(success);
});
}
/// <summary>
/// 恢复出厂设置 (命令 0x60)
/// 需要管理员权限
/// 写操作发送1字节确认码 0x01
/// </summary>
public void FactoryReset(Action<bool> callback = null)
{
if (!CheckConnection()) return;
// 构建恢复出厂设置帧,发送确认码 0x01
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_FACTORY_RESET,
ReadWrite = BLEConstants.RW_WRITE,
Length = 1,
Data = new byte[] { 0x01 }
};
SendFrame(frame, (response) =>
{
bool success = response.IsSuccess;
if (success)
Log("恢复出厂设置命令发送成功,设备将恢复出厂设置");
else if (response.Status == BLEConstants.STATUS_PERMISSION_ERROR)
LogError("恢复出厂设置失败:需要管理员权限");
else
LogError($"恢复出厂设置失败, 状态码=0x{response.Status:X2}");
callback?.Invoke(success);
});
}
#endregion
/// <summary>
/// 查询用户列表 (命令 0x07)
/// </summary>
public void QueryUserList(Action<UserListResponse> callback = null)
{
if (!CheckConnection()) return;
// 构建查询帧
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_QUERY_USER_LIST,
ReadWrite = BLEConstants.RW_READ,
Length = 0,
Data = null
};
SendFrame(frame, (response) =>
{
if (response.IsSuccess && response.Data != null)
{
var userList = UserListResponse.FromBytes(response.Status, response.Data);
callback?.Invoke(userList);
OnUserListReceived?.Invoke(userList);
}
else
{
LogError($"查询用户列表失败: 状态码={response.Status:X2}");
callback?.Invoke(new UserListResponse() { Status = response.Status });
}
});
}
/// <summary>
/// 注销用户 (命令 0x08)
/// </summary>
/// <param name="username">要注销的用户名</param>
/// <param name="callback">回调 (响应结果)</param>
public void UnregisterUser(string username, Action<UnregisterUserResponse> callback = null)
{
if (!CheckConnection()) return;
// 验证输入
if (string.IsNullOrEmpty(username) || username.Length > BLEConstants.MAX_USERNAME_LENGTH)
{
LogError($"用户名长度必须在1-{BLEConstants.MAX_USERNAME_LENGTH}之间");
callback?.Invoke(new UnregisterUserResponse { Status = BLEConstants.STATUS_PARAM_ERROR });
return;
}
// 构建注销请求
var request = new UnregisterUserRequest
{
Username = username
};
byte[] requestData = request.ToBytes();
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_UNREGISTER_USER,
ReadWrite = BLEConstants.RW_WRITE,
Length = (byte)requestData.Length,
Data = requestData
};
SendFrame(frame, (response) =>
{
var unregisterResponse = UnregisterUserResponse.FromBytes(response.Status);
if (unregisterResponse.IsSuccess)
{
Log($"用户注销成功: {username}");
}
else
{
LogError($"用户注销失败: {username}, 状态码={response.Status:X2}");
}
callback?.Invoke(unregisterResponse);
OnUnregisterUserResult?.Invoke(unregisterResponse);
});
}
/// <summary>
/// 主动断开连接 (命令 0x70)
/// 注意设备收到0x70后会立即断开BLE所以不会收到响应需要特殊处理
/// </summary>
public void Disconnect(Action<bool> callback = null)
{
if (!CheckConnection()) return;
// 构建断开连接帧(无数据)
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = BLEConstants.CMD_DISCONNECT,
ReadWrite = BLEConstants.RW_WRITE,
Length = 0,
Data = null
};
Log($"[BLE-DEBUG] Disconnect: 发送0x70命令: {BitConverter.ToString(frame.ToBytes())}");
SendFrameWithoutResponse(frame);
callback?.Invoke(true);
}
#endregion
#region
/// <summary>
/// 发送协议帧(不等待响应)
/// 用于0x70断开命令等特殊场景
/// </summary>
private void SendFrameWithoutResponse(BLEFrame frame)
{
if (!CheckConnection()) return;
byte[] frameBytes = frame.ToBytes();
string deviceAddress = BluetoothManager.Instance.ConnectedDeviceAddress;
Log($"[BLE-DEBUG] SendFrame: 地址={deviceAddress}, 数据={BitConverter.ToString(frameBytes)}, withResponse=false");
try
{
BluetoothLEHardwareInterface.WriteCharacteristic(
deviceAddress,
ServiceUUID.ToLower(),
WriteCharacteristicUUID.ToLower(),
frameBytes,
frameBytes.Length,
false,
(characteristicUUID) =>
{
Log($"[BLE-DEBUG] SendFrame完成");
}
);
}
catch (System.Exception ex)
{
LogError($"[BLE-DEBUG] SendFrame异常: {ex.Message}");
}
}
/// <summary>
/// 发送协议帧(内部方法,供队列使用)
/// </summary>
public void SendFrameInternal(BLEFrame frame, Action<BLEResponse> callback)
{
SendFrameDirect(frame, callback);
}
/// <summary>
/// 发送协议帧(使用队列,顺序执行)
/// 这是推荐的公共接口
/// </summary>
public void SendFrame(BLEFrame frame, Action<BLEResponse> callback, string description = "")
{
// 检查基本连接状态
if (!CheckConnection())
{
LogError($"[BLE-DEBUG] 蓝牙未就绪,无法发送指令: {description}");
callback?.Invoke(new BLEResponse { Status = BLEConstants.STATUS_DEVICE_ERROR });
return;
}
// 加入队列顺序执行
EnqueueCommand(frame, callback, description);
}
/// <summary>
/// 发送协议帧(底层实现,直接发送)
/// </summary>
private void SendFrameDirect(BLEFrame frame, Action<BLEResponse> callback)
{
if (!CheckConnection())
{
LogError("[BLE-DEBUG] CheckConnection failed, invoking callback with error");
callback?.Invoke(new BLEResponse { Status = BLEConstants.STATUS_DEVICE_ERROR });
return;
}
byte[] frameBytes = frame.ToBytes();
// 调试:打印完整的发送帧
if (frame.Command == BLEConstants.CMD_SCHEDULE_TASK)
{
Debug.Log($"[SendFrame] 完整帧数据: {BitConverter.ToString(frameBytes)}");
}
IsWaitingResponse = true;
_responseTimer = ResponseTimeout;
LastCommand = frame.Command;
_pendingCallback = callback;
// 清空接收缓冲区
lock (_bufferLock)
{
_receiveBuffer.Clear();
}
// 通过BLE发送数据
string deviceAddress = BluetoothManager.Instance.ConnectedDeviceAddress;
// 确保UUID是小写
ServiceUUID = ServiceUUID.ToLower();
WriteCharacteristicUUID = WriteCharacteristicUUID.ToLower();
string hexData = BitConverter.ToString(frameBytes);
// 触发发送数据事件用于UI显示
OnRawDataSent?.Invoke(hexData);
try
{
BluetoothLEHardwareInterface.WriteCharacteristic(
deviceAddress,
ServiceUUID,
WriteCharacteristicUUID,
frameBytes,
frameBytes.Length,
true,
(characteristicUUID) => { }
);
}
catch (System.Exception ex)
{
LogError($"发送帧异常: {ex.Message}");
IsWaitingResponse = false;
callback?.Invoke(new BLEResponse { Status = BLEConstants.STATUS_DEVICE_ERROR });
}
}
/// <summary>
/// 处理收到的通知数据
/// </summary>
private void OnNotificationReceived(byte[] data)
{
if (data == null || data.Length == 0) return;
string hexString = BitConverter.ToString(data);
// 触发原始数据事件用于UI显示
OnRawDataReceived?.Invoke(hexString);
// 添加到接收缓冲区并尝试解析
lock (_bufferLock)
{
_receiveBuffer.AddRange(data);
TryParseFrameInternal();
}
}
/// <summary>
/// 尝试从缓冲区解析帧(内部方法,需要在锁内调用)
/// </summary>
private void TryParseFrameInternal()
{
byte[] buffer = _receiveBuffer.ToArray();
// 查找帧头
for (int i = 0; i < buffer.Length - 1; i++)
{
if (buffer[i] == BLEConstants.FRAME_HEADER_1 &&
buffer[i + 1] == BLEConstants.FRAME_HEADER_2)
{
// 检查是否有足够的数据长度字段
if (i + 4 >= buffer.Length)
{
continue;
}
byte dataLength = buffer[i + 4];
int totalFrameLength = 7 + dataLength; // 帧头(2) + 命令(1) + 读写(1) + 长度(1) + 数据(dataLength) + CRC(2)
// 检查是否有完整的帧
if (i + totalFrameLength > buffer.Length)
{
continue;
}
// 提取帧数据
byte[] frameBytes = new byte[totalFrameLength];
Buffer.BlockCopy(buffer, i, frameBytes, 0, totalFrameLength);
// 解析帧
if (BLEFrame.TryParse(frameBytes, out BLEFrame frame))
{
// 从缓冲区移除已解析的数据
int removeLength = i + totalFrameLength;
_receiveBuffer.RemoveRange(0, removeLength);
// 在锁外处理帧,避免死锁和重入问题
// 使用异步方式在下一帧处理
StartCoroutine(HandleFrameAsync(frame));
return;
}
else
{
LogWarning("帧解析失败 (CRC校验可能失败)");
}
}
}
// 清理过期的缓冲区数据 (保留最后100字节)
if (_receiveBuffer.Count > 200)
{
_receiveBuffer.RemoveRange(0, _receiveBuffer.Count - 100);
}
}
/// <summary>
/// 异步处理帧(避免在锁内处理)
/// </summary>
private System.Collections.IEnumerator HandleFrameAsync(BLEFrame frame)
{
yield return null; // 等待一帧,确保锁已释放
HandleReceivedFrame(frame);
}
/// <summary>
/// 尝试从缓冲区解析帧(公共方法)
/// </summary>
private void TryParseFrame()
{
lock (_bufferLock)
{
TryParseFrameInternal();
}
}
/// <summary>
/// 处理收到的帧
/// </summary>
private void HandleReceivedFrame(BLEFrame frame)
{
bool wasWaitingResponse = IsWaitingResponse;
// 检查是否是对等待命令的响应
if (IsWaitingResponse && frame.Command == LastCommand)
{
IsWaitingResponse = false;
_responseTimer = 0;
var response = BLEResponse.FromFrame(frame);
_pendingCallback?.Invoke(response);
_pendingCallback = null;
}
else if (frame.ReadWrite == BLEConstants.RW_NOTIFY)
{
// 处理设备主动通知
OnDataReceived?.Invoke(frame.Data);
}
else if (IsWaitingResponse)
{
// 尝试处理非匹配的响应,可能是硬件响应延迟
IsWaitingResponse = false;
_responseTimer = 0;
var response = BLEResponse.FromFrame(frame);
_pendingCallback?.Invoke(response);
_pendingCallback = null;
}
// 如果之前有等待响应,现在响应已处理,继续处理队列
if (wasWaitingResponse)
{
ProcessCommandQueue();
}
}
/// <summary>
/// 响应超时处理
/// </summary>
private void OnResponseTimeout()
{
IsWaitingResponse = false;
_responseTimer = 0;
LogError($"命令超时: 命令={LastCommand:X2}");
var timeoutResponse = new BLEResponse
{
Status = BLEConstants.STATUS_TIMEOUT
};
_pendingCallback?.Invoke(timeoutResponse);
_pendingCallback = null;
// 超时后继续处理队列
ProcessCommandQueue();
}
#endregion
#region
/// <summary>
/// 检查蓝牙连接状态(带自动初始化)
/// </summary>
private bool CheckConnection()
{
// 检查蓝牙管理器
if (BluetoothManager.Instance == null)
{
LogError("BluetoothManager.Instance 为 null");
return false;
}
// 如果蓝牙未初始化,尝试自动初始化
if (!BluetoothManager.Instance.IsInitialized)
{
Log("蓝牙未初始化,尝试自动初始化...");
BluetoothManager.Instance.Initialize();
return false;
}
// 如果蓝牙未连接
if (!BluetoothManager.Instance.IsConnected)
{
LogError("蓝牙未连接");
ToastUI.Show("100081"); // "请先连接蓝牙设备"
return false;
}
return true;
}
/// <summary>
/// 将指令加入队列,顺序执行
/// </summary>
public void EnqueueCommand(BLEFrame frame, Action<BLEResponse> callback, string description = "")
{
lock (_queueLock)
{
_commandQueue.Enqueue(new CommandTask(frame, callback, description));
Log($"指令已加入队列: {description}, 当前队列长度: {_commandQueue.Count}");
}
// 尝试处理队列
ProcessCommandQueue();
}
/// <summary>
/// 处理指令队列
/// </summary>
private void ProcessCommandQueue()
{
lock (_queueLock)
{
// 如果正在处理或队列为空,直接返回
if (_isProcessingQueue || _commandQueue.Count == 0)
{
return;
}
// 如果正在等待响应,等待完成后再处理
if (IsWaitingResponse)
{
Log("等待当前指令响应完成...");
return;
}
_isProcessingQueue = true;
}
// 获取下一个指令
CommandTask task = null;
lock (_queueLock)
{
if (_commandQueue.Count > 0)
{
task = _commandQueue.Dequeue();
}
}
if (task != null)
{
Log($"开始执行队列指令: {task.Description}, 剩余队列长度: {_commandQueue.Count}");
SendFrameInternal(task.Frame, task.Callback);
}
lock (_queueLock)
{
_isProcessingQueue = false;
}
}
/// <summary>
/// 清空指令队列
/// </summary>
public void ClearCommandQueue()
{
lock (_queueLock)
{
int count = _commandQueue.Count;
_commandQueue.Clear();
Log($"指令队列已清空,清除了 {count} 个指令");
}
}
/// <summary>
/// 获取队列长度
/// </summary>
public int GetCommandQueueCount()
{
lock (_queueLock)
{
return _commandQueue.Count;
}
}
/// <summary>
/// 确保蓝牙已初始化并连接(异步)
/// </summary>
public void EnsureBluetoothReady(System.Action onReady)
{
if (BluetoothManager.Instance == null)
{
LogError("BluetoothManager.Instance 为 null");
return;
}
// 如果已经连接,直接回调
if (BluetoothManager.Instance.IsConnected)
{
onReady?.Invoke();
return;
}
// 如果未初始化,先初始化
if (!BluetoothManager.Instance.IsInitialized)
{
Log("蓝牙未初始化,开始初始化...");
BluetoothManager.Instance.Initialize();
// 订阅初始化完成事件
System.Action<bool> onInitialized = null;
onInitialized = (success) =>
{
BluetoothManager.Instance.OnInitialized -= onInitialized;
if (success)
{
Log("蓝牙初始化成功,可以开始扫描设备");
onReady?.Invoke();
}
else
{
LogError("蓝牙初始化失败");
}
};
BluetoothManager.Instance.OnInitialized += onInitialized;
}
else
{
// 已初始化但未连接
onReady?.Invoke();
}
}
/// <summary>
/// 获取状态码描述
/// </summary>
private string GetStatusMessage(byte status)
{
switch (status)
{
case BLEConstants.STATUS_SUCCESS: return "成功";
case BLEConstants.STATUS_PARAM_ERROR: return "参数错误";
case BLEConstants.STATUS_PERMISSION_ERROR: return "权限错误";
case BLEConstants.STATUS_DEVICE_BUSY: return "设备忙";
case BLEConstants.STATUS_CMD_NOT_SUPPORT: return "命令不支持";
case BLEConstants.STATUS_DATA_CHECK_FAIL: return "数据校验失败";
case BLEConstants.STATUS_TIMEOUT: return "超时";
case BLEConstants.STATUS_DEVICE_ERROR: return "设备错误";
default: return $"未知错误 (0x{status:X2})";
}
}
#region WiFi指令获取接口
/// <summary>
/// 获取完整蓝牙指令字节数组用于WiFi发送
/// 将BLE协议帧转换为字节数组可直接通过TCP发送给服务器
/// </summary>
/// <param name="command">命令码</param>
/// <param name="readWrite">读写标识 0x00=读, 0x01=写, 0x02=通知</param>
/// <param name="data">数据字段可为null</param>
/// <returns>完整的协议帧字节数组包含帧头、命令、数据、CRC</returns>
public byte[] GetCommandBytes(byte command, byte readWrite, byte[] data)
{
var frame = new BLEFrame
{
Header1 = BLEConstants.FRAME_HEADER_1,
Header2 = BLEConstants.FRAME_HEADER_2,
Command = command,
ReadWrite = readWrite,
Length = (byte)(data?.Length ?? 0),
Data = data
};
return frame.ToBytes();
}
/// <summary>
/// 获取完整蓝牙指令字节数组(简化版,默认写操作)
/// </summary>
/// <param name="command">命令码</param>
/// <param name="data">数据字段可为null</param>
/// <returns>完整的协议帧字节数组</returns>
public byte[] GetCommandBytes(byte command, byte[] data)
{
return GetCommandBytes(command, BLEConstants.RW_WRITE, data);
}
/// <summary>
/// 获取读取指令字节数组(简化版,读操作无数据)
/// </summary>
/// <param name="command">命令码</param>
/// <returns>完整的协议帧字节数组</returns>
public byte[] GetReadCommandBytes(byte command)
{
return GetCommandBytes(command, BLEConstants.RW_READ, null);
}
/// <summary>
/// 获取指令的十六进制字符串表示(用于调试)
/// </summary>
/// <param name="command">命令码</param>
/// <param name="readWrite">读写标识</param>
/// <param name="data">数据字段</param>
/// <returns>十六进制字符串,如 "AA-55-23-01-04-..."</returns>
public string GetCommandHexString(byte command, byte readWrite, byte[] data)
{
byte[] bytes = GetCommandBytes(command, readWrite, data);
return BitConverter.ToString(bytes);
}
/// <summary>
/// 从BLEFrame获取完整指令字节数组
/// </summary>
/// <param name="frame">协议帧结构</param>
/// <returns>完整的协议帧字节数组</returns>
public byte[] GetFrameBytes(BLEFrame frame)
{
return frame.ToBytes();
}
#endregion
private void Log(string message)
{
Debug.Log($"[BLECommunication] {message}");
}
private void LogError(string message)
{
Debug.LogError($"[BLECommunication] {message}");
OnCommunicationError?.Invoke(message);
}
private void LogWarning(string message)
{
Debug.LogWarning($"[BLECommunication] {message}");
}
#endregion
}
}