using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class BleUDP : MonoBehaviour { public static BleUDP ins; //单例记录 readonly string localIP = "127.0.0.1"; //本地IP readonly int myPort = 8001; //自身的注册端口 readonly int targetPort = 8000; //发消息的目标端口 Socket client; //UDP对象 float noneMsgTime = 0; //多久没收到字节消息了 Queue byteQueue = new Queue(); //接收信息的线程把字节信息放这里 Queue byteMainQueue = new Queue(); //主线程从byteQueue中取出数据后放在这里,供主线程update使用 public Action OnConnected; public Action OnConnectionFailed; public Action OnCharacteristicChanged; public Action OnScanEnded; [NonSerialized] public BluetoothStatusEnum bluetoothStatusEnum = BluetoothStatusEnum.Connect; void Awake() { if (ins) { Destroy(this.gameObject); return; } ins = this; DontDestroyOnLoad(this.gameObject); client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); client.Bind(new IPEndPoint(IPAddress.Parse(localIP), myPort)); Thread threadReciveMsg = new Thread(ReciveMsg); threadReciveMsg.Start(); } void OnDestroy() { if (ins == this) ins = null; client.Close(); } void Update() { lock (byteQueue) { while (byteQueue.Count > 0) { byteMainQueue.Enqueue(byteQueue.Dequeue()); } } if (bluetoothStatusEnum == BluetoothStatusEnum.Connecting) { if (noneMsgTime > 5) { bluetoothStatusEnum = BluetoothStatusEnum.ConnectFail; EmitOnConnectionFailed(); return; } else if (byteMainQueue.Count > 0) { bluetoothStatusEnum = BluetoothStatusEnum.ConnectSuccess; EmitOnConnected(); } } else if (bluetoothStatusEnum == BluetoothStatusEnum.ConnectSuccess) { if (noneMsgTime > 5) { bluetoothStatusEnum = BluetoothStatusEnum.ConnectFail; EmitOnConnectionFailed(); } } else { byteMainQueue.Clear(); return; } if (byteMainQueue.Count == 0) { noneMsgTime += Time.deltaTime; return; } noneMsgTime = 0; while (byteMainQueue.Count > 0) { EmitOnCharacteristicChanged(byteMainQueue.Dequeue()); } } public void SendMsg(string data) { Debug.LogWarning("sendMsgToBle: " + data); EndPoint point = new IPEndPoint(IPAddress.Parse(localIP), targetPort); client.SendTo(Encoding.UTF8.GetBytes(data), point); } void ReciveMsg() { while (true) { EndPoint point = new IPEndPoint(IPAddress.Any, 0); byte[] buffer = new byte[1024]; int length = client.ReceiveFrom(buffer, ref point); if (!point.ToString().EndsWith(targetPort.ToString())) return; if (length <= 0) continue; byte[] bytes = new byte[length]; Array.Copy(buffer, bytes, length); lock (byteQueue) { byteQueue.Enqueue(bytes); } } } public void ScanNearbyDevices() { EmitOnScanEnded(); } public void Connect() { noneMsgTime = 0; bluetoothStatusEnum = BluetoothStatusEnum.Connecting; SendMsg("V"); } public void Disconnect() { bluetoothStatusEnum = BluetoothStatusEnum.Connect; } void EmitOnConnected() { try { OnConnected?.Invoke(); } catch (Exception) { } } void EmitOnConnectionFailed() { try { OnConnectionFailed?.Invoke(); } catch (Exception) { } } void EmitOnCharacteristicChanged(byte[] bytes) { try { OnCharacteristicChanged?.Invoke(bytes); } catch (Exception) { } } void EmitOnScanEnded() { try { OnScanEnded?.Invoke(); } catch (Exception) { } } }