/// <summary>
 /// Initializes a new instance of the <see cref="Beacon"/> class.
 /// Copy constructor.
 /// </summary>
 /// <param name="otherBeacon">
 /// Other beacon to be copied
 /// </param>
 /// <see cref="Beacon" />
 protected Beacon(Beacon otherBeacon)
 {
     this.identifiers        = new List <Identifier>(otherBeacon.identifiers);
     this.dataFields         = new List <long>(otherBeacon.dataFields);
     this.distance           = otherBeacon.distance;
     this.runningAverageRssi = otherBeacon.runningAverageRssi;
     this.Rssi             = otherBeacon.Rssi;
     this.TxPower          = otherBeacon.TxPower;
     this.BluetoothAddress = otherBeacon.BluetoothAddress;
     this.BeaconTypeCode   = otherBeacon.BeaconTypeCode;
     this.ServiceUuid      = otherBeacon.ServiceUuid;
     this.BluetoothName    = otherBeacon.BluetoothName;
 }
示例#2
0
        public void TestReEncodesBeacon()
        {
            byte[]       bytes  = HexStringToByteArray("02011a1aff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c509");
            BeaconParser parser = new BeaconParser();

            parser.SetBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
            Beacon beacon = parser.FromScanData(bytes, -55, null);

            byte[] regeneratedBytes = parser.GetBeaconAdvertisementData(beacon);
            byte[] expectedMatch    = new byte[bytes.Length - 7];
            Array.Copy(bytes, 7, expectedMatch, 0, expectedMatch.Length);

            CollectionAssert.AreEqual(expectedMatch, regeneratedBytes, "beacon advertisement bytes should be the same after re-encoding");
        }
示例#3
0
        public void TestReEncodesLittleEndianBeacon()
        {
            byte[]       bytes  = HexStringToByteArray("02011a1aff1801beac0102030405060708090a0b0c0d0e0f1011121314c509");
            BeaconParser parser = new BeaconParser();

            parser.SetBeaconLayout("m:2-3=beac,i:4-9,i:10-15l,i:16-23,p:24-24,d:25-25");
            Beacon beacon = parser.FromScanData(bytes, -55, null);

            byte[] regeneratedBytes = parser.GetBeaconAdvertisementData(beacon);
            byte[] expectedMatch    = new byte[bytes.Length - 7];
            Array.Copy(bytes, 7, expectedMatch, 0, expectedMatch.Length);

            CollectionAssert.AreEqual(expectedMatch, regeneratedBytes, "beacon advertisement bytes should be the same after re-encoding");
        }
示例#4
0
        public void TestRecognizeBeacon()
        {
            byte[]       bytes  = HexStringToByteArray("02011a1aff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c509");
            BeaconParser parser = new BeaconParser();

            parser.SetBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
            Beacon beacon = parser.FromScanData(bytes, -55, null);

            Assert.AreEqual(-55, beacon.Rssi, "mRssi should be as passed in");
            Assert.AreEqual("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6", beacon.Identifiers[0].ToString(), "uuid should be parsed");
            Assert.AreEqual("1", beacon.Identifiers[1].ToString(), "id2 should be parsed");
            Assert.AreEqual("2", beacon.Identifiers[2].ToString(), "id3 should be parsed");
            Assert.AreEqual(-59, beacon.TxPower, "txPower should be parsed");
            Assert.AreEqual(0x118, beacon.Manufacturer, "manufacturer should be parsed");
        }
示例#5
0
        public void TestLittleEndianIdentifierParsing()
        {
            byte[]       bytes  = HexStringToByteArray("02011a1aff1801beac0102030405060708090a0b0c0d0e0f1011121314c509");
            BeaconParser parser = new BeaconParser();

            parser.SetBeaconLayout("m:2-3=beac,i:4-9,i:10-15l,i:16-23,p:24-24,d:25-25");
            Beacon beacon = parser.FromScanData(bytes, -55, null);

            Assert.AreEqual(-55, beacon.Rssi, "mRssi should be as passed in");
            Assert.AreEqual("0x010203040506", beacon.Identifiers[0].ToString(), "id1 should be big endian");
            Assert.AreEqual("0x0c0b0a090807", beacon.Identifiers[1].ToString(), "id2 should be little endian");
            Assert.AreEqual("0x0d0e0f1011121314", beacon.Identifiers[2].ToString(), "id3 should be big endian");
            Assert.AreEqual(-59, beacon.TxPower, "txPower should be parsed");
            Assert.AreEqual(0x118, beacon.Manufacturer, "manufacturer should be parsed");
        }
示例#6
0
        /// <summary>
        /// Get BLE advertisement bytes for a Beacon
        /// </summary>
        /// <param name="beacon">the beacon containing the data to be transmitted</param>
        /// <returns>the byte array of the advertisement</returns>
        public byte[] GetBeaconAdvertisementData(Beacon beacon)
        {
            byte[] advertisingBytes;

            int lastIndex = -1;

            if (this.matchingBeaconTypeCodeEndOffset != null &&
                this.matchingBeaconTypeCodeEndOffset.Value > lastIndex)
            {
                lastIndex = this.matchingBeaconTypeCodeEndOffset.Value;
            }

            if (this.powerEndOffset != null && this.powerEndOffset > lastIndex)
            {
                lastIndex = this.powerEndOffset.Value;
            }

            for (int identifierNum = 0;
                 identifierNum < this.identifierStartOffsets.Count;
                 identifierNum++)
            {
                if (this.identifierEndOffsets[identifierNum] != null &&
                    this.identifierEndOffsets[identifierNum] > lastIndex)
                {
                    lastIndex = this.identifierEndOffsets[identifierNum].Value;
                }
            }

            for (int identifierNum = 0; identifierNum < this.dataEndOffsets.Count; identifierNum++)
            {
                if (this.dataEndOffsets[identifierNum] != null &&
                    this.dataEndOffsets[identifierNum] > lastIndex)
                {
                    lastIndex = this.dataEndOffsets[identifierNum].Value;
                }
            }

            advertisingBytes = new byte[lastIndex + 1 - 2];
            long beaconTypeCode = this.MatchingBeaconTypeCode;

            // set type code
            for (int index = this.matchingBeaconTypeCodeStartOffset.Value;
                 index <= this.matchingBeaconTypeCodeEndOffset; index++)
            {
                byte value = (byte)(this.MatchingBeaconTypeCode >>
                                    (8 * (this.matchingBeaconTypeCodeEndOffset - index)) & 0xff);
                advertisingBytes[index - 2] = value;
            }

            // set identifiers
            for (int identifierNum = 0; identifierNum < this.identifierStartOffsets.Count;
                 identifierNum++)
            {
                byte[] identifierBytes = beacon.Identifiers[identifierNum]
                                         .ToByteArrayOfSpecifiedEndianness(this.identifierLittleEndianFlags[identifierNum]);

                for (int index = this.identifierStartOffsets[identifierNum].Value;
                     index <= this.identifierEndOffsets[identifierNum]; index++)
                {
                    int identifierByteIndex = this.identifierEndOffsets[identifierNum].Value - index;
                    if (identifierByteIndex < identifierBytes.Length)
                    {
                        advertisingBytes[index - 2] =
                            identifierBytes[this.identifierEndOffsets[identifierNum].Value - index];
                    }
                    else
                    {
                        advertisingBytes[index - 2] = 0;
                    }
                }
            }

            // set power
            for (int index = this.powerStartOffset.Value; index <= this.powerEndOffset; index++)
            {
                advertisingBytes[index - 2] = (byte)(beacon.TxPower >>
                                                     (8 * (index - this.powerStartOffset)) & 0xff);
            }

            // set data fields
            for (int dataFieldNum = 0; dataFieldNum < this.dataStartOffsets.Count; dataFieldNum++)
            {
                long dataField = beacon.DataFields[dataFieldNum];
                for (int index = this.dataStartOffsets[dataFieldNum].Value;
                     index <= this.dataEndOffsets[dataFieldNum]; index++)
                {
                    int endianCorrectedIndex = index;
                    if (this.dataLittleEndianFlags[dataFieldNum])
                    {
                        endianCorrectedIndex = this.dataEndOffsets[dataFieldNum].Value - index;
                    }

                    advertisingBytes[endianCorrectedIndex - 2] = (byte)(dataField >>
                                                                        (8 * (index - this.dataStartOffsets[dataFieldNum])) & 0xff);
                }
            }

            return(advertisingBytes);
        }
        /// <summary>
        /// Construct a Beacon from a Bluetooth LE packet collected by Android's Bluetooth APIs,
        /// including the raw bluetooth device info
        /// </summary>
        /// <param name="scanData">
        /// The actual packet bytes
        /// </param>
        /// <param name="rssi">
        /// The measured signal strength of the packet
        /// </param>
        /// <param name="device">
        /// The bluetooth device that was detected
        /// </param>
        /// <param name="beaconBuilder">
        /// Beacon Builder
        /// </param>
        /// <returns>
        /// An instance of a <code>Beacon</code>
        /// </returns>
        protected Beacon FromScanData(byte[] scanData, int rssi, BluetoothDevice device, Beacon.Builder beaconBuilder)
        {
            int startByte = 2;
            bool patternFound = false;
            int matchingBeaconSize = this.matchingBeaconTypeCodeEndOffset.Value -
                this.matchingBeaconTypeCodeStartOffset.Value + 1;
            byte[] typeCodeBytes = LongToByteArray(this.MatchingBeaconTypeCode, matchingBeaconSize);

            while (startByte <= 5)
            {
                if (AreByteArraysMatch(scanData, startByte + this.matchingBeaconTypeCodeStartOffset.Value, typeCodeBytes, 0))
                {
                    patternFound = true;
                    break;
                }

                startByte++;
            }

            if (patternFound == false)
            {
                // This is not a beacon
                // TODO LogManager
                /*if (this.ServiceUuid == null)
                {
                    TODO LogManager
                    if (LogManager.isVerboseLoggingEnabled())
                    {
                        LogManager.d(TAG, "This is not a matching Beacon advertisement. " +
                            "(Was expecting %s. The bytes I see are: %s",
                            byteArrayToString(typeCodeBytes), bytesToHex(scanData));
                    }
                }
                else
                {
                    if (LogManager.isVerboseLoggingEnabled())
                    {
                        LogManager.d(TAG, "This is not a matching Beacon advertisement. " +
                            "(Was expecting %s and %s. The bytes I see are: %s",
                            byteArrayToString(serviceUuidBytes),
                            byteArrayToString(typeCodeBytes), bytesToHex(scanData));
                    }
                }*/
                return null;
            }
            else
            {
                //// TODO LogManager
                //// if (LogManager.isVerboseLoggingEnabled())
                //// {
                ////     LogManager.d(TAG, "This is a recognized beacon advertisement -- %s seen",
                ////             byteArrayToString(typeCodeBytes));
                //// }
                ////
                //// TODO LogManager
                //// LogManager.d(Tag, "This is a recognized beacon advertisement -- " +
                ////     getMatchingBeaconTypeCode().ToString("x4") + " seen");
            }

            List<Identifier> identifiers = new List<Identifier>();
            for (int i = 0; i < this.identifierEndOffsets.Count; i++)
            {
                Identifier identifier = Identifier.FromBytes(
                    scanData,
                    this.identifierStartOffsets[i].Value + startByte,
                    this.identifierEndOffsets[i].Value + startByte + 1,
                    this.identifierLittleEndianFlags[i]);

                identifiers.Add(identifier);
            }

            List<long> dataFields = new List<long>();
            for (int i = 0; i < this.dataEndOffsets.Count; i++)
            {
                string dataString = ByteArrayToFormattedString(
                    scanData,
                    this.dataStartOffsets[i].Value + startByte,
                    this.dataEndOffsets[i].Value + startByte,
                    this.dataLittleEndianFlags[i]);

                dataFields.Add(long.Parse(dataString));
                //// TODO LogManager
                //// LogManager.d(Tag, "parsing found data field " + i);
                //// TODO: error handling needed here on the parse
            }

            int txPower = 0;
            string powerString = ByteArrayToFormattedString(
                scanData,
                this.powerStartOffset.Value + startByte,
                this.powerEndOffset.Value + startByte,
                false);
            txPower = int.Parse(powerString);

            // make sure it is a signed integer
            if (txPower > 127)
            {
                txPower -= 256;
            }

            // TODO: error handling needed on the parse
            int beaconTypeCode = 0;
            string beaconTypeString = ByteArrayToFormattedString(
                scanData,
                this.matchingBeaconTypeCodeStartOffset.Value + startByte,
                this.matchingBeaconTypeCodeEndOffset.Value + startByte,
                false);
            beaconTypeCode = int.Parse(beaconTypeString);

            // TODO: error handling needed on the parse
            int manufacturer = 0;
            string manufacturerString =
                ByteArrayToFormattedString(scanData, startByte, startByte + 1, true);
            manufacturer = int.Parse(manufacturerString);

            string macAddress = null;
            string name = null;
            if (device != null)
            {
                macAddress = device.Address;
                name = device.Name;
            }

            return beaconBuilder
                .SetIdentifiers(identifiers)
                .SetDataFields(dataFields)
                .SetTxPower(txPower)
                .SetRssi(rssi)
                .SetBeaconTypeCode(beaconTypeCode)
                .SetBluetoothAddress(macAddress)
                .SetBluetoothAddress(macAddress)
                .SetManufacturer(manufacturer)
                .Build();
        }
        /// <summary>
        /// Get BLE advertisement bytes for a Beacon
        /// </summary>
        /// <param name="beacon">the beacon containing the data to be transmitted</param>
        /// <returns>the byte array of the advertisement</returns>
        public byte[] GetBeaconAdvertisementData(Beacon beacon)
        {
            byte[] advertisingBytes;

            int lastIndex = -1;
            if (this.matchingBeaconTypeCodeEndOffset != null &&
                this.matchingBeaconTypeCodeEndOffset.Value > lastIndex)
            {
                lastIndex = this.matchingBeaconTypeCodeEndOffset.Value;
            }

            if (this.powerEndOffset != null && this.powerEndOffset > lastIndex)
            {
                lastIndex = this.powerEndOffset.Value;
            }

            for (int identifierNum = 0;
                identifierNum < this.identifierStartOffsets.Count;
                identifierNum++)
            {
                if (this.identifierEndOffsets[identifierNum] != null &&
                    this.identifierEndOffsets[identifierNum] > lastIndex)
                {
                    lastIndex = this.identifierEndOffsets[identifierNum].Value;
                }
            }

            for (int identifierNum = 0; identifierNum < this.dataEndOffsets.Count; identifierNum++)
            {
                if (this.dataEndOffsets[identifierNum] != null &&
                    this.dataEndOffsets[identifierNum] > lastIndex)
                {
                    lastIndex = this.dataEndOffsets[identifierNum].Value;
                }
            }

            advertisingBytes = new byte[lastIndex + 1 - 2];
            long beaconTypeCode = this.MatchingBeaconTypeCode;

            // set type code
            for (int index = this.matchingBeaconTypeCodeStartOffset.Value;
                index <= this.matchingBeaconTypeCodeEndOffset; index++)
            {
                byte value = (byte)(this.MatchingBeaconTypeCode >>
                    (8 * (this.matchingBeaconTypeCodeEndOffset - index)) & 0xff);
                advertisingBytes[index - 2] = value;
            }

            // set identifiers
            for (int identifierNum = 0; identifierNum < this.identifierStartOffsets.Count;
                identifierNum++)
            {
                byte[] identifierBytes = beacon.Identifiers[identifierNum]
                    .ToByteArrayOfSpecifiedEndianness(this.identifierLittleEndianFlags[identifierNum]);

                for (int index = this.identifierStartOffsets[identifierNum].Value;
                    index <= this.identifierEndOffsets[identifierNum]; index++)
                {
                    int identifierByteIndex = this.identifierEndOffsets[identifierNum].Value - index;
                    if (identifierByteIndex < identifierBytes.Length)
                    {
                        advertisingBytes[index - 2] =
                            identifierBytes[this.identifierEndOffsets[identifierNum].Value - index];
                    }
                    else
                    {
                        advertisingBytes[index - 2] = 0;
                    }
                }
            }

            // set power
            for (int index = this.powerStartOffset.Value; index <= this.powerEndOffset; index++)
            {
                advertisingBytes[index - 2] = (byte)(beacon.TxPower >>
                    (8 * (index - this.powerStartOffset)) & 0xff);
            }

            // set data fields
            for (int dataFieldNum = 0; dataFieldNum < this.dataStartOffsets.Count; dataFieldNum++)
            {
                long dataField = beacon.DataFields[dataFieldNum];
                for (int index = this.dataStartOffsets[dataFieldNum].Value;
                    index <= this.dataEndOffsets[dataFieldNum]; index++)
                {
                    int endianCorrectedIndex = index;
                    if (this.dataLittleEndianFlags[dataFieldNum])
                    {
                        endianCorrectedIndex = this.dataEndOffsets[dataFieldNum].Value - index;
                    }

                    advertisingBytes[endianCorrectedIndex - 2] = (byte)(dataField >>
                        (8 * (index - this.dataStartOffsets[dataFieldNum])) & 0xff);
                }
            }

            return advertisingBytes;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Beacon.Builder"/> class.
 /// Creates a builder instance.
 /// </summary>
 public Builder()
 {
     this.beacon = new Beacon();
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="Beacon.Builder"/> class.
 /// Creates a builder instance.
 /// </summary>
 public Builder()
 {
     this.beacon = new Beacon();
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="Beacon"/> class.
 /// Copy constructor.
 /// </summary>
 /// <param name="otherBeacon">
 /// Other beacon to be copied
 /// </param>
 /// <see cref="Beacon" />
 protected Beacon(Beacon otherBeacon)
 {
     this.identifiers = new List<Identifier>(otherBeacon.identifiers);
     this.dataFields = new List<long>(otherBeacon.dataFields);
     this.distance = otherBeacon.distance;
     this.runningAverageRssi = otherBeacon.runningAverageRssi;
     this.Rssi = otherBeacon.Rssi;
     this.TxPower = otherBeacon.TxPower;
     this.BluetoothAddress = otherBeacon.BluetoothAddress;
     this.BeaconTypeCode = otherBeacon.BeaconTypeCode;
     this.ServiceUuid = otherBeacon.ServiceUuid;
     this.BluetoothName = otherBeacon.BluetoothName;
 }