using UnityEngine; using System; using System.Collections.Generic; using Kill.Core; namespace Kill.Bluetooth { /// /// 蓝牙设备信息 /// [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; } private string aimMac = ""; // 扫描到的设备列表 public List DiscoveredDevices { get; private set; } = new List(); // 是否自动连接 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; } } void Start() { Initialize(); } 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("正在初始化蓝牙..."); // 先检查蓝牙是否开启,如果没有则尝试启用 CheckAndEnableBluetooth(() => { // 蓝牙已启用,执行初始化 DoInitialize(); }); } /// /// 检查并启用蓝牙 /// private void CheckAndEnableBluetooth(System.Action onBluetoothReady) { #if UNITY_ANDROID && !UNITY_EDITOR using (AndroidJavaClass bluetoothAdapterClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter")) { AndroidJavaObject bluetoothAdapter = bluetoothAdapterClass.CallStatic("getDefaultAdapter"); if (bluetoothAdapter == null) { OnError?.Invoke("设备不支持蓝牙"); OnInitialized?.Invoke(false); return; } bool isEnabled = bluetoothAdapter.Call("isEnabled"); if (!isEnabled) { Log("蓝牙未开启,尝试启用..."); // 尝试静默启用蓝牙 bool enableSuccess = bluetoothAdapter.Call("enable"); if (enableSuccess) { Log("正在启用蓝牙,等待..."); // 等待蓝牙启用 StartCoroutine(WaitForBluetoothEnabled(onBluetoothReady)); } else { // 静默启用失败,请求用户启用 RequestUserEnableBluetooth(onBluetoothReady); } } else { Log("蓝牙已开启"); onBluetoothReady?.Invoke(); } } #elif UNITY_IOS && !UNITY_EDITOR // iOS 检查蓝牙状态 CheckBluetoothStateIOS(onBluetoothReady); #else // 其他平台直接执行初始化 onBluetoothReady?.Invoke(); #endif } #if UNITY_IOS && !UNITY_EDITOR [System.Runtime.InteropServices.DllImport("__Internal")] private static extern int GetBluetoothStateIOS(); [System.Runtime.InteropServices.DllImport("__Internal")] private static extern void OpenBluetoothSettingsIOS(); /// /// iOS 检查蓝牙状态 /// 0 = Unknown, 1 = Resetting, 2 = Unsupported, 3 = Unauthorized, 4 = PoweredOff, 5 = PoweredOn /// private void CheckBluetoothStateIOS(System.Action onBluetoothReady) { int state = GetBluetoothStateIOS(); Log($"iOS 蓝牙状态: {state}"); // 5 = PoweredOn (蓝牙已开启) if (state == 5) { Log("iOS 蓝牙已开启"); onBluetoothReady?.Invoke(); } // 4 = PoweredOff (蓝牙关闭) else if (state == 4) { Log("iOS 蓝牙未开启,提示用户"); // iOS 不能自动打开蓝牙,只能提示用户去设置中开启 ShowIOSTurnOnBluetoothPrompt(); OnError?.Invoke("请在系统设置中开启蓝牙"); OnInitialized?.Invoke(false); } // 3 = Unauthorized (未授权) else if (state == 3) { LogError("iOS 蓝牙未授权"); OnError?.Invoke("请在设置中允许使用蓝牙"); OnInitialized?.Invoke(false); } // 2 = Unsupported (不支持蓝牙) else if (state == 2) { LogError("设备不支持蓝牙"); OnError?.Invoke("设备不支持蓝牙"); OnInitialized?.Invoke(false); } // 其他状态 else { Log($"iOS 蓝牙状态未知: {state},尝试继续初始化"); onBluetoothReady?.Invoke(); } } /// /// 显示 iOS 开启蓝牙提示 /// private void ShowIOSTurnOnBluetoothPrompt() { // 可以在这里显示一个弹窗,引导用户去设置 // 或者使用原生插件跳转到设置页面 OpenBluetoothSettingsIOS(); } #endif #if UNITY_ANDROID && !UNITY_EDITOR /// /// 等待蓝牙启用 /// private System.Collections.IEnumerator WaitForBluetoothEnabled(System.Action onBluetoothReady) { float timeout = 5f; float timer = 0f; while (timer < timeout) { using (AndroidJavaClass bluetoothAdapterClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter")) { AndroidJavaObject bluetoothAdapter = bluetoothAdapterClass.CallStatic("getDefaultAdapter"); if (bluetoothAdapter != null && bluetoothAdapter.Call("isEnabled")) { Log("蓝牙已成功启用"); onBluetoothReady?.Invoke(); yield break; } } yield return new WaitForSeconds(0.5f); timer += 0.5f; } Log("等待蓝牙启用超时"); OnError?.Invoke("蓝牙启用超时"); OnInitialized?.Invoke(false); } /// /// 请求用户启用蓝牙 /// private void RequestUserEnableBluetooth(System.Action onBluetoothReady) { Log("请求用户启用蓝牙..."); using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (AndroidJavaObject currentActivity = unityPlayer.GetStatic("currentActivity")) { AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", "android.bluetooth.adapter.action.REQUEST_ENABLE"); currentActivity.Call("startActivityForResult", intent, 1); } // 等待用户响应 StartCoroutine(WaitForUserEnableBluetooth(onBluetoothReady)); } /// /// 等待用户启用蓝牙 /// private System.Collections.IEnumerator WaitForUserEnableBluetooth(System.Action onBluetoothReady) { float timeout = 30f; float timer = 0f; while (timer < timeout) { using (AndroidJavaClass bluetoothAdapterClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter")) { AndroidJavaObject bluetoothAdapter = bluetoothAdapterClass.CallStatic("getDefaultAdapter"); if (bluetoothAdapter != null && bluetoothAdapter.Call("isEnabled")) { Log("用户已启用蓝牙"); onBluetoothReady?.Invoke(); yield break; } } yield return new WaitForSeconds(0.5f); timer += 0.5f; } Log("用户未启用蓝牙或超时"); OnError?.Invoke("请启用蓝牙后重试"); OnInitialized?.Invoke(false); } #endif /// /// 执行蓝牙初始化 /// // 标记是否已完成初始化 private bool _isFullyInitialized = false; private void DoInitialize() { _isFullyInitialized = false; BluetoothLEHardwareInterface.Initialize(true, false, () => { IsInitialized = true; _isFullyInitialized = true; Log("蓝牙初始化成功"); OnInitialized?.Invoke(true); }, (error) => { // 忽略 "Service not found" 错误,这是插件内部问题,不影响功能 if (error.Contains("Service not found")) { Log($"蓝牙初始化警告: {error}"); Log("继续初始化..."); IsInitialized = true; _isFullyInitialized = true; OnInitialized?.Invoke(true); } // 如果已经初始化完成,这是运行时错误,不是初始化错误 else if (_isFullyInitialized) { Log($"蓝牙运行时错误: {error}"); OnError?.Invoke(error); } else { Log($"蓝牙初始化失败: {error}"); OnError?.Invoke($"初始化失败: {error}"); OnInitialized?.Invoke(false); } }, needLocation: true ); } // /// // /// 延迟尝试自动连接(用于初始化后) // /// // 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; } } /// /// 开始扫描蓝牙设备 /// /// 扫描超时时间(秒),默认10秒 public void StartScan(float timeout = 999f) { if (!IsInitialized) { OnError?.Invoke("蓝牙未初始化,请先调用Initialize()"); return; } 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)); 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)); // 清理设备列表,为下次扫描做准备 DiscoveredDevices.Clear(); Log("断开连接清理完成,可以开始新的扫描"); } /// /// 完全重置蓝牙(断开连接并重新初始化) /// 用于解决断开后无法扫描到设备的问题 /// public void ResetBluetooth() { Log("开始完全重置蓝牙..."); // 停止扫描 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}"); if (aimMac.ToUpper() == address.ToUpper()) { StopScan(); Connect(address); } OnDeviceFound?.Invoke(newDevice); } } /// /// 输出日志 /// private void Log(string message) { Debug.Log($"[BluetoothManager] {message}"); OnLog?.Invoke(message); } /// /// 通知连接成功并可通信 /// private void NotifyConnectedSuccess() { Log("蓝牙连接已就绪,可以开始通信"); OnConnectedSuccess?.Invoke(); } public bool ChangeAimMac(string mac) { aimMac = mac; if(aimMac=="") { return false; } if (IsConnected && mac.ToUpper() == ConnectedDeviceAddress.ToUpper()) { return true; } else { if (IsConnected && mac.ToUpper() != ConnectedDeviceAddress.ToUpper()) { Disconnect(); StartScan(); } else { StartScan(); } return false; } } } }