/// <summary> /// Meldet eine Analyseinstanz auf einem Datenstrom von SI Tabellen an. /// </summary> /// <param name="provider">Die zu aktuelle Hardware Abstraktion.</param> /// <param name="stream">Die eindeutige Nummer (PID) des Datenstroms in der aktuellen <see cref="SourceGroup"/>.</param> /// <param name="parser">Die zu verwendene Analyseeinheit.</param> /// <param name="streamType">Die Art der Tabellenkennungen, die verwendet werden.</param> /// <returns>Die eindeutige Kennung der neu angemeldeten Analyseeinheit.</returns> /// <exception cref="ArgumentNullException">Die Hardware Abstraktion und / oder die Analyseinstanz /// sind nicht gesetzt.</exception> public static Guid AddConsumer(this Hardware provider, ushort stream, TableParser parser, StreamTypes streamType) { // Validate if (null == provider) { throw new ArgumentNullException("provider"); } if (null == parser) { throw new ArgumentNullException("parser"); } // Register return(provider.AddConsumer(stream, streamType, parser.AddPayload)); }
/// <summary> /// Meldet einen Verbraucher für die Auswertung von SI Tabellen einer bestimmten Art an. /// </summary> /// <typeparam name="T">Die gewünschte Art von SI Tabellen.</typeparam> /// <param name="provider">Die zu aktuelle Hardware Abstraktion.</param> /// <param name="stream">Die eindeutige Nummer (PID) des Datenstroms in der aktuellen <see cref="SourceGroup"/>.</param> /// <param name="consumer">Die Methode, an die alle erkannten SI Tabellen der gewünschten Art gemeldet werden.</param> /// <returns>Die eindeutige Kennung des neu angemeldeten Verbrauchers.</returns> /// <exception cref="ArgumentNullException">Die Hardware Abstraktion und / oder der Verbraucher sind nicht gesetzt.</exception> public static Guid AddConsumer <T>(this Hardware provider, ushort stream, Action <T> consumer) where T : Table { // Validate if (null == provider) { throw new ArgumentNullException("provider"); } if (null == consumer) { throw new ArgumentNullException("consumer"); } // Forward return(provider.AddConsumer(stream, TableParser.Create(consumer), Table.GetIsExtendedTable <T>() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable)); }
/// <summary> /// Erzeugt eine neue Hintergrundaufgabe zum Auslesen von SI Tabellen. /// </summary> /// <param name="device">Das zu verwendende Gerät.</param> /// <param name="stream">Die Datenstromkennung, die überwacht werden soll.</param> /// <returns>Die neue Aufgabe.</returns> public static CancellableTask <TTableType[]> GetTableAsync <TTableType>(this Hardware device, ushort stream) where TTableType : Table { // Validate if (device == null) { throw new ArgumentException("no hardware to use", "device"); } // Create the task return (CancellableTask <TTableType[]> .Run(cancel => { // Termination synchronisation var sync = new object(); var done = false; // Parsing state var tables = default(TTableType[]); var expectedVersion = 0; var collectedParts = 0; // Create parser var parser = TableParser.Create(( TTableType table ) => { // Disabled if (done) { return; } // Check version if (tables != null) { if (table.Version != expectedVersion) { tables = null; } } // Discard on count mismatch if (tables != null) { if (tables.Length != (table.LastSection + 1)) { tables = null; } } // Discard on overrun if (tables != null) { if (table.CurrentSection >= tables.Length) { tables = null; } } // Discard on duplicates if (tables != null) { if (tables[table.CurrentSection] != null) { tables = null; } } // Create once if (tables == null) { // Create in full size tables = new TTableType[table.LastSection + 1]; expectedVersion = table.Version; collectedParts = 0; } // Add it tables[table.CurrentSection] = table; // Mark as done if (++collectedParts >= tables.Length) { lock (sync) { done = true; // Our wake up call Monitor.Pulse(sync); } } }); // Register with cleanup var tableType = Table.GetIsExtendedTable <TTableType>() ? StreamTypes.ExtendedTable : StreamTypes.StandardTable; var registration = device.AddConsumer(stream, tableType, parser.AddPayload); try { // Start receiving data device.SetConsumerState(registration, true); // Wait for end and fully process the cancellation token using (cancel.Register(() => { lock (sync) Monitor.Pulse(sync); })) lock (sync) while (!done) { if (cancel.IsCancellationRequested) { return null; } else { Monitor.Wait(sync); } } } finally { // Cleanup device.SetConsumerState(registration, null); } // Report return tables; })); }
/// <summary> /// Meldet einen Datenstrom zum Datenempfang an. /// </summary> /// <param name="pid">Die gewünschte Datestromkennung (PID).</param> /// <param name="type">Die Art der Nutzdaten im Datenstrom.</param> /// <param name="stream">Der Empfänger der Daten.</param> private void AddConsumer(ushort pid, StreamTypes type, StreamBase stream) => m_Consumers.Add(Hardware.AddConsumer(pid, type, stream.AddPayload));
/// <summary> /// Meldet eine Analyseinstanz auf einem Datenstrom von SI Tabellen an. /// </summary> /// <param name="provider">Die zu aktuelle Hardware Abstraktion.</param> /// <param name="stream">Die eindeutige Nummer (PID) des Datenstroms in der aktuellen <see cref="SourceGroup"/>.</param> /// <param name="parser">Die zu verwendene Analyseeinheit.</param> /// <returns>Die eindeutige Kennung des neu angemeldeten Verbrauchers.</returns> /// <exception cref="ArgumentNullException">Die Hardware Abstraktion und / oder die Analyseinstanz /// sind nicht gesetzt.</exception> public static Guid AddConsumer(this Hardware provider, ushort stream, TableParser parser) { // Forward return(provider.AddConsumer(stream, parser, StreamTypes.StandardTable)); }