KEMBAR78
Location Based Development Using Xamarin | PDF
Contents
•  An	
  example	
  app	
  
•  Using	
  Beacons	
  for	
  loca3on	
  detec3on	
  
•  What	
  are	
  Beacons?	
  
•  Which	
  provider	
  should	
  I	
  choose?	
  
•  Which	
  protocol	
  should	
  I	
  use?	
  
•  GeoLoca3on	
  vs	
  Beacons	
  
•  Configuring	
  beacons	
  
•  Development	
  Code	
  
•  The	
  reality	
  of	
  how	
  they	
  work	
  
The AudioPuppy App
•  Both	
  beacon	
  and	
  GPS	
  loca3on	
  detec3on	
  
	
  
•  Plays	
  audio	
  files	
  based	
  on	
  	
  
physical	
  loca3on	
  
Contents
•  An	
  example	
  app	
  
•  Using	
  Beacons	
  for	
  loca3on	
  detec3on	
  
•  What	
  are	
  Beacons?	
  
•  Which	
  provider	
  should	
  I	
  choose?	
  
•  Which	
  protocol	
  should	
  I	
  use?	
  
•  GeoLoca3on	
  vs	
  Beacons	
  
•  Configuring	
  beacons	
  
•  Development	
  Code	
  
•  The	
  reality	
  of	
  how	
  they	
  work	
  
What is a Beacon?
	
   	
   	
  Es*mote	
  specifica*ons	
  as	
  an	
  example	
  
It	
  is:	
  
•  A	
  small	
  computer 	
  32	
  bit	
  ARM	
  Cortex	
  MO	
  CPU 	
  	
  
•  With	
  other	
  components 	
  Es*mote	
  has	
  an	
  acceleromiter	
  	
  
	
   	
   	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  and	
  temperature	
  sensor.	
  
•  A	
  Radio 	
   	
  2.4	
  Ghz	
  using	
  Bluetooth	
  4.0	
  SMART	
  
•  A	
  baJery 	
   	
  CR2477	
  -­‐	
  3	
  years	
  on	
  default	
  seLngs.	
  
•  A	
  cover 	
   	
  Sealed	
  plas*c.	
  
•  Expect	
  a	
  signal	
  range	
  of	
  	
  40-­‐50	
  meters	
  
•  No	
  ‘pairing’	
  required	
  
•  Smartphones	
  can	
  listen	
  to	
  many	
  at	
  the	
  same	
  3me	
  
A	
  Beacon	
  is	
  a	
  Bluetooth	
  Low	
  Energy	
  (BLE)	
  devices.	
  	
  
Choosing a beacon manufacturer
They	
  must:	
  
•  support	
  the	
  beacon	
  protocol	
  you	
  with	
  
to	
  use.	
  
•  have	
  appropriate	
  baJery	
  life	
  
•  baJery	
  life	
  3	
  months	
  or	
  3	
  years?	
  
•  do	
  they	
  have	
  baJery	
  conserva3on	
  
op3ons	
  
•  no3fica3on	
  of	
  impending	
  baJery	
  expiry	
  
•  have	
  an	
  appropriate	
  form	
  factor.	
  
Consider:	
  
•  physical	
  size	
  
•  weather	
  resistant	
  
•  can	
  be	
  physically	
  secured	
  (to	
  prevent	
  
theY)	
  
•  blend	
  with	
  intended	
  environment	
  
•  be	
  configurable:	
  
•  Most	
  have	
  base	
  signal	
  configura3on	
  
(frequency	
  and	
  strength	
  of	
  message)	
  
•  are	
  they	
  server	
  configurable	
  
•  -­‐	
  are	
  they	
  wirelessly	
  configurable	
  (or	
  
physically	
  take	
  baJery	
  out	
  to	
  configure)	
  
•  have	
  an	
  easily	
  replacable	
  baJery.	
  	
  
•  be	
  cost	
  effec3ve:	
  
•  once	
  off	
  purchase	
  
•  charge	
  per	
  transac3on	
  use	
  
•  support	
  other	
  features	
  you	
  need:	
  
•  Temperature	
  detec3on	
  	
  
•  mo3on	
  sensor	
  
•  Holding	
  user	
  data	
  (e.g.	
  url)	
  
For	
  a	
  full	
  evalua3on	
  go	
  to	
  :	
  hJp://www.aislelabs.com/reports/beacon-­‐guide/	
  
Beacon Protocols
•  There	
  are	
  different	
  protocols.	
  This	
  defines	
  the	
  data	
  you	
  get	
  
from	
  the	
  beacon	
  into	
  your	
  app:	
  
•  iBeacon	
   	
   	
  (introduced	
  by	
  Apple	
  in	
  2013)	
  	
  	
  	
  	
  (see	
  slide)	
  
•  Eddystone	
   	
   	
  (introduced	
  by	
  Google	
  in	
  2015)	
  
•  Nearable 	
   	
  (introduced	
  by	
  Es3mote	
  in	
  2014	
  aimed	
  at	
  the	
  wearable	
  market)	
  
•  Manufacturer	
  proprietary	
   	
  (e.g.	
  Gimbal	
  beacons	
  support	
  both	
  their	
  own	
  &	
  
iBeacon)	
  
•  Poten3al	
  uses:	
  
•  Retails	
  store	
  product	
  informa3on,	
  aJach	
  to	
  retail	
  products,	
  auc3on	
  item	
  informa3on,	
  
turn	
  on	
  the	
  TV,	
  loyalty	
  program	
  detec3on,	
  mapping	
  a	
  conferences	
  and	
  exhibi3ons,	
  
direc3on	
  while	
  indoors.	
  
•  My	
  choices:	
  
•  Ini3ally: 	
   	
  Qualcom	
  and	
  Qualcom	
  protocol	
  
•  I	
  now	
  use: 	
   	
  Es3mote	
  and	
  iBeacon	
  
iBeacon Protocol
Property	
   Description	
  
proximityUUID	
   Your	
  businesses	
  UUID	
  that	
  the	
  beacon	
  is	
  assigned	
  to.	
  When	
  you	
  listen	
  for	
  beacon	
  signals	
  you	
  
specify	
  this	
  value	
  and	
  you	
  will	
  only	
  get	
  these	
  beacon	
  message	
  back.	
  	
  
major	
   A	
  random	
  number	
  assigned	
  to	
  identify	
  a	
  beacon	
  which	
  you	
  can	
  change.	
  For	
  example	
  rather	
  than	
  
register	
  beacons	
  for	
  different	
  project	
  to	
  different	
  UUID’s	
  you	
  could	
  assign	
  them	
  to	
  a	
  common	
  
major	
  code.	
  	
  
The	
  names	
  ‘major’	
  and	
  ‘minor’	
  have	
  no	
  signiDicance	
  –	
  any	
  differentiation	
  between	
  this	
  is	
  within	
  
your	
  app.	
  
minor	
   A	
  random	
  number	
  assigned	
  to	
  identify	
  a	
  beacon.	
  	
  
proximity	
   Values:	
  Immediate,	
  Near,	
  Far,	
  Unknown.	
  
With	
  the	
  Estimote	
  beacons	
  I	
  have	
  found	
  that	
  ‘Immediate’	
  is	
  within	
  0.5m,	
  ‘Near’	
  is	
  within	
  	
  2.0m	
  
and	
  ‘Far’	
  could	
  be	
  anything	
  greater	
  than	
  2.0m	
  and	
  up	
  to	
  50m.	
  
You	
  will	
  receive	
  ‘Unknown’	
  values	
  regularly.	
  This	
  means	
  that	
  for	
  some	
  reason	
  the	
  Bluetooth	
  
signal	
  was	
  temporarily	
  interrupted.	
  (No	
  signal	
  is	
  receive	
  if	
  a	
  beacon	
  is	
  out	
  of	
  range).	
  
accuracy	
  (i.e.	
  distance)	
   Is	
  intended	
  to	
  represent	
  the	
  distance	
  in	
  meters,	
  but	
  we	
  advised	
  not	
  to	
  use	
  it	
  in	
  this	
  manner	
  as	
  it	
  
will	
  usually	
  be	
  wrong.	
  You	
  can	
  use	
  this	
  to	
  determine	
  the	
  relative	
  closeness	
  between	
  two	
  beacons.	
  
rssi	
  (in	
  dB)	
   Is	
  the	
  decibel	
  reading	
  of	
  the	
  signal	
  strength,	
  the	
  root	
  data	
  that	
  the	
  above	
  items	
  are	
  derived	
  
from.	
  
GeoLocation vs Beacons
•  When	
  using	
  GPS	
  for	
  loca3on	
  detec3on	
  you	
  define	
  the	
  central	
  
point	
  then	
  a	
  radius.	
  The	
  circumference	
  is	
  called	
  a	
  GeoFence	
  –	
  
you	
  are	
  either	
  inside	
  or	
  outside	
  the	
  ‘fence’.	
  
•  For	
  beacons	
  you	
  place	
  the	
  beacon	
  at	
  the	
  central	
  point,	
  measure	
  
the	
  radius	
  using	
  signal	
  strength,	
  and	
  op3onally	
  record	
  the	
  
La3tude	
  and	
  Longitude	
  of	
  where	
  you	
  placed	
  the	
  beacon.	
  
•  GPS	
  characteris3cs:	
  
•  Satellite	
  based	
  hence	
  it	
  doesn’t	
  work	
  well	
  indoors.	
  
•  Can	
  be	
  very	
  accurate,	
  but	
  not	
  on	
  a	
  standard	
  smartphone	
  …	
  
they	
  are	
  dumbed	
  down	
  to	
  conserve	
  phone	
  baJery	
  life.	
  
•  Beacon	
  characteris3cs:	
  
•  Low	
  energy	
  radio	
  device	
  –	
  beacon	
  baJery	
  life	
  restricted.	
  
•  Ideal	
  for	
  indoors.	
  
Configuring beacons
•  Can	
  change:	
  
•  Frequency	
  messages	
  are	
  sent	
  
•  The	
  power	
  of	
  the	
  message	
  
….	
  impac3ng	
  baJery	
  life	
  (more	
  on	
  this	
  later)	
  
	
  
•  Dynamic	
  configura3on:	
  
•  Does	
  your	
  beacon	
  have	
  the	
  ability	
  to	
  be	
  able	
  to	
  configure	
  the	
  above	
  
remotely?	
  
Contents
•  An	
  example	
  app	
  
•  Using	
  Beacons	
  for	
  loca3on	
  detec3on	
  
•  What	
  are	
  Beacons?	
  
•  Which	
  provider	
  should	
  I	
  choose?	
  
•  Which	
  protocol	
  should	
  I	
  use?	
  
•  GeoLoca3on	
  vs	
  Beacons	
  
•  Development	
  Code	
  
•  The	
  reality	
  of	
  how	
  they	
  work	
  
Xamarin Coding
•  Two	
  op3ons:	
  
•  ‘Ranging’ 	
   	
  -­‐	
  scan	
  for	
  beacons	
  in	
  range	
  and	
  read	
  their	
  values,	
  
•  ‘GeoFencing’ 	
  -­‐	
  not	
  supported	
  by	
  Es3mote	
  (and	
  I’m	
  not	
  sure	
  it	
  	
  
	
   	
   	
  	
  	
  would	
  work	
  anyway	
  due	
  to	
  beacon	
  limita3ons)	
  
•  Coding	
  snippets	
  are	
  available	
  at:	
  
•  Android: 	
   	
  hJps://blog.xamarin.com/use-­‐ibeacons-­‐in-­‐android-­‐with-­‐c/	
  
•  iOS: 	
   	
  hJps://blog.xamarin.com/play-­‐find-­‐the-­‐monkey-­‐with-­‐ios-­‐7-­‐ibeacons/	
  
•  Use	
  the	
  Xamarin.Mobile	
  package	
  
	
  	
  	
  
using System;"
using Foundation;"
using CoreBluetooth;"
using CoreLocation;"
using CoreFoundation;"
namespace iBeacon"
{"
    public class NavigationManager : NSObject"
    {"
        static readonly string uuid = "########-####-####-####-############"; "
        static readonly string appId = "AudioPuppy";"
        private CLLocationManager     beaconLocationMgr;"
        private CLBeaconRegion         beaconRegion;"
        private Boolean             monitoring = false;"
        public void Initialise()"
        {"
            beaconRegion = new CLBeaconRegion (new NSUuid (uuid), appId);"
            beaconRegion.NotifyEntryStateOnDisplay = true;"
            beaconRegion.NotifyOnEntry = true;"
            beaconRegion.NotifyOnExit = true;"
            beaconLocationMgr = new CLLocationManager ();"
            beaconLocationMgr.RequestAlwaysAuthorization ();"
            beaconLocationMgr.DidRangeBeacons "
                += (object sender, CLRegionBeaconsRangedEventArgs e) => "
                    {    ProcessBeaconUpdates( e );     };"
            StartLocationTracking ();"
        }"
        public void StopLocationTracking()"
        {"
            if (monitoring) {"
                if (beaconLocationMgr != null) {"
                    beaconLocationMgr.StopMonitoring (beaconRegion);"
                }"
                monitoring = false;"
            }"
        }"
        public void StartLocationTracking()"
        {"
            if (!monitoring) {"
                if (    beaconLocationMgr != null "
                    &&     SharedValues.SharedObject.TrackingBeacons) {"
                    beaconLocationMgr.StartMonitoring (beaconRegion);"
                }"
                monitoring = true;"
            }"
        }"
        private async void ProcessBeaconUpdates(CLRegionBeaconsRangedEventArgs e)"
        {"
            if (e.Beacons.Length == 0)"
                return;"
            // Record all beacons in range"
            BeaconService.SharedManager.BeaconSightings (e.Beacons);    "
            // Business logic when beacons detected"
            EventService.ProcessForCurrentLocation ();    "
        }"
    }"
}"
Coding considerations
•  Make	
  sure	
  you	
  check	
  that	
  Bluetooth	
  is	
  turned	
  on	
  and	
  consider	
  what	
  
to	
  do	
  both	
  when	
  the	
  user	
  has:	
  
•  forgoJen	
  to	
  turn	
  it	
  on,	
  and	
  	
  
•  purposely	
  turned	
  it	
  off.	
  
•  Background	
  mode:	
  
•  iOS	
  has	
  the	
  ability	
  to	
  start	
  your	
  app	
  when	
  it	
  detects	
  a	
  beacon.	
  
•  Beacon	
  signals	
  arrive	
  less	
  frequently	
  in	
  background	
  mode.	
  
Contents
•  An	
  example	
  app	
  
•  Using	
  Beacons	
  for	
  loca3on	
  detec3on	
  
•  What	
  are	
  Beacons?	
  
•  Which	
  provider	
  should	
  I	
  choose?	
  
•  Which	
  protocol	
  should	
  I	
  use?	
  
•  GeoLoca3on	
  vs	
  Beacons	
  
•  Configuring	
  Beacons	
  
•  Development	
  Code	
  
•  The	
  reality	
  of	
  how	
  they	
  work	
  
Limitation
Bluetooth:	
  	
  
•  penetrates	
  most	
  materials,	
  and	
  
•  is	
  most	
  absorbed	
  by	
  water.	
  
	
  
Beacon	
  limita3on:	
  
•  BaJery	
  life	
  
•  High	
  power	
  and	
  frequency	
  means	
  lower	
  baJery	
  life	
  
•  Power	
  fluctua3ons	
  	
  
Smartphone	
  limita3ons	
  
•  BaJery	
  life	
  compromises	
  
Beacon lab test results
We	
  tested:	
  
•  5	
  Es3mote	
  beacons	
  set	
  with	
  normal	
  power	
  sekngs,	
  and	
  	
  
•  5	
  with	
  a	
  high	
  power	
  and	
  high	
  frequency	
  sekng.	
  
•  At	
  0.2,	
  1.5,	
  2.5	
  and	
  4	
  meters.	
  
•  Each	
  with	
  50	
  message	
  (total	
  of	
  2000	
  readings).	
  
	
  
Lab test results:
Higher	
  power	
  sekngs	
  had:	
  
	
  
•  An	
  increase	
  	
  in	
  accuracy	
  up	
  to	
  2.5m,	
  
•  A	
  marked	
  increase	
  in	
  standard	
  
devia3on	
  at	
  4m	
  (less	
  accuracy),	
  
•  BaJery	
  life	
  reduced	
  from	
  3-­‐4	
  years	
  to	
  
6	
  months.	
  
Challenges
•  Inundated	
  with	
  beacon	
  messages:	
  messages	
  
from	
  all	
  beacons	
  with	
  50m	
  every	
  second.	
  
•  Too	
  much	
  Bluetooth	
  absorp3on	
  
•  Absorbed	
  by	
  water.	
  
•  60%	
  of	
  human	
  are	
  water.	
  
•  Not	
  enough	
  Bluetooth	
  absorp3on	
  
•  The	
  floor	
  above	
  may	
  be	
  closer	
  than	
  your	
  current	
  
floor.	
  
•  ‘Unknown’	
  message	
  
•  1	
  in	
  10	
  is	
  a	
  message	
  “Unknown”	
  meaning	
  in	
  range	
  
but	
  signal	
  is	
  unknown.	
  
•  Message	
  synchronisa3on	
  
•  (See	
  next	
  slide)	
  
•  Signal	
  strength	
  irregulari3es	
  
•  (see	
  lab	
  test	
  results)	
  
•  Out	
  of	
  range	
  detec3on	
  
•  If	
  no	
  messages?	
  
•  If	
  messages	
  in	
  and	
  out	
  of	
  power	
  range?	
  
•  “Significant	
  change”	
  problem	
  
•  Fluctua3ons	
  in	
  signal	
  strength	
  could	
  mean	
  many	
  
things.	
  
•  User	
  behavior	
  irregulari3es	
  
•  Moves	
  forwards,	
  back,	
  away,	
  comes	
  back,	
  …	
  
•  Incoming	
  phone	
  calls	
  
•  How	
  do	
  you	
  handle	
  incoming	
  messages	
  when	
  user	
  is	
  
talking	
  on	
  the	
  phone?	
  
•  Fast	
  moving	
  users	
  
•  Exaggera3ng	
  message	
  synchronisa3on	
  problem.	
  
•  Beacons	
  are	
  imperfect	
  and	
  have	
  their	
  own	
  
characteris3cs.	
  	
  	
  
•  Thread	
  processing	
  
•  Make	
  sure	
  beacon	
  message	
  are	
  processed	
  on	
  a	
  
background	
  thread.	
  
Suggested coding
Create:	
  
•  A	
  Beacon	
  class:	
  
•  Handing	
  characteris3cs	
  of	
  an	
  individual	
  beacon	
  
•  calibra3on,	
  	
  
•  averaging	
  of	
  messages,	
  	
  
•  managing	
  when	
  goes	
  out	
  of	
  range	
  
•  A	
  BeaconsInRange	
  class:	
  
•  A	
  dic3onary	
  of	
  all	
  beacons	
  in	
  range	
  
•  Comparison	
  of	
  one	
  beacon	
  to	
  another	
  to	
  determine	
  highest	
  Rssi	
  
•  A	
  BeaconService	
  class	
  
•  Singleton	
  to	
  manage	
  mul3ple	
  beacon	
  ac3vity:	
  
•  Current	
  beacon	
  
•  Process	
  beacon	
  sigh3ngs	
  (adding	
  and	
  removing	
  beacons	
  from	
  BeaconsInRange)	
  
using System;"
namespace iBeacon"
{"
    public class Beacon "
    {"
        #region Local variables"
        private int         AverageDenominator{ get; set;}"
        private double        CalibrationFactor { get; set;}"
        // previous 4 values stored as the raw uncalibrated value"
        private int         Rssi_1 { get; set;}  "
        private int         Rssi_2 { get; set;}"
        private int         Rssi_3 { get; set;}"
        private int         Rssi_4 { get; set;}"
        #endregion"
        #region Properties"
        public string         Uuid { get; set;}"
        public int             Minor { get; set;}"
        public int             Major { get; set;}"
        private int _averageRssi;"
        public int    AverageRssi { "
            set { _averageRssi = value; } "
            get { return (int) Math.Round(_averageRssi * CalibrationFactor); }"
        }"
        public double        LastUpdate { get; set; }"
        public double        Accuracy { get; set;}"
        private int _rssi;  // Stored as the uncalibrated value"
        public int Rssi { "
            get {"
                if (this.Expired)"
                    return -999;"
                "
                return (int) (Math.Round (_rssi * CalibrationFactor)); "
            }"
            set {"
                LastUpdate = DateTime.Now.ToOADate();"
                Rssi_4 = Rssi_3;"
                Rssi_3 = Rssi_2;"
                Rssi_2 = Rssi_1;"
                Rssi_1 = _rssi;"
                _rssi = value; "
                double aveRssi;"
                if (AverageDenominator == 1 || (Rssi_1 == 0 && Rssi_2 == 0)) "
                    aveRssi = _rssi; "
                else if (AverageDenominator == 2 || (Rssi_2 == 0 && Rssi_3 == 0))"
                    aveRssi = (_rssi + Rssi_1)/2; "
                else if (AverageDenominator == 3 || (Rssi_3 == 0 && Rssi_4 == 0))"
                    aveRssi = (_rssi + Rssi_1 + Rssi_2)/3; "
                else if (AverageDenominator == 4 || (Rssi_4 == 0))"
                    aveRssi = (_rssi + Rssi_1 + Rssi_2 + Rssi_3)/4; "
                else "
                    aveRssi = (_rssi + Rssi_1 + Rssi_2 + Rssi_3 + Rssi_4)/5; "
                AverageRssi = (int)Math.Round (aveRssi);"
            }"
        }"
        #endregion"
        #region Public Methods"
        public bool IsInRange()"
        {"
            if (this.AverageRssi < Settings.MinRssi || this.AverageRssi > Settings.MaxRssi) "
                return false;"
            else"
                return !this.Expired ();"
        }"
        public static Beacon ForKey(int major, int minor)"
        {"
            return BeaconService.SharedManager.BeaconsInRange.ForKey (major, minor);"
        }"
        #endregion"
        #region Constructors"
        public Beacon (string uuid, int major, int minor, int rssi, double accuracy)"
        {"
            this.CalibrationFactor = 1;"
            // HARD CODED FOR PURPOSES OF DEMO"
            switch (minor) {"
            case 12295:"
                this.CalibrationFactor = 0.944661095636026;"
                break;"
            case 29160:"
                this.CalibrationFactor = 1.01113098787517;"
                break;"
            case 45308:"
                this.CalibrationFactor = 1.0499484004128;"
                break;"
            }"
            AverageDenominator = Settings.BeaconAverageCount;"
            this.Rssi_1 = 0;"
            this.Rssi_2 = 0;"
            this.Rssi_3 = 0;"
            this.Rssi_4 = 0;"
            this.AverageRssi = 0;"
            this.Uuid = uuid;"
            this.Minor = minor;"
            this.Major = major;"
            this.Accuracy = accuracy;"
            this.Rssi = rssi;"
        }"
        #endregion"
        #region Private methods"
        private bool Expired()"
        {"
            double now = (int)DateTime.Now.ToOADate();"
            if ((this.LastUpdate + Settings.OutOfRangeSeconds * 1000) < now) {"
                return true;"
            }"
            return false;"
        }"
        #endregion"
    }"
}"
Beacon	
  class	
  
using System;"
using System.Collections.Generic;"
namespace iBeacon"
{"
    public class BeaconsInRange : Dictionary<int, Beacon>"
    {"
        public Beacon ForKey(int major, int minor)"
        {"
            foreach(KeyValuePair<int, Beacon> entry in this)"
            {"
                if (entry.Value.InRange ()) {"
                    if (entry.Value.Major == major && entry.Value.Minor == minor) {"
                        return entry.Value;"
                    }"
                }"
            }"
            return null;"
        }"
        public Beacon GetHighestRssiBeacon(){"
            int highestRssi = -999;"
            Beacon highest = null;"
            foreach(KeyValuePair<int, Beacon> entry in this)"
            {"
                if (entry.Value.InRange ()) {"
                    if (entry.Value.AverageRssi > highestRssi) {"
                        highestRssi = entry.Value.AverageRssi;"
                        highest = entry.Value;  "
                    }"
                }"
            }"
            return highest;"
        }"
    }"
}"
BeaconsInRange	
  class	
  
using System;"
using Foundation;"
using CoreLocation;"
namespace iBeacon"
{"
    public class BeaconService"
    {"
        #region Properties"
        private BeaconsInRange _beaconsInRange = new BeaconsInRange(); "
        public BeaconsInRange BeaconsInRange {"
            get {     return _beaconsInRange; }"
            set { _beaconsInRange = value; }"
        }"
        public Beacon CurrentBeacon { set; get; }"
        #endregion"
        #region Constructors"
        private BeaconService ()"
        {"
            this.CurrentBeacon = null;"
        }"
        #endregion"
        #region Public methods"
        public void BeaconSightings (CLBeacon[] beacons)"
        {"
            foreach (CLBeacon clBeacon in beacons) {"
                Beacon beacon = new Beacon ("
                    clBeacon.ProximityUuid.ToString (), "
                    Int32.Parse (clBeacon.Major.ToString ()),"
                    Int32.Parse (clBeacon.Minor.ToString ()),"
                    clBeacon.Rssi,"
                    clBeacon.Accuracy);"
                if (clBeacon.Proximity != CLProximity.Unknown) {"
                    if (!beacon.InRange () && beacon.Expired ()) {"
                        RemoveFromBeaconList (beacon);"
                    } else {"
                        AddToBeaconList (beacon);"
                    }"
                } else { // Proximity not known"
                    if (beacon.Expired ())"
                        RemoveFromBeaconList (beacon);"
                }"
            }"
        }"
        #endregion"
        #region Private methods"
        private void AddToBeaconList (Beacon beacon)"
        {"
            Beacon myBeacon = null;"
            // If a beacon is already in range, update it's rssi value"
            if (BeaconsInRange.ContainsKey ( beacon.Minor )) {    "
                myBeacon = BeaconsInRange [ beacon.Minor ];"
                myBeacon.Accuracy = beacon.Accuracy;"
                myBeacon.Rssi    = beacon.Rssi;"
                BeaconsInRange [beacon.Minor] = myBeacon;"
            } else {"
                BeaconsInRange.Add (beacon.Minor , beacon); "
                myBeacon = beacon;"
            }"
        }"
        private void RemoveFromBeaconList (Beacon beacon)"
        {"
            if (BeaconsInRange.ContainsKey ( beacon.Minor )) {     "
                BeaconsInRange.Remove (beacon.Minor); "
            }"
        }"
        #endregion"
    }"
}"
BeaconService	
  class	
  
Summary
•  Beacons	
  are	
  used	
  to	
  detect	
  loca3on	
  indoors	
  
•  From	
  the	
  simple	
  to	
  the	
  complex:	
  
•  A	
  user	
  has	
  entered	
  a	
  coffee	
  shop	
  and	
  has	
  been	
  there	
  more	
  than	
  15	
  minutes.	
  
•  To	
  the	
  complex:	
  
•  To	
  mapping	
  100	
  stalls	
  within	
  an	
  exhibi3on	
  and	
  which	
  person	
  was	
  interested	
  
in	
  which	
  stall.	
  
•  There	
  are	
  technology	
  limita3ons,	
  some	
  relevant	
  to	
  your	
  situa3on,	
  
some	
  not.	
  
	
  
Solving	
  the	
  problems	
  is	
  easy	
  …	
  but	
  only	
  aYer	
  you	
  know	
  what	
  they	
  are.	
  
Questions?
And	
  feel	
  free	
  to	
  contact	
  me	
  later.	
  

Location Based Development Using Xamarin