Ejemplo n.º 1
0
        public static DispatchTimer ScheduledDispatchTimer(long delay, DispatchQueue queue, TimerHandler block)
        {
            var dt = new DispatchTimer(delay: delay, queue: queue, block: block);

            dt.Schedule();

            return(dt);
        }
            ///
            /// Core Bluetooth CBCentralManager callback when we discover a beacon. We're not super
            /// interested in any error situations at this point in time.
            ///
            public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
            {
                var serviceData = advertisementData[CBAdvertisement.DataServiceDataKey] as NSDictionary;

                if (serviceData != null)
                {
                    var eft = Eddystone.FrameTypeForFrame(serviceData);

                    // If it's a telemetry frame, stash it away and we'll send it along with the next regular
                    // frame we see. Otherwise, process the UID frame.
                    if (eft == BeaconInfo.EddystoneFrameType.TelemetryFrameType)
                    {
                        var data = Eddystone.TelemetryDataForFrame(advertisementData);
                        if (deviceIDCache.ContainsKey(peripheral.Identifier))
                        {
                            deviceIDCache[peripheral.Identifier] = data;
                        }
                        else
                        {
                            deviceIDCache.Add(peripheral.Identifier, data);
                        }
                    }
                    else if (eft == BeaconInfo.EddystoneFrameType.UIDFrameType ||
                             eft == BeaconInfo.EddystoneFrameType.EIDFrameType)
                    {
                        if (!deviceIDCache.ContainsKey(peripheral.Identifier))
                        {
                            Debug.WriteLine($"deviceIDCache does not contain key: {peripheral.Identifier}.");
                            return;
                        }

                        var telemetry   = deviceIDCache[peripheral.Identifier];
                        var serviceUUID = CBUUID.FromString("FEAA");
                        var _RSSI       = RSSI.Int32Value;

                        var beaconServiceData = serviceData[serviceUUID] as NSData;
                        if (beaconServiceData != null)
                        {
                            var beaconInfo = (eft == BeaconInfo.EddystoneFrameType.UIDFrameType) ?
                                             Eddystone.BeaconInfoForUIDFrameData(beaconServiceData, telemetry, _RSSI) :
                                             Eddystone.BeaconInfoForEIDFrameData(beaconServiceData, telemetry, _RSSI);
                            if (beaconInfo != null)
                            {
                                // NOTE: At this point you can choose whether to keep or get rid of the telemetry
                                //       data. You can either opt to include it with every single beacon sighting
                                //       for this beacon, or delete it until we get a new / "fresh" TLM frame.
                                //       We'll treat it as "report it only when you see it", so we'll delete it
                                //       each time.
                                deviceIDCache.Remove(peripheral.Identifier);

                                if (seenEddystoneCache.ContainsKey(beaconInfo.BeaconId.ToString()))
                                {
                                    var value = seenEddystoneCache[beaconInfo.BeaconId.ToString()]?["onLostTimer"];
                                    if (value != null)
                                    {
                                        var timer = (DispatchTimer)value;
                                        timer.Reschedule();
                                    }

                                    this.beaconScanner.ScannerDelegate?.DidUpdateBeacon(beaconScanner, beaconInfo);
                                }
                                else
                                {
                                    // We've never seen this beacon before
                                    this.beaconScanner.ScannerDelegate?.DidFindBeacon(beaconScanner, beaconInfo);

                                    var onLostTimer = DispatchTimer.ScheduledDispatchTimer(this.onLostTimout,
                                                                                           DispatchQueue.MainQueue,
                                                                                           (DispatchTimer obj) =>
                                    {
                                        var cacheKey = beaconInfo.BeaconId.ToString();
                                        if (seenEddystoneCache.ContainsKey(cacheKey))
                                        {
                                            var beaconCache    = seenEddystoneCache[cacheKey];
                                            var lostBeaconInfo = beaconCache["beaconInfo"] as BeaconInfo;
                                            if (beaconCache != null && lostBeaconInfo != null)
                                            {
                                                this.beaconScanner.ScannerDelegate?.DidLoseBeacon(beaconScanner, beaconInfo);
                                                seenEddystoneCache.Remove(beaconInfo.BeaconId.ToString());
                                            }
                                        }
                                    });
                                    var newMap = new Dictionary <string, object>()
                                    {
                                        { "beaconInfo", beaconInfo },
                                        { "onLostTimer", onLostTimer }
                                    };
                                    if (seenEddystoneCache.ContainsKey(beaconInfo.BeaconId.ToString()))
                                    {
                                        seenEddystoneCache[beaconInfo.BeaconId.ToString()] = newMap;
                                    }
                                    else
                                    {
                                        seenEddystoneCache.Add(beaconInfo.BeaconId.ToString(), newMap);
                                    }
                                }
                            }
                        }
                    }
                    else if (eft == BeaconInfo.EddystoneFrameType.URLFrameType)
                    {
                        var serviceUUID       = CBUUID.FromString("FEAA");
                        var _RSSI             = RSSI.Int32Value;
                        var beaconServiceData = serviceData[serviceUUID] as NSData;
                        if (beaconServiceData != null)
                        {
                            var url = Eddystone.ParseURLFromFrame(beaconServiceData);
                            if (url != null)
                            {
                                this.beaconScanner.ScannerDelegate?.DidObserveURLBeacon(beaconScanner, url, _RSSI);
                            }
                        }
                    }
                }
                else
                {
                    Debug.WriteLine("Unable to find service data; can't process Eddystone");
                }
            }