diff --git a/UniversalBeaconLibrary/Beacon/Beacon.cs b/UniversalBeaconLibrary/Beacon/Beacon.cs
index 05995d6..887f43b 100644
--- a/UniversalBeaconLibrary/Beacon/Beacon.cs
+++ b/UniversalBeaconLibrary/Beacon/Beacon.cs
@@ -225,20 +225,23 @@ public void UpdateBeacon(BluetoothLEAdvertisementReceivedEventArgs btAdv)
// 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)
+ if (BeaconFrameHelper.IsProximityBeaconPayload(manufacturerData.CompanyId, manufacturerDataArry))
{
BeaconType = BeaconTypeEnum.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].Payload = manufacturerDataArry;
+ BeaconFrames[0].Update(beaconFrame);
}
else
{
- BeaconFrames.Add(new UnknownBeaconFrame(manufacturerDataArry));
+ BeaconFrames.Add(beaconFrame);
}
}
}
diff --git a/UniversalBeaconLibrary/Beacon/BeaconFrameHelper.cs b/UniversalBeaconLibrary/Beacon/BeaconFrameHelper.cs
index be06638..d865575 100644
--- a/UniversalBeaconLibrary/Beacon/BeaconFrameHelper.cs
+++ b/UniversalBeaconLibrary/Beacon/BeaconFrameHelper.cs
@@ -107,5 +107,13 @@ public static byte[] CreateEddystoneHeader(EddystoneFrameType eddystoneType)
{
return new byte[] {0xAA, 0xFE, (byte)eddystoneType};
}
+
+ public static bool IsProximityBeaconPayload(ushort companyId, byte[] manufacturerData)
+ {
+ return companyId == ProximityBeaconFrame.CompanyId &&
+ manufacturerData.Length >= 23 &&
+ manufacturerData[0] == ProximityBeaconFrame.DataType &&
+ manufacturerData[1] == ProximityBeaconFrame.DataLength;
+ }
}
}
diff --git a/UniversalBeaconLibrary/Beacon/ProximityBeaconFrame.cs b/UniversalBeaconLibrary/Beacon/ProximityBeaconFrame.cs
new file mode 100644
index 0000000..169549c
--- /dev/null
+++ b/UniversalBeaconLibrary/Beacon/ProximityBeaconFrame.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace UniversalBeaconLibrary.Beacon
+{
+ public class ProximityBeaconFrame : BeaconFrameBase
+ {
+ public const ushort CompanyId = 0x004C;
+ public const byte DataType = 0x02;
+ public const byte DataLength = 0x15;
+
+ private Guid _uuid;
+ private ushort _major;
+ private ushort _minor;
+ private sbyte _txPower;
+
+ public ProximityBeaconFrame(byte[] payload)
+ : base(payload)
+ {
+ ParsePayload();
+ }
+
+ public string UuidAsString => Uuid.ToString("D");
+
+ public Guid Uuid
+ {
+ get { return _uuid; }
+ set
+ {
+ if (_uuid == value) return;
+ _uuid = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(UuidAsString));
+ }
+ }
+
+ public string MajorAsString => Major.ToString("x4");
+
+ public ushort Major
+ {
+ get { return _major; }
+ set
+ {
+ if (_major == value) return;
+ _major = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(MajorAsString));
+ }
+ }
+
+ public string MinorAsString => Minor.ToString("x4");
+
+ public ushort Minor
+ {
+ get { return _minor; }
+ set
+ {
+ if (_minor == value) return;
+ _minor = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(MinorAsString));
+ }
+ }
+
+ public sbyte TxPower
+ {
+ get { return _txPower; }
+ set
+ {
+ if (_txPower == value) return;
+ _txPower = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private void ParsePayload()
+ {
+ var dataType = Payload[0];
+ var dataLength = Payload[1];
+
+ if (dataType != DataType || dataLength != DataLength)
+ throw new InvalidOperationException();
+
+ // need to swap to big-endian
+ var uuidBytes = new byte[16];
+ if (BitConverter.IsLittleEndian)
+ {
+ Array.ConstrainedCopy(Payload, 2, uuidBytes, 0, 16);
+ Array.Reverse(uuidBytes, 0, 4);
+ Array.Reverse(uuidBytes, 4, 2);
+ Array.Reverse(uuidBytes, 6, 2);
+ }
+ Uuid = new Guid(uuidBytes);
+
+ var majorBytes = new byte[2];
+ Array.ConstrainedCopy(Payload, 18, majorBytes, 0, 2);
+ if (BitConverter.IsLittleEndian)
+ Array.Reverse(majorBytes);
+ Major = BitConverter.ToUInt16(majorBytes,0);
+
+ var minorBytes = new byte[2];
+ Array.ConstrainedCopy(Payload, 20, minorBytes, 0, 2);
+ if (BitConverter.IsLittleEndian)
+ Array.Reverse(minorBytes);
+ Minor = BitConverter.ToUInt16(minorBytes, 0);
+
+ TxPower = (sbyte) Payload[22];
+ }
+
+ public override void Update(BeaconFrameBase otherFrame)
+ {
+ base.Update(otherFrame);
+ ParsePayload();
+ }
+ }
+}
diff --git a/UniversalBeaconLibrary/UniversalBeaconLibrary.csproj b/UniversalBeaconLibrary/UniversalBeaconLibrary.csproj
index 30188e4..6aabb84 100644
--- a/UniversalBeaconLibrary/UniversalBeaconLibrary.csproj
+++ b/UniversalBeaconLibrary/UniversalBeaconLibrary.csproj
@@ -118,6 +118,7 @@
+
diff --git a/WindowsBeacons/Converter/BeaconFrameTypeToTextConverter.cs b/WindowsBeacons/Converter/BeaconFrameTypeToTextConverter.cs
index 898a8f2..7c6820d 100644
--- a/WindowsBeacons/Converter/BeaconFrameTypeToTextConverter.cs
+++ b/WindowsBeacons/Converter/BeaconFrameTypeToTextConverter.cs
@@ -33,6 +33,8 @@ public object Convert(object value, Type targetType, object parameter, string la
return "UID Frame";
if (value is UrlEddystoneFrame)
return "URL Frame";
+ if (value is ProximityBeaconFrame)
+ return "Proximity Frame";
return null;
}
diff --git a/WindowsBeacons/FrameTemplateSelector.cs b/WindowsBeacons/FrameTemplateSelector.cs
index cc3616b..f6a005e 100644
--- a/WindowsBeacons/FrameTemplateSelector.cs
+++ b/WindowsBeacons/FrameTemplateSelector.cs
@@ -30,6 +30,8 @@ public class FrameTemplateSelector : DataTemplateSelector
public DataTemplate UrlEddystoneFrameTemplate { get; set; }
+ public DataTemplate ProximityBeaconFrameTemplate { get; set; }
+
protected override DataTemplate SelectTemplateCore(object item)
{
var itemType = item.GetType();
@@ -42,6 +44,8 @@ protected override DataTemplate SelectTemplateCore(object item)
return UidEddystoneFrameTemplate;
if (itemType == typeof(UrlEddystoneFrame))
return UrlEddystoneFrameTemplate;
+ if (itemType == typeof (ProximityBeaconFrame))
+ return ProximityBeaconFrameTemplate;
return base.SelectTemplateCore(item);
diff --git a/WindowsBeacons/MainPage.xaml b/WindowsBeacons/MainPage.xaml
index 7d1773f..4372503 100644
--- a/WindowsBeacons/MainPage.xaml
+++ b/WindowsBeacons/MainPage.xaml
@@ -10,7 +10,6 @@
mc:Ignorable="d"
RequestedTheme="Light">
-
@@ -169,6 +168,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -201,7 +257,8 @@
UrlEddystoneFrameTemplate="{StaticResource UrlEddystoneFrameTemplate}"
TlmEddystoneFrameTemplate="{StaticResource TlmEddystoneFrameTemplate}"
UidEddystoneFrameTemplate="{StaticResource UidEddystoneFrameTemplate}"
- UnknownBeaconFrameTemplate="{StaticResource UnknownBeaconFrameTemplate}"/>
+ ProximityBeaconFrameTemplate="{StaticResource ProximityBeaconFrameTemplate}"
+ UnknownBeaconFrameTemplate="{StaticResource UnknownBeaconFrameTemplate}" />
diff --git a/WindowsBeacons/Strings/de-DE/Resources.resw b/WindowsBeacons/Strings/de-DE/Resources.resw
index b74d997..f2acd8a 100644
--- a/WindowsBeacons/Strings/de-DE/Resources.resw
+++ b/WindowsBeacons/Strings/de-DE/Resources.resw
@@ -179,6 +179,12 @@ Stelle sicher, dass dein Gerät Bluetooth Smart (LE) unterstützt und dass Bluet
https://github.com/andijakl/universal-beacon
+
+ Major:
+
+
+ Minor:
+
Namespace ID:
@@ -230,12 +236,18 @@ Stelle sicher, dass dein Gerät Bluetooth Smart (LE) unterstützt und dass Bluet
https://twitter.com/andijakl
+
+ TX Power:
+
Letztes Update:
URL:
+
+ UUID:
+
Version:
diff --git a/WindowsBeacons/Strings/en-US/Resources.resw b/WindowsBeacons/Strings/en-US/Resources.resw
index 2eba73d..407e328 100644
--- a/WindowsBeacons/Strings/en-US/Resources.resw
+++ b/WindowsBeacons/Strings/en-US/Resources.resw
@@ -179,9 +179,15 @@ Make sure your device supports Bluetooth Smart (LE) and that Bluetooth is activa
https://github.com/andijakl/universal-beacon
+
+ Major:
+
Major ID
+
+ Minor:
+
Minor ID
@@ -236,6 +242,9 @@ Make sure your device supports Bluetooth Smart (LE) and that Bluetooth is activa
https://twitter.com/andijakl
+
+ TX Power:
+
Updated: