/// <summary> /// Analyze the received Bluetooth LE advertisement, and either add a new unique /// beacon to the list of known beacons, or update a previously known beacon /// with the new information. /// </summary> /// <param name="btAdv">Bluetooth advertisement to parse, as received from /// the Windows Bluetooth LE API.</param> private void ReceivedAdvertisement(BLEAdvertisementPacket btAdv) { if (btAdv == null) { return; } // Check if we already know this bluetooth address foreach (var bluetoothBeacon in BluetoothBeacons) { if (bluetoothBeacon.BluetoothAddress == btAdv.BluetoothAddress) { // We already know this beacon // Update / Add info to existing beacon bluetoothBeacon.UpdateBeacon(btAdv); return; } } // Beacon was not yet known - add it to the list. var newBeacon = new Beacon(btAdv); BluetoothBeacons.Add(newBeacon); BeaconAdded?.Invoke(this, newBeacon); }
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); }
/// <summary> /// Convert the Windows specific Bluetooth LE advertisment data to the universal cross-platform structure /// used by the Universal Beacon Library. /// </summary> /// <param name="args">Windows Bluetooth LE advertisment data to convert to cross-platform format.</param> /// <returns>Packet data converted to cross-platform format.</returns> public static BLEAdvertisementPacket ToUniversalBLEPacket(this BluetoothLEAdvertisementReceivedEventArgs args) { var packet = new BLEAdvertisementPacket { Timestamp = args.Timestamp, BluetoothAddress = args.BluetoothAddress, RawSignalStrengthInDBm = args.RawSignalStrengthInDBm, AdvertisementType = (BLEAdvertisementType)args.AdvertisementType, Advertisement = args.Advertisement.ToUniversalAdvertisement() }; return(packet); }
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result) { base.OnScanResult(callbackType, result); switch (result.Device.Type) { case BluetoothDeviceType.Le: case BluetoothDeviceType.Unknown: try { var p = new BLEAdvertisementPacket { // address will be in the form "D1:36:E6:9D:46:52" BluetoothAddress = result.Device.Address.ToNumericAddress(), RawSignalStrengthInDBm = (short)result.Rssi, // TODO: probably needs adjustment Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(result.TimestampNanos / 1000), // TODO: validate this AdvertisementType = (BLEAdvertisementType)result.ScanRecord.AdvertiseFlags, Advertisement = new BLEAdvertisement { LocalName = result.ScanRecord.DeviceName } }; if (result.ScanRecord.ServiceUuids != null) { foreach (var svc in result.ScanRecord.ServiceUuids) { var guid = new Guid(svc.Uuid.ToString()); var data = result.ScanRecord.GetServiceData(svc); p.Advertisement.ServiceUuids.Add(guid); } } var recordData = result.ScanRecord.GetBytes(); var rec = RecordParser.Parse(recordData); foreach (var curRec in rec) { if (curRec is BLEManufacturerData md) { p.Advertisement.ManufacturerData.Add(md); } if (curRec is BLEAdvertisementDataSection sd) { p.Advertisement.DataSections.Add(sd); } } OnAdvertisementPacketReceived?.Invoke(this, new BLEAdvertisementPacketArgs(p)); } catch (Exception) { // TODO } break; default: break; } // result.Device; }