Scanning for beacons using universal beacon library

柔情痞子 提交于 2019-12-13 03:21:29

问题


I am trying to implement a mobile app (on iPhone) that just scans for beacons and displays a notification for each one. I am a noob with beacons/bluetooth.

I implemented it using the universal beacon library (https://github.com/andijakl/universal-beacon) and i've attached my ios bluetooth implementation.

my problem is that i receive about 12 beacon added events even though i only have two (I assume it is picking up all my other bluetooth devices). I also only receive the local name in the advertisement_received event.

My questions are:

  1. how do I distinguish that it is a beacon being added?
  2. how do i get the unique id an url from the beacon? (they are kontakt beacons)

Thanks for any help.

My beacon service:

    public BeaconService()
    {
        // get the platform-specific provider
        var provider = RootWorkItem.Services.Get<IBluetoothPacketProvider>();

        if (null != provider)
        {
            // create a beacon manager, giving it an invoker to marshal collection changes to the UI thread
            _manager = new BeaconManager(provider, Device.BeginInvokeOnMainThread);
            _manager.Start();

            _manager.BeaconAdded += _manager_BeaconAdded;
            provider.AdvertisementPacketReceived += Provider_AdvertisementPacketReceived;
        }
    }

My ios bluetooth implementation:

public class iOSBluetoothPacketProvider : CocoaBluetoothPacketProvider { }

public class CocoaBluetoothPacketProvider : NSObject, IBluetoothPacketProvider
{
    public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
    public event EventHandler<BTError> WatcherStopped;

    private readonly CocoaBluetoothCentralDelegate centralDelegate;
    private readonly CBCentralManager central;

    public CocoaBluetoothPacketProvider()
    {
        Debug.WriteLine("BluetoothPacketProvider()");

        centralDelegate = new CocoaBluetoothCentralDelegate();
        central = new CBCentralManager(centralDelegate, null);
    }

    private void ScanCallback_OnAdvertisementPacketReceived(object sender, BLEAdvertisementPacketArgs e)
    {
        AdvertisementPacketReceived?.Invoke(this, e);
    }

    public void Start()
    {
        Debug.WriteLine("BluetoothPacketProvider:Start()");
        centralDelegate.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;

        // Wait for the PoweredOn state

        //if(CBCentralManagerState.PoweredOn == central.State) {
        //    central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
        //                                               options: new PeripheralScanningOptions { AllowDuplicatesKey = false });
        //}
    }

    public void Stop()
    {
        Debug.WriteLine("BluetoothPacketProvider:Stop()");
        centralDelegate.OnAdvertisementPacketReceived -= ScanCallback_OnAdvertisementPacketReceived;

        central.StopScan();
        WatcherStopped?.Invoke(sender: this, e: new BTError(BTError.BluetoothError.Success));
    }
}
internal class CocoaBluetoothCentralDelegate : CBCentralManagerDelegate
{
    public event EventHandler<BLEAdvertisementPacketArgs> OnAdvertisementPacketReceived;

    #region CBCentralManagerDelegate

    public override void ConnectedPeripheral(CBCentralManager central, CBPeripheral peripheral)
    {
        Debug.WriteLine($"ConnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral})");
    }

    public override void DisconnectedPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
    {
        Debug.WriteLine($"DisconnectedPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
    }

    public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
    {
        Debug.WriteLine($"Cocoa peripheral {peripheral}");
        Debug.WriteLine($"Cocoa advertisementData {advertisementData}");
        Debug.WriteLine($"Cocoa RSSI {RSSI}");

        var bLEAdvertisementPacket = new BLEAdvertisementPacket()
        {
            Advertisement = new BLEAdvertisement()
            {
                LocalName = peripheral.Name,
                ServiceUuids = new List<Guid>(),
                DataSections = new List<BLEAdvertisementDataSection>(),
                ManufacturerData = new List<BLEManufacturerData>()
            },
            AdvertisementType = BLEAdvertisementType.ScanResponse,
            BluetoothAddress = (ulong)peripheral.Identifier.GetHashCode(),
            RawSignalStrengthInDBm = RSSI.Int16Value,
            Timestamp = DateTimeOffset.Now
        };

        //https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataserviceuuidskey
        //if (advertisementData.ContainsKey(CBAdvertisement.DataServiceUUIDsKey))
        //{
        //    bLEAdvertisementPacket.Advertisement.ServiceUuids.Add(
        //        item: new BLEManufacturerData(packetType: BLEPacketType.UUID16List,
        //                                      data: (advertisementData[CBAdvertisement.DataServiceUUIDsKey])));
        //}

        //https://developer.apple.com/documentation/corebluetooth/cbadvertisementdataservicedatakey
        //if (advertisementData.ContainsKey(CBAdvertisement.DataServiceDataKey))
        //{
        //    bLEAdvertisementPacket.Advertisement.DataSections.Add(
        //        item: new BLEManufacturerData(packetType: BLEPacketType.ServiceData,
        //                                      data: advertisementData[CBAdvertisement.DataServiceDataKey]));
        //}

        //https://developer.apple.com/documentation/corebluetooth/cbadvertisementdatamanufacturerdatakey
        if (advertisementData.ContainsKey(CBAdvertisement.DataManufacturerDataKey))
        {
            bLEAdvertisementPacket.Advertisement.ManufacturerData.Add(
                item: new BLEManufacturerData(packetType: BLEPacketType.ManufacturerData,
                                              data: (advertisementData[CBAdvertisement.DataManufacturerDataKey]
                                                     as NSData).ToArray()));
        }

        // Missing CBAdvertisement.DataTxPowerLevelKey

        var bLEAdvertisementPacketArgs = new BLEAdvertisementPacketArgs(data: bLEAdvertisementPacket);
        OnAdvertisementPacketReceived?.Invoke(this, bLEAdvertisementPacketArgs);
    }

    public override void FailedToConnectPeripheral(CBCentralManager central, CBPeripheral peripheral, NSError error)
    {
        Debug.WriteLine($"FailedToConnectPeripheral(CBCentralManager central, CBPeripheral {peripheral}, NSError {error})");
    }

    public override void UpdatedState(CBCentralManager central)
    {
        switch (central.State)
        {
            case CBCentralManagerState.Unknown:
                Debug.WriteLine("CBCentralManagerState.Unknown");
                break;
            case CBCentralManagerState.Resetting:
                Debug.WriteLine("CBCentralManagerState.Resetting");
                break;
            case CBCentralManagerState.Unsupported:
                Debug.WriteLine("CBCentralManagerState.Unsupported");
                break;
            case CBCentralManagerState.Unauthorized:
                Debug.WriteLine("CBCentralManagerState.Unauthorized");
                break;
            case CBCentralManagerState.PoweredOff:
                Debug.WriteLine("CBCentralManagerState.PoweredOff");
                break;
            case CBCentralManagerState.PoweredOn:
                Debug.WriteLine("CBCentralManagerState.PoweredOn");
                central.ScanForPeripherals(peripheralUuids: new CBUUID[] { },
                                                           options: new PeripheralScanningOptions { AllowDuplicatesKey = true });
                break;
            default:
                throw new NotImplementedException();
        }
    }

    public override void WillRestoreState(CBCentralManager central, NSDictionary dict)
    {
        Debug.WriteLine($"WillRestoreState(CBCentralManager central, NSDictionary {dict})");
    }

    #endregion CBCentralManagerDelegate
}

回答1:


So in case anyone is looking for this. The universal beacon library does not have an ios implementation that converts the ios packets to the universal packets. This need to be implemented.

  1. how do I distinguish that it is a beacon being added?

I look for the Eddystone packets and if found I add to the observable list.

  1. how do i get the unique id an url from the beacon? (they are kontakt beacons)

You need to loop through the advertisementData sent with the advertisement and create a BLEAdvertisementDataSection. copy the frame data as NSData.



来源:https://stackoverflow.com/questions/53990097/scanning-for-beacons-using-universal-beacon-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!