微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C#调整BLE扫描窗口大小在Win10上不起作用

如何解决C#调整BLE扫描窗口大小在Win10上不起作用

我找到了调整BLE扫描窗口大小的解决方案:BLE Scan Interval Windows 10

但是,它不起作用。 扫描时会丢失许多信标。

using System;
using System.Linq;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Storage.Streams;

namespace BeaconExample
{
    using System;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Threading.Tasks;

    class BetterScanner
    {
        static Task task;
        /// <summary>
        /// The BLUetoOTH_FIND_RAdio_ParaMS structure facilitates enumerating installed Bluetooth radios.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct BLUetoOTH_FIND_RAdio_ParaM
        {
            internal UInt32 dwSize;
            internal void Initialize()
            {
                this.dwSize = (UInt32)Marshal.SizeOf(typeof(BLUetoOTH_FIND_RAdio_ParaM));
            }
        }

        /// <summary>
        /// Closes an open object handle.
        /// </summary>
        /// <param name="handle">[In] A valid handle to an open object.</param>
        /// <returns>If the function succeeds,the return value is nonzero. If the function fails,the return value is zero. To get extended error information,call GetLastError.</returns>
        [DllImport("Kernel32.dll",SetLastError = true)]
        static extern bool CloseHandle(IntPtr handle);

        /// <summary>
        /// Finds the first bluetooth radio present in device manager
        /// </summary>
        /// <param name="pbtfrp">Pointer to a BLUetoOTH_FIND_RAdio_ParaMS structure</param>
        /// <param name="phRadio">Pointer to where the first enumerated radio handle will be returned. When no longer needed,this handle must be closed via CloseHandle.</param>
        /// <returns>In addition to the handle indicated by phRadio,calling this function will also create a HBLUetoOTH_RAdio_FIND handle for use with the BluetoothFindNexTradio function.
        /// When this handle is no longer needed,it must be closed via the BluetoothFindRadioClose.
        /// Returns NULL upon failure. Call the GetLastError function for more information on the error. The following table describe common errors:</returns>
        [DllImport("irprops.cpl",SetLastError = true)]
        static extern IntPtr BluetoothFindFirsTradio(ref BLUetoOTH_FIND_RAdio_ParaM pbtfrp,out IntPtr phRadio);

        [StructLayout(LayoutKind.Sequential)]
        /*
        private struct LE_SCAN_REQUEST
        {
            internal UInt32 unkNown1;
            internal UInt32 scanType;
            internal UInt32 unkNown2;
            internal UInt16 scanInterval;
            internal UInt16 scanWindow;
            internal UInt32[] unkNown3;
        }
        */
        
        private struct LE_SCAN_REQUEST
        {
            internal int scanType;
            internal ushort scanInterval;
            internal ushort scanWindow;
        };
        

        [DllImport("kernel32.dll",ExactSpelling = true,SetLastError = true,CharSet = CharSet.Auto)]
        static extern bool DeviceIoControl(IntPtr hDevice,uint dwIoControlCode,ref LE_SCAN_REQUEST lpInBuffer,uint nInBufferSize,IntPtr lpOutBuffer,uint nOutBufferSize,out uint lpBytesReturned,IntPtr lpOverlapped);

        /// <summary>
        /// Starts scanning for LE devices.
        /// Example: BetterScanner.StartScanner(0,29,29)
        /// </summary>
        /// <param name="scanType">0 = Passive,1 = Active</param>
        /// <param name="scanInterval">Interval in 0.625 ms units</param>
        /// <param name="scanWindow">Window in 0.625 ms units</param>
        //public static void StartScanner(UInt32 scanType,UInt16 scanInterval,UInt16 scanWindow)
        public static void StartScanner(int scanType,ushort scanInterval,ushort scanWindow)
        {
            Action<object> action = (object obj) => {
                BLUetoOTH_FIND_RAdio_ParaM param = new BLUetoOTH_FIND_RAdio_param();
                param.Initialize();
                IntPtr handle;
                BluetoothFindFirsTradio(ref param,out handle);
                uint outsize;

                /*
                LE_SCAN_REQUEST req = new LE_SCAN_REQUEST
                {
                    unkNown1 = 0,scanType = scanType,unkNown2 = 0,scanInterval = scanInterval,scanWindow = scanWindow,unkNown3 = new UInt32[2] {0,0}
                };
                */
                 
                LE_SCAN_REQUEST req = new LE_SCAN_REQUEST
                {
                    scanType = scanType,};
                 
                bool ret = DeviceIoControl(handle,0x41118c,ref req,8,IntPtr.Zero,out outsize,IntPtr.Zero);
                Console.WriteLine("DeviceControl ret=" + ret);
                if(ret == false)
                {
                    var error = Marshal.GetLastWin32Error();
                    Console.WriteLine("The last Win32 Error was: " + error);
                }
            };
            task = new Task(action,"nothing");
            task.Start();
        }

        public static void StopScanner()
        {
           Console.WriteLine("BetterScanner Stop");
            task.Wait();
        }
    }

    class Program
    {
        const String UUID = "44790ba4-7eb3-4095-9e14-4b43ae67512b";
        const ushort MAJOR = 40033;
        const short RSSI = -40;

        private class BeaconData
        {
            public Guid Uuid { get; set; }
            public ushort Major { get; set; }
            public ushort Minor { get; set; }
            public byte Battery { get; set; }
            public static BeaconData FromBytes(byte[] bytes)
            {
                //if (bytes[0] != 0x02) { throw new ArgumentException("First byte in array was exptected to be 0x02","bytes"); }
                //if (bytes[1] != 0x15) { throw new ArgumentException("Second byte in array was expected to be 0x15","bytes"); }
                //if (bytes.Length != 23) { throw new ArgumentException("Byte array length was expected to be 23","bytes"); }
                return new BeaconData
                {
                    Uuid = new Guid(
                            BitConverter.ToInt32(bytes.Skip(2).Take(4).Reverse().ToArray(),0),BitConverter.ToInt16(bytes.Skip(6).Take(2).Reverse().ToArray(),BitConverter.ToInt16(bytes.Skip(8).Take(2).Reverse().ToArray(),bytes.Skip(10).Take(8).ToArray()),Major = BitConverter.ToUInt16(bytes.Skip(18).Take(2).Reverse().ToArray(),Minor = BitConverter.ToUInt16(bytes.Skip(20).Take(2).Reverse().ToArray(),Battery = (byte)((byte)bytes[23] & (byte)0x7F)
                };
            }
            public static BeaconData FromBuffer(IBuffer buffer)
            {
                var bytes = new byte[buffer.Length];
                if(bytes.Length !=24)
                {
                    return null;
                }
                using (var reader = DataReader.FromBuffer(buffer))
                {
                    reader.ReadBytes(bytes);
                }
                return BeaconData.FromBytes(bytes);
            }
        }

        static void Main(string[] args)
        {
            var watcher = new bluetoothleadvertisementwatcher();
            watcher.Received += Watcher_Received;
            //watcher.SignalStrengthFilter.InRangeThresholdindBm = RSSI;
            //watcher.SignalStrengthFilter.OutOfRangeThresholdindBm = RSSI-10;
            watcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(100);
            watcher.ScanningMode = BluetoothLEScanningMode.Passive;
            BetterScanner.StartScanner(0,29);
            watcher.Start();

            Console.WriteLine("Bluetooth LE Advertisement Watcher Started (Press ESC to exit)");
            while (Console.ReadKey().Key != ConsoleKey.Escape)
            {
            }
            watcher.Stop();
            BetterScanner.StopScanner();
            Console.WriteLine("Bluetooth LE Advertisement Watcher Stopped");
        }

        private static void Watcher_Received(bluetoothleadvertisementwatcher sender,BluetoothLEAdvertisementReceivedEventArgs args)
        {
            const ushort AppleCompanyId = 0x004C;
            Int16 RSSi = args.RawSignalStrengthInDBm;
            foreach (var adv in args.Advertisement.ManufacturerData.Where(x => x.CompanyId == AppleCompanyId))
            {
                var beaconData = BeaconData.FromBuffer(adv.Data);
                if(beaconData == null)
                {
                    continue;
                }
                if (beaconData.Uuid.ToString() == UUID && beaconData.Major == MAJOR)
                {
                    if (RSSi < RSSI)
                    {
                        Console.WriteLine("RSSI=" + RSSi+ ","+beaconData.Uuid+"_"+ beaconData.Major + "_" + beaconData.Minor);
                        continue;
                    }
                    Console.WriteLine(
                        "UUID={0},Major={1},Minor={2},Battery={3},RSSi={4}",beaconData.Uuid,beaconData.Major,beaconData.Minor,beaconData.Battery,args.RawSignalStrengthInDBm);
                }
            }
        }
    }
}

DeviceControl返回false,但最后一个错误代码为0,并且仍然进行延迟扫描。

DeviceControl ret=False
Bluetooth LE Advertisement Watcher Started (Press ESC to exit)
The last Win32 Error was: 0
RSSI=-50,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-50,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-51,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-73,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-50,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-70,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_18
RSSI=-50,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-74,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-48,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_6
RSSI=-64,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_18
RSSI=-75,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-76,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-67,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-78,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9
RSSI=-87,44790ba4-7eb3-4095-9e14-4b43ae67512b_40033_9

有40033_1、3、6、9、18个信标,但是某些信标在一段时间内未扫描。

广告间隔为700毫秒。

我应该检查什么?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。