Skip to content

Commit

Permalink
Merge pull request #4 from kobush/master
Browse files Browse the repository at this point in the history
Adds ProximityBeaconFrame. Thanks for the pull request and the high quality code! Sorry that it took quite some time, but there should be no issues with the code that I can see! Will update the lib on NuGet + the example app in the store as soon as possible.
  • Loading branch information
andijakl committed Jan 8, 2017
2 parents ea73574 + e8e6b46 commit de7482e
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 6 deletions.
11 changes: 7 additions & 4 deletions UniversalBeaconLibrary/Beacon/Beacon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions UniversalBeaconLibrary/Beacon/BeaconFrameHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
115 changes: 115 additions & 0 deletions UniversalBeaconLibrary/Beacon/ProximityBeaconFrame.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
1 change: 1 addition & 0 deletions UniversalBeaconLibrary/UniversalBeaconLibrary.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
<Compile Include="Beacon\BeaconFrameBase.cs" />
<Compile Include="Beacon\BeaconFrameHelper.cs" />
<Compile Include="Beacon\BeaconManager.cs" />
<Compile Include="Beacon\ProximityBeaconFrame.cs" />
<Compile Include="Beacon\TlmEddystoneFrame.cs" />
<Compile Include="Beacon\UidEddystoneFrame.cs" />
<Compile Include="Beacon\UnknownBeaconFrame.cs" />
Expand Down
2 changes: 2 additions & 0 deletions WindowsBeacons/Converter/BeaconFrameTypeToTextConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions WindowsBeacons/FrameTemplateSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);

Expand Down
61 changes: 59 additions & 2 deletions WindowsBeacons/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
mc:Ignorable="d"
RequestedTheme="Light">


<Page.Resources>
<converter:BeaconTypeToTextConverter x:Key="BeaconTypeToTextConverter"/>
<converter:BeaconFrameTypeToTextConverter x:Key="BeaconFrameTypeToTextConverter"/>
Expand Down Expand Up @@ -169,6 +168,63 @@
</DataTemplate>


<DataTemplate x:Key="ProximityBeaconFrameTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ElementName=MainPageItem, Path=LeftColumnWidth, Converter={StaticResource IntToGridLengthConverter}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- Frame type -->
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Text="{Binding Converter={StaticResource BeaconFrameTypeToTextConverter}}"
TextWrapping="Wrap"
Style="{StaticResource FrameTypeTextBlockStyle}"/>
<!-- Uuid -->
<TextBlock Grid.Row="1" Grid.Column="0"
x:Uid="Uuid"
TextWrapping="Wrap"
Style="{StaticResource BoldInfoTextBlockStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Text="{Binding UuidAsString, Mode=OneWay}"
TextWrapping="Wrap"
Style="{StaticResource InfoTextBlockStyle}"/>
<!-- Major -->
<TextBlock Grid.Row="2" Grid.Column="0"
x:Uid="Major"
TextWrapping="Wrap"
Style="{StaticResource BoldInfoTextBlockStyle}"/>
<TextBlock Grid.Row="2" Grid.Column="1"
Text="{Binding MajorAsString, Mode=OneWay}"
TextWrapping="Wrap"
Style="{StaticResource InfoTextBlockStyle}"/>
<!-- Minor -->
<TextBlock Grid.Row="3" Grid.Column="0"
x:Uid="Minor"
TextWrapping="Wrap"
Style="{StaticResource BoldInfoTextBlockStyle}"/>
<TextBlock Grid.Row="3" Grid.Column="1"
Text="{Binding MinorAsString, Mode=OneWay}"
TextWrapping="Wrap"
Style="{StaticResource InfoTextBlockStyle}"/>
<!-- TX Power -->
<TextBlock Grid.Row="4" Grid.Column="0"
x:Uid="TxPower"
TextWrapping="Wrap"
Style="{StaticResource BoldInfoTextBlockStyle}"/>
<TextBlock Grid.Row="4" Grid.Column="1"
Text="{Binding TxPower, Mode=OneWay}"
TextWrapping="Wrap"
Style="{StaticResource InfoTextBlockStyle}"/>
</Grid>
</DataTemplate>

<DataTemplate x:Key="UnknownBeaconFrameTemplate">
<Grid>
<Grid.ColumnDefinitions>
Expand Down Expand Up @@ -201,7 +257,8 @@
UrlEddystoneFrameTemplate="{StaticResource UrlEddystoneFrameTemplate}"
TlmEddystoneFrameTemplate="{StaticResource TlmEddystoneFrameTemplate}"
UidEddystoneFrameTemplate="{StaticResource UidEddystoneFrameTemplate}"
UnknownBeaconFrameTemplate="{StaticResource UnknownBeaconFrameTemplate}"/>
ProximityBeaconFrameTemplate="{StaticResource ProximityBeaconFrameTemplate}"
UnknownBeaconFrameTemplate="{StaticResource UnknownBeaconFrameTemplate}" />

<DataTemplate x:Name="BeaconInfoTemplate">
<Grid>
Expand Down
12 changes: 12 additions & 0 deletions WindowsBeacons/Strings/de-DE/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ Stelle sicher, dass dein Gerät Bluetooth Smart (LE) unterstützt und dass Bluet
<data name="LibraryUrlButton.NavigateUri" xml:space="preserve">
<value>https://github.com/andijakl/universal-beacon</value>
</data>
<data name="Major.Text" xml:space="preserve">
<value>Major:</value>
</data>
<data name="Minor.Text" xml:space="preserve">
<value>Minor:</value>
</data>
<data name="NamespaceId.Text" xml:space="preserve">
<value>Namespace ID: </value>
</data>
Expand Down Expand Up @@ -224,12 +230,18 @@ Stelle sicher, dass dein Gerät Bluetooth Smart (LE) unterstützt und dass Bluet
<data name="TwitterButton.NavigateUri" xml:space="preserve">
<value>https://twitter.com/andijakl</value>
</data>
<data name="TxPower.Text" xml:space="preserve">
<value>TX Power:</value>
</data>
<data name="Updated.Text" xml:space="preserve">
<value>Letztes Update: </value>
</data>
<data name="Url.Text" xml:space="preserve">
<value>URL: </value>
</data>
<data name="Uuid.Text" xml:space="preserve">
<value>UUID:</value>
</data>
<data name="Version.Text" xml:space="preserve">
<value>Version: </value>
</data>
Expand Down
9 changes: 9 additions & 0 deletions WindowsBeacons/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,15 @@ Make sure your device supports Bluetooth Smart (LE) and that Bluetooth is activa
<data name="LibraryUrlButton.NavigateUri" xml:space="preserve">
<value>https://github.com/andijakl/universal-beacon</value>
</data>
<data name="Major.Text" xml:space="preserve">
<value>Major:</value>
</data>
<data name="MajorId.Text" xml:space="preserve">
<value>Major ID</value>
</data>
<data name="Minor.Text" xml:space="preserve">
<value>Minor:</value>
</data>
<data name="MinorId.Text" xml:space="preserve">
<value>Minor ID</value>
</data>
Expand Down Expand Up @@ -230,6 +236,9 @@ Make sure your device supports Bluetooth Smart (LE) and that Bluetooth is activa
<data name="TwitterButton.NavigateUri" xml:space="preserve">
<value>https://twitter.com/andijakl</value>
</data>
<data name="TxPower.Text" xml:space="preserve">
<value>TX Power:</value>
</data>
<data name="Updated.Text" xml:space="preserve">
<value>Updated: </value>
</data>
Expand Down

0 comments on commit de7482e

Please sign in to comment.