private void controller_LeMetaEventReceived(object sender, LeMetaEventReceivedEventArgs e) { if (e.LeMetaEvent == null) { return; } if (e.LeMetaEvent.SubEvent != LeMetaEvent.LeMetaSubEvent.AdvertisingReport) { return; } if (e.LeMetaEvent.AdvertisingEvents == null) { return; } foreach (var advertisingEvent in e.LeMetaEvent.AdvertisingEvents) { var beacon = Beacon.Parse(advertisingEvent); if (beacon != null) { BeaconDetected?.Invoke(this, new BeaconEventArgs(beacon)); continue; } var eddystone = Eddystone.Parse(advertisingEvent); if (eddystone != null) { EddystoneDetected?.Invoke(this, new EddystoneEventArgs(eddystone)); continue; } } }
/// <summary> /// Enable advertising as an Eddystone. /// </summary> /// <param name="eddystone">The Eddystone to emulate.</param> /// <param name="advertisingInterval">The advertising interval. Interval should be between 20 ms and 10.24 seconds. Defaults to 1.28 seconds.</param> public void EnableAdvertising(Eddystone eddystone, TimeSpan?advertisingInterval = null) { throw new NotImplementedException(); }
/// <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); }
internal EddystoneEventArgs(Eddystone eddystone) { Eddystone = eddystone; }