/// <summary> /// Received a new advertisement for this beacon. /// If the Bluetooth address of the new advertisement matches this beacon, /// it will parse the contents of the advertisement and extract known frames. /// </summary> /// <param name="btAdv">Bluetooth advertisement to parse, as received from /// the Windows Bluetooth LE API.</param> public void UpdateBeacon(BluetoothLEAdvertisementReceivedEventArgs btAdv) { if (btAdv == null) { return; } if (btAdv.BluetoothAddress != BluetoothAddress) { throw new BeaconException("Bluetooth address of beacon does not match - not updating beacon information"); } Rssi = btAdv.RawSignalStrengthInDBm; Timestamp = btAdv.Timestamp; //Debug.WriteLine($"Beacon advertisment detected (Strength: {Rssi}): Address: {BluetoothAddress}"); // Check if beacon advertisement contains any actual usable data if (btAdv.Advertisement == null) { return; } if (btAdv.Advertisement.ServiceUuids.Any()) { foreach (var serviceUuid in btAdv.Advertisement.ServiceUuids) { // If we have multiple service UUIDs and already recognized a beacon type, // don't overwrite it with another service Uuid. if (BeaconType == BeaconType.Unknown) { BeaconType = serviceUuid.ToBeaconType(); } } } else { //Debug.WriteLine("Bluetooth LE device does not send Service UUIDs"); } // Data sections if (btAdv.Advertisement.DataSections.Any()) { if (BeaconType == BeaconType.Eddystone) { ParseEddystoneData(btAdv); } else if (BeaconType == BeaconType.AXABeacon) { ParseAxaBeaconData(btAdv); } else if (BeaconType == BeaconType.Unknown) { // Unknown beacon type //Debug.WriteLine("\nUnknown beacon"); //foreach (var dataSection in btAdv.Advertisement.DataSections) //{ // Debug.WriteLine("Data section 0x: " + dataSection.DataType.ToString("X") + " = " + // BitConverter.ToString(dataSection.Data.ToArray())); //} } } // Manufacturer data - currently unused if (btAdv.Advertisement.ManufacturerData.Any()) { foreach (var manufacturerData in btAdv.Advertisement.ManufacturerData) { // Print the company ID + the raw data in hex format //var manufacturerDataString = $"0x{manufacturerData.CompanyId.ToString("X")}: {BitConverter.ToString(manufacturerData.Data.ToArray())}"; //Debug.WriteLine("Manufacturer data: " + manufacturerDataString); ManufacturerId = manufacturerData.CompanyId; var manufacturerDataArry = manufacturerData.Data.ToArray(); if (BeaconFrameHelper.IsProximityBeaconPayload(manufacturerData.CompanyId, manufacturerDataArry)) { //BeaconType = BeaconType.iBeacon; //Debug.WriteLine("iBeacon Frame: " + BitConverter.ToString(manufacturerDataArry)); var beaconFrame = new ProximityBeaconFrame(manufacturerDataArry); // Only one relevant data frame for iBeacons if (BeaconFrames.Any()) { BeaconFrames[0].Update(beaconFrame); } else { BeaconFrames.Add(beaconFrame); } } } } }
/// <summary> /// Received a new advertisement for this beacon. /// If the Bluetooth address of the new advertisement matches this beacon, /// it will parse the contents of the advertisement and extract known frames. /// </summary> /// <param name="btAdv">Bluetooth advertisement to parse, as received from /// the Windows Bluetooth LE API.</param> public void UpdateBeacon(BluetoothLEAdvertisementReceivedEventArgs btAdv) { if (btAdv == null) { return; } Rssi = btAdv.RawSignalStrengthInDBm; Timestamp = btAdv.Timestamp; //Debug.WriteLine($"Beacon advertisment detected (Strength: {Rssi}): Address: {BluetoothAddress}"); // Check if beacon advertisement contains any actual usable data if (btAdv.Advertisement == null) { return; } if (btAdv.Advertisement.ServiceUuids.Any()) { foreach (var serviceUuid in btAdv.Advertisement.ServiceUuids) { // If we have multiple service UUIDs and already recognized a beacon type, // don't overwrite it with another service Uuid. if (BeaconType == BeaconTypeEnum.Unknown) { BeaconType = serviceUuid.Equals(_eddystoneGuid) ? BeaconTypeEnum.Eddystone : BeaconTypeEnum.Unknown; } } } else { //Debug.WriteLine("Bluetooth LE device does not send Service UUIDs"); } // Data sections if (btAdv.Advertisement.DataSections.Any()) { if (BeaconType == BeaconTypeEnum.Eddystone) { // This beacon is according to the Eddystone specification - parse data ParseEddystoneData(btAdv); } } // Manufacturer data - currently unused if (btAdv.Advertisement.ManufacturerData.Any()) { foreach (var manufacturerData in btAdv.Advertisement.ManufacturerData) { // Print the company ID + the raw data in hex format //var manufacturerDataString = $"0x{manufacturerData.CompanyId.ToString("X")}: {BitConverter.ToString(manufacturerData.Data.ToArray())}"; //Debug.WriteLine("Manufacturer data: " + manufacturerDataString); var manufacturerDataArry = manufacturerData.Data.ToArray(); if (manufacturerData.CompanyId == 0x4C && manufacturerData.Data.Length >= 23 && manufacturerDataArry[0] == 0x02) { BeaconType = BeaconTypeEnum.iBeacon; //Debug.WriteLine("iBeacon Frame: " + BitConverter.ToString(manufacturerDataArry)); // Only one relevant data frame for iBeacons if (BeaconFrames.Any()) { BeaconFrames[0].Payload = manufacturerDataArry; } else { BeaconFrames.Add(new UnknownBeaconFrame(manufacturerDataArry)); } } else if ((manufacturerData.CompanyId & 0x150) == 0x150) { BluetoothAddress = GetEstimoteAddress(btAdv); if (BeaconFrames.Any()) { BeaconFrames[0].Payload = manufacturerDataArry; ((EstimoteNearableFrame)BeaconFrames[0]).ParsePayload(); } if (manufacturerDataArry[0] == 0x01) { BeaconType = BeaconTypeEnum.EstimoteNearable; EstimoteNearableFrame enf = new EstimoteNearableFrame(manufacturerDataArry); enf.PropertyChanged += Enf_PropertyChanged; if (!BeaconFrames.Any()) { BeaconFrames.Add(enf); } } else { BeaconType = BeaconTypeEnum.EstimoteStone; } } } } if (_bluetoothAddress == null) { BluetoothAddress = BitConverter.GetBytes(btAdv.BluetoothAddress); } //if (!CheckAddress(btAdv)) //{ // throw new BeaconException("Bluetooth address of beacon does not match - not updating beacon information"); //} }