Beispiel #1
0
        public void Beacon_ParseDataWithoutFlags()
        {
            var data = new byte[] {
                0x00, 0x00, 0x28, 0xEA, 0x6B, 0xB8, 0x5F, 0xD0, 0x1B, 0x1A, 0xFF, 0x4C, 0x00, 0x02, 0x15,
                0xA4, 0x95, 0x00, 0x00, 0xC5, 0xB1, 0x4B, 0x44, 0xB5, 0x12, 0x13, 0x70, 0xF0, 0x2D, 0x74,
                0xDE, 0x00, 0x02, 0x6D, 0x65, 0xC5, 0xBC
            };
            var queue  = new Queue <byte>(data);
            var beacon = Beacon.Parse(LeAdvertisingEvent.Parse(queue));

            Assert.NotNull(beacon);
            Assert.AreEqual(0x4C00, beacon.CompanyId);
            Assert.AreEqual(-59, beacon.CalibratedTxPower);
        }
Beispiel #2
0
        /// <summary>
        /// Parse low energy advertising event to a beacon instance.
        /// </summary>
        /// <param name="e">The event.</param>
        /// <returns>The beacon or null in case of failure.</returns>
        internal static Beacon Parse(LeAdvertisingEvent e)
        {
            if (e.EventType == LeAdvertisingEventType.ScanRsp)
            {
                return(null);
            }
            var payload = new Queue <byte>(e.Payload);

            while (payload.Count > 0)
            {
                var adLength = payload.Dequeue();
                if (payload.Count < adLength)
                {
                    break;
                }
                var adType = payload.Dequeue();
                if (adType == 0xFF && adLength >= 26)
                {
                    var companyId = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
                    var b0advInd  = payload.Dequeue();
                    var b1advInd  = payload.Dequeue();
                    var uuid      = payload.Dequeue(16);
                    var major     = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
                    var minor     = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
                    var txPower   = (sbyte)payload.Dequeue();
                    return(new Beacon
                    {
                        Uuid = uuid.ToLittleEndianFormattedUuidString(),
                        Address = e.Address,
                        Major = major,
                        Minor = minor,
                        Rssi = e.Rssi,
                        CalibratedTxPower = txPower,
                        CompanyId = companyId
                    });
                }
                else
                {
                    if (adLength > 0)
                    {
                        payload.Dequeue(adLength - 1);
                    }
                }
            }

            return(null);
        }
Beispiel #3
0
        public void Beacon_ParseDataWithFlags()
        {
            var data = new byte[] {
                0x00, 0x00, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, 0x1E, 0x02, 0x01, 0x1A, 0x1A, 0xFF, 0xAA,
                0xBB, 0x02, 0x15, 0x4F, 0xE5, 0xD5, 0xF6, 0xAB, 0xCE, 0xDD, 0xFE, 0x15, 0x87, 0x12, 0x3D,
                0x1A, 0x4B, 0x56, 0x7F, 0x04, 0xD2, 0x16, 0x2E, 0xD0, 0xCC
            };
            var queue  = new Queue <byte>(data);
            var beacon = Beacon.Parse(LeAdvertisingEvent.Parse(queue));

            Assert.AreEqual(new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }, beacon.Address);
            Assert.AreEqual("4fe5d5f6-abce-ddfe-1587-123d1a4b567f", beacon.Uuid);
            Assert.AreEqual(1234, beacon.Major);
            Assert.AreEqual(5678, beacon.Minor);
            Assert.AreEqual(-48, beacon.CalibratedTxPower);
            Assert.AreEqual(0xAABB, beacon.CompanyId);
            Assert.AreEqual(-52, beacon.Rssi);
            Assert.IsFalse(beacon.IsAppleIBeacon);
        }
Beispiel #4
0
        /// <summary>
        /// Parse low energy advertising event to a beacon instance.
        /// </summary>
        /// <param name="e">The event.</param>
        /// <returns>The beacon or null in case of failure.</returns>
        internal static Beacon Parse(LeAdvertisingEvent e)
        {
            if (e.EventType == LeAdvertisingEventType.ScanRsp)
            {
                return(null);
            }
            if (e.Payload.Length < 9)
            {
                return(null);
            }
            var payload   = new Queue <byte>(e.Payload);
            var ad1Length = payload.Dequeue();
            var ad1Type   = payload.Dequeue();
            var flags     = payload.Dequeue();
            var ad2Length = payload.Dequeue();
            var ad2Type   = payload.Dequeue();
            var companyId = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
            var b0advInd  = payload.Dequeue();
            var b1advInd  = payload.Dequeue();

            if (ad1Length != 2 || ad1Type != 0x01 || ad2Length < 26 || ad2Type != 0xFF)
            {
                return(null);
            }
            var uuid    = payload.Dequeue(16);
            var major   = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
            var minor   = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
            var txPower = (sbyte)payload.Dequeue();

            return(new Beacon
            {
                Uuid = uuid.ToLittleEndianFormattedUuidString(),
                Address = e.Address,
                Major = major,
                Minor = minor,
                Rssi = e.Rssi,
                CalibratedTxPower = txPower,
                CompanyId = companyId
            });
        }
Beispiel #5
0
        public void Beacon_Parse()
        {
            var address = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC };
            var queue   = new Queue <byte>();

            queue.Enqueue(0x00);
            queue.Enqueue(0x00);
            queue.Enqueue(address.Reverse());
            queue.Enqueue((byte)data.Length);
            queue.Enqueue(data);
            unchecked { queue.Enqueue((byte)-52); }
            var beacon = Beacon.Parse(LeAdvertisingEvent.Parse(queue));

            Assert.AreEqual(address, beacon.Address);
            Assert.AreEqual("4fe5d5f6-abce-ddfe-1587-123d1a4b567f", beacon.Uuid);
            Assert.AreEqual(1234, beacon.Major);
            Assert.AreEqual(5678, beacon.Minor);
            Assert.AreEqual(-48, beacon.CalibratedTxPower);
            Assert.AreEqual(0xAABB, beacon.CompanyId);
            Assert.AreEqual(-52, beacon.Rssi);
            Assert.IsFalse(beacon.IsAppleIBeacon);
        }
Beispiel #6
0
        /// <summary>
        /// Parses an incoming <see cref="LeAdvertisingEvent"/> for Eddystone frames.
        /// </summary>
        /// <param name="e">The incoming event frame.</param>
        /// <returns>An <see cref="Eddystone"/> instance or null in case the event could not be parsed as an Eddystone event.</returns>
        /// <remarks>Implemented according to https://github.com/google/eddystone/blob/master/protocol-specification.md </remarks>
        internal static Eddystone Parse(LeAdvertisingEvent e)
        {
            if (e.EventType == LeAdvertisingEventType.ScanRsp)
            {
                return(null);
            }

            var payload = new Queue <byte>(e.Payload);

            // Skip flags
            var flagsLength = payload.Dequeue();

            payload.Dequeue(flagsLength);

            // Extract and verify Eddystone UUID
            // The Complete List of 16-bit Service UUIDs as defined in The Bluetooth Core Specification Supplement (CSS) v5, Part A, § 1.1.
            // The Complete List of 16-bit Service UUIDs must contain the Eddystone Service UUID of 0xFEAA. This is included to allow background scanning on iOS devices.
            var eddystoneUuidLength = payload.Dequeue();

            if (eddystoneUuidLength != 3)
            {
                return(null);
            }
            payload.Dequeue();
            var eddystoneUuid = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());

            if (eddystoneUuid != 0xAAFE)
            {
                return(null);
            }

            // Extract service data
            // The Service Data data type, Ibid., § 1.11.
            // The Service Data - 16 bit UUID data type must be the Eddystone Service UUID of 0xFEAA
            var serviceDataLength    = payload.Dequeue();
            var serviceDataTypeValue = payload.Dequeue();

            eddystoneUuid = (ushort)((payload.Dequeue() << 8) + payload.Dequeue());
            if (eddystoneUuid != 0xAAFE)
            {
                return(null);
            }
            var       eddystoneFrameType = (EddystoneFrameType)payload.Dequeue();
            Eddystone result             = null;

            switch (eddystoneFrameType)
            {
            case EddystoneFrameType.Uid:
                result = EddystoneUid.ParseFrame(payload);
                break;

            case EddystoneFrameType.Url:
                result = EddystoneUrl.ParseFrame(payload);
                break;

            case EddystoneFrameType.Tlm:
                result = EddystoneTlm.ParseFrame(payload);
                break;

            case EddystoneFrameType.Eid:
                result = EddystoneEid.ParseFrame(payload);
                break;
            }

            if (result != null)
            {
                result.Address = e.Address;
                result.Rssi    = e.Rssi;
            }

            return(result);
        }