Unity+WindowsForms PC端接收蓝牙数据

我的初衷是直接用Unity实现PC端连接蓝牙,接收蓝牙发送的数据。但是能力有限,在网上也找了很久,一直没有找到解决方案。就只能退而求其次通过Unity+WindowsForms两个平台实现这一功能。

项目实例:

https://download.csdn.net/download/qq_34421469/14988605

1.使用WindowsForms连接到蓝牙,接收蓝牙信息后,通过UDP发送(我这里指定了蓝牙,也可以通过查找蓝牙,获取到蓝牙信息连接接收数据)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;

namespace BlueTooth
{
    public partial class Form1 : Form
    {


        private static BluetoothLEDevice bluetoothLeDevice = null;
        static DeviceWatcher deviceWatcher = null;
        static DeviceInformation mydeviceInformation = null;
        static List<DeviceInformation> deviceInformation = null;
        static GattCharacteristic gatt_notify, gatt_write;
        static Thread threadMain;
        static Mutex _mutex;
        private string pointIP = "d2:67:9d:ce:b7:ad";// 目标蓝牙mac地址
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            deviceInformation = new List<DeviceInformation>();
            threadMain = new Thread(new ThreadStart(StartThread)); 
            threadMain.Start();
            FirstStep();
            UdpPeer(1234);
        }
        void StartThread()
        {
            while (true)
            {
                if (queueRec.Count > 0)
                {
                    string str = queueRec.Dequeue();
                    string[] data = str.Split(':');

                    switch (data[0])
                    {
                        case "10003":
                            if (data[1].CompareTo("Start") == 0)
                            {
                                ss = "";
                                //开启
                                FirstStep();
                            }
                            else if (data[1].CompareTo("Close") == 0)
                            {
                                MethodInvoker action_Close = delegate
                                {
                                    textBox1.Text += "Close+";
                                };
                                textBox1.BeginInvoke(action_Close);
                                CloseDevice("StartThread");
                                Application.Exit();

                            }
                            break;
                        default:break;
                    }
                }
            }
        }

        /// <summary>
        /// 第一步
        /// </summary>
        void FirstStep()
        {
            while (true)
            {
                if (bluetoothLeDevice != null)
                {
                    bluetoothLeDevice.Dispose();
                    bluetoothLeDevice = null;
                   
                    MethodInvoker action_s = delegate
                    {
                        textBox1.Text = "正在断开蓝牙连接.......";
                    };
                    textBox1.BeginInvoke(action_s);
                    Thread.Sleep(1000);
                }
                else
                {
                    //第一步
                    FindDevive();
                    break;
                }
            }         
        }


        /// <summary>
        /// 查找设备
        /// </summary>
        void FindDevive()
        {
            deviceInformation = new List<DeviceInformation>();
            MethodInvoker action_s = delegate
            {
                textBox1.Text += "正在搜素设备,请稍后\r\n";
            };
            textBox1.BeginInvoke(action_s);

            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };

            deviceWatcher = DeviceInformation.CreateWatcher(
                                BluetoothLEDevice.GetDeviceSelectorFromPairingState(false),//查找未配对蓝牙?
                                requestedProperties,
                                DeviceInformationKind.AssociationEndpoint);

            deviceWatcher.Added += DeviceWatcher_Added;
            deviceWatcher.Updated += DeviceWatcher_Updated;
            deviceWatcher.Removed += DeviceWatcher_Removed;
            deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
            deviceWatcher.Stopped += DeviceWatcher_Stopped;

            // Start the watcher.
            deviceWatcher.Start();

        }

        private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
        {
            if (getBB(args.Id))
            {
                MethodInvoker action = delegate
                {
                    deviceInformation.Add(args);

                    string mac = "" + args.Id.Split('-')[1];
                    string blenum = "" + mac.Replace(":", "").Substring(2);
                    blenum = "" + Convert.ToInt64(blenum, 16);
                    if (string.Compare(args.Id.Split('-')[1], pointIP) == 0)
                    {
                        //第二步:发现目标设备,开始匹配
                        LinkingDevice();
                    }
                };
                textBox1.BeginInvoke(action);
            }
        }


        /// <summary>
        /// 连接设备
        /// </summary>
        void LinkingDevice()
        {
            MethodInvoker action_s = delegate
            {
                textBox1.Text += "连接设备,请稍后----\r\n";
            };
            textBox1.BeginInvoke(action_s);
            foreach (var deviceinfo in deviceInformation)
            {
                MethodInvoker action_deviceinfo = delegate
                {
                    // textBox1.Text += "deviceinfo.Id+" + deviceinfo.Id + "---pointIP----+" + pointIP + "\r\n";
                };
                textBox1.BeginInvoke(action_deviceinfo);

                if (deviceinfo.Id.Contains("" + pointIP))
                {
                    MethodInvoker action = delegate
                    {
                        //3
                        textBox1.Text += "匹配IP蓝牙:" + deviceinfo.Id + ",请稍后\r\n\r\n";
                    };
                    textBox1.BeginInvoke(action);

                    mydeviceInformation = deviceinfo;
                }
            }

            if (null != mydeviceInformation)
            {
                ConnectDevice(mydeviceInformation);
            }
            else
            {
                MethodInvoker action_1 = delegate
                {
                    textBox1.Text += "连接失败,未搜索到该设备。\r\n";
                };
                textBox1.BeginInvoke(action_1);
            }

            deviceWatcher.Stop();
            deviceWatcher = null;
        }

        /// <summary>
        /// 写入信息
        /// </summary>
        /// <param name="hexstring"></param>
        async void BLE_HexString_Write(string hexstring)
        {
            var writer = new DataWriter();
            writer.WriteBytes(HexStringToByteArray(hexstring));

            GattCommunicationStatus sta1 = await gatt_write.WriteValueAsync(writer.DetachBuffer());
            if (sta1 == GattCommunicationStatus.Success)
            {
                //Console.WriteLine("Send :" + hexstring);
                MethodInvoker invoker = delegate {
                    textBox1.Text += (hexstring + "\r\n");
                };
                textBox1.BeginInvoke(invoker);
            }
        }


        /// <summary>
        /// 关闭设备
        /// </summary>
        void CloseDevice(string message)
        {
            ClearBluetoothLEDevice();
            gatt_write = null;
            mydeviceInformation = null;
            deviceInformation = new List<DeviceInformation>();

            ss = "";
            if (deviceWatcher!=null)
            { 
                deviceWatcher = null;
            }

            MethodInvoker invoker = delegate {
                textBox1.Text += (message + ":已断开设备连接。\r\n");
            };
            textBox1.BeginInvoke(invoker);
        }


        private void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
        {
            //throw new NotImplementedException();
           // CloseDevice("DeviceWatcher_Stopped");
        }
        private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
        {
            //throw new NotImplementedException();
        }
        private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
        {
            //throw new NotImplementedException();
           // CloseDevice("DeviceWatcher_Removed");
        }
        private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
        {
            //throw new NotImplementedException();
        }

        private bool ClearBluetoothLEDevice()
        {
            try
            {
                if (gatt_notify != null)
                    gatt_notify.ValueChanged -= S1_ValueChanged;

                if (bluetoothLeDevice != null)
                {
                    bluetoothLeDevice.Dispose();
                    bluetoothLeDevice = null;
                }

                return true;
            }
            catch (Exception ep1)
            {
                MethodInvoker invoker = delegate {
                    textBox1.Text += ep1.ToString();
                };
                textBox1.BeginInvoke(invoker);
            }
            return false;
        }
        string ss = "";
        private bool getBB(string s)
        {
            if (ss.Contains(s))
                return false;
            else
            {
                ss += s;
                return true;
            }
        }
        private delegate void InvokeCallback(string msg);
        async void ConnectDevice(DeviceInformation deviceInfo)
        {
          
            bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);

            GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync();
            if (result.Status == GattCommunicationStatus.Success)
            {
                MethodInvoker invoker_Status = delegate
                {
                    textBox1.Text += "result.Status:" + result.Status + "\r\n";
                };
                textBox1.BeginInvoke(invoker_Status);
                IReadOnlyList<GattDeviceService> ses = result.Services;
                GattDeviceService service0 = result.Services[0];
                GattDeviceService service1 = result.Services[1];
                GattDeviceService service2 = result.Services[2];
                string svf = service2.Uuid.ToString();

                GattCharacteristicsResult result2 = await service2.GetCharacteristicsAsync();

                if (result2.Status == GattCommunicationStatus.Success)
                {
                    var characteristics = result2.Characteristics;
                    gatt_notify = characteristics[0];
                    gatt_write = characteristics[1];
                    string notiy = gatt_notify.CharacteristicProperties.ToString();//Notify
                    string write = gatt_write.CharacteristicProperties.ToString();//WriteWithoutResponse
                    string notify_uuid = gatt_notify.Uuid.ToString();
                    string write_uuid = gatt_write.Uuid.ToString();
                    GattCommunicationStatus status = await gatt_notify.WriteClientCharacteristicConfigurationDescriptorAsync(
                        GattClientCharacteristicConfigurationDescriptorValue.Notify);
                    gatt_notify.ValueChanged += S1_ValueChanged;
                    MethodInvoker invoker = delegate
                    {
                        textBox1.Text += "连接成功\r\n";
                    };
                    textBox1.BeginInvoke(invoker);
                }
                else
                {
                    MethodInvoker invoker = delegate
                    {
                        textBox1.Text += "连接失败\r\n";
                    };
                    textBox1.BeginInvoke(invoker);

                    if (gatt_notify != null)
                        gatt_notify.ValueChanged -= S1_ValueChanged;

                    if (bluetoothLeDevice != null)
                    {
                        bluetoothLeDevice.Dispose();
                        bluetoothLeDevice = null;
                    }
                    MessageBox.Show("不能重复运行软件,请关闭重新启动所有体验软件!", "系统消息");
                    Application.Exit();
                }
            }
        }
        /// <summary>
        /// 重启
        /// </summary>
        private void Restart()
        {
            Thread thtmp = new Thread(new ParameterizedThreadStart(run));
            object appName = Application.ExecutablePath;
            Thread.Sleep(3000);
            thtmp.Start(appName);

        }
        private void run(Object obj)
        {
            Process ps = new Process();
            ps.StartInfo.FileName = obj.ToString();
            ps.Start();
        }
        /// <summary>
        /// 获取到蓝牙数据后发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void S1_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            var reader = DataReader.FromBuffer(args.CharacteristicValue);
            byte[] vs = new byte[args.CharacteristicValue.Length];
            reader.ReadBytes(vs);
            string strData = ByteArrayToHexString(vs);
            MethodInvoker invoker = delegate
            {
                textBox1.Text += (strData + "\r\n");
                //之前程序运行到10分钟左右会崩溃 加入下面代码解决
                if (textBox1.Text.Length >= textBox1.MaxLength)
                {
                    textBox1.Text = "";
                }
                //发送接收到的数据到2D模拟灭火(本机)
                SendM("10004:" + strData);
            };
            textBox1.BeginInvoke(invoker);
        }

        /// <summary>
        /// 字符串转字节数组
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            }

            return buffer;
        }

        /// <summary>
        /// 字节数组转字符串
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ByteArrayToHexString(byte[] data)
        {
            if (data == null)
                return "";
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
            }
            return sb.ToString().ToUpper();
        }

        /*----------UDP------------*/
        public string EncodingMOD = "UTF8";
        public static Encoding ecd;
        int recv;
        byte[] data = new byte[4096];
        public static EndPoint Remote;
        public static Socket newsock;
        public static string localip;
        Thread rcv;
        Thread threadSend;
        public string recivestring = "";
        public void UdpPeer(int port)
        {
            uint IOC_IN = 0x80000000;
            uint IOC_VENDOR = 0x18000000;
            uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
            if (EncodingMOD == "UTF8" || EncodingMOD == "utf8")
            {
                ecd = Encoding.UTF8;
            }
            else if (EncodingMOD == "ASCII" || EncodingMOD == "ascii")
            {
                ecd = Encoding.ASCII;
            }
            else
            {
                ecd = Encoding.Default;
            }
            string hostName = Dns.GetHostName();//本机名 
            IPAddress[] addressList = Dns.GetHostAddresses(hostName);//会返回所有地址,包括IPv4和IPv6 
            localip = addressList[0].ToString();
            localip = "127.0.0.1";// textBox4.Text.Trim();
            MethodInvoker action_s = delegate
            {
                textBox1.Text = ("连接的主机IP地址:" + localip + "\r\n");
            };
            textBox1.BeginInvoke(action_s);

            //得到本机IP,设置UDP端口号         
            IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
            newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            newsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            newsock.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
            //绑定网络地址
            newsock.Bind(ip);
            IPEndPoint sender = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2345);
            Remote = (EndPoint)(sender);
            rcv = new Thread(new ThreadStart(RecTread));
            rcv.Start();
        }

        void SendTread()
        {
            while (true)
            {
                SendM("");
                Thread.Sleep(50000);
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        Queue<string> queueRec = new Queue<string>();

        public void RecTread()
        {
            while (true)
            {
                //if (isStop) return;

                data = new byte[4096];
                if (EncodingMOD == "UTF8" || EncodingMOD == "utf8")
                {
                    ecd = Encoding.UTF8;
                }
                else if (EncodingMOD == "ASCII" || EncodingMOD == "ascii")
                {
                    ecd = Encoding.ASCII;
                }
                else
                {
                    ecd = Encoding.Default;
                }

                try
                {
                    //发送接收信息
                    recv = newsock.ReceiveFrom(data, ref Remote);
                    recivestring = ecd.GetString(data, 0, recv);
                }
                catch (Exception ex)
                {

                    MethodInvoker action_ex = delegate
                    {
                        textBox1.Text = ("ex:" + ex.Message + "\r\n");
                    };
                    textBox1.BeginInvoke(action_ex);
                }

                MethodInvoker action_s = delegate
                {
                    textBox1.Text = ("recivestring:" + recivestring + "\r\n");
                };
                textBox1.BeginInvoke(action_s);


                if (!queueRec.Contains(recivestring))
                {
                    queueRec.Enqueue(recivestring);
                }
            }
        }

        public static void mSendMessage(string ip, int port, string Mes)
        {
            byte[] senddata = ecd.GetBytes(Mes);
            IPEndPoint sender = new IPEndPoint(IPAddress.Parse(ip), port);
            EndPoint mRemote = (EndPoint)(sender);
            newsock.SendTo(senddata, senddata.Length, SocketFlags.None, mRemote);
        }

        /// <summary>
        /// 本机发送消息
        /// </summary>
        /// <param name="Mes"></param>
        public static void SendM(string Mes)
        {
            byte[] senddata = ecd.GetBytes(Mes);
            if (newsock != null)
            {
                try
                {
                    newsock.SendTo(senddata, senddata.Length, SocketFlags.None, Remote);
                }
                catch
                {

                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("真的要退出程序吗?", "退出程序", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                QuiteUDP();
                Application.Exit();
            }
            else
            {
                e.Cancel = true;
            }
        }

        /// <summary>
        /// 结束UDP
        /// </summary>
        public void QuiteUDP()
        {
            if (newsock != null)
            {
                newsock.Close();
                newsock = null;
                rcv.Abort();
                rcv = null;
                threadSend.Abort();
                threadSend = null;
                threadMain.Abort();
                threadMain = null;
            }
        }

    }
}

2.unity实现接收WindowsForms发过来的数据

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;
using System;
using System.Text;
using System.Threading;

public class UdpClient
{
    public static string EncodingMOD = "UTF8";
    public static Encoding ecd;
    public static int recv;
    public static byte[] data = new byte[4096];
    public static EndPoint Remote;
    public static Socket newsock;
    public static string localip;
    public static Thread rcv;
    //	bool recivebyte = false;
    public static string recivestring = "";

    public static void UdpPeer(int port)
    {
        uint IOC_IN = 0x80000000;
        uint IOC_VENDOR = 0x18000000;
        uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
        if (EncodingMOD == "UTF8" || EncodingMOD == "utf8")
        {
            ecd = Encoding.UTF8;
        }
        else if (EncodingMOD == "ASCII" || EncodingMOD == "ascii")
        {
            ecd = Encoding.ASCII;
        }
        else
        {
            ecd = Encoding.Default;
        }
        string hostName = Dns.GetHostName();//本机名 
        IPAddress[] addressList = Dns.GetHostAddresses(hostName);//会返回所有地址,包括IPv4和IPv6 
        localip = addressList[0].ToString();
        //得到本机IP,设置UDP端口号         
        IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
        newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        newsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        newsock.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
        //绑定网络地址
        newsock.Bind(ip);
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        Remote = (EndPoint)(sender);
        rcv = new Thread(new ThreadStart(RecTread));
        rcv.Start();
    }

    public static void RecTread()
    {
        while (true)
        {
            data = new byte[4096];
            if (EncodingMOD == "UTF8" || EncodingMOD == "utf8")
            {
                ecd = Encoding.UTF8;
            }
            else if (EncodingMOD == "ASCII" || EncodingMOD == "ascii")
            {
                ecd = Encoding.ASCII;
            }
            else
            {
                ecd = Encoding.Default;
            }
            //接收信息
            recv = newsock.ReceiveFrom(data, ref Remote);
            recivestring = ecd.GetString(data, 0, recv);
        }
    }

    public static void QuiteUDP()
    {
        if (newsock != null)
        {
            newsock.Close();
            rcv.Abort();
        }
    }

    public void OnApplicationQuit()
    {
        if (newsock != null)
        {
            newsock.Close();
            rcv.Abort();
        }
    }
    /// <summary>
    /// 发送数据
    /// </summary>
    /// <param name="ip">127.0.0.1</param>
    /// <param name="port">2345</param>
    /// <param name="Mes">发送的数据内容</param>
	public static void mSendMessage(string ip, int port, string Mes)
    {
        byte[] senddata = ecd.GetBytes(Mes);
        IPEndPoint sender = new IPEndPoint(IPAddress.Parse(ip), port);
        EndPoint mRemote = sender;
        newsock.SendTo(senddata, senddata.Length, SocketFlags.None, mRemote);
    }
    public static void SendM(string Mes)
    {
        byte[] senddata = ecd.GetBytes(Mes);
        if (newsock != null)
        {
            try
            {
                newsock.SendTo(senddata, senddata.Length, SocketFlags.None, Remote);
            }
            catch
            {

            }
        }
    }
}

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值