using UnityEngine; using System; using System.Collections.Generic; /// /// 蓝牙设备信息 /// [Serializable] public class BluetoothDevice { public string Address; // 设备地址 public string Name; // 设备名称 public int Rssi; // 信号强度 public BluetoothDevice(string address, string name, int rssi = 0) { Address = address; Name = name; Rssi = rssi; } } /// /// 蓝牙管理器 - 提供基础的蓝牙扫描、连接、断开功能 /// public class BluetoothManager : MonoBehaviour { public static BluetoothManager Instance { get; private set; } // 事件定义 public event Action OnInitialized; // 初始化完成事件 public event Action OnDeviceFound; // 发现设备事件 public event Action OnConnected; // 连接成功事件 (参数: 设备地址) public event Action OnConnectFailed; // 连接失败事件 (参数: 设备地址) public event Action OnDisconnected; // 断开连接事件 (参数: 设备地址) public event Action OnError; // 错误事件 public event Action OnLog; // 日志事件 public event Action OnConnectedSuccess; // 连接成功并可通信事件 (无参数,用于通知BLECommunicationManager) // 状态 public bool IsInitialized { get; private set; } public bool IsScanning { get; private set; } public bool IsConnected { get; private set; } public string ConnectedDeviceAddress { get; private set; } // 扫描到的设备列表 public List DiscoveredDevices { get; private set; } = new List(); // 上一次连接的设备地址 private const string LAST_DEVICE_ADDRESS_KEY = "LastConnectedDeviceAddress"; private const string LAST_DEVICE_NAME_KEY = "LastConnectedDeviceName"; // 是否自动连接 public bool AutoConnect = true; // 连接超时设置 public float ConnectionTimeout = 10f; // 连接超时时间(秒) private float _connectionTimer; private bool _isConnecting; private string _connectingAddress; private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } private void OnDestroy() { if (Instance == this) { Instance = null; } } private void Update() { // 检查连接超时 if (_isConnecting) { _connectionTimer -= Time.deltaTime; if (_connectionTimer <= 0) { // 连接超时 _isConnecting = false; Log($"连接超时: {_connectingAddress}"); OnConnectFailed?.Invoke(_connectingAddress); OnError?.Invoke($"连接超时: 无法连接到设备 {_connectingAddress}"); _connectingAddress = null; } } } /// /// 初始化蓝牙 /// public void Initialize() { if (IsInitialized) { Log("蓝牙已经初始化"); OnInitialized?.Invoke(true); return; } Log("正在初始化蓝牙..."); BluetoothLEHardwareInterface.Initialize(true, false, () => { IsInitialized = true; Log("蓝牙初始化成功"); OnInitialized?.Invoke(true); // 初始化成功后,延迟尝试自动连接上一次设备 // 延迟是为了让用户有机会先进行手动扫描 if (AutoConnect) { Log("将在3秒后尝试自动连接上一次设备..."); Invoke(nameof(TryAutoConnectDelayed), 3f); } }, (error) => { // 忽略 "Service not found" 错误,这是插件内部问题,不影响功能 if (error.Contains("Service not found")) { Log($"蓝牙初始化警告: {error}"); Log("继续初始化..."); IsInitialized = true; OnInitialized?.Invoke(true); // 初始化成功后,延迟尝试自动连接上一次设备 if (AutoConnect) { Log("将在3秒后尝试自动连接上一次设备..."); Invoke(nameof(TryAutoConnectDelayed), 3f); } } else { Log($"蓝牙初始化失败: {error}"); OnError?.Invoke($"初始化失败: {error}"); OnInitialized?.Invoke(false); } } ); } /// /// 延迟尝试自动连接(用于初始化后) /// private void TryAutoConnectDelayed() { // 如果用户已经开始扫描或连接,跳过自动连接 if (IsScanning || IsConnected || _isConnecting) { Log("用户正在进行扫描或连接,跳过自动连接"); return; } TryAutoConnect(); } /// /// 尝试自动连接上一次连接的设备 /// private void TryAutoConnect() { string lastAddress = PlayerPrefs.GetString(LAST_DEVICE_ADDRESS_KEY, ""); string lastName = PlayerPrefs.GetString(LAST_DEVICE_NAME_KEY, ""); if (string.IsNullOrEmpty(lastAddress)) { Log("没有上一次连接的设备记录"); return; } Log($"尝试自动连接上一次设备: {lastName} [{lastAddress}]"); // 先扫描设备,找到后再连接 StartScanForAutoConnect(lastAddress); } /// /// 为自动连接扫描设备 /// private void StartScanForAutoConnect(string targetAddress) { if (!IsInitialized) { Log("蓝牙未初始化,无法扫描"); return; } Log("[BLE-DEBUG] 自动连接: 开始扫描..."); // 清空设备列表 DiscoveredDevices.Clear(); // 扫描5秒 BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) => { // 先添加到设备列表 AddOrUpdateDevice(address, name, 0); // 检查是否是要找的设备(统一使用大写比较) if (address.ToUpper() == targetAddress.ToUpper()) { Log($"[BLE-DEBUG] 自动连接: 找到设备 {name}"); BluetoothLEHardwareInterface.StopScan(); // 延迟100ms再连接,确保扫描完全停止(与手动连接流程一致) _pendingAutoConnectAddress = targetAddress; Invoke(nameof(DelayedAutoConnect), 0.1f); } }, (address, name, rssi, bytes) => { // 先添加到设备列表 AddOrUpdateDevice(address, name, rssi); // 检查是否是要找的设备(统一使用大写比较) if (address.ToUpper() == targetAddress.ToUpper()) { Log($"[BLE-DEBUG] 自动连接: 找到设备 {name}, RSSI: {rssi}"); BluetoothLEHardwareInterface.StopScan(); // 延迟100ms再连接,确保扫描完全停止(与手动连接流程一致) _pendingAutoConnectAddress = targetAddress; Invoke(nameof(DelayedAutoConnect), 0.1f); } }, true ); // 5秒后停止扫描 Invoke(nameof(StopScan), 5f); } // 用于自动连接的临时地址存储 private string _pendingAutoConnectAddress; /// /// 延迟自动连接(确保扫描完全停止后再连接) /// private void DelayedAutoConnect() { if (!string.IsNullOrEmpty(_pendingAutoConnectAddress)) { Log($"[BLE-DEBUG] 自动连接: 延迟连接 {_pendingAutoConnectAddress}"); Connect(_pendingAutoConnectAddress); _pendingAutoConnectAddress = null; } } /// /// 保存连接的设备信息 /// private void SaveLastConnectedDevice(string address, string name) { // 统一使用大写格式保存,确保地址格式一致 string normalizedAddress = address.ToUpper(); PlayerPrefs.SetString(LAST_DEVICE_ADDRESS_KEY, normalizedAddress); PlayerPrefs.SetString(LAST_DEVICE_NAME_KEY, name); PlayerPrefs.Save(); Log($"保存设备连接记录: {name} [{normalizedAddress}]"); } /// /// 清除设备连接记录 /// public void ClearLastConnectedDevice() { PlayerPrefs.DeleteKey(LAST_DEVICE_ADDRESS_KEY); PlayerPrefs.DeleteKey(LAST_DEVICE_NAME_KEY); PlayerPrefs.Save(); Log("清除设备连接记录"); } /// /// 开始扫描蓝牙设备 /// /// 扫描超时时间(秒),默认10秒 public void StartScan(float timeout = 10f) { if (!IsInitialized) { OnError?.Invoke("蓝牙未初始化,请先调用Initialize()"); return; } // 取消自动连接,避免干扰手动扫描 CancelInvoke(nameof(TryAutoConnectDelayed)); if (IsScanning) { Log("已经在扫描中,先停止当前扫描..."); StopScan(); } // 如果还在连接状态,先断开 if (IsConnected) { Log("警告: 扫描时仍处于连接状态,先断开连接..."); Disconnect(); // 延迟一点再开始扫描 Invoke(nameof(DelayedStartScan), 1f); return; } // 清空之前的设备列表 DiscoveredDevices.Clear(); IsScanning = true; Log($"开始扫描蓝牙设备 (超时: {timeout}秒)..."); // 开始扫描 BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, // 回调1:基础设备信息(地址和名称) (address, name) => { AddOrUpdateDevice(address, name, 0); }, // 回调2:包含RSSI和制造商数据 (address, name, rssi, bytes) => { AddOrUpdateDevice(address, name, rssi); }, true // 允许不带有制造商数据的RSSI ); // 设置超时自动停止 Invoke(nameof(StopScan), timeout); } /// /// 延迟开始扫描(用于断开连接后) /// private void DelayedStartScan() { Log("延迟扫描开始..."); // 清空设备列表 DiscoveredDevices.Clear(); IsScanning = true; BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) => { AddOrUpdateDevice(address, name, 0); }, (address, name, rssi, bytes) => { AddOrUpdateDevice(address, name, rssi); }, true ); Invoke(nameof(StopScan), 10f); } /// /// 停止扫描 /// public void StopScan() { if (!IsScanning) return; IsScanning = false; // 取消所有扫描相关的Invoke CancelInvoke(nameof(StopScan)); CancelInvoke(nameof(DelayedStartScan)); CancelInvoke(nameof(TryAutoConnectDelayed)); BluetoothLEHardwareInterface.StopScan(); Log("停止扫描蓝牙设备"); } /// /// 连接指定设备 /// /// 设备地址 public void Connect(string deviceAddress) { if (!IsInitialized) { OnError?.Invoke("蓝牙未初始化"); return; } if (IsConnected) { OnError?.Invoke("已连接到设备,请先断开连接"); return; } // 如果正在连接其他设备,先取消 if (_isConnecting) { Log($"取消之前的连接尝试: {_connectingAddress}"); _isConnecting = false; } Log($"正在连接设备: {deviceAddress}"); // 启动连接超时计时 _isConnecting = true; // 统一使用大写格式保存地址 _connectingAddress = deviceAddress.ToUpper(); _connectionTimer = ConnectionTimeout; BluetoothLEHardwareInterface.ConnectToPeripheral(deviceAddress, // 连接成功回调 (address) => { Log($"设备连接成功: {address}"); }, // 服务发现回调 (address, serviceUUID) => { Log($"[BLE-DEBUG] 发现服务: {serviceUUID}"); }, // 特征发现回调 (address, serviceUUID, characteristicUUID) => { Log($"[BLE-DEBUG] 发现特征: Service={serviceUUID}, Char={characteristicUUID}"); // 首次发现特征时设置连接状态 if (!IsConnected) { // 连接成功,停止超时计时 _isConnecting = false; _connectingAddress = null; IsConnected = true; // 统一使用大写格式保存地址,确保与断开时使用的格式一致 ConnectedDeviceAddress = address.ToUpper(); // 保存连接的设备信息 var device = DiscoveredDevices.Find(d => d.Address.ToUpper() == address.ToUpper()); string deviceName = device != null ? device.Name : "Unknown"; SaveLastConnectedDevice(address, deviceName); OnConnected?.Invoke(address); // 延迟通知连接成功并可通信 Invoke(nameof(NotifyConnectedSuccess), 0.5f); } }, // 断开连接回调 (disconnectAddress) => { // 如果正在连接中就被断开,说明连接失败 if (_isConnecting && disconnectAddress.ToUpper() == _connectingAddress?.ToUpper()) { _isConnecting = false; Log($"连接失败: {disconnectAddress}"); OnConnectFailed?.Invoke(disconnectAddress); _connectingAddress = null; } // 设备断开连接(使用不区分大小写的地址比较) else if (IsConnected && disconnectAddress.ToUpper() == ConnectedDeviceAddress?.ToUpper()) { IsConnected = false; string disconnectedAddr = ConnectedDeviceAddress; ConnectedDeviceAddress = null; Log($"设备断开连接: {disconnectAddress}"); OnDisconnected?.Invoke(disconnectAddress); // 执行清理 CleanupAfterDisconnect(); } else { Log($"收到未处理的断开回调: {disconnectAddress}, 当前连接状态: IsConnected={IsConnected}"); } } ); } /// /// 按名称连接设备 /// /// 设备名称 public void ConnectByName(string deviceName) { var device = DiscoveredDevices.Find(d => d.Name == deviceName); if (device != null) { Connect(device.Address); } else { OnError?.Invoke($"未找到设备: {deviceName}"); } } /// /// 断开当前连接(带协议通知) /// 先发送0x70断开命令给设备,再断开BLE连接 /// public void Disconnect() { if (!IsConnected) { Log("当前没有连接的设备"); return; } string addressToDisconnect = ConnectedDeviceAddress; Log($"正在断开连接: {addressToDisconnect}"); // 先停止扫描,避免扫描干扰断开过程 if (IsScanning) { StopScan(); } // 取消可能正在进行的连接尝试 if (_isConnecting) { _isConnecting = false; _connectingAddress = null; } // 先通过BLE协议发送断开命令(0x70) Log($"检查BLECommunicationManager: Instance={(BLECommunicationManager.Instance != null ? "存在" : "null")}"); if (BLECommunicationManager.Instance != null) { Log("发送断开命令(0x70)到设备..."); BLECommunicationManager.Instance.Disconnect((success) => { Log($"断开命令发送结果: {(success ? "成功" : "失败")}"); // 无论命令是否成功,都执行BLE断开 PerformBLEDisconnect(addressToDisconnect); }); } else { Log("BLECommunicationManager.Instance 为 null,跳过0x70命令,直接断开BLE"); // 如果没有BLE通信管理器,直接断开BLE PerformBLEDisconnect(addressToDisconnect); } } /// /// 执行BLE层断开连接 /// private void PerformBLEDisconnect(string addressToDisconnect) { Log($"执行BLE断开: {addressToDisconnect}"); BluetoothLEHardwareInterface.DisconnectPeripheral(addressToDisconnect, (address) => { Log($"BLE断开连接回调: {address}"); } ); // 立即清理状态 IsConnected = false; ConnectedDeviceAddress = null; OnDisconnected?.Invoke(addressToDisconnect); // 延迟清理 Invoke(nameof(CleanupAfterDisconnect), 0.5f); } /// /// 断开连接后的清理工作 /// private void CleanupAfterDisconnect() { Log("执行断开连接后的清理..."); // 确保停止扫描 if (IsScanning) { StopScan(); } // 取消可能冲突的Invoke CancelInvoke(nameof(StopScan)); CancelInvoke(nameof(DelayedStartScan)); CancelInvoke(nameof(TryAutoConnectDelayed)); // 清理设备列表,为下次扫描做准备 DiscoveredDevices.Clear(); Log("断开连接清理完成,可以开始新的扫描"); } /// /// 完全重置蓝牙(断开连接并重新初始化) /// 用于解决断开后无法扫描到设备的问题 /// public void ResetBluetooth() { Log("开始完全重置蓝牙..."); // 保存上一次连接的设备信息 string lastAddress = PlayerPrefs.GetString(LAST_DEVICE_ADDRESS_KEY, ""); string lastName = PlayerPrefs.GetString(LAST_DEVICE_NAME_KEY, ""); // 停止扫描 if (IsScanning) { StopScan(); } // 断开连接 - 先发送0x70断开命令,再断开BLE连接 if (IsConnected) { string addressToDisconnect = ConnectedDeviceAddress; Log($"重置蓝牙: 正在断开连接 {addressToDisconnect}"); // 先通过BLE协议发送断开命令(0x70) if (BLECommunicationManager.Instance != null) { Log("重置蓝牙: 发送断开命令(0x70)到设备..."); BLECommunicationManager.Instance.Disconnect((success) => { Log($"重置蓝牙: 断开命令发送结果: {(success ? "成功" : "失败")}"); // 无论命令是否成功,都执行BLE断开 BluetoothLEHardwareInterface.DisconnectPeripheral(addressToDisconnect, (addr) => {}); }); } else { // 如果没有BLE通信管理器,直接断开BLE BluetoothLEHardwareInterface.DisconnectPeripheral(addressToDisconnect, (addr) => {}); } IsConnected = false; ConnectedDeviceAddress = null; } // 取消所有Invoke CancelInvoke(); // 清理设备列表 DiscoveredDevices.Clear(); // 反初始化蓝牙 BluetoothLEHardwareInterface.DeInitialize(() => { IsInitialized = false; Log("蓝牙已反初始化,准备重新初始化..."); // 延迟重新初始化 Loom.QueueOnMainThread(() => { Invoke(nameof(ReinitializeBluetooth), 1f); }); }); } /// /// 重新初始化蓝牙(断开连接后使用,不触发自动连接) /// private void ReinitializeBluetooth() { Log("重新初始化蓝牙..."); BluetoothLEHardwareInterface.Initialize(true, false, () => { IsInitialized = true; Log("蓝牙重新初始化成功,现在可以扫描设备了"); OnInitialized?.Invoke(true); // 注意:这里不触发自动连接,避免干扰用户操作 }, (error) => { if (error.Contains("Service not found")) { Log("蓝牙重新初始化警告,继续..."); IsInitialized = true; OnInitialized?.Invoke(true); } else { Log($"蓝牙重新初始化失败: {error}"); OnError?.Invoke($"重新初始化失败: {error}"); } } ); } /// /// 反初始化蓝牙 /// public void DeInitialize() { if (IsConnected) { Disconnect(); } if (IsScanning) { StopScan(); } BluetoothLEHardwareInterface.DeInitialize(() => { IsInitialized = false; Log("蓝牙已反初始化"); }); } /// /// 添加或更新设备到列表 /// private void AddOrUpdateDevice(string address, string name, int rssi) { // 调试日志:显示所有发现的设备(包括无名称的) Log($"扫描到设备: Name='{name}', Address={address}, RSSI={rssi}"); // 查找是否已存在 var existingDevice = DiscoveredDevices.Find(d => d.Address.ToUpper() == address.ToUpper()); if (existingDevice != null) { // 更新RSSI existingDevice.Rssi = rssi; Log($"更新设备信号: {existingDevice.Name} [{address}] RSSI: {rssi}"); } else { // 过滤掉没有名称的设备 if (string.IsNullOrEmpty(name) || name == "No Name" || name == "Unknown") { Log($"过滤无名称设备: [{address}]"); return; } // 添加新设备 var newDevice = new BluetoothDevice(address, name, rssi); DiscoveredDevices.Add(newDevice); Log($"发现新设备: {name} [{address}] RSSI: {rssi}"); OnDeviceFound?.Invoke(newDevice); } } /// /// 输出日志 /// private void Log(string message) { Debug.Log($"[BluetoothManager] {message}"); OnLog?.Invoke(message); } /// /// 通知连接成功并可通信 /// private void NotifyConnectedSuccess() { Log("蓝牙连接已就绪,可以开始通信"); OnConnectedSuccess?.Invoke(); } }