using System; using System.Collections.Concurrent; using System.Net.Sockets; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace OpenRfid.LlrpService { /// /// High-throughput .NET 8 LLRP Fixed Reader Socket Service /// Connects to Impinj Speedway / Zebra FX9600 dock door portals on Port 5084 /// public class Program { private static readonly ConcurrentDictionary CooldownCache = new(); public static async Task Main(string[] args) { string host = args.Length > 0 ? args[0] : "192.168.1.100"; int port = args.Length > 1 ? int.Parse(args[1]) : 5084; Console.WriteLine($"[INFO] Initializing .NET 8 LLRP Client -> {host}:{port}..."); using var cts = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); }; try { using var client = new TcpClient(); await client.ConnectAsync(host, port, cts.Token); Console.WriteLine($"[SUCCESS] Connected to LLRP portal reader at {host}:{port}"); using var stream = client.GetStream(); byte[] buffer = new byte[8192]; while (!cts.Token.IsCancellationRequested) { int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cts.Token); if (bytesRead == 0) break; // Parse LLRP frame header (Type & Length) ushort messageType = (ushort)(((buffer[0] & 0x03) << 8) | buffer[1]); uint messageLength = (uint)((buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]); // Message Type 61 = RO_ACCESS_REPORT if (messageType == 61) { ProcessRoAccessReport(buffer, bytesRead); } } } catch (OperationCanceledException) { Console.WriteLine("[INFO] LLRP Service shutdown requested."); } catch (Exception ex) { Console.WriteLine($"[ERROR] Connection error: {ex.Message}"); } } private static void ProcessRoAccessReport(byte[] frame, int length) { // Simple fast EPC hex extraction demo from LLRP parameter stream long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // Clean cooldown cache every 30s foreach (var kvp in CooldownCache) { if (now - kvp.Value > 10000) CooldownCache.TryRemove(kvp.Key, out _); } Console.WriteLine($"[LLRP] Received RO_ACCESS_REPORT ({length} bytes). Processing tag batch..."); } } }