/// <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>
 /// Construct a Beacon from a Bluetooth LE packet 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>
 /// <returns>
 /// An instance of a <code>Beacon</code>
 /// </returns>
 public Beacon FromScanData(byte[] scanData, int rssi, BluetoothDevice device)
 {
     return this.FromScanData(scanData, rssi, device, new Beacon.Builder());
 }