Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8f6af7112 | ||
|
|
684513ee59 |
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -1776,46 +1776,4 @@
|
|||||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||||
<value>Nominální surový kalibrační faktor odpovídající 100 %. Tato hodnota se používá pro výpočet položky „iPerl CalibFactor (%)“ v konfiguraci výsledků.</value>
|
<value>Nominální surový kalibrační faktor odpovídající 100 %. Tato hodnota se používá pro výpočet položky „iPerl CalibFactor (%)“ v konfiguraci výsledků.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
|
||||||
|
|
||||||
Účel: Identifikuje komponentu, na kterou odkazují testy procedury.
|
|
||||||
Použití: Vyhledání komponenty a výběr Method v proceduře.
|
|
||||||
Rozsah hodnot: Jedinečný název komponenty.
|
|
||||||
Výchozí hodnota: SmartCommunicationGenesis
|
|
||||||
Uplatnění: Po přejmenování je nutný restart; zkontrolujte odkazy v procedurách.</value></data>
|
|
||||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
|
||||||
|
|
||||||
Účel: Časový limit pro požadavek na zrušení jednotlivého Genesis GCI volání.
|
|
||||||
Použití: Volání GciBridge z GenesisCommunicationForm (připojení, login, registry a související slot operace).
|
|
||||||
Rozsah hodnot: Celé číslo: 500–5000 ms.
|
|
||||||
Výchozí hodnota: 1800 ms.
|
|
||||||
Uplatnění: Načte se na začátku aktivity vodoměru. Každé volání/pokus má vlastní limit; více kroků může trvat déle. Zrušení musí podporovat spodní vrstva ovladače. Ostatní uživatelé bridge zachovají původní limity.</value></data>
|
|
||||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
|
||||||
|
|
||||||
Účel: Uložené nastavení opakování komunikace.
|
|
||||||
Použití: Aktuální tok Genesis slot/GCI jej nečte; nespouští opakování neúspěšné operace.
|
|
||||||
Rozsah hodnot: Celé číslo: 1–10.
|
|
||||||
Výchozí hodnota: 4
|
|
||||||
Uplatnění: Zachováno pro kompatibilitu; bez vlivu na opakování slot/GCI.</value></data>
|
|
||||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
|
||||||
|
|
||||||
Účel: Uložená prodleva mezi opakováními komunikace.
|
|
||||||
Použití: Aktuální tok Genesis slot/GCI ji nečte; neřídí zpoždění zavření formuláře.
|
|
||||||
Rozsah hodnot: Celé číslo: 0–5000 ms.
|
|
||||||
Výchozí hodnota: 0 ms
|
|
||||||
Uplatnění: Zachováno pro kompatibilitu; bez vlivu na prodlevy slot/GCI.</value></data>
|
|
||||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
|
||||||
|
|
||||||
Účel: Počet pracovních vláken pro nakonfigurované hlavy Genesis.
|
|
||||||
Použití: GenesisCommunicationForm: vytvoření vláken a rozdělení slotů. Nemění počet vodoměrů.
|
|
||||||
Rozsah hodnot: Celé číslo: 1–10.
|
|
||||||
Výchozí hodnota: 10
|
|
||||||
Uplatnění: Vyžaduje restart. Sestavení TURA_SPECIAL používají samostatné přidělování slotů.</value></data>
|
|
||||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
|
||||||
|
|
||||||
Účel: Počet neúspěšných vodoměrů, při kterém se zobrazí výsledek kontroly.
|
|
||||||
Použití: GenesisCommunicationSeq: aktivita iPERL_check při sestavení s IPERL. Uživatel může pokračovat nebo přerušit; nejde o obecný limit chyb slotů.
|
|
||||||
Rozsah hodnot: Celé číslo: 1–40. Práh: počet neúspěšných >= nastavení.
|
|
||||||
Výchozí hodnota: 10
|
|
||||||
Uplatnění: Použije se při následující příslušné kontrole; ne při běžných slot aktivitách.</value></data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -2238,46 +2238,4 @@
|
|||||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||||
<value>Roher Kalibrierfaktor, der 100 % entspricht. Dieser Wert wird zur Berechnung von „iPerl CalibFactor (%)“ in der Ergebnis-Konfiguration verwendet.</value>
|
<value>Roher Kalibrierfaktor, der 100 % entspricht. Dieser Wert wird zur Berechnung von „iPerl CalibFactor (%)“ in der Ergebnis-Konfiguration verwendet.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
|
||||||
|
|
||||||
Zweck: Identifiziert die Komponente, auf die die Tests der Prozedur verweisen.
|
|
||||||
Verwendung: Komponentensuche und Auswahl von Method in der Prozedur.
|
|
||||||
Wertebereich: Eindeutiger Komponentenname.
|
|
||||||
Standardwert: SmartCommunicationGenesis
|
|
||||||
Anwendung: Nach Umbenennung neu starten und Prozedurverweise prüfen.</value></data>
|
|
||||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
|
||||||
|
|
||||||
Zweck: Frist für die Abbruchanforderung eines einzelnen Genesis-GCI-Aufrufs.
|
|
||||||
Verwendung: GciBridge-Aufrufe aus GenesisCommunicationForm (Verbindung, Login, Register und zugehörige Slot-Operationen).
|
|
||||||
Wertebereich: Ganzzahl: 500–5000 ms.
|
|
||||||
Standardwert: 1800 ms.
|
|
||||||
Anwendung: Zu Beginn jeder Zähleraktivität gelesen. Jeder Aufruf/Versuch erhält eine eigene Frist; mehrere Schritte können länger dauern. Der Treiber muss den Abbruch unterstützen. Andere Bridge-Aufrufer behalten ihre bisherigen Zeitlimits.</value></data>
|
|
||||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
|
||||||
|
|
||||||
Zweck: Gespeicherte Einstellung für Kommunikationswiederholungen.
|
|
||||||
Verwendung: Der aktuelle Genesis-Slot/GCI-Ablauf liest diesen Wert nicht; fehlgeschlagene Operationen werden dadurch nicht wiederholt.
|
|
||||||
Wertebereich: Ganzzahl: 1–10.
|
|
||||||
Standardwert: 4
|
|
||||||
Anwendung: Für Kompatibilität gespeichert; keine Wirkung auf Slot/GCI-Wiederholungen.</value></data>
|
|
||||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
|
||||||
|
|
||||||
Zweck: Gespeicherte Pause zwischen Kommunikationswiederholungen.
|
|
||||||
Verwendung: Der aktuelle Genesis-Slot/GCI-Ablauf liest diesen Wert nicht; die Verzögerung beim Schließen des Formulars bleibt unverändert.
|
|
||||||
Wertebereich: Ganzzahl: 0–5000 ms.
|
|
||||||
Standardwert: 0 ms
|
|
||||||
Anwendung: Für Kompatibilität gespeichert; keine Wirkung auf Slot/GCI-Pausen.</value></data>
|
|
||||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
|
||||||
|
|
||||||
Zweck: Anzahl der Arbeitsthreads für konfigurierte Genesis-Köpfe.
|
|
||||||
Verwendung: GenesisCommunicationForm: Thread-Erstellung und Slot-Verteilung. Ändert nicht die Anzahl der Zähler.
|
|
||||||
Wertebereich: Ganzzahl: 1–10.
|
|
||||||
Standardwert: 10
|
|
||||||
Anwendung: Neustart erforderlich. TURA_SPECIAL-Builds verwenden eine separate Slot-Zuweisung.</value></data>
|
|
||||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
|
||||||
|
|
||||||
Zweck: Anzahl fehlgeschlagener Zähler, ab der das Prüfergebnis angezeigt wird.
|
|
||||||
Verwendung: GenesisCommunicationSeq: Aktivität iPERL_check bei Builds mit IPERL. Der Benutzer kann fortfahren oder abbrechen; kein allgemeiner Grenzwert für Slot-Fehler.
|
|
||||||
Wertebereich: Ganzzahl: 1–40. Schwelle: Fehleranzahl >= Einstellung.
|
|
||||||
Standardwert: 10
|
|
||||||
Anwendung: Gilt bei der nächsten entsprechenden Prüfung, nicht bei normalen Slot-Aktivitäten.</value></data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -2509,46 +2509,4 @@
|
|||||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||||
<value>Raw calibration factor representing 100 %. This value is used to calculate 'iPerl CalibFactor (%)' in the results configuration.</value>
|
<value>Raw calibration factor representing 100 %. This value is used to calculate 'iPerl CalibFactor (%)' in the results configuration.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
|
||||||
|
|
||||||
Purpose: Identifies the component referenced by procedure tests.
|
|
||||||
Used in: Component lookup and procedure Method selection.
|
|
||||||
Allowed values: Use a unique component name.
|
|
||||||
Default: SmartCommunicationGenesis.
|
|
||||||
Application: Restart required after renaming; review procedure references.</value></data>
|
|
||||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
|
||||||
|
|
||||||
Purpose: Cancellation deadline for each Genesis GCI request.
|
|
||||||
Used in: GciBridge requests made by GenesisCommunicationForm (connect, login, registers and related slot operations).
|
|
||||||
Allowed values: Integer: 500–5000 ms.
|
|
||||||
Default: 1800 ms.
|
|
||||||
Application: Read at the start of each meter activity. Each request/attempt gets its own deadline; a multi-step test can take longer. Cancellation is cooperative: the underlying driver must honor the token. Legacy callers outside this flow retain their original timeouts.</value></data>
|
|
||||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
|
||||||
|
|
||||||
Purpose: Stored communication retry setting.
|
|
||||||
Used in: Not consumed by the current Genesis slot/GCI workflow; does not cause failed slot operations to retry.
|
|
||||||
Allowed values: Integer: 1–10.
|
|
||||||
Default: 4.
|
|
||||||
Application: Stored for compatibility; no slot/GCI retry effect.</value></data>
|
|
||||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
|
||||||
|
|
||||||
Purpose: Stored delay between communication retries.
|
|
||||||
Used in: Not consumed by the current Genesis slot/GCI workflow; does not control the form closing delay.
|
|
||||||
Allowed values: Integer: 0–5000 ms.
|
|
||||||
Default: 0 ms.
|
|
||||||
Application: Stored for compatibility; no slot/GCI delay effect.</value></data>
|
|
||||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
|
||||||
|
|
||||||
Purpose: Number of worker threads for processing configured Genesis heads.
|
|
||||||
Used in: GenesisCommunicationForm: worker creation and slot distribution. Does not change the number of configured meters.
|
|
||||||
Allowed values: Integer: 1–10.
|
|
||||||
Default: 10.
|
|
||||||
Application: Restart required. TURA_SPECIAL builds use a separate slot scheduling branch.</value></data>
|
|
||||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
|
||||||
|
|
||||||
Purpose: Number of failed meters that triggers a check-result prompt.
|
|
||||||
Used in: GenesisCommunicationSeq: iPERL_check activity, when compiled with IPERL. User may Continue or Abort. Not a general slot-error stop limit.
|
|
||||||
Allowed values: Integer: 1–40.
|
|
||||||
Default: 10. Threshold uses failed count >= setting.
|
|
||||||
Application: Applied to the next applicable check; no effect on ordinary slot activities.</value></data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -274,46 +274,4 @@
|
|||||||
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
<data name="IperlCalibFactorNominalTooltip" xml:space="preserve">
|
||||||
<value>Nominálny surový kalibračný faktor zodpovedajúci 100 %. Táto hodnota sa používa na výpočet položky „iPerl CalibFactor (%)“ v konfigurácii výsledkov.</value>
|
<value>Nominálny surový kalibračný faktor zodpovedajúci 100 %. Táto hodnota sa používa na výpočet položky „iPerl CalibFactor (%)“ v konfigurácii výsledkov.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenesisTooltip_nameTextBox" xml:space="preserve"><value>Name
|
|
||||||
|
|
||||||
Účel: Identifikuje komponent, na ktorý odkazujú testy procedúry.
|
|
||||||
Použitie: Vyhľadanie komponentu a výber Method v procedúre.
|
|
||||||
Rozsah hodnôt: Jedinečný názov komponentu.
|
|
||||||
Prednastavená hodnota: SmartCommunicationGenesis
|
|
||||||
Uplatnenie: Po premenovaní je potrebný reštart; skontrolujte odkazy v procedúrach.</value></data>
|
|
||||||
<data name="GenesisTooltip_commTimeoutTextBox" xml:space="preserve"><value>CommTimeout
|
|
||||||
|
|
||||||
Účel: Časový limit pre požiadavku na zrušenie jednotlivého Genesis GCI volania.
|
|
||||||
Použitie: Volania GciBridge z GenesisCommunicationForm (pripojenie, login, registre a súvisiace slot operácie).
|
|
||||||
Rozsah hodnôt: Celé číslo: 500–5000 ms.
|
|
||||||
Prednastavená hodnota: 1800 ms.
|
|
||||||
Uplatnenie: Načíta sa na začiatku aktivity vodomera. Každé volanie/pokus má vlastný limit; viac krokov môže trvať dlhšie. Zrušenie musí podporovať spodná vrstva ovládača. Ostatní používatelia bridge zachovajú pôvodné limity.</value></data>
|
|
||||||
<data name="GenesisTooltip_maxCommRetriesTextBox" xml:space="preserve"><value>MaxCommRetries
|
|
||||||
|
|
||||||
Účel: Uložené nastavenie opakovania komunikácie.
|
|
||||||
Použitie: Aktuálny tok Genesis slot/GCI ho nečíta; nespúšťa opakovanie neúspešnej operácie.
|
|
||||||
Rozsah hodnôt: Celé číslo: 1–10.
|
|
||||||
Prednastavená hodnota: 4
|
|
||||||
Uplatnenie: Zachované pre kompatibilitu; bez vplyvu na opakovanie slot/GCI.</value></data>
|
|
||||||
<data name="GenesisTooltip_delayBetweenRetriesTextBox" xml:space="preserve"><value>DelayBetweenRetries
|
|
||||||
|
|
||||||
Účel: Uložená pauza medzi opakovaniami komunikácie.
|
|
||||||
Použitie: Aktuálny tok Genesis slot/GCI ju nečíta; neriadi oneskorenie zatvorenia formulára.
|
|
||||||
Rozsah hodnôt: Celé číslo: 0–5000 ms.
|
|
||||||
Prednastavená hodnota: 0 ms
|
|
||||||
Uplatnenie: Zachované pre kompatibilitu; bez vplyvu na pauzy slot/GCI.</value></data>
|
|
||||||
<data name="GenesisTooltip_nrThreadsTextBox" xml:space="preserve"><value>NrThreads
|
|
||||||
|
|
||||||
Účel: Počet pracovných vlákien pre nakonfigurované hlavy Genesis.
|
|
||||||
Použitie: GenesisCommunicationForm: vytvorenie vlákien a rozdelenie slotov. Nemení počet vodomerov.
|
|
||||||
Rozsah hodnôt: Celé číslo: 1–10.
|
|
||||||
Prednastavená hodnota: 10
|
|
||||||
Uplatnenie: Vyžaduje reštart. Zostavenia TURA_SPECIAL používajú samostatné prideľovanie slotov.</value></data>
|
|
||||||
<data name="GenesisTooltip_iperlCheckErrorsToStopTextBox" xml:space="preserve"><value>IperlCheckErrorsToStop
|
|
||||||
|
|
||||||
Účel: Počet neúspešných vodomerov, pri ktorom sa zobrazí výsledok kontroly.
|
|
||||||
Použitie: GenesisCommunicationSeq: aktivita iPERL_check pri zostavení s IPERL. Používateľ môže pokračovať alebo prerušiť; nejde o všeobecný limit chýb slotov.
|
|
||||||
Rozsah hodnôt: Celé číslo: 1–40. Prah: počet neúspešných >= nastavenie.
|
|
||||||
Prednastavená hodnota: 10
|
|
||||||
Uplatnenie: Použije sa pri nasledujúcej príslušnej kontrole; nie pri bežných slot aktivitách.</value></data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CordonelPreadjustmentUi;
|
using CordonelPreadjustmentUi;
|
||||||
using CordonelPreadjustmentUi.Processes.Itinerary;
|
using CordonelPreadjustmentUi.Processes.Itinerary;
|
||||||
using GenesisCordonelInterface.API;
|
using GenesisCordonelInterface.API;
|
||||||
using GenesisCordonelInterface.Core;
|
using GenesisCordonelInterface.Core;
|
||||||
@@ -37,41 +37,6 @@ using UdsWriterType = TBF.Rig.Output.DataStorage.UniDataStorageWriter.Writer;
|
|||||||
|
|
||||||
namespace TBF.Rig.BridgeComponents.GciBridge
|
namespace TBF.Rig.BridgeComponents.GciBridge
|
||||||
{
|
{
|
||||||
/// <summary>Per-async-flow Genesis request timeout; absent for legacy callers.</summary>
|
|
||||||
public static class GenesisRequestTimeout
|
|
||||||
{
|
|
||||||
private static readonly AsyncLocal<int?> current = new AsyncLocal<int?>();
|
|
||||||
private static readonly ILog timeoutLog = LogManager.GetLogger(typeof(GenesisRequestTimeout));
|
|
||||||
|
|
||||||
public static IDisposable Begin(int milliseconds)
|
|
||||||
{
|
|
||||||
if (milliseconds < 500 || milliseconds > 5000) throw new ArgumentOutOfRangeException(nameof(milliseconds));
|
|
||||||
var previous = current.Value;
|
|
||||||
current.Value = milliseconds;
|
|
||||||
return new Scope(previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CancellationTokenSource CreateDeadline(CancellationToken callerToken, string operation)
|
|
||||||
{
|
|
||||||
var milliseconds = current.Value;
|
|
||||||
if (!milliseconds.HasValue) return null;
|
|
||||||
var source = CancellationTokenSource.CreateLinkedTokenSource(callerToken);
|
|
||||||
timeoutLog.DebugFormat("Genesis CommTimeout applied: Operation={0}, TimeoutMs={1}", operation, milliseconds.Value);
|
|
||||||
source.Token.Register(() => timeoutLog.WarnFormat("Genesis request cancellation requested: Operation={0}, TimeoutMs={1}, CallerCancelled={2}", operation, milliseconds.Value, callerToken.IsCancellationRequested));
|
|
||||||
source.CancelAfter(milliseconds.Value);
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class Scope : IDisposable
|
|
||||||
{
|
|
||||||
private readonly int? previous;
|
|
||||||
private bool disposed;
|
|
||||||
public Scope(int? previous) { this.previous = previous; }
|
|
||||||
public void Dispose() { if (!disposed) { current.Value = previous; disposed = true; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TBF bridge component for integration with the sibling GCI project.
|
/// TBF bridge component for integration with the sibling GCI project.
|
||||||
/// The component can be linked to UniDataStorage reader and writer components.
|
/// The component can be linked to UniDataStorage reader and writer components.
|
||||||
@@ -323,8 +288,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
GciPublicModels.GciInitSlotRequest request,
|
GciPublicModels.GciInitSlotRequest request,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "InitSlotAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (request == null)
|
if (request == null)
|
||||||
@@ -406,8 +369,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
GciPublicModels.GciInitSlotRequest request,
|
GciPublicModels.GciInitSlotRequest request,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "UpdateSlotAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (request == null)
|
if (request == null)
|
||||||
@@ -486,8 +447,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slotId,
|
int slotId,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetSlotAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -564,8 +523,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "CleanSlotAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slot <= 0)
|
if (slot <= 0)
|
||||||
@@ -642,8 +599,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
public async Task<GciPublicModels.GciCleanAllSlotsResult> CleanAllSlotsAsync(
|
public async Task<GciPublicModels.GciCleanAllSlotsResult> CleanAllSlotsAsync(
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "CleanAllSlotsAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
GciPublicModels.GciCleanAllSlotsResult result =
|
GciPublicModels.GciCleanAllSlotsResult result =
|
||||||
@@ -716,8 +671,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slotId,
|
int slotId,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPcbIdAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -835,8 +788,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ConnectAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slot <= 0)
|
if (slot <= 0)
|
||||||
@@ -869,8 +820,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slotId,
|
int slotId,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "LoginAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -942,8 +891,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slotId,
|
int slotId,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "DisconnectAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -1023,8 +970,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
string password,
|
string password,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "SetPasswordAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -1101,8 +1046,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
string registerName,
|
string registerName,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ReadRegisterAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -1193,8 +1136,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
bool refreshSystemState = false,
|
bool refreshSystemState = false,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "WriteRegisterAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
|
|
||||||
if (slotId <= 0)
|
if (slotId <= 0)
|
||||||
@@ -1298,8 +1239,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
string pcbId,
|
string pcbId,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPasswordAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureReader();
|
EnsureReader();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(pcbId))
|
if (string.IsNullOrWhiteSpace(pcbId))
|
||||||
@@ -1378,8 +1317,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int meterSize,
|
int meterSize,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "GetPreAdjustmentCalibrationParamsAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureReader();
|
EnsureReader();
|
||||||
|
|
||||||
if (meterSize < 0)
|
if (meterSize < 0)
|
||||||
@@ -1567,8 +1504,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
/// <returns>Complete workflow result including all retry statistics and operation results.</returns>
|
/// <returns>Complete workflow result including all retry statistics and operation results.</returns>
|
||||||
public async Task<GciFullLoginResult> ConnectFullPassLoginWithRetryAsync(int slotId, CancellationToken token = default)
|
public async Task<GciFullLoginResult> ConnectFullPassLoginWithRetryAsync(int slotId, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "ConnectFullPassLoginWithRetryAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
EnsureExternalInterface();
|
EnsureExternalInterface();
|
||||||
EnsureReader();
|
EnsureReader();
|
||||||
|
|
||||||
@@ -1670,8 +1605,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
IEnumerable<GciPublicModels.MeterBatchDebugStatus> selectedSlots,
|
IEnumerable<GciPublicModels.MeterBatchDebugStatus> selectedSlots,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_DetectAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_DetectAsync);
|
const string operation = nameof(PreAdjustment_DetectAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -1745,8 +1678,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_PreparationAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_PreparationAsync);
|
const string operation = nameof(PreAdjustment_PreparationAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -1827,8 +1758,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_AmplitudeTestAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_AmplitudeTestAsync);
|
const string operation = nameof(PreAdjustment_AmplitudeTestAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -1909,8 +1838,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_TemperatureCalibrationAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_TemperatureCalibrationAsync);
|
const string operation = nameof(PreAdjustment_TemperatureCalibrationAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -2018,8 +1945,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_OffsetTestAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_OffsetTestAsync);
|
const string operation = nameof(PreAdjustment_OffsetTestAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -2100,8 +2025,6 @@ namespace TBF.Rig.BridgeComponents.GciBridge
|
|||||||
int slot,
|
int slot,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
using var deadline = GenesisRequestTimeout.CreateDeadline(token, "PreAdjustment_CompletionAsync");
|
|
||||||
token = deadline == null ? token : deadline.Token;
|
|
||||||
const string operation = nameof(PreAdjustment_CompletionAsync);
|
const string operation = nameof(PreAdjustment_CompletionAsync);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1407,11 +1407,22 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string WriteQ3Calibration(TestMethodCfg cfg, Test test, WaterMeter wm)
|
public string WriteQ3Calibration(TestMethodCfg cfg, Test test, WaterMeter wm)
|
||||||
|
{
|
||||||
|
return WriteQ3Calibration(cfg, test, wm, test);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="test">The preceding Q3 measurement test whose result receives the factors.</param>
|
||||||
|
/// <param name="validationTest">The current Write Q3 Calibration activity; its error limits validate the factors.</param>
|
||||||
|
public string WriteQ3Calibration(TestMethodCfg cfg, Test test, WaterMeter wm, Test validationTest)
|
||||||
{
|
{
|
||||||
if (genesisHead != null && genesisHead.DebugLevel == DebugMode.Simulate)
|
if (genesisHead != null && genesisHead.DebugLevel == DebugMode.Simulate)
|
||||||
{
|
{
|
||||||
if (test == null || wm == null) return "Missing Genesis meter or test";
|
if (test == null || wm == null) return "Missing Genesis meter or test";
|
||||||
if (!genesisHead.CalculateQ3Calibration() || !genesisHead.Q3CalibValid)
|
double errorLimitLo;
|
||||||
|
double errorLimitHi;
|
||||||
|
GenesisSmartReader.TryGetEffectiveQ3CalibrationErrorLimits(validationTest == null ? 0 : validationTest.ErrLimLo,
|
||||||
|
validationTest == null ? 0 : validationTest.ErrLimHi, out errorLimitLo, out errorLimitHi);
|
||||||
|
if (!genesisHead.CalculateQ3CalibrationWithErrorLimits(errorLimitLo, errorLimitHi) || !genesisHead.Q3CalibValid)
|
||||||
return "Q3 simulation requires valid measurement data";
|
return "Q3 simulation requires valid measurement data";
|
||||||
var result = ProcessData.BatchRslts.GetTestRslt(test.Name, test.Part);
|
var result = ProcessData.BatchRslts.GetTestRslt(test.Name, test.Part);
|
||||||
StoreCalibrationValuesResults(result, genesisHead, wm);
|
StoreCalibrationValuesResults(result, genesisHead, wm);
|
||||||
@@ -1434,7 +1445,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
return "Missing Test";
|
return "Missing Test";
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.Run(() => WriteQ3Calibration_Async(genesisHead, cfg, test, wm))
|
return Task.Run(() => WriteQ3Calibration_Async(genesisHead, cfg, test, wm, validationTest))
|
||||||
.GetAwaiter()
|
.GetAwaiter()
|
||||||
.GetResult();
|
.GetResult();
|
||||||
}
|
}
|
||||||
@@ -1443,7 +1454,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
|
|
||||||
private async Task<string> WriteQ3Calibration_Async(GenesisSmartReader genesisSmartReader,
|
private async Task<string> WriteQ3Calibration_Async(GenesisSmartReader genesisSmartReader,
|
||||||
TestMethodCfg cfg,
|
TestMethodCfg cfg,
|
||||||
Test test, WaterMeter wm)
|
Test test, WaterMeter wm, Test validationTest)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1489,7 +1500,16 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
|
|
||||||
CancellationToken token = default;
|
CancellationToken token = default;
|
||||||
|
|
||||||
bool areInitialisedData = genesisSmartReader.CalculateQ3Calibration();
|
Test effectiveValidationTest = validationTest ?? test;
|
||||||
|
double errorLimitLo;
|
||||||
|
double errorLimitHi;
|
||||||
|
bool procedureLimitsConfigured = GenesisSmartReader.TryGetEffectiveQ3CalibrationErrorLimits(
|
||||||
|
effectiveValidationTest == null ? 0 : effectiveValidationTest.ErrLimLo,
|
||||||
|
effectiveValidationTest == null ? 0 : effectiveValidationTest.ErrLimHi,
|
||||||
|
out errorLimitLo, out errorLimitHi);
|
||||||
|
log.Info($"WriteQ3Calibration_Async( Slot: {genesisSmartReader.GetSlotNr}) - Q3 factor validation limits: {errorLimitLo} .. {errorLimitHi}% ({(procedureLimitsConfigured ? "Write Q3 Calibration activity" : "default")})");
|
||||||
|
|
||||||
|
bool areInitialisedData = genesisSmartReader.CalculateQ3CalibrationWithErrorLimits(errorLimitLo, errorLimitHi);
|
||||||
if (!areInitialisedData)
|
if (!areInitialisedData)
|
||||||
{
|
{
|
||||||
log.Error("WriteQ3Calibration_Async() - CalculateQ3Calibration Initialised Data not valid");
|
log.Error("WriteQ3Calibration_Async() - CalculateQ3Calibration Initialised Data not valid");
|
||||||
@@ -1501,7 +1521,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
if (!genesisSmartReader.Q3CalibValid)
|
if (!genesisSmartReader.Q3CalibValid)
|
||||||
{
|
{
|
||||||
log.Error("WriteQ3Calibration_Async() - Q3Channel not valid");
|
log.Error("WriteQ3Calibration_Async() - Q3Channel not valid");
|
||||||
return "Q3Channel not valid";
|
return $"Q3Channel not valid ({errorLimitLo} .. {errorLimitHi}%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get Activity Status
|
//Get Activity Status
|
||||||
@@ -2056,4 +2076,4 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3928,6 +3928,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>Compatibility limit used when the Write Q3 Calibration activity has no error limits configured.</summary>
|
||||||
|
public const double DefaultQ3CalibrationFactorErrorLimit = 5.0;
|
||||||
|
|
||||||
private double[] q3CalibInitial = {Double.NaN,Double.NaN,Double.NaN};
|
private double[] q3CalibInitial = {Double.NaN,Double.NaN,Double.NaN};
|
||||||
private bool[] isChQ3CalibValid = { false,false,false};
|
private bool[] isChQ3CalibValid = { false,false,false};
|
||||||
private double[] q3CalibCh = {Double.NaN,Double.NaN,Double.NaN};
|
private double[] q3CalibCh = {Double.NaN,Double.NaN,Double.NaN};
|
||||||
@@ -3979,6 +3982,17 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
|
|
||||||
|
|
||||||
public bool CalculateQ3Calibration()
|
public bool CalculateQ3Calibration()
|
||||||
|
{
|
||||||
|
return CalculateQ3CalibrationWithErrorLimits(-DefaultQ3CalibrationFactorErrorLimit,
|
||||||
|
DefaultQ3CalibrationFactorErrorLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates Q3 factors using the limits configured on the procedure activity that writes them.
|
||||||
|
/// A pair for which the high limit is not greater than the low limit (the normal unset 0 / 0
|
||||||
|
/// value) falls back to the historical +/- 5 % validation.
|
||||||
|
/// </summary>
|
||||||
|
public bool CalculateQ3CalibrationWithErrorLimits(double errorLimitLo, double errorLimitHi)
|
||||||
{
|
{
|
||||||
if (Double.IsNaN(refVolume) || Double.IsInfinity(refVolume) || refVolume <= 0 || Double.IsNaN(refTime) || Double.IsInfinity(refTime) || refTime <= 0)
|
if (Double.IsNaN(refVolume) || Double.IsInfinity(refVolume) || refVolume <= 0 || Double.IsNaN(refTime) || Double.IsInfinity(refTime) || refTime <= 0)
|
||||||
{
|
{
|
||||||
@@ -3986,13 +4000,24 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateQ3Calibration( refVolume, refTime);
|
CalculateQ3Calibration(refVolume, refTime, errorLimitLo, errorLimitHi);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateQ3Calibration(double refVolume, double refTime)
|
public void CalculateQ3Calibration(double refVolume, double refTime)
|
||||||
{
|
{
|
||||||
GetQ3Calibration(refVolume, refTime, q3CalibInitial, ref isChQ3CalibValid,ref q3DiffPercentageCalibCh, ref q3CalibCh);
|
CalculateQ3Calibration(refVolume, refTime, -DefaultQ3CalibrationFactorErrorLimit,
|
||||||
|
DefaultQ3CalibrationFactorErrorLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CalculateQ3Calibration(double refVolume, double refTime, double errorLimitLo, double errorLimitHi)
|
||||||
|
{
|
||||||
|
double effectiveErrorLimitLo;
|
||||||
|
double effectiveErrorLimitHi;
|
||||||
|
TryGetEffectiveQ3CalibrationErrorLimits(errorLimitLo, errorLimitHi,
|
||||||
|
out effectiveErrorLimitLo, out effectiveErrorLimitHi);
|
||||||
|
GetQ3Calibration(refVolume, refTime, q3CalibInitial, effectiveErrorLimitLo,
|
||||||
|
effectiveErrorLimitHi, ref isChQ3CalibValid, ref q3DiffPercentageCalibCh, ref q3CalibCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] q3CalibCh)
|
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] q3CalibCh)
|
||||||
@@ -4002,6 +4027,36 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] calibDiffPercent, ref double[] q3CalibCh)
|
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] calibDiffPercent, ref double[] q3CalibCh)
|
||||||
|
{
|
||||||
|
GetQ3Calibration(refVolume, refTime, initCalibFactor,
|
||||||
|
-DefaultQ3CalibrationFactorErrorLimit, DefaultQ3CalibrationFactorErrorLimit,
|
||||||
|
ref isChQ3CalibValid, ref calibDiffPercent, ref q3CalibCh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves the error limits used to validate a calculated Q3 factor. TBF stores an unset
|
||||||
|
/// limit pair as equal values (normally 0 / 0), so only an ordered finite pair is considered set.
|
||||||
|
/// </summary>
|
||||||
|
public static bool TryGetEffectiveQ3CalibrationErrorLimits(double errorLimitLo, double errorLimitHi,
|
||||||
|
out double effectiveErrorLimitLo, out double effectiveErrorLimitHi)
|
||||||
|
{
|
||||||
|
if (!Double.IsNaN(errorLimitLo) && !Double.IsInfinity(errorLimitLo) &&
|
||||||
|
!Double.IsNaN(errorLimitHi) && !Double.IsInfinity(errorLimitHi) &&
|
||||||
|
errorLimitHi > errorLimitLo)
|
||||||
|
{
|
||||||
|
effectiveErrorLimitLo = errorLimitLo;
|
||||||
|
effectiveErrorLimitHi = errorLimitHi;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveErrorLimitLo = -DefaultQ3CalibrationFactorErrorLimit;
|
||||||
|
effectiveErrorLimitHi = DefaultQ3CalibrationFactorErrorLimit;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor,
|
||||||
|
double errorLimitLo, double errorLimitHi, ref bool[] isChQ3CalibValid,
|
||||||
|
ref double[] calibDiffPercent, ref double[] q3CalibCh)
|
||||||
{
|
{
|
||||||
log.Debug("=== Q3 CALIBRATION START ===");
|
log.Debug("=== Q3 CALIBRATION START ===");
|
||||||
|
|
||||||
@@ -4021,7 +4076,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug($"Inputs: refVolume={refVolume}, refTime={refTime}, initCalibFactors={string.Join(",", initCalibFactor)}");
|
log.Debug($"Inputs: refVolume={refVolume}, refTime={refTime}, initCalibFactors={string.Join(",", initCalibFactor)}, errorLimits={errorLimitLo}..{errorLimitHi}%");
|
||||||
|
|
||||||
if (_rawStartEndByChannel == null)
|
if (_rawStartEndByChannel == null)
|
||||||
{
|
{
|
||||||
@@ -4110,10 +4165,16 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
}
|
}
|
||||||
|
|
||||||
q3CalibCh[iChannel] = (refVolume / recalculatedDeltaVolume) * initCalibFactor[iChannel];
|
q3CalibCh[iChannel] = (refVolume / recalculatedDeltaVolume) * initCalibFactor[iChannel];
|
||||||
double diffPercent = Math.Abs((initCalibFactor[iChannel] - q3CalibCh[iChannel] ) / initCalibFactor[iChannel]) * 100.0;
|
// Procedure error limits are an ordered range, e.g. -2 .. +2, so validation
|
||||||
isChQ3CalibValid[iChannel] = diffPercent <= 5.0 && !double.IsNaN(q3CalibCh[iChannel]) && !double.IsInfinity(q3CalibCh[iChannel]) && q3CalibCh[iChannel] >= 1 && q3CalibCh[iChannel] <= ushort.MaxValue;
|
// must retain the direction of the factor change. Keep the persisted difference
|
||||||
|
// absolute for compatibility with the existing calibration-result fields.
|
||||||
|
double signedDiffPercent = ((q3CalibCh[iChannel] - initCalibFactor[iChannel]) / initCalibFactor[iChannel]) * 100.0;
|
||||||
|
double diffPercent = Math.Abs(signedDiffPercent);
|
||||||
|
isChQ3CalibValid[iChannel] = signedDiffPercent >= errorLimitLo && signedDiffPercent <= errorLimitHi &&
|
||||||
|
!double.IsNaN(q3CalibCh[iChannel]) && !double.IsInfinity(q3CalibCh[iChannel]) &&
|
||||||
|
q3CalibCh[iChannel] >= 1 && q3CalibCh[iChannel] <= ushort.MaxValue;
|
||||||
calibDiffPercent[iChannel] = diffPercent;
|
calibDiffPercent[iChannel] = diffPercent;
|
||||||
log.Debug($"Calculated Q3Calib Ch[{iChannel}] ={q3CalibCh[iChannel]} DiffPercent={diffPercent}% isValid[{isChQ3CalibValid[iChannel]}] IninitCalibFactor={initCalibFactor}");
|
log.Debug($"Calculated Q3Calib Ch[{iChannel}] ={q3CalibCh[iChannel]} SignedDiffPercent={signedDiffPercent}% DiffPercent={diffPercent}% isValid[{isChQ3CalibValid[iChannel]}] IninitCalibFactor={initCalibFactor}");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("=== Q3 CALIBRATION END ===");
|
log.Debug("=== Q3 CALIBRATION END ===");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using TBF.Rig.TestMethods.iPerlCommunication;
|
using TBF.Rig.TestMethods.iPerlCommunication;
|
||||||
///
|
///
|
||||||
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
|
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
|
||||||
///
|
///
|
||||||
@@ -765,8 +765,6 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
|
|
||||||
CommErr error;
|
CommErr error;
|
||||||
string resultStr = string.Empty;
|
string resultStr = string.Empty;
|
||||||
using var requestTimeout = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(cfg.CommTimeout);
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// RFID communication activity call
|
/// RFID communication activity call
|
||||||
@@ -1090,7 +1088,9 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
BeforeTest = currentTest;
|
BeforeTest = currentTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gciFullLoginResult = iHead.OptoHeadTest.WriteQ3Calibration(cfg, BeforeTest, wm);
|
// Keep the Q3 measurement result on the preceding test, but validate against the
|
||||||
|
// limits configured on the current "Write Q3 Calibration Slot" activity.
|
||||||
|
var gciFullLoginResult = iHead.OptoHeadTest.WriteQ3Calibration(cfg, BeforeTest, wm, currentTest);
|
||||||
if (!string.IsNullOrEmpty(gciFullLoginResult) &&
|
if (!string.IsNullOrEmpty(gciFullLoginResult) &&
|
||||||
gciFullLoginResult.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
|
gciFullLoginResult.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
///
|
///
|
||||||
/// Copyright (c) 2015-2022 Sensus Slovensko a.s.
|
/// Copyright (c) 2015-2022 Sensus Slovensko a.s.
|
||||||
///
|
///
|
||||||
|
|
||||||
@@ -58,9 +58,6 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
testMethodCfg.UseWebService = tmpCfg.UseWebService;
|
testMethodCfg.UseWebService = tmpCfg.UseWebService;
|
||||||
testMethodCfg.BaseUrl = tmpCfg.BaseUrl;
|
testMethodCfg.BaseUrl = tmpCfg.BaseUrl;
|
||||||
testMethodCfg.RelativeUrl = tmpCfg.RelativeUrl;
|
testMethodCfg.RelativeUrl = tmpCfg.RelativeUrl;
|
||||||
log.InfoFormat("Genesis runtime configuration applied: Name={0}, CommTimeout={1}ms, MaxRetries={2}, DelayBetweenRetries={3}ms, ErrorsToStop={4}",
|
|
||||||
Name, testMethodCfg.CommTimeout, testMethodCfg.MaxCommRetries,
|
|
||||||
testMethodCfg.DelayBetweenRetries, testMethodCfg.IperlCheckErrorsToStop);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -83,12 +80,6 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
: base(cfg)
|
: base(cfg)
|
||||||
{
|
{
|
||||||
testMethodCfg = cfg as TestMethodCfg;
|
testMethodCfg = cfg as TestMethodCfg;
|
||||||
if (testMethodCfg != null)
|
|
||||||
log.InfoFormat("Genesis component configuration loaded: Name={0}, CommTimeout={1}ms, MaxRetries={2}, DelayBetweenRetries={3}ms, NrThreads={4}, ErrorsToStop={5}",
|
|
||||||
testMethodCfg.Name, testMethodCfg.CommTimeout, testMethodCfg.MaxCommRetries,
|
|
||||||
testMethodCfg.DelayBetweenRetries, testMethodCfg.NrThreads, testMethodCfg.IperlCheckErrorsToStop);
|
|
||||||
else
|
|
||||||
log.Error("Genesis component received an incompatible or null configuration.");
|
|
||||||
CreateMilestonesAndConditions();
|
CreateMilestonesAndConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
///
|
///
|
||||||
/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
|
/// Copyright (c) 2015-2020 Sensus Slovensko a.s.
|
||||||
///
|
///
|
||||||
|
|
||||||
@@ -12,21 +12,15 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
{
|
{
|
||||||
public partial class TestMethodCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl
|
public partial class TestMethodCfgCtrl : Configs.ConfigCtrlUtils, IComponentCfgCtrl
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(TestMethodCfgCtrl));
|
public bool ShowMore { get { return false; } }
|
||||||
|
|
||||||
public bool ShowMore { get { return false; } }
|
iPerlCommunication.TestMethodCfg config;
|
||||||
|
|
||||||
TestMethodCfg config;
|
|
||||||
public IComponentCfg Config
|
public IComponentCfg Config
|
||||||
{
|
{
|
||||||
get { return config as IComponentCfg; }
|
get { return config as IComponentCfg; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
config = value as TestMethodCfg;
|
config = value as iPerlCommunication.TestMethodCfg;
|
||||||
if (config == null)
|
|
||||||
log.ErrorFormat("Genesis Properties configuration rejected: expected {0}, received {1}", typeof(TestMethodCfg).FullName, value == null ? "null" : value.GetType().FullName);
|
|
||||||
else
|
|
||||||
LogConfiguration("loaded");
|
|
||||||
Redraw();
|
Redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +28,6 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
public TestMethodCfgCtrl()
|
public TestMethodCfgCtrl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
InitializeSettingToolTips();
|
|
||||||
dfltQ2corrFactorsGroupBox.Visible = false;
|
dfltQ2corrFactorsGroupBox.Visible = false;
|
||||||
useWebServiceGroupBox.Visible = false;
|
useWebServiceGroupBox.Visible = false;
|
||||||
var factorHint = new System.Windows.Forms.Label
|
var factorHint = new System.Windows.Forms.Label
|
||||||
@@ -57,7 +50,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
void Redraw()
|
void Redraw()
|
||||||
{
|
{
|
||||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||||
classNameLabel.Text = config.Factory == null ? "TestMethods.GenesisCommunication" : config.Factory.ClassName;
|
classNameLabel.Text = config.Factory.ClassName;
|
||||||
nameTextBox.Text = config.Name;
|
nameTextBox.Text = config.Name;
|
||||||
commTimeoutTextBox.Text = config.CommTimeout.ToString();
|
commTimeoutTextBox.Text = config.CommTimeout.ToString();
|
||||||
maxCommRetriesTextBox.Text = config.MaxCommRetries.ToString();
|
maxCommRetriesTextBox.Text = config.MaxCommRetries.ToString();
|
||||||
@@ -65,7 +58,22 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
nrThreadsTextBox.Text = config.NrThreads.ToString();
|
nrThreadsTextBox.Text = config.NrThreads.ToString();
|
||||||
iperlCheckErrorsToStopTextBox.Text = config.IperlCheckErrorsToStop.ToString();
|
iperlCheckErrorsToStopTextBox.Text = config.IperlCheckErrorsToStop.ToString();
|
||||||
|
|
||||||
|
textBox15rl.Text = config.DfltQ2c_15_rl.ToString();
|
||||||
|
textBox15lr.Text = config.DfltQ2c_15_lr.ToString();
|
||||||
|
textBox20rl.Text = config.DfltQ2c_20_rl.ToString();
|
||||||
|
textBox20lr.Text = config.DfltQ2c_20_lr.ToString();
|
||||||
|
textBox25_63rl.Text = config.DfltQ2c_25_63_rl.ToString();
|
||||||
|
textBox25_63lr.Text = config.DfltQ2c_25_63_lr.ToString();
|
||||||
|
textBox25_10rl.Text = config.DfltQ2c_25_10_rl.ToString();
|
||||||
|
textBox25_10lr.Text = config.DfltQ2c_25_10_lr.ToString();
|
||||||
|
textBox32rl.Text = config.DfltQ2c_32_rl.ToString();
|
||||||
|
textBox32lr.Text = config.DfltQ2c_32_lr.ToString();
|
||||||
|
textBox40rl.Text = config.DfltQ2c_40_rl.ToString();
|
||||||
|
textBox40lr.Text = config.DfltQ2c_40_lr.ToString();
|
||||||
|
|
||||||
|
useWebServiceCheckBox.Checked = config.UseWebService;
|
||||||
|
baseUrlTextBox.Text = config.BaseUrl;
|
||||||
|
relativeUrlTextBox.Text = config.RelativeUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlock()
|
public void Unlock()
|
||||||
@@ -77,18 +85,28 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
nrThreadsTextBox.Enabled = true;
|
nrThreadsTextBox.Enabled = true;
|
||||||
iperlCheckErrorsToStopTextBox.Enabled = true;
|
iperlCheckErrorsToStopTextBox.Enabled = true;
|
||||||
|
|
||||||
|
textBox15rl.Enabled = true;
|
||||||
|
textBox15lr.Enabled = true;
|
||||||
|
textBox20rl.Enabled = true;
|
||||||
|
textBox20lr.Enabled = true;
|
||||||
|
textBox25_63rl.Enabled = true;
|
||||||
|
textBox25_63lr.Enabled = true;
|
||||||
|
textBox25_10rl.Enabled = true;
|
||||||
|
textBox25_10lr.Enabled = true;
|
||||||
|
textBox32rl.Enabled = true;
|
||||||
|
textBox32lr.Enabled = true;
|
||||||
|
textBox40rl.Enabled = true;
|
||||||
|
textBox40lr.Enabled = true;
|
||||||
|
|
||||||
|
useWebServiceCheckBox.Enabled = true;
|
||||||
|
ManageCheckGroupBox(useWebServiceCheckBox, useWebServiceGroupBox);
|
||||||
|
baseUrlTextBox.Enabled = useWebServiceCheckBox.Enabled;
|
||||||
|
relativeUrlTextBox.Enabled = useWebServiceCheckBox.Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||||
{
|
{
|
||||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||||
if (config == null)
|
|
||||||
{
|
|
||||||
message += Environment.NewLine + "Genesis configuration is not loaded.";
|
|
||||||
log.Error("Genesis Properties validation failed: configuration is not loaded.");
|
|
||||||
return CfgUpdateFlags.Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dummy;
|
int dummy;
|
||||||
if (!int.TryParse(commTimeoutTextBox.Text, out dummy) || dummy < 500 || dummy > 5000)
|
if (!int.TryParse(commTimeoutTextBox.Text, out dummy) || dummy < 500 || dummy > 5000)
|
||||||
@@ -104,21 +122,79 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
if (!int.TryParse(delayBetweenRetriesTextBox.Text, out dummy) || dummy < 0 || dummy > 5000)
|
if (!int.TryParse(delayBetweenRetriesTextBox.Text, out dummy) || dummy < 0 || dummy > 5000)
|
||||||
{
|
{
|
||||||
flags |= CfgUpdateFlags.Error;
|
flags |= CfgUpdateFlags.Error;
|
||||||
message += Environment.NewLine + "'Delay between retries' should be in range 0 .. 5000";
|
message += Environment.NewLine + "'Comm. timeout' should be in range 0 .. 5000";
|
||||||
}
|
}
|
||||||
if (!int.TryParse(nrThreadsTextBox.Text, out dummy) || (dummy < 1 || dummy > 10))
|
if (!int.TryParse(nrThreadsTextBox.Text, out dummy) || (dummy < 1 || dummy > 10))
|
||||||
{
|
{
|
||||||
flags |= CfgUpdateFlags.Error;
|
flags |= CfgUpdateFlags.Error;
|
||||||
message += Environment.NewLine + "'Nr. threads' should be in range 1 .. 10";
|
message += Environment.NewLine + "'Nr. threads' should be in range 1 .. 10";
|
||||||
}
|
}
|
||||||
if (!int.TryParse(iperlCheckErrorsToStopTextBox.Text, out dummy) || ((dummy < 1) || (dummy > 40)))
|
if (!int.TryParse(iperlCheckErrorsToStopTextBox.Text, out dummy) || ((dummy < 1) && (dummy > 40)))
|
||||||
{
|
{
|
||||||
flags |= CfgUpdateFlags.Error;
|
flags |= CfgUpdateFlags.Error;
|
||||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, iperlCheckErrorsToStopLabel.Text);
|
message += Environment.NewLine + string.Format(Strings.Invalid_0, iperlCheckErrorsToStopLabel.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & CfgUpdateFlags.Error) != 0)
|
if (!int.TryParse(textBox15rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
log.WarnFormat("Genesis Properties validation failed: {0}", message);
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN15 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox15lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN15 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox20rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN20 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox20lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN20 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox25_63rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 6.3 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox25_63lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 6.3 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox25_10rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 10 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox25_10lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN25 Q3 10 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox32rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN32 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox32lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN32 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox40rl.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN40 RL should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
if (!int.TryParse(textBox40lr.Text, out dummy) || dummy < -50 || dummy > 50)
|
||||||
|
{
|
||||||
|
flags |= CfgUpdateFlags.Error;
|
||||||
|
message += Environment.NewLine + "Default Q2 correction factor DN40 LR should be in range -50 .. 50";
|
||||||
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
@@ -127,8 +203,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
{
|
{
|
||||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||||
|
|
||||||
string message = string.Empty;
|
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||||
if ((VerifyCfg(ref message) & CfgUpdateFlags.Error) != 0) return CfgUpdateFlags.Error;
|
|
||||||
|
|
||||||
if (config.Name != nameTextBox.Text)
|
if (config.Name != nameTextBox.Text)
|
||||||
{
|
{
|
||||||
@@ -136,11 +211,26 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
|
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.RestartRqrd);
|
||||||
}
|
}
|
||||||
|
|
||||||
var CommTimeout = config.CommTimeout;
|
var CommTimeout = config.CommTimeout;;
|
||||||
var MaxCommRetries = config.MaxCommRetries;
|
var MaxCommRetries = config.MaxCommRetries;
|
||||||
var DelayBetweenRetries = config.DelayBetweenRetries;
|
var DelayBetweenRetries = config.DelayBetweenRetries;
|
||||||
var NrThreads = config.NrThreads;
|
var NrThreads = config.NrThreads;
|
||||||
var IperlCheckErrorsToStop = config.IperlCheckErrorsToStop;
|
var IperlCheckErrorsToStop = config.IperlCheckErrorsToStop;
|
||||||
|
var DfltQ2c_15_rl = config.DfltQ2c_15_rl;
|
||||||
|
var DfltQ2c_15_lr = config.DfltQ2c_15_lr;
|
||||||
|
var DfltQ2c_20_rl = config.DfltQ2c_20_rl;
|
||||||
|
var DfltQ2c_20_lr = config.DfltQ2c_20_lr;
|
||||||
|
var DfltQ2c_25_63_rl = config.DfltQ2c_25_63_rl;
|
||||||
|
var DfltQ2c_25_63_lr = config.DfltQ2c_25_63_lr;
|
||||||
|
var DfltQ2c_25_10_rl = config.DfltQ2c_25_10_rl;
|
||||||
|
var DfltQ2c_25_10_lr = config.DfltQ2c_25_10_lr;
|
||||||
|
var DfltQ2c_32_rl = config.DfltQ2c_32_rl;
|
||||||
|
var DfltQ2c_32_lr = config.DfltQ2c_32_lr;
|
||||||
|
var DfltQ2c_40_rl = config.DfltQ2c_40_rl;
|
||||||
|
var DfltQ2c_40_lr = config.DfltQ2c_40_lr;
|
||||||
|
var UseWebService = config.UseWebService;
|
||||||
|
var BaseUrl = config.BaseUrl;
|
||||||
|
var RelativeUrl = config.RelativeUrl;
|
||||||
|
|
||||||
flags |= UpdateDifferent(ref CommTimeout, commTimeoutTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
flags |= UpdateDifferent(ref CommTimeout, commTimeoutTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
flags |= UpdateDifferent(ref MaxCommRetries, maxCommRetriesTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
flags |= UpdateDifferent(ref MaxCommRetries, maxCommRetriesTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
@@ -148,7 +238,22 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
flags |= UpdateDifferent(ref NrThreads, nrThreadsTextBox.Text, CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
flags |= UpdateDifferent(ref NrThreads, nrThreadsTextBox.Text, CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||||
flags |= UpdateDifferent(ref IperlCheckErrorsToStop, iperlCheckErrorsToStopTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
flags |= UpdateDifferent(ref IperlCheckErrorsToStop, iperlCheckErrorsToStopTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_15_rl, textBox15rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_15_lr, textBox15lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_20_rl, textBox20rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_20_lr, textBox20lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_25_63_rl, textBox25_63rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_25_63_lr, textBox25_63lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_25_10_rl, textBox25_10rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_25_10_lr, textBox25_10lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_32_rl, textBox32rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_32_lr, textBox32lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_40_rl, textBox40rl.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref DfltQ2c_40_lr, textBox40lr.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
|
||||||
|
flags |= UpdateDifferent(ref UseWebService, useWebServiceCheckBox.Checked, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref BaseUrl, baseUrlTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
flags |= UpdateDifferent(ref RelativeUrl, relativeUrlTextBox.Text, CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||||
|
|
||||||
|
|
||||||
config.CommTimeout = CommTimeout;
|
config.CommTimeout = CommTimeout;
|
||||||
@@ -156,44 +261,30 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
|
|||||||
config.DelayBetweenRetries = DelayBetweenRetries;
|
config.DelayBetweenRetries = DelayBetweenRetries;
|
||||||
config.NrThreads = NrThreads;
|
config.NrThreads = NrThreads;
|
||||||
config.IperlCheckErrorsToStop = IperlCheckErrorsToStop;
|
config.IperlCheckErrorsToStop = IperlCheckErrorsToStop;
|
||||||
|
config.DfltQ2c_15_rl = DfltQ2c_15_rl;
|
||||||
|
config.DfltQ2c_15_lr = DfltQ2c_15_lr;
|
||||||
|
config.DfltQ2c_20_rl = DfltQ2c_20_rl;
|
||||||
|
config.DfltQ2c_20_lr = DfltQ2c_20_lr;
|
||||||
|
config.DfltQ2c_25_63_rl = DfltQ2c_25_63_rl;
|
||||||
|
config.DfltQ2c_25_63_lr = DfltQ2c_25_63_lr;
|
||||||
|
config.DfltQ2c_25_10_rl = DfltQ2c_25_10_rl;
|
||||||
|
config.DfltQ2c_25_10_lr = DfltQ2c_25_10_lr;
|
||||||
|
config.DfltQ2c_32_rl = DfltQ2c_32_rl;
|
||||||
|
config.DfltQ2c_32_lr = DfltQ2c_32_lr;
|
||||||
|
config.DfltQ2c_40_rl = DfltQ2c_40_rl;
|
||||||
|
config.DfltQ2c_40_lr = DfltQ2c_40_lr;
|
||||||
|
config.UseWebService = UseWebService;
|
||||||
|
config.BaseUrl = BaseUrl;
|
||||||
|
config.RelativeUrl = RelativeUrl;
|
||||||
|
|
||||||
LogConfiguration("updated; flags=" + flags);
|
|
||||||
|
|
||||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||||
{
|
{
|
||||||
TestMethod.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
iPerlCommunication.TestMethod.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ToolTip settingsToolTip;
|
|
||||||
|
|
||||||
private void InitializeSettingToolTips()
|
|
||||||
{
|
|
||||||
if (components == null) components = new System.ComponentModel.Container();
|
|
||||||
settingsToolTip = new ToolTip(components) { AutoPopDelay = 30000, InitialDelay = 400, ReshowDelay = 100, ShowAlways = true };
|
|
||||||
settingsToolTip.SetToolTip(nameTextBox, Strings.ResourceManager.GetString("GenesisTooltip_nameTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(nameLabel, settingsToolTip.GetToolTip(nameTextBox));
|
|
||||||
settingsToolTip.SetToolTip(commTimeoutTextBox, Strings.ResourceManager.GetString("GenesisTooltip_commTimeoutTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(commTimeoutLabel, settingsToolTip.GetToolTip(commTimeoutTextBox));
|
|
||||||
settingsToolTip.SetToolTip(maxCommRetriesTextBox, Strings.ResourceManager.GetString("GenesisTooltip_maxCommRetriesTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(maxNrRetriesLabel, settingsToolTip.GetToolTip(maxCommRetriesTextBox));
|
|
||||||
settingsToolTip.SetToolTip(delayBetweenRetriesTextBox, Strings.ResourceManager.GetString("GenesisTooltip_delayBetweenRetriesTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(delayBetweenRetriesLabel, settingsToolTip.GetToolTip(delayBetweenRetriesTextBox));
|
|
||||||
settingsToolTip.SetToolTip(nrThreadsTextBox, Strings.ResourceManager.GetString("GenesisTooltip_nrThreadsTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(nrThreadsLabel, settingsToolTip.GetToolTip(nrThreadsTextBox));
|
|
||||||
settingsToolTip.SetToolTip(iperlCheckErrorsToStopTextBox, Strings.ResourceManager.GetString("GenesisTooltip_iperlCheckErrorsToStopTextBox", Strings.Culture));
|
|
||||||
settingsToolTip.SetToolTip(iperlCheckErrorsToStopLabel, settingsToolTip.GetToolTip(iperlCheckErrorsToStopTextBox));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LogConfiguration(string action)
|
|
||||||
{
|
|
||||||
log.InfoFormat("Genesis Properties {0}: Name={1}, CommTimeout={2}ms, MaxRetries={3}, DelayBetweenRetries={4}ms, NrThreads={5}, ErrorsToStop={6}; Q3 source=WaterMeterData.Text1-Text3; legacy fields preserved",
|
|
||||||
action, config.Name, config.CommTimeout, config.MaxCommRetries,
|
|
||||||
config.DelayBetweenRetries, config.NrThreads, config.IperlCheckErrorsToStop);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ManageCheckGroupBox(CheckBox chk, GroupBox grp)
|
private void ManageCheckGroupBox(CheckBox chk, GroupBox grp)
|
||||||
{
|
{
|
||||||
/// Make sure the CheckBox isn't in the GroupBox. This will only happen the first time.
|
/// Make sure the CheckBox isn't in the GroupBox. This will only happen the first time.
|
||||||
|
|||||||
@@ -165,195 +165,6 @@ namespace TBFTests
|
|||||||
|
|
||||||
// ReSharper restore SqlResolve
|
// ReSharper restore SqlResolve
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GenesisPropertiesLoadUpdateAndPreserveLegacySettings()
|
|
||||||
{
|
|
||||||
var cfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(new TBF.Rig.TestMethods.GenesisCommunication.Factory());
|
|
||||||
cfg.Name = "Genesis test";
|
|
||||||
cfg.DfltQ2c_15_rl = 17969;
|
|
||||||
cfg.UseWebService = true;
|
|
||||||
cfg.BaseUrl = "legacy-base";
|
|
||||||
cfg.RelativeUrl = "legacy-path";
|
|
||||||
// Exercise the existing XML contract before opening Properties.
|
|
||||||
using (var writer = new StringWriter())
|
|
||||||
{
|
|
||||||
TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg.Serializer.Serialize(writer, cfg);
|
|
||||||
using (var reader = new StringReader(writer.ToString()))
|
|
||||||
cfg = (TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg)TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg.Serializer.Deserialize(reader);
|
|
||||||
}
|
|
||||||
// Name is stored in the component entity, outside the XML payload.
|
|
||||||
cfg.Name = "Genesis test";
|
|
||||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
|
||||||
{
|
|
||||||
ctrl.Config = cfg;
|
|
||||||
Assert.AreSame(cfg, ctrl.Config);
|
|
||||||
Assert.AreEqual("Genesis test", ctrl.Controls.Find("nameTextBox", true)[0].Text);
|
|
||||||
Assert.AreEqual("1800", ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text);
|
|
||||||
string message = "";
|
|
||||||
Assert.AreEqual(Common.CfgUpdateFlags.None, ctrl.VerifyCfg(ref message), message);
|
|
||||||
ctrl.Unlock();
|
|
||||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2300";
|
|
||||||
bool notified = false;
|
|
||||||
EventHandler<TBF.Rig.CfgChangeArgs> handler = (sender, args) => { notified = true; };
|
|
||||||
TBF.Rig.TestMethods.GenesisCommunication.TestMethod.CfgChangeHandler += handler;
|
|
||||||
try { ctrl.UpdateCfg(); }
|
|
||||||
finally { TBF.Rig.TestMethods.GenesisCommunication.TestMethod.CfgChangeHandler -= handler; }
|
|
||||||
Assert.IsTrue(notified);
|
|
||||||
Assert.AreEqual(2300, cfg.CommTimeout);
|
|
||||||
Assert.AreEqual(17969, cfg.DfltQ2c_15_rl);
|
|
||||||
Assert.IsTrue(cfg.UseWebService);
|
|
||||||
Assert.AreEqual("legacy-base", cfg.BaseUrl);
|
|
||||||
Assert.AreEqual("legacy-path", cfg.RelativeUrl);
|
|
||||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "41";
|
|
||||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2400";
|
|
||||||
Assert.AreNotEqual(0, (int)(ctrl.UpdateCfg() & Common.CfgUpdateFlags.Error));
|
|
||||||
Assert.AreEqual(2300, cfg.CommTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GenesisPropertiesValidateAllNumericBoundariesAndExposeTooltips()
|
|
||||||
{
|
|
||||||
var cfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(new TBF.Rig.TestMethods.GenesisCommunication.Factory());
|
|
||||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
|
||||||
{
|
|
||||||
ctrl.Config = cfg;
|
|
||||||
ctrl.Unlock();
|
|
||||||
var tips = (System.Windows.Forms.ToolTip)typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl)
|
|
||||||
.GetField("settingsToolTip", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(ctrl);
|
|
||||||
var names = new[] { "commTimeoutTextBox", "maxCommRetriesTextBox", "delayBetweenRetriesTextBox", "nrThreadsTextBox", "iperlCheckErrorsToStopTextBox" };
|
|
||||||
var minima = new[] { 500, 1, 0, 1, 1 };
|
|
||||||
var maxima = new[] { 5000, 10, 5000, 10, 40 };
|
|
||||||
for (int i = 0; i < names.Length; i++)
|
|
||||||
{
|
|
||||||
var field = ctrl.Controls.Find(names[i], true)[0];
|
|
||||||
string original = field.Text;
|
|
||||||
Assert.IsFalse(string.IsNullOrWhiteSpace(tips.GetToolTip(field)));
|
|
||||||
Assert.IsTrue(tips.GetToolTip(field).Split('\n').Length >= 6);
|
|
||||||
foreach (var value in new[] { minima[i], maxima[i] })
|
|
||||||
{
|
|
||||||
field.Text = value.ToString();
|
|
||||||
string message = "";
|
|
||||||
Assert.AreEqual(Common.CfgUpdateFlags.None, ctrl.VerifyCfg(ref message), names[i] + message);
|
|
||||||
}
|
|
||||||
foreach (var value in new[] { (minima[i] - 1).ToString(), (maxima[i] + 1).ToString(), "bad", "", "1.5" })
|
|
||||||
{
|
|
||||||
field.Text = value;
|
|
||||||
string message = "";
|
|
||||||
Assert.AreNotEqual(0, (int)(ctrl.VerifyCfg(ref message) & Common.CfgUpdateFlags.Error), names[i] + ":" + value);
|
|
||||||
}
|
|
||||||
field.Text = original;
|
|
||||||
}
|
|
||||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2500";
|
|
||||||
ctrl.Controls.Find("maxCommRetriesTextBox", true)[0].Text = "6";
|
|
||||||
ctrl.Controls.Find("delayBetweenRetriesTextBox", true)[0].Text = "300";
|
|
||||||
ctrl.Controls.Find("nrThreadsTextBox", true)[0].Text = "3";
|
|
||||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "2";
|
|
||||||
var flags = ctrl.UpdateCfg();
|
|
||||||
Assert.AreNotEqual(0, (int)(flags & Common.CfgUpdateFlags.RestartRqrd));
|
|
||||||
Assert.AreEqual(2500, cfg.CommTimeout);
|
|
||||||
Assert.AreEqual(6, cfg.MaxCommRetries);
|
|
||||||
Assert.AreEqual(300, cfg.DelayBetweenRetries);
|
|
||||||
Assert.AreEqual(3, cfg.NrThreads);
|
|
||||||
Assert.AreEqual(2, cfg.IperlCheckErrorsToStop);
|
|
||||||
StringAssert.Contains(tips.GetToolTip(ctrl.Controls.Find("commTimeoutTextBox", true)[0]), "Genesis");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GenesisRuntimeReceivesLiveSettingsButKeepsRestartOnlyThreadCount()
|
|
||||||
{
|
|
||||||
var factory = new TBF.Rig.TestMethods.GenesisCommunication.Factory();
|
|
||||||
var runtimeCfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(factory);
|
|
||||||
var editedCfg = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg(factory);
|
|
||||||
var component = new TBF.Rig.TestMethods.GenesisCommunication.TestMethod(runtimeCfg);
|
|
||||||
var eventField = typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethod).GetField("CfgChangeHandler",
|
|
||||||
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
|
||||||
var originalHandlers = eventField.GetValue(null);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
component.StartChangeHandler();
|
|
||||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
|
||||||
{
|
|
||||||
ctrl.Config = editedCfg;
|
|
||||||
ctrl.Unlock();
|
|
||||||
ctrl.Controls.Find("commTimeoutTextBox", true)[0].Text = "2500";
|
|
||||||
ctrl.Controls.Find("maxCommRetriesTextBox", true)[0].Text = "6";
|
|
||||||
ctrl.Controls.Find("delayBetweenRetriesTextBox", true)[0].Text = "300";
|
|
||||||
ctrl.Controls.Find("iperlCheckErrorsToStopTextBox", true)[0].Text = "2";
|
|
||||||
ctrl.Controls.Find("nrThreadsTextBox", true)[0].Text = "3";
|
|
||||||
ctrl.UpdateCfg();
|
|
||||||
Assert.AreEqual(2500, runtimeCfg.CommTimeout);
|
|
||||||
Assert.AreEqual(6, runtimeCfg.MaxCommRetries);
|
|
||||||
Assert.AreEqual(300, runtimeCfg.DelayBetweenRetries);
|
|
||||||
Assert.AreEqual(2, runtimeCfg.IperlCheckErrorsToStop);
|
|
||||||
Assert.AreEqual(10, runtimeCfg.NrThreads);
|
|
||||||
Assert.AreEqual(3, editedCfg.NrThreads);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally { eventField.SetValue(null, originalHandlers); }
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void GenesisTooltipsFollowUiCultureAndFallbackToEnglish()
|
|
||||||
{
|
|
||||||
var original = System.Threading.Thread.CurrentThread.CurrentUICulture;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cultures = new[] { "en-US", "sk-SK", "cs-CZ", "de-DE", "fr-FR" };
|
|
||||||
var headings = new[] { "Default:", "Prednastaven\u00e1 hodnota:", "V\u00fdchoz\u00ed hodnota:", "Standardwert:", "Default:" };
|
|
||||||
for (int i = 0; i < cultures.Length; i++)
|
|
||||||
{
|
|
||||||
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(cultures[i]);
|
|
||||||
using (var ctrl = new TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl())
|
|
||||||
{
|
|
||||||
var tips = (System.Windows.Forms.ToolTip)typeof(TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfgCtrl)
|
|
||||||
.GetField("settingsToolTip", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(ctrl);
|
|
||||||
foreach (var field in new[] { "nameTextBox", "commTimeoutTextBox", "maxCommRetriesTextBox", "delayBetweenRetriesTextBox", "nrThreadsTextBox", "iperlCheckErrorsToStopTextBox" })
|
|
||||||
StringAssert.Contains(tips.GetToolTip(ctrl.Controls.Find(field, true)[0]), headings[i], cultures[i] + field);
|
|
||||||
var timeout = tips.GetToolTip(ctrl.Controls.Find("commTimeoutTextBox", true)[0]);
|
|
||||||
StringAssert.Contains(timeout, "500\u20135000 ms");
|
|
||||||
StringAssert.Contains(timeout, "1800 ms");
|
|
||||||
Assert.AreEqual(timeout, tips.GetToolTip(ctrl.Controls.Find("commTimeoutLabel", true)[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally { System.Threading.Thread.CurrentThread.CurrentUICulture = original; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async System.Threading.Tasks.Task GenesisTimeoutChangesCancellationDeadlineAndPreservesLegacyCallers()
|
|
||||||
{
|
|
||||||
Assert.IsNull(TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "legacy"));
|
|
||||||
using (TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(5000))
|
|
||||||
using (var longDeadline = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "long-test"))
|
|
||||||
{
|
|
||||||
using (TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.Begin(500))
|
|
||||||
using (var shortDeadline = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "short-test"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await System.Threading.Tasks.Task.Delay(3000, shortDeadline.Token);
|
|
||||||
Assert.Fail("Expected the configured 500 ms deadline to cancel the operation.");
|
|
||||||
}
|
|
||||||
catch (System.OperationCanceledException) { Assert.IsTrue(shortDeadline.IsCancellationRequested); }
|
|
||||||
Assert.IsFalse(longDeadline.IsCancellationRequested);
|
|
||||||
}
|
|
||||||
using (var restored = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "restored-test"))
|
|
||||||
{
|
|
||||||
await System.Threading.Tasks.Task.Delay(700);
|
|
||||||
Assert.IsFalse(restored.IsCancellationRequested);
|
|
||||||
}
|
|
||||||
using (var caller = new System.Threading.CancellationTokenSource())
|
|
||||||
using (var linked = TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(caller.Token, "caller-test"))
|
|
||||||
{
|
|
||||||
caller.Cancel();
|
|
||||||
Assert.IsTrue(linked.IsCancellationRequested);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Assert.IsNull(TBF.Rig.BridgeComponents.GciBridge.GenesisRequestTimeout.CreateDeadline(System.Threading.CancellationToken.None, "legacy-after"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Execute(SQLiteConnection connection, string sql)
|
private static void Execute(SQLiteConnection connection, string sql)
|
||||||
{
|
{
|
||||||
using (var command = connection.CreateCommand()) { command.CommandText = sql; command.ExecuteNonQuery(); }
|
using (var command = connection.CreateCommand()) { command.CommandText = sql; command.ExecuteNonQuery(); }
|
||||||
|
|||||||
@@ -0,0 +1,263 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.communication;
|
||||||
|
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis.Protocols.StreamingProtocol;
|
||||||
|
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||||
|
|
||||||
|
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader
|
||||||
|
{
|
||||||
|
// Golden frames have CRCs generated independently with Python binascii.crc_hqx.
|
||||||
|
// No ports, databases, GCI engine or production-code changes are required.
|
||||||
|
[TestClass]
|
||||||
|
[TestCategory("GenesisReadRegression")]
|
||||||
|
public class GenesisReadDataRegressionTests
|
||||||
|
{
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("@h 1 0 10000000 FFFFFF00 00000400 00100000 00000000 00008000 00400000 00800000 FFFFF000 0C 00018000 8D2C", 1, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 1 0 10000000 FFFFFF00 00000400 00100000 00000200 00008000 00400000 00800000 FFFFF000 0C 00018000 7BAC", 1, 512, 0.002048)]
|
||||||
|
[DataRow("@h 1 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 700D", 1, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 1 0 10000000 FFFFFF00 00000400 00100000 00000800 00008000 00400000 00800000 FFFFF000 0C 00018000 674F", 1, 2048, 0.000512)]
|
||||||
|
[DataRow("@h 2 0 10000000 FFFFFF00 00000400 00100000 00000000 00008000 00400000 00800000 FFFFF000 0C 00018000 3F43", 2, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 2 0 10000000 FFFFFF00 00000400 00100000 00000200 00008000 00400000 00800000 FFFFF000 0C 00018000 C9C3", 2, 512, 0.002048)]
|
||||||
|
[DataRow("@h 2 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 C262", 2, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 2 0 10000000 FFFFFF00 00000400 00100000 00000800 00008000 00400000 00800000 FFFFF000 0C 00018000 D520", 2, 2048, 0.000512)]
|
||||||
|
[DataRow("@h 3 0 10000000 FFFFFF00 00000400 00100000 00000000 00008000 00400000 00800000 FFFFF000 0C 00018000 A179", 3, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 3 0 10000000 FFFFFF00 00000400 00100000 00000200 00008000 00400000 00800000 FFFFF000 0C 00018000 57F9", 3, 512, 0.002048)]
|
||||||
|
[DataRow("@h 3 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 5C58", 3, 1024, 0.001024)]
|
||||||
|
[DataRow("@h 3 0 10000000 FFFFFF00 00000400 00100000 00000800 00008000 00400000 00800000 FFFFF000 0C 00018000 4B1A", 3, 2048, 0.000512)]
|
||||||
|
public void ProtocolH_GoldenFramesPreserveChannelUnitsAndScale(string frame, int channel, int scale, double volume)
|
||||||
|
{
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
Assert.IsTrue(decoder.DecodeMsg(frame));
|
||||||
|
var data = decoder.DataCalib;
|
||||||
|
Assert.IsNotNull(data);
|
||||||
|
Assert.IsTrue(data.IsValid);
|
||||||
|
Assert.AreEqual(channel, data.Channel);
|
||||||
|
Assert.AreEqual(scale, data.VolumeScaleRawPerMl);
|
||||||
|
Assert.AreEqual(volume, data.VolumeCm, 1e-12);
|
||||||
|
Assert.AreEqual(1048576d, data.AccuVolumeRaw);
|
||||||
|
Assert.AreEqual(1024d, data.DeltaVolumeRaw);
|
||||||
|
Assert.AreEqual(volume / 1024, data.DeltaVolumeQm, 1e-15);
|
||||||
|
Assert.AreEqual(1.5, data.TimeS, 1e-12);
|
||||||
|
Assert.AreEqual(.5, data.SampleIntervalS, 1e-12);
|
||||||
|
Assert.AreEqual(.001, data.AmplitudeUpV, 1e-12);
|
||||||
|
Assert.AreEqual(.002, data.AmplitudeDownV, 1e-12);
|
||||||
|
Assert.AreEqual(-1d, data.TemperatureDegC, 1e-12);
|
||||||
|
Assert.AreEqual(65536d, data.OverflowTimeS);
|
||||||
|
Assert.IsNull(decoder.DataFlowTest);
|
||||||
|
double previousVolume = double.NaN, previousTime = double.NaN;
|
||||||
|
var telegram = new OptoTelegramRaw();
|
||||||
|
telegram.UpdateFromSmart(data, 17, 2.5f, ref previousVolume, ref previousTime);
|
||||||
|
Assert.AreEqual(channel - 1, telegram.iChannel);
|
||||||
|
Assert.AreEqual(volume * 1000, telegram.VolumeRawExt, 1e-9);
|
||||||
|
Assert.AreEqual(1.5, telegram.TimestampExt, 1e-12);
|
||||||
|
Assert.AreEqual(17, telegram.Counter);
|
||||||
|
Assert.AreEqual(2.5f, telegram.RefFlow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("@h 1 0 00000000 00000000 00000400 00100000 00000400 00008000 00400000 00800000 00000000 0C 00018000 0A39", 0, 0, 0)]
|
||||||
|
[DataRow("@h 1 0 7FFFFFFF 7FFFFFFF 00000400 00100000 00000400 00008000 00400000 00800000 7FFFFFFF 0C 00018000 89B0", 2147483647, 2147483647, 2147483647)]
|
||||||
|
[DataRow("@h 1 0 80000000 80000000 00000400 00100000 00000400 00008000 00400000 00800000 80000000 0C 00018000 3E06", -2147483648, -2147483648, -2147483648)]
|
||||||
|
[DataRow("@h 1 0 FFFFFFFF FFFFFFFF 00000400 00100000 00000400 00008000 00400000 00800000 FFFFFFFF 0C 00018000 6870", -1, -1, -1)]
|
||||||
|
public void ProtocolH_SignedFieldsPreserveTwosComplement(string frame, int total, int delta, int temperature)
|
||||||
|
{
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
Assert.IsTrue(decoder.DecodeMsg(frame));
|
||||||
|
var data = decoder.DataCalib;
|
||||||
|
Assert.AreEqual(total, data.RawTotalTimeOfFlight);
|
||||||
|
Assert.AreEqual(delta, data.RawDeltaTimeOfFlight);
|
||||||
|
Assert.AreEqual(total / 274877906944d, data.TotalTimeOfFlightS, 1e-15);
|
||||||
|
Assert.AreEqual(delta / 274877906944d, data.DeltaTimeOfFlightS, 1e-15);
|
||||||
|
Assert.AreEqual(temperature / 4096d, data.TemperatureDegC, 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("@f 00000000 00000000 F603", 0.0, 0.0)]
|
||||||
|
[DataRow("@f 7FFFFFFF FFFFFFFF 3996", 2147.483647, 65535.99998474121)]
|
||||||
|
[DataRow("@f FFFFFFFF 00010000 21AD", -1e-06, 1.0)]
|
||||||
|
[DataRow("@f 80000000 00008000 0541", -2147.483648, 0.5)]
|
||||||
|
public void ProtocolF_PreservesSignedVolumeAndUnsignedTime(string frame, double volume, double time)
|
||||||
|
{
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
Assert.IsTrue(decoder.DecodeMsg(frame));
|
||||||
|
Assert.IsNotNull(decoder.DataFlowTest);
|
||||||
|
Assert.IsTrue(decoder.DataFlowTest.IsValid);
|
||||||
|
Assert.AreEqual(volume, decoder.DataFlowTest.VolumeCm, 1e-9);
|
||||||
|
Assert.AreEqual(time, decoder.DataFlowTest.TimeS, 1e-12);
|
||||||
|
Assert.IsNull(decoder.DataCalib);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow(null)]
|
||||||
|
[DataRow("")]
|
||||||
|
[DataRow("garbage")]
|
||||||
|
[DataRow("@h")]
|
||||||
|
[DataRow("@h 1")]
|
||||||
|
[DataRow("@h 1 invalid")]
|
||||||
|
[DataRow("@f 00000001 00010000 ZZZZ")]
|
||||||
|
[DataRow("@h\t1\t0\t10000000\tFFFFFF00\t00000400\t00100000\t00000400\t00008000\t00400000\t00800000\tFFFFF000\t0C\t00018000\t700D")]
|
||||||
|
[DataRow("@h 1 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 700D ")]
|
||||||
|
[DataRow("@he 1 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 700D")]
|
||||||
|
public void InvalidOrUnsupportedInputProducesNoMeasurement(string frame)
|
||||||
|
{
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
decoder.DecodeMsg(frame);
|
||||||
|
Assert.IsNull(decoder.DataCalib);
|
||||||
|
Assert.IsNull(decoder.DataFlowTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow(1)]
|
||||||
|
[DataRow(2)]
|
||||||
|
[DataRow(3)]
|
||||||
|
[DataRow(4)]
|
||||||
|
[DataRow(5)]
|
||||||
|
[DataRow(6)]
|
||||||
|
[DataRow(7)]
|
||||||
|
[DataRow(8)]
|
||||||
|
[DataRow(9)]
|
||||||
|
[DataRow(10)]
|
||||||
|
[DataRow(11)]
|
||||||
|
[DataRow(12)]
|
||||||
|
[DataRow(13)]
|
||||||
|
public void AlteringAnyCalibrationFieldWithoutUpdatingCrcRejectsRecord(int field)
|
||||||
|
{
|
||||||
|
var words = Golden.Split(' ');
|
||||||
|
words[field] = words[field] == "0" ? "1" : "0";
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
Assert.IsFalse(decoder.DecodeMsg(string.Join(" ", words)));
|
||||||
|
Assert.IsNull(decoder.DataCalib);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("en-US")]
|
||||||
|
[DataRow("sk-SK")]
|
||||||
|
[DataRow("de-DE")]
|
||||||
|
public void HexDecodingIsIndependentOfCulture(string culture)
|
||||||
|
{
|
||||||
|
var previous = System.Threading.Thread.CurrentThread.CurrentCulture;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(culture);
|
||||||
|
var decoder = new StreamingDecoder();
|
||||||
|
Assert.IsTrue(decoder.DecodeMsg(Golden));
|
||||||
|
Assert.AreEqual(.001024, decoder.DataCalib.VolumeCm, 1e-12);
|
||||||
|
Assert.AreEqual(-1d, decoder.DataCalib.TemperatureDegC);
|
||||||
|
}
|
||||||
|
finally { System.Threading.Thread.CurrentThread.CurrentCulture = previous; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void DiagnosticModeRetainsBadCrcButMarksRecordInvalid()
|
||||||
|
{
|
||||||
|
var corrupted = Golden.Substring(0, Golden.Length - 4) + "0000";
|
||||||
|
var decoder = new StreamingDecoder(false);
|
||||||
|
Assert.IsFalse(decoder.DecodeMsg(corrupted));
|
||||||
|
Assert.IsNotNull(decoder.DataCalib);
|
||||||
|
Assert.IsFalse(decoder.DataCalib.IsValid);
|
||||||
|
Assert.AreEqual(.001024, decoder.DataCalib.VolumeCm, 1e-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CrcMatchesIndependentCcittFalseCheckVector()
|
||||||
|
{
|
||||||
|
Assert.AreEqual((ushort)0x29B1, Crc16Ccitt.CalculateMsb1021(Encoding.ASCII.GetBytes("123456789")));
|
||||||
|
Assert.AreEqual((ushort)0xFFFF, Crc16Ccitt.CalculateMsb1021(new byte[0]));
|
||||||
|
}
|
||||||
|
private static void InitializeReaderForTest(GenesisSmartReader reader)
|
||||||
|
{
|
||||||
|
const int channelCount = 3;
|
||||||
|
|
||||||
|
SetPrivateField(reader, "volumeRawExtLast", new double[channelCount]);
|
||||||
|
SetPrivateField(reader, "timestampExtLast", new double[channelCount]);
|
||||||
|
|
||||||
|
SetPrivateField(reader, "lastTimestamp", new double[channelCount]);
|
||||||
|
SetPrivateField(reader, "timestampSec", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||||
|
SetPrivateField(reader, "timestampSec0", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||||
|
|
||||||
|
SetPrivateField(reader, "lastVolumeRaw", new double[channelCount]);
|
||||||
|
SetPrivateField(reader, "volumeLtr", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||||
|
SetPrivateField(reader, "volumeLtr0", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||||
|
|
||||||
|
var optoData = new OptoTelegramRaw[GenesisSmartReader.OptoDataBufferSize];
|
||||||
|
for (int i = 0; i < optoData.Length; i++)
|
||||||
|
optoData[i] = new OptoTelegramRaw();
|
||||||
|
|
||||||
|
SetPrivateField(reader, "optoData", optoData);
|
||||||
|
SetPrivateField(reader, "optoDataCount", 0);
|
||||||
|
SetPrivateField(reader, "toBeFlushed", new OptoTelegramRaw());
|
||||||
|
|
||||||
|
SetPrivateField(reader, "flowDirectionDetection", new FlowDirectionDetection());
|
||||||
|
SetPrivateField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||||
|
SetPrivateField(reader, "synchronized", false);
|
||||||
|
SetPrivateField(reader, "synchronized2", false);
|
||||||
|
SetPrivateField(reader, "partOfTelegram", string.Empty);
|
||||||
|
SetPrivateField(reader, "startDataProcessing", true);
|
||||||
|
|
||||||
|
reader.StopQueueData = false;
|
||||||
|
|
||||||
|
reader.TestStartTelegramIx = 0;
|
||||||
|
reader.TestEndTelegramIx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetPrivateField(object target, string name, object value)
|
||||||
|
{
|
||||||
|
var field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
Assert.IsNotNull(field, name);
|
||||||
|
field.SetValue(target, value);
|
||||||
|
}
|
||||||
|
private static T ReadField<T>(object target, string name)
|
||||||
|
{
|
||||||
|
return (T)target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ProcessOptoLinePreservesPayloadAndCounterThroughReaderPipeline()
|
||||||
|
{
|
||||||
|
var reader = new GenesisSmartReader(new TBF.Rig.RegisterReaders.GenesisRegReader.GenesisCfg(new TBF.Rig.RegisterReaders.GenesisRegReader.Factory()));
|
||||||
|
InitializeReaderForTest(reader);
|
||||||
|
bool complete;
|
||||||
|
reader.ProcessOptoLine(Golden, DataStreamState.ProcessAndSave, out complete);
|
||||||
|
Assert.IsFalse(complete);
|
||||||
|
Assert.AreEqual(1, ReadField<int>(reader, "optoDataCount"));
|
||||||
|
var rows = ReadField<OptoTelegramRaw[]>(reader, "optoData");
|
||||||
|
Assert.AreEqual(0, rows[0].iChannel);
|
||||||
|
Assert.AreEqual(1.024, rows[0].VolumeRawExt, 1e-9);
|
||||||
|
Assert.AreEqual(1.5, rows[0].TimestampExt, 1e-12);
|
||||||
|
Assert.AreEqual(0, rows[0].Counter);
|
||||||
|
reader.ProcessOptoLine("invalid telegram", DataStreamState.ProcessAndSave, out complete);
|
||||||
|
Assert.AreEqual(1, ReadField<int>(reader, "optoDataCount"));
|
||||||
|
reader.ProcessOptoLine(Golden, DataStreamState.ProcessAndSave, out complete);
|
||||||
|
Assert.AreEqual(2, ReadField<int>(reader, "optoDataCount"));
|
||||||
|
Assert.AreEqual(1, rows[1].Counter);
|
||||||
|
Assert.AreEqual(rows[0].VolumeRawExt, rows[1].VolumeRawExt, 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataTestMethod]
|
||||||
|
[DataRow("stop")]
|
||||||
|
[DataRow("queue")]
|
||||||
|
[DataRow("processing")]
|
||||||
|
public void ReaderStopGatesPreventMeasurementsFromBeingAppended(string gate)
|
||||||
|
{
|
||||||
|
var reader = new GenesisSmartReader(new TBF.Rig.RegisterReaders.GenesisRegReader.GenesisCfg(new TBF.Rig.RegisterReaders.GenesisRegReader.Factory()));
|
||||||
|
InitializeReaderForTest(reader);
|
||||||
|
if (gate == "stop") SetPrivateField(reader, "_isStopping", true);
|
||||||
|
if (gate == "queue") reader.StopQueueData = true;
|
||||||
|
if (gate == "processing") SetPrivateField(reader, "startDataProcessing", false);
|
||||||
|
bool complete;
|
||||||
|
reader.ProcessOptoLine(Golden, DataStreamState.ProcessAndSave, out complete);
|
||||||
|
Assert.AreEqual(0, ReadField<int>(reader, "optoDataCount"));
|
||||||
|
Assert.IsFalse(complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string Golden = "@h 1 0 10000000 FFFFFF00 00000400 00100000 00000400 00008000 00400000 00800000 FFFFF000 0C 00018000 700D";
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
-1
@@ -236,6 +236,40 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
Assert.AreEqual(15625.0, calib[1], 0.001);
|
Assert.AreEqual(15625.0, calib[1], 0.001);
|
||||||
Assert.AreEqual(15625.0, calib[2], 0.001);
|
Assert.AreEqual(15625.0, calib[2], 0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void GetQ3Calibration_ShouldUseWriteActivityLimits_AndFallbackWhenTheyAreUnset()
|
||||||
|
{
|
||||||
|
double limitLo;
|
||||||
|
double limitHi;
|
||||||
|
Assert.IsFalse(GenesisSmartReader.TryGetEffectiveQ3CalibrationErrorLimits(0.0, 0.0, out limitLo, out limitHi));
|
||||||
|
Assert.AreEqual(-5.0, limitLo);
|
||||||
|
Assert.AreEqual(5.0, limitHi);
|
||||||
|
Assert.IsTrue(GenesisSmartReader.TryGetEffectiveQ3CalibrationErrorLimits(-2.0, 2.0, out limitLo, out limitHi));
|
||||||
|
Assert.AreEqual(-2.0, limitLo);
|
||||||
|
Assert.AreEqual(2.0, limitHi);
|
||||||
|
|
||||||
|
var sut = new GenesisSmartReader();
|
||||||
|
// At refTime 120 s, this gives a calculated factor 3 % above the initial factor.
|
||||||
|
var raw = CreateKnownStartEndData(
|
||||||
|
(100.0, 100.0 + (200.0 / 1.03 / 12.0), 10.0, 20.0),
|
||||||
|
(200.0, 200.0 + (200.0 / 1.03 / 12.0), 10.0, 20.0),
|
||||||
|
(300.0, 300.0 + (200.0 / 1.03 / 12.0), 10.0, 20.0));
|
||||||
|
SetPrivateField(sut, "_rawStartEndByChannel", raw);
|
||||||
|
SetPrivateField(sut, "_recalculatedStartEndByChannel", raw);
|
||||||
|
SetPrivateField(sut, "optoDataCount", 2);
|
||||||
|
sut.TestStartTelegramIx = 0;
|
||||||
|
sut.TestEndTelegramIx = 1;
|
||||||
|
|
||||||
|
var valid = new bool[3];
|
||||||
|
var differences = new double[3];
|
||||||
|
var factors = new double[3];
|
||||||
|
sut.GetQ3Calibration(200.0, 120.0, ValidInitFactors, -2.0, 2.0,
|
||||||
|
ref valid, ref differences, ref factors);
|
||||||
|
|
||||||
|
CollectionAssert.AreEqual(new[] { false, false, false }, valid);
|
||||||
|
Assert.IsTrue(differences.All(x => x > 2.9 && x < 3.1));
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void CalculateQ3Calibration_ShouldComputeExpectedChannelValues_FromSimulationData()
|
public void CalculateQ3Calibration_ShouldComputeExpectedChannelValues_FromSimulationData()
|
||||||
@@ -424,4 +458,4 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
|||||||
Assert.Fail($"Field '{fieldName}' not found.");
|
Assert.Fail($"Field '{fieldName}' not found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
<ItemGroup><Compile Include="GenesisRecoveryTests.cs" /><Compile Include="GenesisParallelSchedulingTests.cs" /><Compile Include="Rig\RegisterReaders\GenesisRegReader\GenesisReadDataRegressionTests.cs" /></ItemGroup>
|
<ItemGroup><Compile Include="GenesisRecoveryTests.cs" /><Compile Include="GenesisParallelSchedulingTests.cs" /></ItemGroup>
|
||||||
<!-- Project dependencies may copy an older SQLite interop DLL with a newer timestamp. -->
|
<!-- Project dependencies may copy an older SQLite interop DLL with a newer timestamp. -->
|
||||||
<Target Name="EnsureMatchingSQLiteInterop" AfterTargets="Build">
|
<Target Name="EnsureMatchingSQLiteInterop" AfterTargets="Build">
|
||||||
<Copy SourceFiles="@(SQLiteInteropFiles)"
|
<Copy SourceFiles="@(SQLiteInteropFiles)"
|
||||||
|
|||||||
Reference in New Issue
Block a user