Exemplo n.º 1
0
        /// <summary>
        /// Returns an asynchronous stream over `TagEvent`s generated by `reader` with an optional timeout
        /// </summary>
        public static async IAsyncEnumerable <TagEvent> EventStream(
            ReaderManager reader,
            TimeSpan?timeout = null,
            [EnumeratorCancellation] CancellationToken enumCancellation = default
            )
        {
            CancellationTokenSource timeoutTokenSource  = null;
            CancellationTokenSource combinedTokenSource = null;

            if (timeout != null)
            {
                timeoutTokenSource = new CancellationTokenSource();
                timeoutTokenSource.CancelAfter(timeout.Value);
                combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(enumCancellation, timeoutTokenSource.Token);
            }
            var cancellationToken = combinedTokenSource?.Token ?? enumCancellation;

            var buffer         = new BufferBlock <TagEvent>();
            var tagDataHandler = new TagDataListener(tagData => buffer.Post(tagData));

            try
            {
                reader.reader.OnRoAccessReportReceived += tagDataHandler.OnRoAccessReport;
                while (!cancellationToken.IsCancellationRequested)
                {
                    TagEvent tagEvent;
                    try
                    {
                        tagEvent = await buffer.ReceiveAsync(cancellationToken);
                    }
                    catch (TaskCanceledException)
                    {
                        break;
                    }
                    yield return(tagEvent);
                }
            }
            finally
            {
                reader.reader.OnRoAccessReportReceived -= tagDataHandler.OnRoAccessReport;

                timeoutTokenSource?.Dispose();
                combinedTokenSource?.Dispose();
            }
        }
Exemplo n.º 2
0
        /// Scan for tags using an inventory command, returning a dictionary mapping tagIds
        /// to scan results.
        ///
        /// Returns results after all target tags have been read, or the timeout has elapsed
        private async Task <Dictionary <ushort, TagMetadata> > ScanTags(ushort[] tags, TimeSpan timeout)
        {
            this.progress.Info($"Scanning for: {TagString(tags)}\n");

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var targetTags  = new HashSet <ushort>(tags);
            var scanResults = new Dictionary <ushort, (TagEvent latest, int count)>();

            // Start an inventory command and read tag events from the event stream
            _ = this.reader.Inventory(TimeSpan.FromSeconds(1));
            await foreach (var tagEvent in TagDataListener.EventStream(this.reader, timeout))
            {
                if (targetTags.Contains(tagEvent.TagId))
                {
                    var count = 0;
                    if (scanResults.ContainsKey(tagEvent.TagId))
                    {
                        count = scanResults[tagEvent.TagId].count;
                    }
                    scanResults[tagEvent.TagId] = (tagEvent, count + 1);
                }

                if (scanResults.Count == tags.Length)
                {
                    // Received data from every target tag at least once
                    break;
                }
            }

            var duration = stopwatch.Elapsed.TotalSeconds;

            this.progress.Info($"Found {TagString(scanResults.Keys)} in {duration} seconds\n");

            return(TagMetadata.FromScanResults(scanResults, duration));
        }