Example #1
0
        private async void OnTogglePublisherButtonClickedAsync(object sender, RoutedEventArgs e)
        {
            if (_bluetoothLEAdvertisementPublisher.Status != BluetoothLEAdvertisementPublisherStatus.Started)
            {
                Beacon beacon = new Beacon();
                beacon.ManufacturerId = ManufacturerId;
                beacon.Code = BeaconCode;
                beacon.Id1 = BeaconId1;

                try
                {
                    beacon.Id2 = UInt16.Parse(BeaconId2);
                    beacon.Id3 = UInt16.Parse(BeaconId3);
                }
                catch (Exception)
                {
                }

                beacon.MeasuredPower = -58;

                System.Diagnostics.Debug.WriteLine("Will try to advertise as beacon " + beacon.ToString());

                BluetoothLEAdvertisementDataSection dataSection = BeaconFactory.BeaconToSecondDataSection(beacon);
                _bluetoothLEAdvertisementPublisher.Advertisement.DataSections.Add(dataSection);

                try
                {
                    _bluetoothLEAdvertisementPublisher.Start();
                }
                catch (Exception ex)
                {
                    MessageDialog messageDialog = new MessageDialog("Failed to start Bluetooth LE Advertisement Publisher: " + ex.Message);
                    await messageDialog.ShowAsync();
                }
            }
            else
            {
                _bluetoothLEAdvertisementPublisher.Stop();
            }
        }
Example #2
0
        /// <summary>
        /// Constructs a Beacon instance and sets the properties based on the given data.
        /// 
        /// The expected specification of the data is as follows:
        /// 
        /// Byte(s)     Name
        /// --------------------------
        /// 0-1         Manufacturer ID (16-bit unsigned integer, big endian)
        /// 2-3         Beacon code (two 8-bit unsigned integers, but can be considered as one 16-bit unsigned integer in little endian)
        /// 4-19        ID1 (UUID)
        /// 20-21       ID2 (16-bit unsigned integer, big endian)
        /// 22-23       ID3 (16-bit unsigned integer, big endian)
        /// 24          Measured Power (signed 8-bit integer)
        /// 25          Reserved for use by the manufacturer to implement special features (optional)
        /// 
        /// For more details on the beacon specifications see https://github.com/AltBeacon/spec
        /// 
        /// The minimum length of the given byte array is 25. If it is longer than 26 bits,
        /// everything after the 26th bit is ignored.
        /// </summary>
        /// <param name="data">The data to populate the Beacon instance properties with.</param>
        /// <returns>A newly created Beacon instance or null in case of a failure.</returns>
        public static Beacon BeaconFromByteArray([ReadOnlyArray] byte[] data)
        {
            if (data == null || data.Length < SecondBeaconDataSectionMinimumLengthInBytes)
            {
                // The given data is null or too short
                return null;
            }

            Beacon beacon = new Beacon();
            beacon.Code = BitConverter.ToUInt16(data, 2); // Bytes 2-3
            beacon.Id1 = FormatUuid(BitConverter.ToString(data, 4, 16)); // Bytes 4-19
            beacon.MeasuredPower = Convert.ToSByte(BitConverter.ToString(data, 24, 1), 16); // Byte 24

            if (data.Length >= SecondBeaconDataSectionMinimumLengthInBytes + 1)
            {
                beacon.MfgReserved = data[25]; // Byte 25
            }

            // Data is expected to be big endian. Thus, if we are running on a little endian,
            // we need to switch the bytes
            if (BitConverter.IsLittleEndian)
            {
                data = ChangeInt16ArrayEndianess(data);
            }

            beacon.ManufacturerId = BitConverter.ToUInt16(data, 0); // Bytes 0-1
            beacon.Id2 = BitConverter.ToUInt16(data, 20); // Bytes 20-21
            beacon.Id3 = BitConverter.ToUInt16(data, 22); // Bytes 22-23

            return beacon;
        }
Example #3
0
 /// <summary>
 /// Compares the given beacon to this.
 /// </summary>
 /// <param name="beacon">The beacon to compare to.</param>
 /// <returns>True, if the beacons match.</returns>
 public bool Matches(Beacon beacon)
 {
     return beacon.Id1.Equals(Id1)
         && beacon.Id2 == Id2
         && beacon.Id3 == Id3;
 }
Example #4
0
        /// <summary>
        /// Creates the second part of the beacon advertizing packet.
        /// Uses the beacon IDs 1, 2, 3 and measured power to create the data section.
        /// </summary>
        /// <param name="beacon">A beacon instance.</param>
        /// <param name="includeMfgReservedByte">Defines whether we should add the additional, manufacturer reserved byte or not.</param>
        /// <returns>A newly created data section.</returns>
        public static BluetoothLEAdvertisementDataSection BeaconToSecondDataSection(
            Beacon beacon, bool includeMfgReservedByte = false)
        {
            string[] temp = beacon.Id1.Split(HexStringSeparator);
            string beaconId1 = string.Join("", temp);

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(ManufacturerIdToString(beacon.ManufacturerId));
            stringBuilder.Append(BeaconCodeToString(beacon.Code));
            stringBuilder.Append(beaconId1.ToUpper());

            byte[] beginning = HexStringToByteArray(stringBuilder.ToString());

            byte[] data = includeMfgReservedByte
                ? new byte[SecondBeaconDataSectionMinimumLengthInBytes + 1]
                : new byte[SecondBeaconDataSectionMinimumLengthInBytes];

            beginning.CopyTo(data, 0);
            ChangeInt16ArrayEndianess(BitConverter.GetBytes(beacon.Id2)).CopyTo(data, 20);
            ChangeInt16ArrayEndianess(BitConverter.GetBytes(beacon.Id3)).CopyTo(data, 22);
            data[24] = (byte)Convert.ToSByte(beacon.MeasuredPower);

            if (includeMfgReservedByte)
            {
                data[25] = beacon.MfgReserved;
            }

            BluetoothLEAdvertisementDataSection dataSection = new BluetoothLEAdvertisementDataSection();
            dataSection.DataType = SecondBeaconDataSectionDataType;
            dataSection.Data = data.AsBuffer();

            return dataSection;
        }
Example #5
0
        /// <summary>
        /// Updates the beacon data, if the given beacon matches this one.
        /// </summary>
        /// <param name="beacon">The beacon with new data.</param>
        /// <returns>True, if the given beacon matches this one (and the data was updated). False otherwise.</returns>
        public bool Update(Beacon beacon)
        {
            bool matches = Matches(beacon);

            if (matches)
            {
                Timestamp = beacon.Timestamp;
                RawSignalStrengthInDBm = beacon.RawSignalStrengthInDBm;

                if (_lastSeenTimer != null)
                {
                    _lastSeenTimer.Dispose();
                    _lastSeenTimer = new Timer(LastSeenTimerCallbackAsync, null,
                        LastSeenTimerTimeoutInMilliseconds, LastSeenTimerTimeoutInMilliseconds);
                }
            }

            return matches;
        }