Restore Genesis communication and Q3 calibration from special branches

A – Registration and execution
- Register GenesisCommunication Factory in the component list.
- Separate the Genesis form and sequence from iPerl communication.

B – Communication activities
- Restore initialization, connection, PCB reading, password and login.
- Include grouped login, mode switching and disconnection.
- Support processing up to 10 slots.

C1 – Input calibration factors
- Read three factors from Water meters / Text1–Text3.
- Validate integer values in the range 1–65535.
- Preserve the default of 15625 when all three fields are empty.

D – Q3 calibration
- Connect the Prepare Q3 → measurement → Write Q3 workflow.
- Add channel processing to FlyingStart and FlyingStartMassCollection.
- Reset previous measurement data and validate calculated factors.
- Mark factors as stored only after StoreCalibration succeeds.

E – Results and database
- Store calibration factors separately for each meter and channel.
- Add result entities, mappings and Q3 data.
- Extend DB.cs / EnsureSchema to create and update the schema.
- Preserve compatibility with the existing binary format.

Validation:
- Debug build and 18 tests passed.
- Simulated communication runs follow the same activity sequence.
- The complete Q3 workflow has not yet been verified on hardware.

Known limitation:
- An inherited mismatch in simulated responses and error propagation
  can produce an incorrect OK result; this change does not fix it.
This commit is contained in:
Michal Buzik 2026-09-09 15:04:49 +02:00
parent 88b8bc5534
commit 52bd0d01ce
46 changed files with 12378 additions and 716 deletions

View File

@ -189,6 +189,15 @@ namespace Results
return null;
}
public MeterTestRslt GetEachMeterTestRslt(string name, int wmNr0, CompoundMeterId meterId)
{
if (Batch.WaterMeters != null && Batch.WaterMeters.Count > wmNr0)
{
return Batch.WaterMeters[wmNr0].GetMeterTestRslt(name, meterId);
}
return null;
}
/// <summary>
/// Returns true when all tests were done

View File

@ -111,7 +111,7 @@ namespace Results
if (SessionFactory == null)
{
DatabaseMigrationHelper.EnsureSchema(dbType, connectionString);
SessionFactory = CreateSessionFactory();
SessionFactory = CreateSessionFactory();
}
return SessionFactory.OpenSession();
@ -273,8 +273,16 @@ namespace Results
log.Debug(tstRslt.ToString(1));
}
// Save batch, TestRslt, WaterMeter, MeterTestRslt, etc.
session.SaveOrUpdate(batch);
// Important: after this, TestRslt.Id should be generated
session.Flush();
// Optional table support
SolveSaveCalibFactors(batch, session);
//Commit - store results
transaction.Commit();
}
catch (Exception exc)
@ -295,6 +303,51 @@ namespace Results
return true;
}
private static void SolveSaveCalibFactors(Batch batch, ISession session)
{
bool hasCalibrationFactors = false;
try
{
foreach (var tstRslt in batch.TestRslts)
{
if (tstRslt.CalibFactorResultsToSave != null &&
tstRslt.CalibFactorResultsToSave.Count > 0)
{
hasCalibrationFactors = true;
break;
}
}
if (hasCalibrationFactors)
{
foreach (var tstRslt in batch.TestRslts)
{
if (tstRslt.CalibFactorResultsToSave == null ||
tstRslt.CalibFactorResultsToSave.Count == 0)
{
continue;
}
foreach (var calib in tstRslt.CalibFactorResultsToSave)
{
calib.TestRslt = tstRslt;
calib.ErrorStr = TestRsltCalibFactorHelper.Truncate(calib.ErrorStr, 240);
session.SaveOrUpdate(calib);
}
}
}
}catch(Exception exc)
{
log.ErrorFormat("DB - Cannot save calibration factors: {0}", exc.Message);
throw;
}
}
public static Batch LoadBatch(int batchNr)
{
@ -321,6 +374,14 @@ namespace Results
batch.WaterMeters = session.QueryOver<WaterMeter>()
.Where(x => (x.Batch.Id == batch.Id))
.List();
foreach (var tstRslt in batch.TestRslts)
{
tstRslt.CalibFactorResultsToSave = TestRsltCalibFactorHelper.GetByTestRsltId( session, tstRslt.Id);
}
}
return (batches.Count > 0) ? batches[0] : null;

View File

@ -0,0 +1,37 @@
namespace Results.Entities
{
public class MeterTestCalibFactorRslt
{
public virtual int Id { get; protected set; }
public virtual MeterTestRslt MeterTestRslt { get; set; }
/// 1, 2, 3 - calculated calib factor index
public virtual int CalibFactorIndex { get; set; }
/// Base calib factor originally set in meter
public virtual int BaseCalibFactor { get; set; }
/// Newly calculated calib factor
public virtual int CalculatedCalibFactor { get; set; }
/// true = calculated value was stored/written to meter
public virtual bool Stored { get; set; }
public virtual string ErrorStr { get; set; } // max 240 chars
public virtual double TimeStart { get; set; }
public virtual double TimeEnd { get; set; }
public virtual double CalibRawStart { get; set; }
public virtual double CalibRawEnd { get; set; }
public virtual double Error { get; set; }
public MeterTestCalibFactorRslt()
{
Stored = false;
ErrorStr = string.Empty;
}
}
}

View File

@ -59,7 +59,11 @@ namespace Results.Entities
#endif
public virtual WaterMeter WaterMeter { get; set; } /// reference to the WaterMeter entity
public virtual TestRslt TestRslt { get; set; } /// reference to the TestRslt entity
public virtual TestRslt TestRslt { get; set; }
/// reference to the TestRslt entity
public virtual int Q3Channel { get; set; }
/// Wrappers
public virtual string Name() { return TestRslt.Name(); }
@ -99,6 +103,7 @@ namespace Results.Entities
public virtual WaterMeterData WaterMeterData() { return WaterMeter.WaterMeterData; }
public virtual Batch Batch() { return WaterMeter.Batch; }
public virtual bool IsPilotRslt()
{
return (CompoundMeterId == (byte)Common.CompoundMeterId.Single) ||

View File

@ -11,6 +11,32 @@ namespace Results.Entities
{
public class TestRslt
{
/// <summary>Gets the three channel records for one physical meter, in channel order.</summary>
public virtual IList<TestRsltCalibFactor> GetCalibrationFactors(WaterMeter meter)
{
if (meter == null) throw new ArgumentNullException(nameof(meter));
lock (this)
{
if (CalibFactorResultsToSave == null) CalibFactorResultsToSave = new List<TestRsltCalibFactor>();
var result = new List<TestRsltCalibFactor>(3);
for (int channel = 1; channel <= 3; channel++)
{
TestRsltCalibFactor found = null;
foreach (var row in CalibFactorResultsToSave)
if (row.WaterMeterPosition == meter.WMPosition && row.CalibFactorIndex == channel)
{ found = row; break; }
if (found == null)
{
found = new TestRsltCalibFactor { TestRslt = this, WaterMeterPosition = meter.WMPosition, CalibFactorIndex = channel };
CalibFactorResultsToSave.Add(found);
}
result.Add(found);
}
return result;
}
}
/// Identity
public virtual int Id { get; protected set; }
public virtual Batch Batch { get; set; }
@ -152,6 +178,11 @@ namespace Results.Entities
public virtual int Counter4 { get; set; }
public virtual int Counter5 { get; set; }
/// <summary>
/// Not maped table - exist only in Genesis DB !!
/// </summary>
public virtual IList<TestRsltCalibFactor> CalibFactorResultsToSave { get; set; }
/// Wrappers
public virtual string Name() { return Common.Utils.GetTestName(TestData.Name, TestData.Repeats, RepetitionNr); }
public virtual string Key() { return string.Format("{0}~{1}~{2}~{3}", TestData.Name, Part, TestData.Repeats, RepetitionNr); } /// Unique key
@ -266,15 +297,27 @@ namespace Results.Entities
MethodClass = string.Empty;
Remark = string.Empty;
CalibFactorResultsToSave = new List<TestRsltCalibFactor>();
}
public TestRslt(Batch batch, TestData testData, int part, int repetitionNr)
public TestRslt(
Batch batch,
TestData testData,
int part,
int repetitionNr)
: this(batch, testData, part, repetitionNr, null)
{
}
public TestRslt(Batch batch, TestData testData, int part, int repetitionNr, List<TestRsltCalibFactor> calibFactor)
: this()
{
Batch = batch;
TestData = testData;
Part = part;
RepetitionNr = repetitionNr;
CalibFactorResultsToSave = calibFactor != null ? new List<TestRsltCalibFactor>(calibFactor) : new List<TestRsltCalibFactor>();
}
public virtual void CopyContentFrom(TestRslt src)

View File

@ -0,0 +1,39 @@
namespace Results.Entities
{
public class TestRsltCalibFactor
{
public virtual int Id { get; protected set; }
public virtual TestRslt TestRslt { get; set; }
public virtual int WaterMeterPosition { get; set; }
public virtual int CalibFactorIndex { get; set; } // 1, 2, 3
public virtual bool IsCalibFactorValid { get; set; }
public virtual int BaseCalibFactor { get; set; }
public virtual int CalculatedCalibFactor { get; set; }
public virtual bool Stored { get; set; }
public virtual string ErrorStr { get; set; } // varchar(240)
public virtual double TimeStart { get; set; }
public virtual double TimeEnd { get; set; }
public virtual double CalibRawStart { get; set; }
public virtual double CalibRawEnd { get; set; }
public virtual double Error { get; set; }
public virtual double VolumeStart { get; set; }
public virtual double VolumeEnd { get; set; }
public TestRsltCalibFactor()
{
Stored = false;
ErrorStr = string.Empty;
IsCalibFactorValid = false;
}
}
}

View File

@ -124,6 +124,9 @@ namespace Results.Entities
public virtual bool LastRecordIsNok { get; set; } /// Not mapped to DB !!! Previous record verification result
public virtual bool PrintLabel { get; set; } /// Not mapped to DB !!!
/// mapped to DB !!! Q3 channel number
public virtual int Q3Channel { get; set; }
public virtual WaterMeterData WaterMeterData { get; set; }
public virtual Batch Batch { get; set; }
public virtual IList<MeterTestRslt> MeterTestRslts { get; set; }
@ -506,6 +509,7 @@ namespace Results.Entities
FWVersion = string.Empty;
#endif
PrintLabel = true;
Q3Channel = 0; //No Q3 calibration by default
}
@ -570,6 +574,7 @@ namespace Results.Entities
Workflow = src.Workflow; /// Not mapped to DB
LastRecordIsNok = src.LastRecordIsNok; /// Not mapped to DB
PrintLabel = src.PrintLabel; /// Not mapped to DB
Q3Channel = src.Q3Channel; /// Mapped to DB
foreach (var mtr in MeterTestRslts)
{
@ -611,9 +616,10 @@ namespace Results.Entities
foreach (var mtr in MeterTestRslts)
{
if ((mtr.CompoundMeterId == (byte)CompoundMeterId.Single || mtr.CompoundMeterId == (byte)CompoundMeterId.Compound || mtr.CompoundMeterId == (byte)CompoundMeterId.HeatMeterEnergy)
&& mtr.TestDone
&& (mtr.Q3Channel != 0 ||
(mtr.TestDone
&& (mtr.Publish() != Publish.Never)
&& (mtr.Publish() != Publish.Internal))
&& (mtr.Publish() != Publish.Internal))))
{
testNames.Add(mtr.Name());
}

View File

@ -51,6 +51,7 @@ namespace Results.Entities
public virtual bool Compound { get; set; }
public virtual bool HeatMeter { get; set; }
public virtual int WMTypeId { get; set; } /// Mapped to DB only when ORACLE_DB is defined
public virtual int Q3Channel { get; set; } /// Q3 Channel = 0 no set > 0 is Q3 calibration
/// <summary>
/// Default constructor, safe values
@ -59,6 +60,7 @@ namespace Results.Entities
{
PulsesPerLtr = 1;
PulsesPerLtrAux = 1;
Q3Channel = 0;
}
/// <summary>
@ -101,6 +103,7 @@ namespace Results.Entities
Compound = oriWMData.Compound;
HeatMeter = oriWMData.HeatMeter;
WMTypeId = oriWMData.WMTypeId;
Q3Channel = oriWMData.Q3Channel;
}
@ -146,6 +149,7 @@ namespace Results.Entities
if (Compound != wmd.Compound) return false;
if (HeatMeter != wmd.HeatMeter) return false;
if (WMTypeId != wmd.WMTypeId) return false;
if (Q3Channel != wmd.Q3Channel) return false;
return true;
}

View File

@ -29,12 +29,48 @@ namespace Results.Entities.helpers
using (var conn = new MySqlConnection(connectionString))
{
conn.Open();
using (var create = conn.CreateCommand())
{
create.CommandText = "CREATE TABLE IF NOT EXISTS TestRsltCalibFactor (Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, TestRsltId INT NOT NULL DEFAULT 0, WaterMeterPosition INT NOT NULL DEFAULT 0, IsCalibFactorValid INT NOT NULL DEFAULT 0, VolumeStart DOUBLE NOT NULL DEFAULT 0, VolumeEnd DOUBLE NOT NULL DEFAULT 0, CalibFactorIndex INT NOT NULL DEFAULT 0, BaseCalibFactor INT NOT NULL DEFAULT 0, CalculatedCalibFactor INT NOT NULL DEFAULT 0, Stored INT NOT NULL DEFAULT 0, ErrorStr VARCHAR(240) NULL, TimeStart DOUBLE NOT NULL DEFAULT 0, TimeEnd DOUBLE NOT NULL DEFAULT 0, CalibRawStart DOUBLE NOT NULL DEFAULT 0, CalibRawEnd DOUBLE NOT NULL DEFAULT 0, Error DOUBLE NOT NULL DEFAULT 0)";
create.ExecuteNonQuery();
}
EnsureColumnMySql(conn, "TestRsltCalibFactor", "TestRsltId", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "WaterMeterPosition", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "IsCalibFactorValid", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "VolumeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "VolumeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "CalibFactorIndex", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "BaseCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "CalculatedCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "Stored", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "ErrorStr", "VARCHAR(240) NULL");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "TimeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "TimeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "CalibRawStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "CalibRawEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRsltCalibFactor", "Error", "DOUBLE NOT NULL DEFAULT 0");
using (var create = conn.CreateCommand())
{
create.CommandText = "CREATE TABLE IF NOT EXISTS MeterTestCalibFactorRslt (Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, MeterTestRslt_id INT NOT NULL DEFAULT 0, CalibFactorIndex INT NOT NULL DEFAULT 0, BaseCalibFactor INT NOT NULL DEFAULT 0, CalculatedCalibFactor INT NOT NULL DEFAULT 0, Stored INT NOT NULL DEFAULT 0, ErrorStr VARCHAR(240) NULL, TimeStart DOUBLE NOT NULL DEFAULT 0, TimeEnd DOUBLE NOT NULL DEFAULT 0, CalibRawStart DOUBLE NOT NULL DEFAULT 0, CalibRawEnd DOUBLE NOT NULL DEFAULT 0, Error DOUBLE NOT NULL DEFAULT 0)";
create.ExecuteNonQuery();
}
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "MeterTestRslt_id", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "CalibFactorIndex", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "BaseCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "CalculatedCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "Stored", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "ErrorStr", "VARCHAR(240) NULL");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "TimeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "TimeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "CalibRawStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "CalibRawEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestCalibFactorRslt", "Error", "DOUBLE NOT NULL DEFAULT 0");
// Q3Channel migrations from develop/SLM-PT50_genesisDirectDecode_special_2.
// Kept as a visible template only; the related Q3 logic is not part of this change.
// EnsureColumnMySql(conn, "WaterMeterData", "Q3Channel", "INT NOT NULL DEFAULT 0");
// EnsureColumnMySql(conn, "WaterMeter", "Q3Channel", "INT NOT NULL DEFAULT 0");
// EnsureColumnMySql(conn, "MeterTestRslt", "Q3Channel", "INT NOT NULL DEFAULT 0");
// Genesis Q3 result columns.
EnsureColumnMySql(conn, "WaterMeterData", "Q3Channel", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "WaterMeter", "Q3Channel", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "MeterTestRslt", "Q3Channel", "INT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRslt", "ConductMean", "FLOAT NOT NULL DEFAULT 0");
EnsureColumnMySql(conn, "TestRslt", "ConductStart", "FLOAT NOT NULL DEFAULT 0");
@ -135,12 +171,48 @@ namespace Results.Entities.helpers
using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=" + databaseFile))
{
conn.Open();
using (var create = conn.CreateCommand())
{
create.CommandText = "CREATE TABLE IF NOT EXISTS TestRsltCalibFactor (Id INTEGER PRIMARY KEY AUTOINCREMENT, TestRsltId INT NOT NULL DEFAULT 0, WaterMeterPosition INT NOT NULL DEFAULT 0, IsCalibFactorValid INT NOT NULL DEFAULT 0, VolumeStart DOUBLE NOT NULL DEFAULT 0, VolumeEnd DOUBLE NOT NULL DEFAULT 0, CalibFactorIndex INT NOT NULL DEFAULT 0, BaseCalibFactor INT NOT NULL DEFAULT 0, CalculatedCalibFactor INT NOT NULL DEFAULT 0, Stored INT NOT NULL DEFAULT 0, ErrorStr VARCHAR(240) NULL, TimeStart DOUBLE NOT NULL DEFAULT 0, TimeEnd DOUBLE NOT NULL DEFAULT 0, CalibRawStart DOUBLE NOT NULL DEFAULT 0, CalibRawEnd DOUBLE NOT NULL DEFAULT 0, Error DOUBLE NOT NULL DEFAULT 0)";
create.ExecuteNonQuery();
}
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "TestRsltId", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "WaterMeterPosition", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "IsCalibFactorValid", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "VolumeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "VolumeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "CalibFactorIndex", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "BaseCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "CalculatedCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "Stored", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "ErrorStr", "VARCHAR(240) NULL");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "TimeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "TimeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "CalibRawStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "CalibRawEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "TestRsltCalibFactor", "Error", "DOUBLE NOT NULL DEFAULT 0");
using (var create = conn.CreateCommand())
{
create.CommandText = "CREATE TABLE IF NOT EXISTS MeterTestCalibFactorRslt (Id INTEGER PRIMARY KEY AUTOINCREMENT, MeterTestRslt_id INT NOT NULL DEFAULT 0, CalibFactorIndex INT NOT NULL DEFAULT 0, BaseCalibFactor INT NOT NULL DEFAULT 0, CalculatedCalibFactor INT NOT NULL DEFAULT 0, Stored INT NOT NULL DEFAULT 0, ErrorStr VARCHAR(240) NULL, TimeStart DOUBLE NOT NULL DEFAULT 0, TimeEnd DOUBLE NOT NULL DEFAULT 0, CalibRawStart DOUBLE NOT NULL DEFAULT 0, CalibRawEnd DOUBLE NOT NULL DEFAULT 0, Error DOUBLE NOT NULL DEFAULT 0)";
create.ExecuteNonQuery();
}
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "MeterTestRslt_id", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "CalibFactorIndex", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "BaseCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "CalculatedCalibFactor", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "Stored", "INT NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "ErrorStr", "VARCHAR(240) NULL");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "TimeStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "TimeEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "CalibRawStart", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "CalibRawEnd", "DOUBLE NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestCalibFactorRslt", "Error", "DOUBLE NOT NULL DEFAULT 0");
// Q3Channel migrations from develop/SLM-PT50_genesisDirectDecode_special_2.
// Kept as a visible template only; the related Q3 logic is not part of this change.
// EnsureColumnSQLite(conn, "WaterMeterData", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
// EnsureColumnSQLite(conn, "WaterMeter", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
// EnsureColumnSQLite(conn, "MeterTestRslt", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
// Genesis Q3 result columns.
EnsureColumnSQLite(conn, "WaterMeterData", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "WaterMeter", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestRslt", "Q3Channel", "INTEGER NOT NULL DEFAULT 0");
EnsureColumnSQLite(conn, "MeterTestRslt", "FlipMode", "INTEGER NULL");
EnsureColumnSQLite(conn, "WaterMeter", "CalibFactorNominal", "REAL NOT NULL DEFAULT 4096");

View File

@ -0,0 +1,117 @@
using System.Collections.Generic;
using log4net;
using NHibernate;
namespace Results.Entities.helpers
{
public static class TestRsltCalibFactorHelper
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestRsltCalibFactorHelper));
public static bool TableExists(ISession session)
{
try
{
session.CreateSQLQuery( "SELECT 1 FROM TestRsltCalibFactor LIMIT 1")
.UniqueResult();
return true;
}
catch
{
return false;
}
}
public static void DeleteByTestRsltIdNoTransaction(
ISession session,
int testRsltId)
{
log.DebugFormat("Deleting TestRsltCalibFactor records for TestRsltId: {0}", testRsltId);
session.CreateSQLQuery(@" DELETE FROM TestRsltCalibFactor WHERE TestRsltId = :testRsltId")
.SetParameter("testRsltId", testRsltId)
.ExecuteUpdate();
}
public static IList<TestRsltCalibFactor> GetByTestRsltId(
ISession session,
int testRsltId)
{
return session.QueryOver<TestRsltCalibFactor>()
.Where(x => x.TestRslt.Id == testRsltId)
.OrderBy(x => x.CalibFactorIndex).Asc
.List();
}
public static string Truncate(string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
return string.Empty;
return value.Length <= maxLength
? value
: value.Substring(0, maxLength);
}
public static void CreateTableIfNotExists(ISession session)
{
if (TableExists(session))
return;
string sql;
if (DB.DbType == Common.DBType.MySql)
{
sql = @"
CREATE TABLE IF NOT EXISTS TestRsltCalibFactor (
Id INT NOT NULL AUTO_INCREMENT,
TestRsltId INT NOT NULL,
CalibFactorIndex INT NOT NULL,
BaseCalibFactor INT NOT NULL,
CalculatedCalibFactor INT NOT NULL,
IsCalibFactorValid BIT NOT NULL,
Stored BIT NOT NULL,
ErrorStr VARCHAR(240) NULL,
TimeStart DOUBLE NOT NULL,
TimeEnd DOUBLE NOT NULL,
CalibRawStart DOUBLE NOT NULL,
CalibRawEnd DOUBLE NOT NULL,
Error DOUBLE NOT NULL,
VolumeStart DOUBLE NOT NULL,
VolumeEnd DOUBLE NOT NULL,
PRIMARY KEY (Id),
INDEX IX_TestRsltCalibFactor_TestRsltId (TestRsltId),
CONSTRAINT FK_TestRsltCalibFactor_TestRslt
FOREIGN KEY (TestRsltId) REFERENCES TestRslt(Id)
ON DELETE CASCADE
);";
}
else
{
sql = @"
CREATE TABLE IF NOT EXISTS TestRsltCalibFactor (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
TestRsltId INTEGER NOT NULL,
CalibFactorIndex INTEGER NOT NULL,
BaseCalibFactor INTEGER NOT NULL,
CalculatedCalibFactor INTEGER NOT NULL,
IsCalibFactorValid INTEGER NOT NULL,
Stored INTEGER NOT NULL,
ErrorStr VARCHAR(240) NULL,
TimeStart DOUBLE NOT NULL,
TimeEnd DOUBLE NOT NULL,
CalibRawStart DOUBLE NOT NULL,
CalibRawEnd DOUBLE NOT NULL,
Error DOUBLE NOT NULL,
VolumeStart DOUBLE NOT NULL,
VolumeEnd DOUBLE NOT NULL,
FOREIGN KEY (TestRsltId) REFERENCES TestRslt(Id) ON DELETE CASCADE
);";
}
log.InfoFormat("Creating TestRsltCalibFactor table: {0}", sql);
session.CreateSQLQuery(sql).ExecuteUpdate();
}
}
}

View File

@ -69,7 +69,7 @@ namespace Results.Forms
public void Update(Results.Entities.WaterMeter wMtr)
{
if (wMtr == null || wMtr.Disabled)
if (wMtr == null || (wMtr.Disabled && wMtr.Q3Channel == 0))
{
/// Water meter position is disabled
this.disabled = true;

View File

@ -81,7 +81,7 @@ namespace Results.Forms
public void Update(Results.Entities.WaterMeter wMtr)
{
if (wMtr == null || wMtr.Disabled)
if (wMtr == null || (wMtr.Disabled && wMtr.Q3Channel == 0))
{
/// Water meter position is disabled
this.disabled = true;
@ -114,8 +114,11 @@ namespace Results.Forms
lView.Items.Clear();
foreach (var mtr in wMtr.MeterTestRslts)
{
if (mtr != null && mtr.IsPilotRslt() && mtr.TestDone && mtr.Publish() != Publish.Never
&& mtr.Publish() != Publish.Internal)
if (mtr != null && mtr.IsPilotRslt() &&
(mtr.Q3Channel!=0 || (mtr.TestDone &&
mtr.Publish() != Publish.Never &&
mtr.Publish() != Publish.Internal)
) )
{
ListViewItem lvi = new ListViewItem(testNames[ix++]);

View File

@ -0,0 +1,36 @@
using FluentNHibernate.Mapping;
using Results.Entities;
namespace Results.Mappings
{
public class MeterTestCalibFactorRsltMap : ClassMap<MeterTestCalibFactorRslt>
{
public MeterTestCalibFactorRsltMap()
{
Id(x => x.Id);
References(x => x.MeterTestRslt).Column("MeterTestRslt_id")
.Not.Nullable()
.Cascade.None();
Map(x => x.CalibFactorIndex).Not.Nullable();
Map(x => x.BaseCalibFactor).Not.Nullable();
Map(x => x.CalculatedCalibFactor).Not.Nullable();
Map(x => x.Stored).Not.Nullable();
Map(x => x.ErrorStr)
.Length(240)
.Nullable();
Map(x => x.TimeStart).Not.Nullable();
Map(x => x.TimeEnd).Not.Nullable();
Map(x => x.CalibRawStart).Not.Nullable();
Map(x => x.CalibRawEnd).Not.Nullable();
Map(x => x.Error).Not.Nullable();
}
}
}

View File

@ -50,6 +50,7 @@ namespace Results.Mappings
#endif
References(x => x.WaterMeter);
References(x => x.TestRslt);
Map(x => x.Q3Channel);
}
}
}

View File

@ -0,0 +1,43 @@
using FluentNHibernate.Mapping;
using Results.Entities;
namespace Results.Mappings
{
class TestRsltCalibFactorMap : ClassMap<TestRsltCalibFactor>
{
public TestRsltCalibFactorMap()
{
Id(x => x.Id);
References(x => x.TestRslt)
.Column("TestRsltId")
.Not.Nullable();
Map(x => x.WaterMeterPosition).Not.Nullable();
Map(x => x.CalibFactorIndex).Not.Nullable();
Map(x => x.IsCalibFactorValid).Not.Nullable();
Map(x => x.BaseCalibFactor).Not.Nullable();
Map(x => x.CalculatedCalibFactor).Not.Nullable();
Map(x => x.Stored).Not.Nullable();
Map(x => x.ErrorStr)
.Length(240)
.Nullable();
Map(x => x.TimeStart).Not.Nullable();
Map(x => x.TimeEnd).Not.Nullable();
Map(x => x.CalibRawStart).Not.Nullable();
Map(x => x.CalibRawEnd).Not.Nullable();
Map(x => x.Error).Not.Nullable();
Map(x => x.VolumeStart).Not.Nullable();
Map(x => x.VolumeEnd).Not.Nullable();
}
}
}

View File

@ -58,6 +58,8 @@ namespace Results.Mappings
#if ORACLE_DB
Map(x => x.WMTypeId);
#endif
}
Map(x => x.Q3Channel);
}
}
}

View File

@ -66,6 +66,7 @@ namespace Results.Mappings
Map(x => x.Pruefindex);
Map(x => x.HydrPruefung);
#endif
Map(x => x.Q3Channel);// Genesis meter identification
References(x => x.WaterMeterData);
References(x => x.Batch);
HasMany(x => x.MeterTestRslts)

View File

@ -281,4 +281,11 @@
</PropertyGroup>
<Error Condition="!Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
</Target>
<ItemGroup>
<Compile Include="Entities\MeterTestCalibFactorRslt.cs" />
<Compile Include="Entities\TestRsltCalibFactor.cs" />
<Compile Include="Entities\helpers\TestRsltCalibFactorHelper.cs" />
<Compile Include="Mappings\MeterTestCalibFactorRsltMap.cs" />
<Compile Include="Mappings\TestRsltCalibFactorMap.cs" />
</ItemGroup>
</Project>

View File

@ -26,7 +26,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
public int HeadCommunicationComPortNr;
public int OptoComPortNr;
public int RfidComPortNr; /// 0 = use MuxBoardNr
public int MuxBoardNr; /// 0 = use RfidComPort(Nr), otherwise mux. board nr. 1 .. 4
public int MuxBoardNr; /// 0 = use RfidComPort(Nr), otherwise mux. board nr. 1 .. 4 in new 1 .. 10 - paralel genesis access
public int Group; /// Number written to QuidoRS to connct the watermeter to RfidComPort, 1 .. 10
//public CommunicationInterface CommunicationInterface; /// Communication Interface: RFID or NFC
public string CommunicationInterfaceBridge; /// Communication Interface: RFID or NFC

View File

@ -157,7 +157,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
message += Environment.NewLine + "'Head communication serial port nr.' is not valid";
}
if (!int.TryParse(muxBoardNrTextBox.Text, out dummy) || dummy < 1 || dummy > 4)
if (!int.TryParse(muxBoardNrTextBox.Text, out dummy) || dummy < 1 || dummy > 10)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + string.Format(Strings.Invalid_0, muxBoardNrLabel.Text);

View File

@ -76,11 +76,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Location = new System.Drawing.Point(3, 4);
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.tabControl1.Location = new System.Drawing.Point(2, 3);
this.tabControl1.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(687, 540);
this.tabControl1.Size = new System.Drawing.Size(458, 351);
this.tabControl1.TabIndex = 0;
//
// tabPage1
@ -99,40 +99,42 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
this.tabPage1.Controls.Add(this.nameTextBox);
this.tabPage1.Controls.Add(this.nameLabel);
this.tabPage1.Controls.Add(this.classNameLabel);
this.tabPage1.Location = new System.Drawing.Point(4, 29);
this.tabPage1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.tabPage1.Size = new System.Drawing.Size(679, 507);
this.tabPage1.Padding = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.tabPage1.Size = new System.Drawing.Size(450, 325);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Config";
this.tabPage1.UseVisualStyleBackColor = true;
//
// label5
//
this.label5.Location = new System.Drawing.Point(372, 55);
this.label5.Location = new System.Drawing.Point(248, 36);
this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(100, 23);
this.label5.Size = new System.Drawing.Size(67, 15);
this.label5.TabIndex = 28;
this.label5.Text = "Slot Nr:";
//
// textBoxSlotNr
//
this.textBoxSlotNr.Enabled = false;
this.textBoxSlotNr.Location = new System.Drawing.Point(480, 55);
this.textBoxSlotNr.Location = new System.Drawing.Point(320, 36);
this.textBoxSlotNr.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.textBoxSlotNr.Name = "textBoxSlotNr";
this.textBoxSlotNr.Size = new System.Drawing.Size(74, 26);
this.textBoxSlotNr.Size = new System.Drawing.Size(51, 20);
this.textBoxSlotNr.TabIndex = 27;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.headPortNrTextBox);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Location = new System.Drawing.Point(11, 450);
this.groupBox2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.groupBox2.Location = new System.Drawing.Point(7, 292);
this.groupBox2.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.groupBox2.Size = new System.Drawing.Size(621, 52);
this.groupBox2.Padding = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.groupBox2.Size = new System.Drawing.Size(414, 34);
this.groupBox2.TabIndex = 26;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Head Communication";
@ -140,41 +142,37 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
// headPortNrTextBox
//
this.headPortNrTextBox.Enabled = false;
this.headPortNrTextBox.Location = new System.Drawing.Point(494, 19);
this.headPortNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.headPortNrTextBox.Location = new System.Drawing.Point(329, 12);
this.headPortNrTextBox.Name = "headPortNrTextBox";
this.headPortNrTextBox.Size = new System.Drawing.Size(49, 26);
this.headPortNrTextBox.Size = new System.Drawing.Size(34, 20);
this.headPortNrTextBox.TabIndex = 8;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(361, 22);
this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label2.Location = new System.Drawing.Point(241, 14);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(107, 20);
this.label2.Size = new System.Drawing.Size(72, 13);
this.label2.TabIndex = 7;
this.label2.Text = "Serial port nr.:";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(234, 126);
this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label4.Location = new System.Drawing.Point(156, 82);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(52, 20);
this.label4.Size = new System.Drawing.Size(37, 13);
this.label4.TabIndex = 25;
this.label4.Text = "1 .. 10";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(234, 90);
this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label3.Location = new System.Drawing.Point(156, 58);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(43, 20);
this.label3.Size = new System.Drawing.Size(37, 13);
this.label3.TabIndex = 24;
this.label3.Text = "1 .. 4";
this.label3.Text = "1 .. 10";
//
// groupBox1
//
@ -182,11 +180,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.rfidPortNrTextBox);
this.groupBox1.Controls.Add(this.rfidSerialPortNrLabel);
this.groupBox1.Location = new System.Drawing.Point(11, 363);
this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.groupBox1.Location = new System.Drawing.Point(7, 236);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.groupBox1.Size = new System.Drawing.Size(621, 85);
this.groupBox1.Size = new System.Drawing.Size(414, 55);
this.groupBox1.TabIndex = 23;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "RFID / NFC communication (in case mux. board is not used)";
@ -195,38 +191,35 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
//
this.comboBoxCommunicationInterface.Enabled = false;
this.comboBoxCommunicationInterface.FormattingEnabled = true;
this.comboBoxCommunicationInterface.Location = new System.Drawing.Point(202, 34);
this.comboBoxCommunicationInterface.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.comboBoxCommunicationInterface.Location = new System.Drawing.Point(135, 22);
this.comboBoxCommunicationInterface.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.comboBoxCommunicationInterface.Name = "comboBoxCommunicationInterface";
this.comboBoxCommunicationInterface.Size = new System.Drawing.Size(152, 28);
this.comboBoxCommunicationInterface.Size = new System.Drawing.Size(103, 21);
this.comboBoxCommunicationInterface.TabIndex = 9;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(8, 38);
this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label1.Location = new System.Drawing.Point(5, 25);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(187, 20);
this.label1.Size = new System.Drawing.Size(124, 13);
this.label1.TabIndex = 8;
this.label1.Text = "Communication Interface";
//
// rfidPortNrTextBox
//
this.rfidPortNrTextBox.Enabled = false;
this.rfidPortNrTextBox.Location = new System.Drawing.Point(494, 32);
this.rfidPortNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.rfidPortNrTextBox.Location = new System.Drawing.Point(329, 21);
this.rfidPortNrTextBox.Name = "rfidPortNrTextBox";
this.rfidPortNrTextBox.Size = new System.Drawing.Size(49, 26);
this.rfidPortNrTextBox.Size = new System.Drawing.Size(34, 20);
this.rfidPortNrTextBox.TabIndex = 7;
//
// rfidSerialPortNrLabel
//
this.rfidSerialPortNrLabel.AutoSize = true;
this.rfidSerialPortNrLabel.Location = new System.Drawing.Point(361, 38);
this.rfidSerialPortNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.rfidSerialPortNrLabel.Location = new System.Drawing.Point(241, 25);
this.rfidSerialPortNrLabel.Name = "rfidSerialPortNrLabel";
this.rfidSerialPortNrLabel.Size = new System.Drawing.Size(107, 20);
this.rfidSerialPortNrLabel.Size = new System.Drawing.Size(72, 13);
this.rfidSerialPortNrLabel.TabIndex = 6;
this.rfidSerialPortNrLabel.Text = "Serial port nr.:";
//
@ -243,11 +236,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
this.optoDataGroupBox.Controls.Add(this.radioButton2);
this.optoDataGroupBox.Controls.Add(this.optoSerialPortLabel);
this.optoDataGroupBox.Controls.Add(this.optoSerialPortTextBox);
this.optoDataGroupBox.Location = new System.Drawing.Point(11, 164);
this.optoDataGroupBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.optoDataGroupBox.Location = new System.Drawing.Point(7, 107);
this.optoDataGroupBox.Name = "optoDataGroupBox";
this.optoDataGroupBox.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.optoDataGroupBox.Size = new System.Drawing.Size(621, 189);
this.optoDataGroupBox.Size = new System.Drawing.Size(414, 123);
this.optoDataGroupBox.TabIndex = 18;
this.optoDataGroupBox.TabStop = false;
this.optoDataGroupBox.Text = "Opto-data";
@ -257,9 +248,10 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
this.checkBox_EnableShowChanels.Checked = true;
this.checkBox_EnableShowChanels.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox_EnableShowChanels.Enabled = false;
this.checkBox_EnableShowChanels.Location = new System.Drawing.Point(351, 147);
this.checkBox_EnableShowChanels.Location = new System.Drawing.Point(234, 96);
this.checkBox_EnableShowChanels.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.checkBox_EnableShowChanels.Name = "checkBox_EnableShowChanels";
this.checkBox_EnableShowChanels.Size = new System.Drawing.Size(238, 24);
this.checkBox_EnableShowChanels.Size = new System.Drawing.Size(159, 16);
this.checkBox_EnableShowChanels.TabIndex = 10;
this.checkBox_EnableShowChanels.Text = "Enable Show Channels";
this.checkBox_EnableShowChanels.UseVisualStyleBackColor = true;
@ -267,58 +259,56 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
// tBBeginDataFlush
//
this.tBBeginDataFlush.Enabled = false;
this.tBBeginDataFlush.Location = new System.Drawing.Point(474, 105);
this.tBBeginDataFlush.Location = new System.Drawing.Point(316, 68);
this.tBBeginDataFlush.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.tBBeginDataFlush.MaxLength = 8;
this.tBBeginDataFlush.Name = "tBBeginDataFlush";
this.tBBeginDataFlush.Size = new System.Drawing.Size(69, 26);
this.tBBeginDataFlush.Size = new System.Drawing.Size(47, 20);
this.tBBeginDataFlush.TabIndex = 9;
this.tBBeginDataFlush.Text = "2000";
this.tBBeginDataFlush.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
//
// labelFlush
//
this.labelFlush.Location = new System.Drawing.Point(328, 109);
this.labelFlush.Location = new System.Drawing.Point(219, 71);
this.labelFlush.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.labelFlush.Name = "labelFlush";
this.labelFlush.Size = new System.Drawing.Size(140, 22);
this.labelFlush.Size = new System.Drawing.Size(93, 14);
this.labelFlush.TabIndex = 8;
this.labelFlush.Text = "Begin Data Flush:";
//
// tcpipPortLabel
//
this.tcpipPortLabel.AutoSize = true;
this.tcpipPortLabel.Location = new System.Drawing.Point(46, 109);
this.tcpipPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.tcpipPortLabel.Location = new System.Drawing.Point(31, 71);
this.tcpipPortLabel.Name = "tcpipPortLabel";
this.tcpipPortLabel.Size = new System.Drawing.Size(68, 20);
this.tcpipPortLabel.Size = new System.Drawing.Size(47, 13);
this.tcpipPortLabel.TabIndex = 4;
this.tcpipPortLabel.Text = "Port nr..:";
//
// tcpipPortTextBox
//
this.tcpipPortTextBox.Enabled = false;
this.tcpipPortTextBox.Location = new System.Drawing.Point(161, 105);
this.tcpipPortTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.tcpipPortTextBox.Location = new System.Drawing.Point(107, 68);
this.tcpipPortTextBox.Name = "tcpipPortTextBox";
this.tcpipPortTextBox.Size = new System.Drawing.Size(57, 26);
this.tcpipPortTextBox.Size = new System.Drawing.Size(39, 20);
this.tcpipPortTextBox.TabIndex = 5;
//
// ipAddressLabel
//
this.ipAddressLabel.AutoSize = true;
this.ipAddressLabel.Location = new System.Drawing.Point(46, 74);
this.ipAddressLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.ipAddressLabel.Location = new System.Drawing.Point(31, 48);
this.ipAddressLabel.Name = "ipAddressLabel";
this.ipAddressLabel.Size = new System.Drawing.Size(93, 20);
this.ipAddressLabel.Size = new System.Drawing.Size(63, 13);
this.ipAddressLabel.TabIndex = 2;
this.ipAddressLabel.Text = "IP address.:";
//
// ipAddressTextBox
//
this.ipAddressTextBox.Enabled = false;
this.ipAddressTextBox.Location = new System.Drawing.Point(161, 69);
this.ipAddressTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.ipAddressTextBox.Location = new System.Drawing.Point(107, 45);
this.ipAddressTextBox.Name = "ipAddressTextBox";
this.ipAddressTextBox.Size = new System.Drawing.Size(145, 26);
this.ipAddressTextBox.Size = new System.Drawing.Size(98, 20);
this.ipAddressTextBox.TabIndex = 3;
//
// radioButton1
@ -326,10 +316,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
this.radioButton1.AutoSize = true;
this.radioButton1.Checked = true;
this.radioButton1.Enabled = false;
this.radioButton1.Location = new System.Drawing.Point(33, 29);
this.radioButton1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.radioButton1.Location = new System.Drawing.Point(22, 19);
this.radioButton1.Name = "radioButton1";
this.radioButton1.Size = new System.Drawing.Size(109, 24);
this.radioButton1.Size = new System.Drawing.Size(83, 17);
this.radioButton1.TabIndex = 0;
this.radioButton1.TabStop = true;
this.radioButton1.Text = "Use TCP/IP";
@ -339,10 +328,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
//
this.radioButton2.AutoSize = true;
this.radioButton2.Enabled = false;
this.radioButton2.Location = new System.Drawing.Point(351, 29);
this.radioButton2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.radioButton2.Location = new System.Drawing.Point(234, 19);
this.radioButton2.Name = "radioButton2";
this.radioButton2.Size = new System.Drawing.Size(129, 24);
this.radioButton2.Size = new System.Drawing.Size(92, 17);
this.radioButton2.TabIndex = 1;
this.radioButton2.Text = "Use serial port";
this.radioButton2.UseVisualStyleBackColor = true;
@ -350,108 +338,98 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
// optoSerialPortLabel
//
this.optoSerialPortLabel.AutoSize = true;
this.optoSerialPortLabel.Location = new System.Drawing.Point(361, 69);
this.optoSerialPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.optoSerialPortLabel.Location = new System.Drawing.Point(241, 45);
this.optoSerialPortLabel.Name = "optoSerialPortLabel";
this.optoSerialPortLabel.Size = new System.Drawing.Size(107, 20);
this.optoSerialPortLabel.Size = new System.Drawing.Size(72, 13);
this.optoSerialPortLabel.TabIndex = 6;
this.optoSerialPortLabel.Text = "Serial port nr.:";
//
// optoSerialPortTextBox
//
this.optoSerialPortTextBox.Enabled = false;
this.optoSerialPortTextBox.Location = new System.Drawing.Point(494, 65);
this.optoSerialPortTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.optoSerialPortTextBox.Location = new System.Drawing.Point(329, 42);
this.optoSerialPortTextBox.Name = "optoSerialPortTextBox";
this.optoSerialPortTextBox.Size = new System.Drawing.Size(49, 26);
this.optoSerialPortTextBox.Size = new System.Drawing.Size(34, 20);
this.optoSerialPortTextBox.TabIndex = 7;
//
// groupTextBox
//
this.groupTextBox.Enabled = false;
this.groupTextBox.Location = new System.Drawing.Point(172, 121);
this.groupTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.groupTextBox.Location = new System.Drawing.Point(115, 79);
this.groupTextBox.Name = "groupTextBox";
this.groupTextBox.Size = new System.Drawing.Size(49, 26);
this.groupTextBox.Size = new System.Drawing.Size(34, 20);
this.groupTextBox.TabIndex = 22;
//
// groupLabel
//
this.groupLabel.AutoSize = true;
this.groupLabel.Location = new System.Drawing.Point(7, 126);
this.groupLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.groupLabel.Location = new System.Drawing.Point(5, 82);
this.groupLabel.Name = "groupLabel";
this.groupLabel.Size = new System.Drawing.Size(67, 20);
this.groupLabel.Size = new System.Drawing.Size(45, 13);
this.groupLabel.TabIndex = 21;
this.groupLabel.Text = "Group 2";
//
// muxBoardNrTextBox
//
this.muxBoardNrTextBox.Enabled = false;
this.muxBoardNrTextBox.Location = new System.Drawing.Point(172, 86);
this.muxBoardNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.muxBoardNrTextBox.Location = new System.Drawing.Point(115, 56);
this.muxBoardNrTextBox.Name = "muxBoardNrTextBox";
this.muxBoardNrTextBox.Size = new System.Drawing.Size(49, 26);
this.muxBoardNrTextBox.Size = new System.Drawing.Size(34, 20);
this.muxBoardNrTextBox.TabIndex = 20;
//
// muxBoardNrLabel
//
this.muxBoardNrLabel.AutoSize = true;
this.muxBoardNrLabel.Location = new System.Drawing.Point(7, 90);
this.muxBoardNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.muxBoardNrLabel.Location = new System.Drawing.Point(5, 58);
this.muxBoardNrLabel.Name = "muxBoardNrLabel";
this.muxBoardNrLabel.Size = new System.Drawing.Size(159, 20);
this.muxBoardNrLabel.Size = new System.Drawing.Size(106, 13);
this.muxBoardNrLabel.TabIndex = 19;
this.muxBoardNrLabel.Text = "Group 1 (mux. board)";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(172, 50);
this.nameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.nameTextBox.Location = new System.Drawing.Point(115, 32);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(180, 26);
this.nameTextBox.Size = new System.Drawing.Size(121, 20);
this.nameTextBox.TabIndex = 17;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(7, 55);
this.nameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.nameLabel.Location = new System.Drawing.Point(5, 36);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(51, 20);
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 16;
this.nameLabel.Text = "Name";
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(168, 14);
this.classNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.classNameLabel.Location = new System.Drawing.Point(112, 9);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(90, 20);
this.classNameLabel.Size = new System.Drawing.Size(60, 13);
this.classNameLabel.TabIndex = 15;
this.classNameLabel.Text = "ClassName";
//
// tabPage2
//
this.tabPage2.Location = new System.Drawing.Point(4, 29);
this.tabPage2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
this.tabPage2.Size = new System.Drawing.Size(679, 507);
this.tabPage2.Padding = new System.Windows.Forms.Padding(2, 3, 2, 3);
this.tabPage2.Size = new System.Drawing.Size(450, 325);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Test";
this.tabPage2.UseVisualStyleBackColor = true;
//
// GenesisCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tabControl1);
this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.Name = "GenesisCfgCtrl";
this.Size = new System.Drawing.Size(694, 548);
this.Size = new System.Drawing.Size(463, 356);
this.Load += new System.EventHandler(this.WaterMeterCfgCtrl_Load);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);

View File

@ -0,0 +1,49 @@
using System.Threading;
using System.Threading.Tasks;
using GenesisCordonelInterface.API;
using GenesisCordonelInterface.Core.Threading;
using TBF.Rig.BridgeComponents.GciBridge;
namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
{
public class GciBridgeClient : IGciBridgeClient
{
private readonly GciBridge bridge;
public GciBridgeClient(GciBridge bridge)
{
this.bridge = bridge;
}
public Task<RetryResult<PublicModels.RegisterReadResult>>
ReadRegisterWithRetryAsync(
int slotId,
string registerName,
CancellationToken token = default)
{
return bridge.ReadRegisterWithRetryAsync(
slotId,
registerName,
token);
}
public Task<RetryResult<PublicModels.RegisterWriteResult>>
WriteRegisterWithRetryAsync(
int slotId,
string registerName,
ushort value,
bool verify,
bool throwOnError,
CancellationToken token = default)
{
return bridge.WriteRegisterWithRetryAsync(
slotId,
registerName,
value,
verify,
throwOnError,
token);
}
}
}

View File

@ -0,0 +1,25 @@
using System.Threading;
using System.Threading.Tasks;
using GenesisCordonelInterface.API;
using GenesisCordonelInterface.Core.Threading;
namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
{
public interface IGciBridgeClient
{
Task<RetryResult<PublicModels.RegisterReadResult>>
ReadRegisterWithRetryAsync(
int slotId,
string registerName,
CancellationToken token = default);
Task<RetryResult<PublicModels.RegisterWriteResult>>
WriteRegisterWithRetryAsync(
int slotId,
string registerName,
ushort value,
bool verify,
bool throwOnError,
CancellationToken token = default);
}
}

View File

@ -1,16 +1,29 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using GenesisCordonelInterface.API;
using log4net;
using TBF.Rig.BridgeComponents.GciBridge;
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
using TBF.Rig.RegisterReaders.GenesisRegReader.communication.common;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
using PublicModels = TBF.Rig.BridgeComponents.GciBridge.Interfaces.PublicModels;
namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
{
public class ReadPcbResult
{
public bool IsConnected { get; set; }
public bool IsLoggedOn { get; set; }
public bool IsValidPcb { get; set; }
public string PcbId { get; set; }
public string Message { get; set; }
}
public class RadioService
{
private static readonly ILog log = LogManager.GetLogger(typeof(RadioService));
@ -18,6 +31,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
static string okResponse = "Command complete, no errors";
static string errorResponse = "Unable to execute";
private bool bConnected = false;
private GciBridge _bridge;
public RadioService(GciBridge genesisHeadCommInterfaceBridgeComponent)
@ -26,260 +41,492 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
log.Debug("RadioService created with GciBridge= " + genesisHeadCommInterfaceBridgeComponent + "");
}
public async Task<string> ReadRequest_PCBAsyn1(GenesisSmartReader iHead)
private async Task<ReadPcbResult> EnsureConnectedAsync(
GenesisSmartReader head,
CancellationToken token = default)
{
if (iHead?.CommInterfaceBridge == null)
return null;
var connectTask = iHead.CommInterfaceBridge.ConnectAsync(iHead.GetSlotNr);
// Wait either for ConnectAsync or timeout
if (await Task.WhenAny(connectTask, Task.Delay(TimeSpan.FromMinutes(1))) != connectTask)
log.Debug("EnsureConnectedAsync called for iHead: " + head);
if (head?.CommInterfaceBridge == null)
{
// Timed out
return null;
return new ReadPcbResult
{
IsConnected = false,
IsLoggedOn = false,
IsValidPcb = false,
Message = "CommInterfaceBridge is null."
};
}
var slotInfo = await _bridge.GetSlotAsync(head.GetSlotNr);
if (slotInfo == null || !slotInfo.Success)
{
//just no definet yet ?
log.Debug("EnsureConnectedAsync() - SlotInfo is null.");
}
else if (slotInfo.IsConnected)
{
log.Debug("EnsureConnectedAsync() - Slot: " + slotInfo);
return new ReadPcbResult
{
IsConnected = true,
IsLoggedOn = slotInfo.IsLoggedOn,
IsValidPcb = false,
PcbId = slotInfo.PcbId,
Message = "Already connected."
};
}
log.Debug("EnsureConnectedAsync() - Connecting...");
var connectTask = head.CommInterfaceBridge.ConnectAsync(head.GetSlotNr, token);
var timeoutTask = Task.Delay(TimeSpan.FromMinutes(1), token);
var completedTask = await Task.WhenAny(connectTask, timeoutTask);
if (completedTask != connectTask)
{
return new ReadPcbResult
{
IsConnected = false,
IsLoggedOn = false,
IsValidPcb = false,
Message = "Connect timeout."
};
}
var result = await connectTask;
if (result == null || !result.Success || !result.IsConnected)
return null;
string pcbId = result.PcbId;
if (!string.IsNullOrEmpty(pcbId))
if (result == null || !result.Success)
{
if (iHead.ConfigStruct != null)
iHead.ConfigStruct.PCBNumberString = pcbId;
return pcbId;
return new ReadPcbResult
{
IsConnected = false,
IsLoggedOn = false,
IsValidPcb = false,
Message = result == null ? "Connect result is null." : "Connect failed."
};
}
return null;
return new ReadPcbResult
{
IsConnected = result.IsConnected,
IsLoggedOn = false,
IsValidPcb = false,
Message = "Connected OK."
};
}
public async Task<string> ReadRequest_PCBAsync(GenesisSmartReader iHead)
public async Task<PublicModels.UdsPasswordResult> FindKeyStone(
string txtPCBId,
CancellationToken token = default)
{
log.Debug("ReadRequest_PCB called for iHead: " + iHead);
string pcbId = txtPCBId?.Trim();
if (iHead?.CommInterfaceBridge == null)
return null;
if (string.IsNullOrWhiteSpace(pcbId))
throw new Exception("PCB ID is empty.");
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));
token.ThrowIfCancellationRequested();
PublicModels.GciConnectResult result;
PublicModels.UdsPasswordResult result = await _bridge.GetPasswordAsync(pcbId, token);
try
{
log.Debug("ReadRequest_PCB() - calling ConnectAsync");
log.Debug("GetPasswordAsync PCB=" + pcbId + " Result: " + result);
result = await iHead.CommInterfaceBridge
.ConnectAsync(iHead.GetSlotNr, cts.Token)
.ConfigureAwait(false);
log.Debug("ReadRequest_PCB() - ConnectAsync completed");
}
catch (OperationCanceledException)
{
log.Debug("ReadRequest_PCB() - ConnectAsync timeout/cancelled");
return null;
}
catch (Exception ex)
{
log.Error("ReadRequest_PCB() - ConnectAsync failed", ex);
return null;
}
if (result == null || !result.Success || !result.IsConnected)
{
log.Debug("ReadRequest_PCB() - invalid result: " + result);
return null;
}
string pcbId = result.PcbId;
if (string.IsNullOrEmpty(pcbId))
{
log.Debug("ReadRequest_PCB() - pcbId is empty");
return null;
}
if (iHead.ConfigStruct != null)
{
iHead.ConfigStruct.PCBNumberString = pcbId;
log.Debug("ReadRequest_PCB() - PCBNumberString: " + pcbId);
}
return pcbId;
return result;
}
public string ReadRequest_PCB(ref GenesisSmartReader iHead)
public async Task<GenesisCordonelInterface.API.PublicModels.GciLoginResult> LoginByPasswordAsync(
int slotId, string txtPassword,
CancellationToken token = default)
{
var head = iHead; // <-- copy to local (no longer ref)
if (string.IsNullOrWhiteSpace(txtPassword))
throw new Exception("LoginByPasswordAsync() - PASSWORD is empty.");
token.ThrowIfCancellationRequested();
log.Debug($"LoginByPasswordAsync( Slot: {slotId}) - set password to: " + txtPassword.Substring(0, 4) + "************");
var gciSetPasswordResult = await _bridge.SetPasswordAsync(slotId,txtPassword, token);
log.Debug($"LoginByPasswordAsync( Slot: {slotId}) - SetPasswordAsync Result: " + gciSetPasswordResult);
// LOGIN
log.Debug($"LoginByPasswordAsync( Slot: {slotId}) - START LOGIN");
var gciSlotInfo = await _bridge.GetSlotAsync(slotId);
log.Debug($"LoginByPasswordAsync( Checked before Login() Slot: {slotId}) - START LOGIN Slot: {gciSlotInfo}");
GenesisCordonelInterface.API.PublicModels.GciLoginResult result = await _bridge.LoginAsync(slotId, token);
log.Debug($"LoginByPasswordAsync( Slot: {slotId}) Result: " + result);
log.Debug($"LoginByPasswordAsync( Slot: {slotId}) - END LOGIN, Success: {result.Success}");
// ~ LOGIN
return result;
}
public async Task<ReadPcbResult> ReadRequest_PCBAsync( GenesisSmartReader head, bool bReload = false)
{
log.Debug("ReadRequest_PCB called for iHead: " + head);
if (head?.CommInterfaceBridge == null)
return null;
{
return new ReadPcbResult
{
IsConnected = false,
IsValidPcb = false,
Message = "CommInterfaceBridge is null."
};
}
try
{
var connectTask = Task.Run(async () =>
await head.CommInterfaceBridge.ConnectAsync(head.GetSlotNr)
);
// CONNECT ONLY IF NEEDED
var connectResult = await EnsureConnectedAsync(head);
var completedTask = Task.WhenAny(
connectTask,
Task.Delay(TimeSpan.FromMinutes(1))
).GetAwaiter().GetResult();
if (completedTask != connectTask)
if (!connectResult.IsConnected)
{
log.Debug("ReadRequest_PCB() - Timeout happened");
return null;
return connectResult;
}
var result = connectTask.GetAwaiter().GetResult();
log.Debug("ReadRequest_PCB() - Result: " + result);
log.Debug($"ReadRequest_PCB() connect - {connectResult.Message}");
if (result == null || !result.Success || !result.IsConnected)
return null;
var pcbId = result.PcbId;
log.Debug("Result pcbId: " + pcbId);
if (!string.IsNullOrEmpty(pcbId) && head.ConfigStruct != null)
//Check if exist PCB
if (!bReload)
{
head.ConfigStruct.PCBNumberString = pcbId;
log.Debug("Result set to ConfigStruct.PCBNumberString = " + head.ConfigStruct.PCBNumberString);
var gciSlotInfo = await head.CommInterfaceBridge.GetSlotAsync(head.GetSlotNr);
if (gciSlotInfo == null && gciSlotInfo.Success && string.IsNullOrEmpty(gciSlotInfo.PcbId))
{
log.Debug(
$"BuildConnection() - SlotNr: {head.GetSlotNr} already exist PCB: {gciSlotInfo.PcbId}");
return new ReadPcbResult
{
IsConnected = gciSlotInfo.IsConnected,
IsValidPcb = true,
PcbId = gciSlotInfo.PcbId,
Message = "PCB already exist."
};
}
}
return pcbId;
// PCB READ LOOP
string validPcbId = null;
int maxAttempts = 5;
DateTime startTime = DateTime.UtcNow;
TimeSpan maxDuration = TimeSpan.FromSeconds(30);
//LOOP
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
if (DateTime.UtcNow - startTime > maxDuration)
{
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) - PCB max duration exceeded");
break;
}
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) - PCB attempt {attempt}/{maxAttempts}");
var pcbTask = head.CommInterfaceBridge.GetPcbIdAsync(head.GetSlotNr);
var timeoutTaskPcb = Task.Delay(TimeSpan.FromSeconds(5));
var completedTaskPcb = await Task.WhenAny(pcbTask, timeoutTaskPcb);
if (completedTaskPcb != pcbTask)
{
log.Debug($"ReadRequest_PCB() PCB attempt {attempt} - Timeout");
continue;
}
var resultPCB = await pcbTask;
// VALIDATION BLOCK
{
if (resultPCB == null)
{
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) PCB attempt {attempt} - result is null");
continue;
}
if (!resultPCB.Success)
{
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) PCB attempt {attempt} - Success=false");
continue;
}
string pcbId = resultPCB.PcbId;
if (string.IsNullOrWhiteSpace(pcbId))
{
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) PCB attempt {attempt} - PCB empty");
continue;
}
pcbId = pcbId.Trim();
if (pcbId.Length != 9)
{
log.Debug( $"ReadRequest_PCB({head.GetSlotNr}) PCB attempt {attempt} - Invalid PCB length: '{pcbId}', len={pcbId.Length}");
continue;
}
validPcbId = pcbId;
log.Debug($"ReadRequest_PCB({head.GetSlotNr}) PCB valid: {validPcbId}");
break;
}
}
if (string.IsNullOrEmpty(validPcbId))
{
return new ReadPcbResult
{
IsConnected = connectResult.IsConnected,
IsValidPcb = false,
PcbId = null,
Message = "Valid PCB not found."
};
}
if (head.ConfigStruct != null)
{
head.ConfigStruct.PCBNumberString = validPcbId;
}
return new ReadPcbResult
{
IsConnected = connectResult.IsConnected,
IsValidPcb = true,
PcbId = validPcbId,
Message = "PCB OK"
};
}
catch (Exception ex)
{
log.Error("ReadRequest_PCB() failed", ex);
return null;
}
}
log.Error("ReadRequest_PCBAsync() failed", ex);
public string ReadRequest_PCB2(ref GenesisSmartReader iHead)
{
return ReadRequest_PCBAsync(iHead).GetAwaiter().GetResult();
}
public string ReadRequest_PCB1(ref GenesisSmartReader iHead)
{
log.Debug("ReadRequest_PCB called for iHead: " + iHead.ToString());
if (iHead?.CommInterfaceBridge == null)
return null;
// -- connection --
var connectTask = iHead.CommInterfaceBridge.ConnectAsync(iHead.GetSlotNr);
log.Debug("ReadRequest_PCB() - ConnectAsync created, Now waiting for result");
var completedTask = Task.WhenAny(
connectTask,
Task.Delay(TimeSpan.FromMinutes(1))
).GetAwaiter().GetResult();
log.Debug("ReadRequest_PCB() - CompletedTask: " + completedTask);
// Timeout happened
if (completedTask != connectTask)
{
log.Debug("ReadRequest_PCB() - Timeout happened");
return null;
}
var result = connectTask.GetAwaiter().GetResult();
log.Debug("ReadRequest_PCB() - ConnectAsync completed");
if (result == null || !result.Success || !result.IsConnected)
return null;
log.Debug("ReadRequest_PCB() - result: " + result);
//~ -- connection --
string pcbId = result.PcbId;
log.Debug("ReadRequest_PCB() - pcbId: " + pcbId);
if (!string.IsNullOrEmpty(pcbId))
{
if (iHead.ConfigStruct != null)
return new ReadPcbResult
{
iHead.ConfigStruct.PCBNumberString = pcbId;
log.Debug("ReadRequest_PCB() - iHead.ConfigStruct.PCBNumberString: " +
iHead.ConfigStruct.PCBNumberString);
IsConnected = false,
IsValidPcb = false,
PcbId = null,
Message = ex.Message
};
}
}
public async Task<bool> PrepareLoginAdnConnect_Async(
GenesisSmartReader iHead,
bool isConnected,
CancellationToken token = default)
{
log.Debug("PrepareLoginAdnConnect_Async called for iHead: " + iHead + " isConnected: " + isConnected);
if (iHead?.CommInterfaceBridge == null)
return false;
try
{
token.ThrowIfCancellationRequested();
var connectResult = await EnsureConnectedAsync(iHead, token);
if (!connectResult.IsConnected)
return false;
log.Debug($"PrepareLoginAdnConnect_Async() connect - {connectResult.Message}");
if (connectResult.IsLoggedOn)
return true;
//get stored PCB - Keystone
log.Debug("Have we PCB stored?");
string pcb = iHead.ConfigStruct?.PCBNumberString;
if (string.IsNullOrWhiteSpace(pcb))
{
pcb = connectResult.PcbId;
if (string.IsNullOrWhiteSpace(pcb))
{
pcb = iHead.SerialNr;
}
//GET PCB FROM Meter
if (string.IsNullOrWhiteSpace(pcb))
{
log.Debug("PrepareLoginAdnConnect_Async() No PCB stored. Trying to get PCB from Meter");
var pcbResult = await ReadRequest_PCBAsync(iHead);
if (pcbResult.IsValidPcb)
{
pcb = pcbResult.PcbId;
iHead.SerialNr = pcb;
if (iHead.ConfigStruct != null)
{
iHead.ConfigStruct.PCBNumberString = pcb;
}
}
}
}
return pcbId;
if (string.IsNullOrWhiteSpace(pcb))
{
log.Debug("PrepareLoginAdnConnect_Async() No PCB stored. MISSING PCB!!!!!");
return false;
}
log.Debug( $"PrepareLoginAdnConnect_Async() Start Find Keystone Slot: {iHead.GetSlotNr} PCB:{iHead.SerialNr} Calib PCB:{pcb} - find keystone");
var keyStoneResult = await FindKeyStone(pcb, token);
if (keyStoneResult == null || !keyStoneResult.Success)
return false;
//LOGIN
log.Debug( $"PrepareLoginAdnConnect_Async() Start Login Slot: {iHead.GetSlotNr} PCB:{iHead.SerialNr} Calib PCB:{pcb} - login");
GenesisCordonelInterface.API.PublicModels.GciLoginResult loginByPasswordAsync =
await LoginByPasswordAsync(iHead.GetSlotNr, keyStoneResult.Password, token);
if (loginByPasswordAsync == null || !loginByPasswordAsync.Success)
{
return false;
}
log.Debug($"PrepareLoginAdnConnect_Async() Login OK");
return true;
}
log.Debug("ReadRequest_PCB() - pcbId is empty");
return null;
}
public ProtocolStatuses GetActivityStatusMode(GenesisSmartReader iHead)
{
if (iHead?.CommInterfaceBridge == null)
return ProtocolStatuses.Unknown;
var connectResult = iHead.CommInterfaceBridge
.ConnectAsync(iHead.GetSlotNr)
.GetAwaiter()
.GetResult();
if (connectResult == null || !connectResult.Success || !connectResult.IsConnected)
return ProtocolStatuses.Unknown;
var pcbResult = iHead.CommInterfaceBridge
.GetPcbIdAsync(iHead.GetSlotNr)
.GetAwaiter()
.GetResult();
if (pcbResult == null || !pcbResult.Success || string.IsNullOrWhiteSpace(pcbResult.PcbId))
return ProtocolStatuses.Unknown;
if (iHead.ConfigStruct != null)
catch (OperationCanceledException)
{
iHead.ConfigStruct.PCBNumberString = pcbResult.PcbId;
log.Debug("PrepareLoginAdnConnect_Async() canceled.");
return false;
}
return ProtocolStatuses.Active;
}
public DiagnosticLedState SetOptoStatusMode(GenesisSmartReader iHead, DiagnosticLedState opthoStatusMode)
public static readonly String LedMode = "GENESISFLOW_LedMode";
public static readonly String SampleRate = "GENESISFLOW_SampleRate";
public static readonly String CalFactor1 = "GENESISFLOW_CalFactor1";
public static readonly String CalFactor2 = "GENESISFLOW_CalFactor2";
public static readonly String CalFactor3 = "GENESISFLOW_CalFactor3";
public static readonly String ResetAccumulators = "GENESISFLOW_ResetAccumulators";
public static readonly String ForwardArrow = "GENESISFLOW_ForwardArrow";
public static readonly String StoreCalibration = "GENESISFLOW_StoreCalibration";
public static readonly String TriggerIdle = "GENESISFLOW_TriggerIdle";
public static readonly String MeterSize = "GENESISFLOW_MeterSize";
public async Task<LedState> GetActivityLedStatusMode_Async(
GenesisSmartReader iHead,
bool isConnected,
CancellationToken token = default)
{
log.Debug("GetActivityLedStatusMode_Async called for iHead: " + iHead + " isConnected: " + isConnected);
if (iHead?.CommInterfaceBridge == null)
return DiagnosticLedState.StatusUnknown;
return LedState.Unknown;
var connectResult = iHead.CommInterfaceBridge
.ConnectAsync(iHead.GetSlotNr)
.GetAwaiter()
.GetResult();
if (connectResult == null || !connectResult.Success || !connectResult.IsConnected)
return DiagnosticLedState.StatusUnknown;
//SetDiagnosticLEDState
var pcbResult = iHead.CommInterfaceBridge
.GetPcbIdAsync(iHead.GetSlotNr)
.GetAwaiter()
.GetResult();
if (pcbResult == null || !pcbResult.Success || string.IsNullOrWhiteSpace(pcbResult.PcbId))
return DiagnosticLedState.StatusUnknown;
if (iHead.ConfigStruct != null)
try
{
iHead.ConfigStruct.PCBNumberString = pcbResult.PcbId;
var loginAdnConnectAsync = await PrepareLoginAdnConnect_Async(iHead, isConnected, token);
if (!loginAdnConnectAsync)
return LedState.Unknown;
//Get Activity Status
var registerReadResult =
await _bridge.ReadRegisterWithRetryAsync(iHead.GetSlotNr,LedMode, token);
if (registerReadResult == null || !registerReadResult.Success)
{
return LedState.Unknown;
}
log.Debug($"GetActivityStatusMode() Read Register OK Response: {registerReadResult}");
try
{
byte[] bytes = HexFormatter.HexStringToByteArray(registerReadResult.Result.RawHex);
//Convert byte array to int
if (bytes == null || bytes.Length < 4)
{
log.Debug("Invalid byte array length");
return LedState.Unknown;
}
int value = BitConverter.ToInt32(bytes, 0);
// continue your real status logic here...
return value == 6 ? LedState.active : LedState.inactive;
}catch(Exception ex)
{
log.Error("GetActivityStatusMode() failed", ex);
return LedState.Unknown;
}
}
catch (OperationCanceledException)
{
log.Debug("GetActivityLedStatusMode_Async() canceled.");
return LedState.Unknown;
}
catch (Exception ex)
{
log.Error("GetActivityLedStatusMode_Async() failed", ex);
return LedState.Unknown;
}
return DiagnosticLedState.StatusUnknown;
}
public async Task<bool> SetLedMode_Async(GenesisSmartReader iHead, LedState ledMode, bool isConnected,
CancellationToken token = default)
{
log.Debug("SetLedMode_Async called for iHead: " + iHead + " isConnected: " + isConnected);
if (iHead?.CommInterfaceBridge == null)
return false;
try
{
var loginAdnConnectAsync = await PrepareLoginAdnConnect_Async(iHead, isConnected, token);
if (!loginAdnConnectAsync)
return false;
//Get Activity Status
byte valueLed = (ledMode == LedState.active) ? (byte)6 : (byte)0;
log.Debug($"SetLedMode_Async() Set Led Mode: {valueLed}");
var registerWriteResult =
await _bridge.WriteRegisterAsync(iHead.GetSlotNr, LedMode, valueLed, false, false, token);
if (registerWriteResult == null || !registerWriteResult.Success)
{
return false;
}
log.Debug($"SetLedMode_Async() Write Register OK Response: {registerWriteResult}");
return true;
}
catch (OperationCanceledException)
{
log.Debug("GetActivityLedStatusMode_Async() canceled.");
return false;
}
catch (Exception ex)
{
log.Error("GetActivityLedStatusMode_Async() failed", ex);
return false;
}
finally
{
log.Debug("SetLedMode_Async() - End - DO DISCONNECT");
var gciDisconnectResult = await _bridge.DisconnectAsync(iHead.GetSlotNr);
log.Debug($"SetLedMode_Async() Disconnect Result: {gciDisconnectResult}");
}
}
public async Task<bool> Disconnect_Async(GenesisSmartReader iHead)
{
try
{
log.Debug("Disconnect_Async() - Start");
var gciSlotInfo = await _bridge.GetSlotAsync(iHead.GetSlotNr);
log.Debug($"Disconnect_Async() - Slot: {iHead.GetSlotNr} - SlotInfo: {gciSlotInfo}");
log.Debug("Disconnect_Async() - DO DISCONNECT");
var gciDisconnectResult = await _bridge.DisconnectAsync(iHead.GetSlotNr);
log.Debug($"Disconnect_Async() Disconnect Result: {gciDisconnectResult}");
return gciDisconnectResult.Success;
}catch(Exception ex)
{
log.Error("Disconnect_Async() failed", ex);
return false;
}
}
private static ushort SafeIntToUShort(int value)
{
@ -316,29 +563,41 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication
}
public bool SetActivityMode_Active(GenesisSmartReader iHead)
public async Task<bool> SetActivityMode_Active(GenesisSmartReader iHead,
bool isConnected, CancellationToken token = default)
{
log.Debug("SetActivityMode_Active called for iHead: " + iHead + " isConnected: " + isConnected);
if (iHead?.CommInterfaceBridge == null)
return false;
var connectResult = iHead.CommInterfaceBridge
.ConnectAsync(iHead.GetSlotNr)
.GetAwaiter()
.GetResult();
try
{
token.ThrowIfCancellationRequested();
if (connectResult == null || !connectResult.Success || !connectResult.IsConnected)
var connectResult = await EnsureConnectedAsync(iHead, token);
if (!connectResult.IsConnected)
return false;
isConnected = connectResult.IsConnected;
log.Debug($"SetActivityMode_Active() connect - {connectResult.Message}");
//Set LED to state 4
// string version = _bridge?.GciExternalInterface?.GetPcbId(iHead.GetSlotNr);
// if (!string.IsNullOrEmpty(version))
// {
// if (iHead.ConfigStruct != null) // store mechanism
// {
// iHead.ConfigStruct.Version = version;
// }
// return true;
// }
}catch(OperationCanceledException)
{
return false;
//Set LED to state 4
// string version = _bridge?.GciExternalInterface?.GetPcbId(iHead.GetSlotNr);
// if (!string.IsNullOrEmpty(version))
// {
// if (iHead.ConfigStruct != null) // store mechanism
// {
// iHead.ConfigStruct.Version = version;
// }
// return true;
// }
}
return false;
}

View File

@ -0,0 +1,9 @@
namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.common
{
public enum LedState : int
{
Unknown = -1,
inactive = 0,
active = 1,
}
}

View File

@ -40,6 +40,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
public void Destroy()
{
if(Head != null && Head.OptoHeadTest != null)
{
Head.OptoHeadTest.CloseConnection();
}
stopWorkerThread = true;
if (optoThread != null)
{

View File

@ -216,6 +216,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
public int ChannelsCount { get => iChanelsCount; }
private static int iChanelsCount = 3;
private int firstChanel;
@ -1339,16 +1341,6 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
void DataStreamPostProcessing()
{
PrepareCalculatedChannelData();
try
{
log.DebugFormat("DataStreamPostProcessing() - harcoded call GetQ3Calibration(200.0, 120.0, 15625.0);");
SetQ3Calibration(new double[]{15625.0,15625.0,15625.0 });
CalculateQ3Calibration(200.0, 120.0);
}
catch (Exception ex)
{
log.Error($"DataStreamPostProcessing -- Q3 CALIBRATION -- failed: {ex}");
}
}
/// <summary>
@ -1882,7 +1874,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
_readLoopTask = Task.Run(() =>
{
log.Debug($"OPTHO {OptoComPortNr} background read loop started.");
logStream.Debug($"OPTHO {OptoComPortNr} background read loop started.");
while (!token.IsCancellationRequested)
{
@ -1938,12 +1930,12 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Error($"OPTHO {OptoComPortNr} background read error: {ex.Message}");
logStream.Error($"OPTHO {OptoComPortNr} background read error: {ex.Message}");
Thread.Sleep(100);
}
}
log.Debug($"OPTHO {OptoComPortNr} background read loop stopped.");
logStream.Debug($"OPTHO {OptoComPortNr} background read loop stopped.");
}, token);
}
@ -2024,7 +2016,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
{
try
{
log.Debug($"OPTHO {OptoComPortNr} processing loop started.");
logStream.Debug($"OPTHO {OptoComPortNr} processing loop started.");
while (!token.IsCancellationRequested)
{
@ -2054,14 +2046,14 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (blockCompleted)
{
log.Debug("Processing loop completed flow block detected.");
logStream.Debug("Processing loop completed flow block detected.");
if (resetSerialBuffersOnCompletedFlowBlock)
ResetDataBuffer();
}
}
catch (Exception ex)
{
log.Error($"Processing loop failed: {ex}");
logStream.Error($"Processing loop failed: {ex}");
}
continue;
@ -2075,16 +2067,16 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Error($"OPTHO {OptoComPortNr} processing loop error: {ex}");
logStream.Error($"OPTHO {OptoComPortNr} processing loop error: {ex}");
Thread.Sleep(50);
}
}
log.Debug($"OPTHO {OptoComPortNr} processing loop stopped.");
logStream.Debug($"OPTHO {OptoComPortNr} processing loop stopped.");
}
catch (Exception ex)
{
log.Error($"StartProcessingLoop fatal error: {ex}");
logStream.Error($"StartProcessingLoop fatal error: {ex}");
}
}, token);
}
@ -2113,13 +2105,13 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
// 🔴 STEP 1: Check if we should start processing
if (startDataProcessing && optoState == DataStreamState.ProcessAndSave)
{
log.DebugFormat("Read Opto Data Line timestamp:{0} to process from queue: {1}",timestamp.ToString("HH:mm:ss.fff") , line);
logStream.DebugFormat("Read Opto Data Line timestamp:{0} to process from queue: {1}",timestamp.ToString("HH:mm:ss.fff") , line);
bool blockCompleted;
ProcessOptoLine(line, optoState, out blockCompleted);
if (blockCompleted)
{
log.Debug("ReadOptoData() completed flow block detected.");
logStream.Debug("ReadOptoData() completed flow block detected.");
if (resetSerialBuffersOnCompletedFlowBlock) // DO NOT call ResetDataBuffer() here
ResetDataBuffer();
}
@ -2127,7 +2119,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Error($"OPTHO {OptoComPortNr} processing queued line failed: {ex.Message}");
logStream.Error($"OPTHO {OptoComPortNr} processing queued line failed: {ex.Message}");
}
}
}
@ -2154,14 +2146,14 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (streamingDecode.DataFlowTest != null && streamingDecode.DataFlowTest.IsValid)
{
blockCompleted = HandleFlowMarker();
log.Debug("ComPort: " + OptoComPortNr + " Decoded Flow data: " + streamingDecode.DataFlowTest +
" OPTHO RX ← " + HexFormatter.ToSerialHex(bytes));
logStream.Debug("ComPort: " + OptoComPortNr + " Decoded Flow data: " + streamingDecode.DataFlowTest +
" OPTHO RX ← " + HexFormatter.ToSerialHex(bytes));
}
if (calibData != null && calibData.IsValid)
{
log.Debug("ComPort: " + OptoComPortNr + " Decoded Calib: " + calibData + " OPTHO RX ← " +
HexFormatter.ToSerialHex(bytes));
logStream.Debug("ComPort: " + OptoComPortNr + " Decoded Calib: " + calibData + " OPTHO RX ← " +
HexFormatter.ToSerialHex(bytes));
MarkCalibrationChannelSeen(calibData.Channel);
}
@ -2181,7 +2173,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (optoData[bufferIx] == null)
{
log.ErrorFormat("{0}: optoData[{1}] was null, recreating.", Name, bufferIx);
logStream.ErrorFormat("{0}: optoData[{1}] was null, recreating.", Name, bufferIx);
optoData[bufferIx] = new OptoTelegramRaw();
}
@ -2194,7 +2186,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
int iChanel = calibData.Channel - 1;
if (iChanel >= 0 && iChanel < iChanelsCount)
{
log.Debug(
logStream.Debug(
$"Before UpdateFromSmart ch={iChanel + 1}: " +
$"volumeRawExtLast={volumeRawExtLast[iChanel]}, " +
$"timestampExtLast={timestampExtLast[iChanel]}, " +
@ -2262,7 +2254,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
var encoding = optoSerialPort?.Encoding ?? Encoding.ASCII;
byte[] bytes = encoding.GetBytes(line);
received = HexFormatter.ToSerialHex(bytes);
log.Debug("RX ← " + received);
logStream.Debug("RX ← " + received);
try
{
@ -2271,19 +2263,19 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
CalibrationRecord data = _streamingDecode.DataCalib;
if (data != null && data.IsValid)
{
log.Info($"OPTHO {OptoComPortNr} DataCalib Parsed opto data: " + data + " RX ← " +
received);
logStream.Info($"OPTHO {OptoComPortNr} DataCalib Parsed opto data: " + data + " RX ← " +
received);
MarkCalibrationChannelSeen(data.Channel);
}
FlowTestRecord dataFlow = _streamingDecode.DataFlowTest;
if (dataFlow != null && dataFlow.IsValid)
{
log.Info($"OPTHO {OptoComPortNr} FLOW Parsed opto data: " + dataFlow + " RX ← " + received);
logStream.Info($"OPTHO {OptoComPortNr} FLOW Parsed opto data: " + dataFlow + " RX ← " + received);
if (HandleFlowMarker())
{
log.Debug("ReadOptoData() completed flow block detected.");
logStream.Debug("ReadOptoData() completed flow block detected.");
if (resetSerialBuffersOnCompletedFlowBlock)
ResetDataBuffer(); // no ResetDataBuffer() here
}
@ -2292,7 +2284,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Error($"OPTHO {OptoComPortNr} Read error: {ex.Message}");
logStream.Error($"OPTHO {OptoComPortNr} Read error: {ex.Message}");
}
// string line = optoSerialPort.ReadExisting();
@ -2337,11 +2329,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (TimeoutException)
{
log.Debug($"ReadOptoData() OPTHO {OptoComPortNr} timeout - continuing.");
logStream.Debug($"ReadOptoData() OPTHO {OptoComPortNr} timeout - continuing.");
}
catch (Exception ex)
{
log.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
logStream.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
}
}
@ -2357,11 +2349,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
{
optoSerialPort.DiscardInBuffer();
optoSerialPort.DiscardOutBuffer();
log.Debug("-- Reaset Data Buffer --");
logStream.Debug("-- Reaset Data Buffer --");
return;
}
}
log.Debug("-- Reaset Data Buffer - no serial port --");
logStream.Debug("-- Reaset Data Buffer - no serial port --");
}
void ISmartReader.SetNfcInterface()
@ -2387,17 +2379,17 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
byte[] bytes = optoSerialPort.Encoding.GetBytes(line);
string received = HexFormatter.ToSerialHex(bytes);
log.Debug("RX ← " + received);
logStream.Debug("RX ← " + received);
return line;
}
}
catch (TimeoutException)
{
log.Debug($"ReadOptoData() OPTHO {OptoComPortNr} ReadLine timeout (3s) - continuing.");
logStream.Debug($"ReadOptoData() OPTHO {OptoComPortNr} ReadLine timeout (3s) - continuing.");
}
catch (Exception ex)
{
log.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
logStream.Error($"ReadOptoData() OPTHO {OptoComPortNr} Read error: {ex.Message}");
}
return string.Empty;
@ -2408,7 +2400,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (completedTask == readTask)
return await readTask;
log.Debug("ReadOptoData timeout after " + timeoutMs + " ms");
logStream.Debug("ReadOptoData timeout after " + timeoutMs + " ms");
return string.Empty;
}
@ -2960,7 +2952,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (data == null || !data.IsValid)
continue;
log.Info($"OPTHO {OptoComPortNr} Parsed optho data:" + data);
logStream.Info($"OPTHO {OptoComPortNr} Parsed optho data:" + data);
int dch = data.Channel - 1;
if (dch >= 0 && dch < iChanelsCount)
@ -2973,7 +2965,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
logStream.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
}
}
}
@ -2984,7 +2976,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
log.Debug($"Try get End Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr}");
logStream.Debug($"Try get End Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr}");
if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort();
if (!Double.IsNaN(volumeLtr[ch]))
@ -2995,12 +2987,12 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
//Solve roll over
if (endWMState < beginWMState)
{
log.Debug($"Solve roll over! endWMState: {endWMState} < beginWMState: {beginWMState}");
logStream.Debug($"Solve roll over! endWMState: {endWMState} < beginWMState: {beginWMState}");
const double VOL_RANGE_LITERS = 16777216.0 * 0.00025; // 4,194.304 l
endWMState += VOL_RANGE_LITERS;
volumeLtr[ch] = endWMState;
ReadPulses();
log.Debug(
logStream.Debug(
$"Solve roll over! Upgraded endWMState: {endWMState}, beginWMState: {beginWMState}");
}
}
@ -3009,7 +3001,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
//}
log.Warn("Default NaN value returned! Data Opto stream reading failed!");
logStream.Warn("Default NaN value returned! Data Opto stream reading failed!");
return Double.NaN;
}).ConfigureAwait(false);
}
@ -3019,14 +3011,14 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
{
if (ConfigStruct == null)
{
log.Debug("ConfigStruct is null - created new in ReadSerialNr()");
logStream.Debug("ConfigStruct is null - created new in ReadSerialNr()");
ConfigStruct = new ConfigStruct();
}
return await Task.Run(() =>
{
log.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}");
logStream.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}");
Start();
@ -3050,7 +3042,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
StreamingDecoder _streamingDecode = new StreamingDecoder(true);
_streamingDecode.DecodeMsg(readOptoDataWithTimeout);
CalibrationRecord data = _streamingDecode.DataCalib;
log.Info($"OPTHO {OptoComPortNr} Parsed optho data:" + data);
logStream.Info($"OPTHO {OptoComPortNr} Parsed optho data:" + data);
if (data == null || !data.IsValid)
continue;
@ -3066,7 +3058,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
catch (Exception ex)
{
log.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
logStream.Warn($"Parsing DiagnosticLedState4Data: {ex.Message}");
}
}
}
@ -3076,7 +3068,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
}
log.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr0}");
logStream.Debug($"Try get Start Volume! COM: {this.OptoComPortNr}, Volume: {volumeLtr0}");
if (optoSerialPort != null && optoSerialPort.IsOpen) CloseOptoSerialPort();
if (!Double.IsNaN(volumeLtr0[ch]))
@ -3087,7 +3079,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
//}
log.Warn("Default NaN value returned! Data Opto stream reading failed!");
logStream.Warn("Default NaN value returned! Data Opto stream reading failed!");
return Double.NaN;
}).ConfigureAwait(false);
}
@ -3099,7 +3091,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
if (ConfigStruct == null)
{
log.Debug("ConfigStruct is null - created new in ReadSerialNr()");
logStream.Debug("ConfigStruct is null - created new in ReadSerialNr()");
ConfigStruct = new ConfigStruct();
}
@ -3109,11 +3101,11 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
return await Task.Run(() =>
{
log.Debug($"Try get ReadSerialNr! COM: {this.RfidComPortNr}");
logStream.Debug($"Try get ReadSerialNr! COM: {this.RfidComPortNr}");
SerialNr = OptoHeadTest.ReadRequest_PCB();
if (string.IsNullOrEmpty(SerialNr))
{
log.Debug("ReadSerialNr successful");
logStream.Debug("ReadSerialNr successful");
}
//optoHeadTest.CloseConnection();
@ -3898,7 +3890,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
_startupFlushActive = false;
log.WarnFormat(
"Startup flush finished. Ignored {0} incoming opto lines.",
"Startup flush finished. ({0}) Ignored {1} incoming opto lines.",
Name,
_startupFlushIgnoredLines);
}
}
@ -3915,7 +3908,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
_startupFlushActive = false;
log.WarnFormat(
"Startup flush finished. Ignored {0} incoming opto lines. Window: {1:HH:mm:ss.fff} - {2:HH:mm:ss.fff}",
"Startup flush finished. ({0}) Ignored {1} incoming opto lines. Window: {2:HH:mm:ss.fff} - {3:HH:mm:ss.fff}",
Name,
_startupFlushIgnoredLines,
_startupFlushFirstIgnoredUtc,
_startupFlushLastIgnoredUtc);
@ -3937,6 +3931,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
private double[] q3CalibInitial = {Double.NaN,Double.NaN,Double.NaN};
private bool[] isChQ3CalibValid = { false,false,false};
private double[] q3CalibCh = {Double.NaN,Double.NaN,Double.NaN};
private double[] q3DiffPercentageCalibCh = {Double.NaN,Double.NaN,Double.NaN};
public bool Q3CalibValid
@ -3954,6 +3949,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
public double[] Q3CalibValue { get => q3CalibInitial; }
public double[] Q3CalibDiffPercentageValue { get => q3DiffPercentageCalibCh; }
public bool Q3Calib_Ch1Valid { get => isChQ3CalibValid[0]; }
public bool Q3Calib_Ch2Valid { get => isChQ3CalibValid[1]; }
@ -3964,14 +3960,48 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
public int GetSlotNr { get => genesisHeadCfg?.SlotNr ?? -1; }
void SetQ3Calibration(double[] q3CalibInitial) { this.q3CalibInitial = q3CalibInitial; }
//TODO BUMI implement variable values for Q3Channel!
public void SetQ3Calibration(double[] q3CalibInitial)
{
if (q3CalibInitial == null || q3CalibInitial.Length != 3 ||
Array.Exists(q3CalibInitial, x => double.IsNaN(x) || double.IsInfinity(x) || x < 1 || x > ushort.MaxValue))
throw new ArgumentException("Three valid Genesis calibration factors are required.", nameof(q3CalibInitial));
this.q3CalibInitial = (double[])q3CalibInitial.Clone();
refVolume = double.NaN;
refTime = double.NaN;
Array.Clear(isChQ3CalibValid, 0, isChQ3CalibValid.Length);
}
private double refVolume = double.NaN;
private double refTime = double.NaN;
public double RefVolume { get => refVolume; set => refVolume = value; }
public double RefTime { get => refTime; set => refTime = value; }
public bool CalculateQ3Calibration()
{
if (Double.IsNaN(refVolume) || Double.IsInfinity(refVolume) || refVolume <= 0 || Double.IsNaN(refTime) || Double.IsInfinity(refTime) || refTime <= 0)
{
log.Debug("RefVolume or RefTime is NaN");
return false;
}
CalculateQ3Calibration( refVolume, refTime);
return true;
}
public void CalculateQ3Calibration(double refVolume, double refTime)
{
GetQ3Calibration(refVolume, refTime, q3CalibInitial, ref isChQ3CalibValid, ref q3CalibCh);
GetQ3Calibration(refVolume, refTime, q3CalibInitial, ref isChQ3CalibValid,ref q3DiffPercentageCalibCh, ref q3CalibCh);
}
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] q3CalibCh)
{
var differences = new double[3];
GetQ3Calibration(refVolume, refTime, initCalibFactor, ref isChQ3CalibValid, ref differences, ref q3CalibCh);
}
public void GetQ3Calibration(double refVolume, double refTime, double[] initCalibFactor, ref bool[] isChQ3CalibValid, ref double[] calibDiffPercent, ref double[] q3CalibCh)
{
log.Debug("=== Q3 CALIBRATION START ===");
@ -3991,7 +4021,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
}
}
log.Debug($"Inputs: refVolume={refVolume}, refTime={refTime}, initCalibFactor={initCalibFactor}");
log.Debug($"Inputs: refVolume={refVolume}, refTime={refTime}, initCalibFactors={string.Join(",", initCalibFactor)}");
if (_rawStartEndByChannel == null)
{
@ -4081,25 +4111,13 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
q3CalibCh[iChannel] = (refVolume / recalculatedDeltaVolume) * initCalibFactor[iChannel];
double diffPercent = Math.Abs((initCalibFactor[iChannel] - q3CalibCh[iChannel] ) / initCalibFactor[iChannel]) * 100.0;
isChQ3CalibValid[iChannel] = diffPercent <= 5.0;
isChQ3CalibValid[iChannel] = diffPercent <= 5.0 && !double.IsNaN(q3CalibCh[iChannel]) && !double.IsInfinity(q3CalibCh[iChannel]) && q3CalibCh[iChannel] >= 1 && q3CalibCh[iChannel] <= ushort.MaxValue;
calibDiffPercent[iChannel] = diffPercent;
log.Debug($"Calculated Q3Calib Ch[{iChannel}] ={q3CalibCh[iChannel]} DiffPercent={diffPercent}% isValid[{isChQ3CalibValid[iChannel]}] IninitCalibFactor={initCalibFactor}");
}
log.Debug("=== Q3 CALIBRATION END ===");
}
void newPokus()
{
//TODO BUMI implement genesis communication
//volat z GCI Bridge
//vybere sa component - GCI bridge
// - rozhranie
// - database
}
}
}
}

View File

@ -67,7 +67,7 @@ namespace TBF.Rig.Sequences
//
// /// 3th argument
// IList<ITestParams> iPerlCommParams = new List<ITestParams>();
// foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as iPerlCommunicationParams);
// foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams);
//
// /*myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(iPerlCfg, tests, iPerlCommParams);
// myRef.modelessDlg.Show();*/
@ -75,6 +75,14 @@ namespace TBF.Rig.Sequences
// myRef.modelessDlg = new SmartCommunicationForm( testMethod , tests, iPerlCommParams);
// myRef.modelessDlg.Show();
if (testMethod is TestMethods.GenesisCommunication.TestMethod genesisMethod)
{
var parameters = multiTestParams.Cast<TestMethods.GenesisCommunication.iPerlCommunicationParams>().ToList();
myRef.modelessDlg = new TestMethods.GenesisCommunication.GenesisCommunicationForm(genesisMethod, tests, parameters);
myRef.modelessDlg.Show();
return;
}
/// 1nd argument
TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg;
@ -88,7 +96,7 @@ namespace TBF.Rig.Sequences
myRef.modelessDlg.Show();*/
myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(
testMethod as TBF.Rig.TestMethods.iPerlCommunication.TestMethod, tests, iPerlCommParams);
testMethod as TestMethods.iPerlCommunication.TestMethod, tests, iPerlCommParams);
myRef.modelessDlg.Show();
}
catch (Exception e)
@ -1477,15 +1485,24 @@ namespace TBF.Rig.Sequences
for (int wmNr0 = BatchRslts.Batch.WaterMeters.Count - 1; wmNr0 >= 0; wmNr0--)
{
var wm = BatchRslts.Batch.WaterMeters[wmNr0];
if (wm.Disabled)
{
/// Do not save disabled watermeters to DB, remove them from the list
BatchRslts.Batch.WaterMeters.RemoveAt(wmNr0);
if (wm.Q3Channel == 0){
if (wm.Disabled)
{
/// Do not save disabled watermeters to DB, remove them from the list
BatchRslts.Batch.WaterMeters.RemoveAt(wmNr0);
}
else
{
/// Determine whether the watermeter passed all required tests
wm.Passed = wm.PassedFromTests();
}
}
else
{
/// Determine whether the watermeter passed all required tests
wm.Passed = wm.PassedFromTests();
if (!wm.Disabled)
{
wm.Passed = wm.PassedFromTests();
}
}
}

View File

@ -1305,7 +1305,10 @@ namespace TBF.Rig.Sequences
var smryItems = DEItem.GetSummaryColumns();
for (int i = 0; i < BatchRslts.Batch.WaterMeters.Count; i++)
//TODO BUMI check this part
//Make channels showing the data
int iWMCount = false ? BatchRslts.WMPositionsCount : BatchRslts.Batch.WaterMeters.Count;
for (int i = 0; i < iWMCount; i++)
{
if (BatchRslts.Batch.WaterMeters != null &&
BatchRslts.Batch.WaterMeters.Count > i &&

View File

@ -198,7 +198,7 @@ namespace TBF.Rig
new TestMethods.FlyingStartFirstRepetWithMassColl.HeatMeters.Factory(),
new TestMethods.FlyingStartTankCollection.Single.Factory(),
new TestMethods.FlyingStartTankCollection.Compound.Factory(),
//new TestMethods.GenesisCommunication.GenesisHead.Factory(),
new TestMethods.GenesisCommunication.Factory(),
new TestMethods.GrabImage.Factory(),
new TestMethods.iPerlCommunication.TestMethodFactory(), /// iPerlCommunication
new TestMethods.LeakTest.Factory(),

View File

@ -12,6 +12,8 @@ using TBF.Rig;
using TBF.Rig.GenericDevices;
using TBF.Boxes;
using TBF.Resources;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
using TBF.Rig.Sequences;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
using TBF.UiBridge;
@ -464,6 +466,11 @@ namespace TBF.Rig.TestMethods.FlyingStart
}
while (!e.Contains(Event.TestCompleted) && !e.Contains(Event.Next)); /// 'Next' button is enabled in Debug version only
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_in_calculation);
//------------------------------------------------
/// Measurement loop end
StopRecordingStatistics();
@ -532,7 +539,7 @@ namespace TBF.Rig.TestMethods.FlyingStart
tstRslt.TimeBtwnMassMsrmnts = 0;
tstRslt.ConstMasterRaw = outPath.FlowMeter.LtrPerPulse; /// Uncorrected master flowmeter coefficient
tstRslt.VolumeMaster = tstRslt.ConstMasterRaw * tstRslt.PulsesMaster; /// [l] volume from the master flow meter
double flowMID = 3.6 * tstRslt.VolumeMaster / tstRslt.TestTime; /// [m3/h]
double flowMID = tstRslt.TestTime == 0 ? 0 : 3.6 * tstRslt.VolumeMaster / tstRslt.TestTime; /// [m3/h]
/// Corrected data
tstRslt.MassStart = 0;
@ -542,7 +549,7 @@ namespace TBF.Rig.TestMethods.FlyingStart
/// Main result calculation
tstRslt.VolumeCTV = tstRslt.ConstMasterCorr * tstRslt.PulsesMaster; /// [l] 1000.0f is because density is in [kg/m3]
tstRslt.Flow = 3.6 * tstRslt.VolumeCTV / tstRslt.TestTime;
tstRslt.Flow = tstRslt.TestTime==0 ? 0 : 3.6 * tstRslt.VolumeCTV / tstRslt.TestTime;
tstRslt.ErrorMaster = 0.0; /// Not available without a mass measurement
tstRslt.ConstMaster = tstRslt.ConstMasterCorr;
@ -660,6 +667,7 @@ namespace TBF.Rig.TestMethods.FlyingStart
TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = regReader as TestMethods.iPerlCommunication.iPerlHead.IperlHead;
GenericDevices.IRegReaderLiveCamera cameraRoi = regReader as GenericDevices.IRegReaderLiveCamera;
//GenesisHead Genesis = regReader as GenesisHead;
TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader GenesisSmart = regReader as TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader;
if (meterRslt != null && regReader != null)
{
@ -711,6 +719,24 @@ namespace TBF.Rig.TestMethods.FlyingStart
Genesis.Log(" MeterError = " + calError.ToString() + " %");
}
else*/
if (GenesisSmart != null)
{
log.Debug("GenesisSmart - store data on end!");
int CH1=0, CH2=1, CH3=2;
CalculateMeterResults(meterRslt, GenesisSmart, tstRslt,GenesisSmart.TimestampSecStart, GenesisSmart.TimestampSecEnd, GenesisSmart.VolumeLtrStart, GenesisSmart.VolumeLtrEnd);
//Init Calculate Calibration
GenesisSmart.RefVolume = meterRslt.VolumeRef;
GenesisSmart.RefTime = meterRslt.TestTime;
//Store Raw Calibration Data to database
WaterMeterParentCopy(i, CH1,testName,meterRslt,GenesisSmart,tstRslt);
WaterMeterParentCopy(i, CH2,testName,meterRslt,GenesisSmart,tstRslt);
WaterMeterParentCopy(i, CH3,testName,meterRslt,GenesisSmart,tstRslt);
}
else
{
if (dstrReader != null)
{
@ -918,6 +944,217 @@ namespace TBF.Rig.TestMethods.FlyingStart
// }
// }
private const int CountCh = 3;
private static void WaterMeterParentCopy(int i, int iCH, string testName, MeterTestRslt meterRslt,
GenesisSmartReader genesisSmart,
TestRslt tstRslt)
{
try
{
WaterMeter waterMeterParent = BatchRslts.Batch.WaterMeters[i];
int wmNrChX = (i * CountCh) + BatchRslts.WMPositionsCount + iCH + 1;
String sSerialNr =
(string.IsNullOrEmpty(waterMeterParent.SerialNr) ? (i + 1).ToString() : waterMeterParent.SerialNr) +
"_CH" + (iCH + 1);
WaterMeter chXWaterMeter = null;
//------ add new water meter to batch ------
if (BatchRslts.Batch.WaterMeters.Count < wmNrChX || BatchRslts.Batch.WaterMeters[wmNrChX - 1] == null)
{
log.Debug("add new water meter to batch, CH = " + (iCH + 1) + " CH = " + wmNrChX);
chXWaterMeter = new WaterMeter()
{
MeterTestRslts = new List<MeterTestRslt>(),
};
//This will delete each setting before
chXWaterMeter.CopyContentFrom(waterMeterParent);
chXWaterMeter.Batch = BatchRslts.Batch;
chXWaterMeter.WaterMeterData = waterMeterParent.WaterMeterData;
chXWaterMeter.SerialNr = sSerialNr;
chXWaterMeter.WMPosition = wmNrChX;
chXWaterMeter.Q3Channel = iCH + 1;
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
chXWaterMeter.Disabled = false;
BatchRslts.Batch.WaterMeters.Add(chXWaterMeter);
}
else
{
chXWaterMeter = BatchRslts.Batch.WaterMeters[wmNrChX - 1];
chXWaterMeter.Batch = BatchRslts.Batch;
chXWaterMeter.WaterMeterData = waterMeterParent.WaterMeterData;
chXWaterMeter.SerialNr = sSerialNr;
chXWaterMeter.WMPosition = wmNrChX;
chXWaterMeter.Q3Channel = iCH + 1;
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
chXWaterMeter.Disabled = false;
}
//~------ add new water meter to batch ------~
//create copy of meterRslt and add to additionalResultsByChannel
MeterTestRslt meterTestRsltChX = new MeterTestRslt(chXWaterMeter, meterRslt.TestRslt,
(CompoundMeterId)meterRslt.CompoundMeterId);
meterTestRsltChX.Q3Channel = iCH + 1;
chXWaterMeter.MeterTestRslts.Add(meterTestRsltChX);
MeterTestRslt chanelXMeterRslt =
BatchRslts.GetMeterTestRslt(testName, wmNrChX - 1, Common.CompoundMeterId.Single);
if (chanelXMeterRslt != null)
{
chanelXMeterRslt?.CopyContentFrom(meterRslt);
if (iCH == 0)
{
chanelXMeterRslt.Q3Channel = 1;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh1,
genesisSmart.TimestampSecEndRawCh1, genesisSmart.VolumeLtrStartRawCh1,
genesisSmart.VolumeLtrEndRawCh1);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 0)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[0];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 1;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh1;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh1;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh1;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh1;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH1", ex);
}
}
else if (iCH == 1)
{
chanelXMeterRslt.Q3Channel = 2;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh2,
genesisSmart.TimestampSecEndRawCh2, genesisSmart.VolumeLtrStartRawCh2,
genesisSmart.VolumeLtrEndRawCh2);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 1)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[1];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 2;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh2;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh2;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh2;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh2;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH2", ex);
}
}
else if (iCH == 2)
{
chanelXMeterRslt.Q3Channel = 3;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh3,
genesisSmart.TimestampSecEndRawCh3, genesisSmart.VolumeLtrStartRawCh3,
genesisSmart.VolumeLtrEndRawCh3);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 2)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[2];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 3;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh3;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh3;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh3;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh3;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH3", ex);
}
}
if (!genesisSmart.EnableShowChanels)
{
chXWaterMeter.Disabled = !genesisSmart.EnableShowChanels;
//meterTestRsltChX.TestDone = false;
}
else
{
chXWaterMeter.Disabled = false;
meterTestRsltChX.TestDone = true;
}
meterTestRsltChX.Passed = meterRslt.Passed;
}
}
catch (Exception ex)
{
log.Error("Error in WaterMeterParentCopy", ex);
}
}
private static void CalculateMeterResults(MeterTestRslt meterRslt, IRegReaderDatastream dstrReader, TestRslt tstRslt, double dstrReaderTimestampSecStart, double dstrReaderTimestampSecEnd, double dstrReaderVolumeLtrStart, double dstrReaderVolumeLtrEnd)
{
try
{
meterRslt.TimestampStart = dstrReaderTimestampSecStart;
meterRslt.TimestampEnd = !dstrReader.NoSamples
? dstrReaderTimestampSecEnd
: (dstrReaderTimestampSecStart + tstRslt.TestTime);
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
meterRslt.VolumeStart = dstrReaderVolumeLtrStart; /// liter
meterRslt.VolumeEnd = dstrReaderVolumeLtrEnd; /// liter
meterRslt.VolumeMeter =
Math.Abs(dstrReaderVolumeLtrEnd - dstrReaderVolumeLtrStart);
meterRslt.VolumeRef = tstRslt.TestTime == 0
? tstRslt.VolumeCTV
: tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.PulsesMaster = tstRslt.TestTime == 0
? tstRslt.PulsesMaster
: tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter,
meterRslt.VolumeRef); // Error based on volume difference
}catch(Exception ex)
{
log.Error($"Error in calculate meter results, meterRslt.Name:{meterRslt.Name()} Calculation Bug Detail:", ex);
}
}
IList<Event> Simulate(Config.Entities.Test test, int repetitionNr, bool isLastRepetition,
Compound.TestParams compoundTestParams,
@ -943,6 +1180,14 @@ namespace TBF.Rig.TestMethods.FlyingStart
else if (test.Name.ToLower().Contains("q1")) MakeSimulated(test, 1, 0, -5.1f);
else MakeSimulated(test, 1, 0, 0.9f);
//TODO bumi do simulate foe Q3 Calibration
///
/// Single meters
///
SimulateQ3CalibrationData(test,1, 0, -5.1f);
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Completed));
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0)));
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
@ -958,5 +1203,46 @@ namespace TBF.Rig.TestMethods.FlyingStart
return new List<Event> { TestAndLogUiCmdStop(test, e) ? Event.UiCmdStop : Event.Done };
}
private void SimulateQ3CalibrationData(Test test,int repetitionNr, int part, float errorPctBase)
{
string testName = test.Name;
string fullTestName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(fullTestName, part);
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
{
if (!test.IsPartCompatible(Utils.PartNr(i + 1, BatchRslts.Batch.Compound))) continue;
Results.Entities.MeterTestRslt meterRslt =
BatchRslts.GetMeterTestRslt(testName, i, Common.CompoundMeterId.Single);
GenericDevices.IRegReader regReader = sensPath.RegisterReaders[i];
TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader GenesisSmart =
regReader as TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader;
if (GenesisSmart != null)
{
log.Debug("GenesisSmart - store data on end!");
int CH1 = 0, CH2 = 1, CH3 = 2;
CalculateMeterResults(meterRslt, GenesisSmart, tstRslt, GenesisSmart.TimestampSecStart,
GenesisSmart.TimestampSecEnd, GenesisSmart.VolumeLtrStart, GenesisSmart.VolumeLtrEnd);
//Init Calculate Calibration
GenesisSmart.RefVolume = meterRslt.VolumeRef;
GenesisSmart.RefTime = meterRslt.TestTime;
//Store Raw Calibration Data to database
WaterMeterParentCopy(i, CH1, testName, meterRslt, GenesisSmart, tstRslt);
WaterMeterParentCopy(i, CH2, testName, meterRslt, GenesisSmart, tstRslt);
WaterMeterParentCopy(i, CH3, testName, meterRslt, GenesisSmart, tstRslt);
}
}
}
}
}

View File

@ -18,6 +18,7 @@ using TBF.Rig.GenericDevices;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
using TBF.Rig.RegisterReaders.PoseidonReader;
using TBF.Rig.RegisterReaders.PoseidonReader.implementations;
using TBF.Rig.Sequences;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
using TBF.UiBridge;
@ -1106,12 +1107,13 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
bUpgradeCountOfMeters = true;
int CH1=0, CH2=1, CH3=2;
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH1 + 1]
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH2 + 1]
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH3 + 1]
CalculateMeterResults(meterRslt, GenesisSmart, tstRslt,GenesisSmart.TimestampSecStart, GenesisSmart.TimestampSecEnd, GenesisSmart.VolumeLtrStart, GenesisSmart.VolumeLtrEnd);
//Init Calculate Calibration
GenesisSmart.RefVolume = meterRslt.VolumeRef;
GenesisSmart.RefTime = meterRslt.TestTime;
//Store Raw Calibration Data to database
WaterMeterParentCopy(i, CH1,testName,meterRslt,GenesisSmart,tstRslt);
WaterMeterParentCopy(i, CH2,testName,meterRslt,GenesisSmart,tstRslt);
WaterMeterParentCopy(i, CH3,testName,meterRslt,GenesisSmart,tstRslt);
@ -1376,91 +1378,212 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
GenesisSmartReader genesisSmart,
TestRslt tstRslt)
{
WaterMeter waterMeterParent = BatchRslts.Batch.WaterMeters[i];
int wmNrChX = (i*CountCh) + BatchRslts.WMPositionsCount + iCH + 1;
String sSerialNr = waterMeterParent.SerialNr + "_CH" + (iCH + 1);
WaterMeter chXWaterMeter = null;
//------ add new water meter to batch ------
if (BatchRslts.Batch.WaterMeters.Count < wmNrChX || BatchRslts.Batch.WaterMeters[wmNrChX-1] == null)
try
{
log.Debug("add new water meter to batch, CH = " + (iCH + 1) + " CH = " + wmNrChX);
chXWaterMeter = new WaterMeter()
WaterMeter waterMeterParent = BatchRslts.Batch.WaterMeters[i];
int wmNrChX = (i * CountCh) + BatchRslts.WMPositionsCount + iCH + 1;
String sSerialNr =
(string.IsNullOrEmpty(waterMeterParent.SerialNr) ? (i+1).ToString() : waterMeterParent.SerialNr) +
"_CH" + (iCH + 1);
WaterMeter chXWaterMeter = null;
//------ add new water meter to batch ------
if (BatchRslts.Batch.WaterMeters.Count < wmNrChX || BatchRslts.Batch.WaterMeters[wmNrChX - 1] == null)
{
Batch = BatchRslts.Batch,
WaterMeterData = waterMeterParent.WaterMeterData,
MeterTestRslts = new List<MeterTestRslt>(),
SerialNr = sSerialNr,
WMPosition = wmNrChX,
YearOfProduction = 0,
Disabled = false,
};
chXWaterMeter.CopyContentFrom(waterMeterParent);
log.Debug("add new water meter to batch, CH = " + (iCH + 1) + " CH = " + wmNrChX);
chXWaterMeter = new WaterMeter()
{
MeterTestRslts = new List<MeterTestRslt>(),
};
//This will delete each setting before
chXWaterMeter.CopyContentFrom(waterMeterParent);
chXWaterMeter.SerialNr = sSerialNr;
chXWaterMeter.WMPosition = wmNrChX;
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
chXWaterMeter.Disabled = false;
chXWaterMeter.Batch = BatchRslts.Batch;
chXWaterMeter.WaterMeterData = waterMeterParent.WaterMeterData;
BatchRslts.Batch.WaterMeters.Add(chXWaterMeter);
}
else
{
chXWaterMeter = BatchRslts.Batch.WaterMeters[wmNrChX-1];
}
//~------ add new water meter to batch ------~
//create copy of meterRslt and add to additionalResultsByChannel
MeterTestRslt meterTestRsltChX = new MeterTestRslt(chXWaterMeter, meterRslt.TestRslt, (CompoundMeterId)meterRslt.CompoundMeterId);
chXWaterMeter.MeterTestRslts.Add(meterTestRsltChX);
MeterTestRslt chanelXMeterRslt = BatchRslts.GetMeterTestRslt(testName, wmNrChX-1, Common.CompoundMeterId.Single);
if (chanelXMeterRslt != null)
{
chanelXMeterRslt?.CopyContentFrom(meterRslt);
if (iCH == 0)
{
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartRawCh1,
genesisSmart.TimestampSecEndRawCh1, genesisSmart.VolumeLtrStartRawCh1, genesisSmart.VolumeLtrEndRawCh1);
}
else if (iCH == 1)
{
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartRawCh2,
genesisSmart.TimestampSecEndRawCh2, genesisSmart.VolumeLtrStartRawCh2, genesisSmart.VolumeLtrEndRawCh2);
}
else if (iCH == 2)
{
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartRawCh3,
genesisSmart.TimestampSecEndRawCh3, genesisSmart.VolumeLtrStartRawCh3, genesisSmart.VolumeLtrEndRawCh3);
}
chXWaterMeter.SerialNr = sSerialNr;
chXWaterMeter.WMPosition = wmNrChX;
chXWaterMeter.Q3Channel = iCH+1;
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
chXWaterMeter.Disabled = false;
if (!genesisSmart.EnableShowChanels)
{
chXWaterMeter.Disabled = !genesisSmart.EnableShowChanels;
meterTestRsltChX.TestDone = false;
BatchRslts.Batch.WaterMeters.Add(chXWaterMeter);
}
else
{
meterTestRsltChX.TestDone = true;
}
chXWaterMeter = BatchRslts.Batch.WaterMeters[wmNrChX - 1];
meterTestRsltChX.Passed = meterRslt.Passed;
chXWaterMeter.Batch = BatchRslts.Batch;
chXWaterMeter.WaterMeterData = waterMeterParent.WaterMeterData;
chXWaterMeter.SerialNr = sSerialNr;
chXWaterMeter.WMPosition = wmNrChX;
chXWaterMeter.Q3Channel = iCH+1;
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
chXWaterMeter.Disabled = false;
}
//~------ add new water meter to batch ------~
//create copy of meterRslt and add to additionalResultsByChannel
MeterTestRslt meterTestRsltChX = new MeterTestRslt(chXWaterMeter, meterRslt.TestRslt,
(CompoundMeterId)meterRslt.CompoundMeterId);
meterTestRsltChX.Q3Channel = iCH + 1;
chXWaterMeter.MeterTestRslts.Add(meterTestRsltChX);
MeterTestRslt chanelXMeterRslt =
BatchRslts.GetMeterTestRslt(testName, wmNrChX - 1, Common.CompoundMeterId.Single);
if (chanelXMeterRslt != null)
{
chanelXMeterRslt?.CopyContentFrom(meterRslt);
if (iCH == 0)
{
chanelXMeterRslt.Q3Channel = 1;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh1,
genesisSmart.TimestampSecEndRawCh1, genesisSmart.VolumeLtrStartRawCh1,
genesisSmart.VolumeLtrEndRawCh1);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 0)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[0];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 1;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh1;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh1;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh1;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh1;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH1", ex);
}
}
else if (iCH == 1)
{
chanelXMeterRslt.Q3Channel = 2;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh2,
genesisSmart.TimestampSecEndRawCh2, genesisSmart.VolumeLtrStartRawCh2,
genesisSmart.VolumeLtrEndRawCh2);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 1)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[1];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 2;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh2;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh2;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh2;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh2;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH2", ex);
}
}
else if (iCH == 2)
{
chanelXMeterRslt.Q3Channel = 3;
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt,
genesisSmart.TimestampSecStartRawCh3,
genesisSmart.TimestampSecEndRawCh3, genesisSmart.VolumeLtrStartRawCh3,
genesisSmart.VolumeLtrEndRawCh3);
try
{
TestRsltCalibFactor testRsltCalibFactor = null;
if (tstRslt.GetCalibrationFactors(waterMeterParent).Count > 2)
{
testRsltCalibFactor = tstRslt.GetCalibrationFactors(waterMeterParent)[2];
}
else
{
//store in table
testRsltCalibFactor = new TestRsltCalibFactor();
tstRslt.GetCalibrationFactors(waterMeterParent).Add(testRsltCalibFactor);
testRsltCalibFactor.CalibFactorIndex = 3;
}
testRsltCalibFactor.TestRslt = chanelXMeterRslt.TestRslt;
testRsltCalibFactor.TimeStart = genesisSmart.TimestampSecStartRawCh3;
testRsltCalibFactor.TimeEnd = genesisSmart.TimestampSecEndRawCh3;
testRsltCalibFactor.VolumeStart = genesisSmart.VolumeLtrStartRawCh3;
testRsltCalibFactor.VolumeEnd = genesisSmart.VolumeLtrEndRawCh3;
testRsltCalibFactor.Error = chanelXMeterRslt.Error;
}
catch (Exception ex)
{
log.Error("Error in store to DB result set CH3", ex);
}
}
if (!genesisSmart.EnableShowChanels)
{
chXWaterMeter.Disabled = !genesisSmart.EnableShowChanels;
//meterTestRsltChX.TestDone = false;
}
else
{
chXWaterMeter.Disabled = false;
meterTestRsltChX.TestDone = true;
}
meterTestRsltChX.Passed = meterRslt.Passed;
}
}catch(Exception ex)
{
log.Error("Error in WaterMeterParentCopy", ex);
}
}
private static void CalculateMeterResults(MeterTestRslt meterRslt, IRegReaderDatastream dstrReader, TestRslt tstRslt, double dstrReaderTimestampSecStart, double dstrReaderTimestampSecEnd, double dstrReaderVolumeLtrStart, double dstrReaderVolumeLtrEnd)
{
meterRslt.TimestampStart = dstrReaderTimestampSecStart;
meterRslt.TimestampEnd = !dstrReader.NoSamples
? dstrReaderTimestampSecEnd
: (dstrReaderTimestampSecStart + tstRslt.TestTime);
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
meterRslt.VolumeStart = dstrReaderVolumeLtrStart; /// liter
meterRslt.VolumeEnd = dstrReaderVolumeLtrEnd; /// liter
meterRslt.VolumeMeter =
Math.Abs(dstrReaderVolumeLtrEnd - dstrReaderVolumeLtrStart);
meterRslt.VolumeRef = tstRslt.TestTime==0? tstRslt.VolumeCTV : tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.PulsesMaster = tstRslt.TestTime == 0? tstRslt.PulsesMaster :
tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
try
{
meterRslt.TimestampStart = dstrReaderTimestampSecStart;
meterRslt.TimestampEnd = !dstrReader.NoSamples
? dstrReaderTimestampSecEnd
: (dstrReaderTimestampSecStart + tstRslt.TestTime);
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
meterRslt.VolumeStart = dstrReaderVolumeLtrStart; /// liter
meterRslt.VolumeEnd = dstrReaderVolumeLtrEnd; /// liter
meterRslt.VolumeMeter = Math.Abs(dstrReaderVolumeLtrEnd - dstrReaderVolumeLtrStart);
meterRslt.VolumeRef = tstRslt.TestTime == 0
? tstRslt.VolumeCTV
: tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.PulsesMaster = tstRslt.TestTime == 0
? tstRslt.PulsesMaster
: tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter,
meterRslt.VolumeRef); // Error based on volume difference
}catch(Exception ex)
{
log.Error($"Error in calculate meter results, meterRslt.Name:{meterRslt.Name()} Calculation Bug Detail:", ex);
}
}
@ -1504,6 +1627,12 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
MakeSimulated(test, repetitionNr, test.Part, errorPctBase + repetitionNr * 0.1f);
}
//TODO bumi do simulate foe Q3 Calibration
///
/// Single meters
///
SimulateQ3CalibrationData(test,1, 0, -5.1f);
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Completed));
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0)));
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
@ -1520,6 +1649,64 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
return new List<Event> { TestAndLogUiCmdStop(test, e) ? Event.UiCmdStop : Event.Done };
}
private void SimulateQ3CalibrationData(Test test,int repetitionNr, int part, float errorPctBase)
{
string testName = test.Name;
string fullTestName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(fullTestName, part);
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
{
if (WaterMeters.Count > i && WaterMeters[i] != null)
WaterMeters[i].SerialNr = "Simul_" + (i + 1).ToString();
}
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
{
if (!test.IsPartCompatible(Utils.PartNr(i + 1, BatchRslts.Batch.Compound))) continue;
Results.Entities.MeterTestRslt meterRslt =
BatchRslts.GetEachMeterTestRslt(testName, i, Common.CompoundMeterId.Single);
if (meterRslt == null) continue;
if (meterRslt?.WaterMeter == null) continue;
if (string.IsNullOrEmpty(meterRslt.WaterMeter.SerialNr))
{
meterRslt.WaterMeter.SerialNr = "Simul_" + (i + 1).ToString();
meterRslt.WaterMeter.SerialNrAux = "Simul_" + (i + 1).ToString();
log.Debug("Simul_SerialNr: " + meterRslt.WaterMeter.SerialNr);
}
GenericDevices.IRegReader regReader = sensPath.RegisterReaders[i];
TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader GenesisSmart =
regReader as TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader;
if (GenesisSmart != null)
{
log.Debug("GenesisSmart - store data on end!");
int CH1 = 0, CH2 = 1, CH3 = 2;
CalculateMeterResults(meterRslt, GenesisSmart, tstRslt, GenesisSmart.TimestampSecStart,
GenesisSmart.TimestampSecEnd, GenesisSmart.VolumeLtrStart, GenesisSmart.VolumeLtrEnd);
//Init Calculate Calibration
GenesisSmart.RefVolume = meterRslt.VolumeRef;
GenesisSmart.RefTime = meterRslt.TestTime;
//Store Raw Calibration Data to database
WaterMeterParentCopy(i, CH1, testName, meterRslt, GenesisSmart, tstRslt);
log.Debug($"GenesisSmart - i:{i}, CH1:{CH1}, testName:{testName}, meterRslt:{meterRslt.Id}, GenesisSmart:{GenesisSmart.Name}, tstRslt:{tstRslt.Id}");
WaterMeterParentCopy(i, CH2, testName, meterRslt, GenesisSmart, tstRslt);
log.Debug($"GenesisSmart - i:{i}, CH2:{CH2}, testName:{testName}, meterRslt:{meterRslt.Id}, GenesisSmart:{GenesisSmart.Name}, tstRslt:{tstRslt.Id}");
WaterMeterParentCopy(i, CH3, testName, meterRslt, GenesisSmart, tstRslt);
log.Debug($"GenesisSmart - i:{i}, CH3:{CH3}, testName:{testName}, meterRslt:{meterRslt.Id}, GenesisSmart:{GenesisSmart.Name}, tstRslt:{tstRslt.Id}");
}
}
}
IList<Event> Simulate2(Config.Entities.Test test, int repetitionNr, bool isLastRepetition,
Compound.CombinedTestParams compoundTestParams,

View File

@ -0,0 +1,40 @@
///
/// Copyright (c) 2015-2019 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
namespace TBF.Rig.TestMethods.GenesisCommunication
{
public class CommCompletedEventArgs : EventArgs
{
public int ThreadId;
public int WMNr0; /// 0-based water meter position
public GenesisSmartReader Ihead;
public Results.Entities.WaterMeter Wm;
public string CommMessage;
public CommErr CommErr;
public CommCompletedEventArgs(int threadId, int wmNr0, GenesisSmartReader ihead, Results.Entities.WaterMeter wm, string commMessage, CommErr commErr)
{
this.ThreadId = threadId;
this.WMNr0 = wmNr0;
this.Ihead = ihead;
this.Wm = wm;
this.CommMessage = commMessage;
this.CommErr = commErr;
}
public override string ToString()
{
return string.Format("Thread={0} WMNr0={1} IHead={2} WM={3} CommMsg={4} CommErr={5}",
ThreadId,
WMNr0,
(Ihead != null) ? Ihead.Name : "null",
(Wm != null) ? Wm.WMPosition : -1,
(CommMessage != null) ? CommMessage : "null",
CommErr);
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Globalization;
namespace TBF.Rig.TestMethods.GenesisCommunication
{
public static class GenesisCalibrationFactors
{
// Preserve the special branch default only when no channel has been configured.
public const ushort DefaultFactor = 15625;
public static bool TryParse(string text1, string text2, string text3,
out double[] factors, out string error)
{
factors = null;
error = null;
var text = new[] { text1, text2, text3 };
if (Array.TrueForAll(text, string.IsNullOrWhiteSpace))
{
factors = new double[] { DefaultFactor, DefaultFactor, DefaultFactor };
return true;
}
var parsed = new double[3];
for (int channel = 0; channel < parsed.Length; channel++)
{
ushort value;
if (!ushort.TryParse(text[channel]?.Trim(), NumberStyles.None,
CultureInfo.InvariantCulture, out value) || value == 0)
{
error = "Genesis calibration Text" + (channel + 1) + " must be an integer from 1 to 65535. Set all three channels.";
return false;
}
parsed[channel] = value;
}
factors = parsed;
return true;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,15 +32,15 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
System.Windows.Forms.Form modelessDlg;
///
delegate void iPerlCommFormDlgt(GenesisCommunicationSeq myRef, iPerlCommunication.TestMethod method, Test test, iPerlCommunicationParams testParams);
delegate void iPerlCommFormDlgt(GenesisCommunicationSeq myRef, TestMethod method, Test test, iPerlCommunicationParams testParams);
///
void OpenIPerlCommForm(GenesisCommunicationSeq myRef, iPerlCommunication.TestMethod method, Test test, iPerlCommunicationParams testParams)
void OpenIPerlCommForm(GenesisCommunicationSeq myRef, TestMethod method, Test test, iPerlCommunicationParams testParams)
{
//TODO solve this wia SmartCommunicationForm
throw new NotImplementedException();
//myRef.modelessDlg = new iPerlCommunicationForm(method, test, testParams);
//myRef.modelessDlg.Show();
myRef.modelessDlg = new GenesisCommunicationForm(method, test, testParams);
myRef.modelessDlg.Show();
}
@ -72,7 +72,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
processDataLoggingOp = new TBF.Rig.Operations.ProcessDataLoggingOp(processDataLogger, this, false);
string cmd;
if (testParams.Activity.ToLower().Equals(cmd = iPerlCommunicationForm.GetDefaultQ2CorrectionsStr.ToLower()))
if (testParams.Activity.ToLower().Equals(cmd = GenesisCommunicationForm.GetDefaultQ2CorrectionsStr.ToLower()))
{
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted));

View File

@ -33,13 +33,13 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
/// Private parameterless constructor invoked by all other (public) constructors
TestMethodCfg()
{
Name = "SmartCommunication";
Name = "SmartCommunicationGenesis";
ParentName = string.Empty;
CommTimeout = 1800; /// ms
MaxCommRetries = 4;
WaitTimeAfterFailure = 2200;
PassThroughWaitTime = 1500;
NrThreads = 2; /// 1, 2 or 4 threads
NrThreads = 10; /// 1, 2 or 4 threads
IperlCheckErrorsToStop = 10;
MciTimeoutMs = 4000; // ms, NFC interface
BaudRate = 57600; // NFC Interface

View File

@ -28,6 +28,14 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
public TestMethodCfgCtrl()
{
InitializeComponent();
dfltQ2corrFactorsGroupBox.Visible = false;
useWebServiceGroupBox.Visible = false;
var factorHint = new System.Windows.Forms.Label
{
AutoSize = true, Location = dfltQ2corrFactorsGroupBox.Location,
Text = "Q3 factors: Water meters / Text1, Text2, Text3 (CH1, CH2, CH3)."
};
Controls.Add(factorHint);
}
private void EntryFormCfgCtrl_Load(object sender, EventArgs e)
@ -116,10 +124,10 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Comm. timeout' should be in range 0 .. 5000";
}
if (!int.TryParse(nrThreadsTextBox.Text, out dummy) || (dummy != 1 && dummy != 2 && dummy != 4))
if (!int.TryParse(nrThreadsTextBox.Text, out dummy) || (dummy < 1 || dummy > 10))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Nr. threads' should be 1, 2 or 4";
message += Environment.NewLine + "'Nr. threads' should be in range 1 .. 10";
}
if (!int.TryParse(iperlCheckErrorsToStopTextBox.Text, out dummy) || ((dummy < 1) && (dummy > 40)))
{

View File

@ -10,7 +10,6 @@ using Config.Entities;
using TBF.Resources;
using TBF.Rig.Generic;
using TBF.Rig.TestMethods.iPerlCommunication;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
namespace TBF.Rig.TestMethods.GenesisCommunication
{
@ -31,7 +30,7 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
public override void InitializeAll()
{
Activity = iPerlCommunicationForm.ReadConfigurationStr;
Activity = GenesisCommunicationForm.SlotInitializeStr;
SimultWithPrevious = false;
SimultWithNext = false;
}
@ -51,62 +50,79 @@ namespace TBF.Rig.TestMethods.GenesisCommunication
if (i == 0)
{
var retVal = new List<string>();
retVal.Add(iPerlCommunicationForm.ReadConfigurationStr);
retVal.Add(iPerlCommunicationConstants.ReadAdditionalCommonParametersStr);
retVal.Add(iPerlCommunicationForm.ReadSerialNrStr);
retVal.Add(string.Format("{0} A0", iPerlCommunicationForm.SetTestModeStr));
retVal.Add(string.Format("{0} A4", iPerlCommunicationForm.SetTestModeStr));
retVal.Add(iPerlCommunicationForm.ReadCalibrationStr);
retVal.Add(iPerlCommunicationForm.ReadCalibrationV4Str);
retVal.Add(iPerlCommunicationForm.NormalizeCalibrationFactorStr);
retVal.Add(iPerlCommunicationForm.NormalizeCalibrationV4FactorsStr);
retVal.Add(iPerlCommunicationForm.GetDefaultQ2CorrectionsStr);
retVal.Add(iPerlCommunicationForm.ReadQ2CorrectionStr);
retVal.Add(iPerlCommunicationForm.ResetQ2CorrectionStr);
retVal.Add(iPerlCommunicationForm.WriteDefaultQ2CorrectionsStr);
retVal.Add(iPerlCommunicationForm.InitOrReadQ2CorrectionsStr);
retVal.Add(iPerlCommunicationForm.WriteCalibrationFactorStr);
retVal.Add(iPerlCommunicationForm.WriteCalibrationV4FactorsStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionAltStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionGreeceStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionRLStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionLRStr);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionAltIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionPlusIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionPlusAltIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionGreeceIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionRLIncl05Str);
retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionLRIncl05Str);
retVal.Add(iPerlCommunicationSeq.Q2correctedFromCmd + "Qx");
retVal.Add(iPerlCommunicationSeq.StrictQ2ErrorCheckStr + "Qx");
retVal.Add(iPerlCommunicationSeq.Q2correctionCheckCmd);
retVal.Add(iPerlCommunicationSeq.IperlCheckCmd);
retVal.Add(iPerlCommunicationForm.UpdateBothQ2FactorsTestRLOnlyStr);
retVal.Add(iPerlCommunicationForm.UpdateBothQ2FactorsTestLROnlyStr);
retVal.Add(iPerlCommunicationForm.UpdateQ2CorrectionsStr);
retVal.Add(iPerlCommunicationForm.ConditnlUpdateQ2CorrectionsStr);
retVal.Add(iPerlCommunicationForm.ConditnlUpdateQ2CorrRLStr);
retVal.Add(iPerlCommunicationForm.ConditnlUpdateQ2CorrLRStr);
retVal.Add("Q2 corrected from Q2adj");
retVal.Add("Q2 correction check Q2bc Q2ac");
retVal.Add(iPerlCommunicationForm.SetActiveModeStr);
retVal.Add(iPerlCommunicationForm.SetIdleModeStr);
retVal.Add("---");
retVal.Add(iPerlCommunicationForm.Reset2HzCorrectionStr);
retVal.Add(iPerlCommunicationForm.Write2HzCorrectionStr);
retVal.Add(iPerlCommunicationForm.DewaReworkRLStr);
retVal.Add(iPerlCommunicationForm.DewaReworkLRStr);
retVal.Add(iPerlCommunicationForm.StartTestingSealedMetersStr);
retVal.Add(iPerlCommunicationForm.EndTestingSealedMetersStr);
retVal.Add(string.Format("{0} if enabled", iPerlCommunicationForm.ReadConfigurationStr));
retVal.Add(string.Format("{0} 80", iPerlCommunicationForm.SetTestModeStr));
retVal.Add("iPerl_check prevWorkStep direction q2factors");
for (iPerlCommunication.ConditionID id = iPerlCommunication.ConditionID.A; id < iPerlCommunication.ConditionID.Count; id++)
{
retVal.Add(string.Format(iPerlCommunication.SequenceConditionOp.ConditionNameFmt, id));
}
retVal.Add(GenesisCommunicationForm.SlotInitializeStr);
retVal.Add(GenesisCommunicationForm.SlotUpdateStr);
retVal.Add(GenesisCommunicationForm.SlotConnectStr);
retVal.Add(GenesisCommunicationForm.SlotPCBSlotStr);
retVal.Add(GenesisCommunicationForm.SlotSetPasswordStr);
retVal.Add(GenesisCommunicationForm.SlotLoginStr);
retVal.Add(GenesisCommunicationForm.SlotGroupedLoginStr);
retVal.Add(GenesisCommunicationForm.SlotSetTestModeStr);
retVal.Add(GenesisCommunicationForm.SlotSetActiveModeStr);
retVal.Add(GenesisCommunicationForm.SlotDisconnectStr);
retVal.Add(GenesisCommunicationForm.PrepareSlotQ3CalibrationStr);
retVal.Add(GenesisCommunicationForm.WriteSlotQ3CalibrationStr);
retVal.Add(GenesisCommunicationForm.CheckMeterPrepareStr);
retVal.Add(GenesisCommunicationForm.HoldSlotStr);
// retVal.Add(GenesisCommunicationForm.ReadConfigurationStr);
// retVal.Add(GenesisCommunicationForm.ReadSerialNrStr);
// retVal.Add(string.Format("{0} A0", GenesisCommunicationForm.SetTestModeStr));
// retVal.Add(string.Format("{0} A4", GenesisCommunicationForm.SetTestModeStr));
// retVal.Add(GenesisCommunicationForm.ReadCalibrationStr);
// retVal.Add(GenesisCommunicationForm.ReadCalibrationV4Str);
// retVal.Add(GenesisCommunicationForm.NormalizeCalibrationFactorStr);
// retVal.Add(GenesisCommunicationForm.NormalizeCalibrationV4FactorsStr);
// retVal.Add(GenesisCommunicationForm.GetDefaultQ2CorrectionsStr);
// retVal.Add(GenesisCommunicationForm.ReadQ2CorrectionStr);
// retVal.Add(GenesisCommunicationForm.ResetQ2CorrectionStr);
// retVal.Add(GenesisCommunicationForm.WriteDefaultQ2CorrectionsStr);
// retVal.Add(GenesisCommunicationForm.InitOrReadQ2CorrectionsStr);
// retVal.Add(GenesisCommunicationForm.WriteCalibrationFactorStr);
// retVal.Add(GenesisCommunicationForm.WriteCalibrationV4FactorsStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionAltStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionGreeceStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionRLStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionLRStr);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionAltIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionPlusIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionPlusAltIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionGreeceIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionRLIncl05Str);
// retVal.Add(GenesisCommunicationForm.WriteQ2CorrectionLRIncl05Str);
// retVal.Add(iPerlCommunicationSeq.Q2correctedFromCmd + "Qx");
// retVal.Add(iPerlCommunicationSeq.StrictQ2ErrorCheckStr + "Qx");
// retVal.Add(iPerlCommunicationSeq.Q2correctionCheckCmd);
// retVal.Add(iPerlCommunicationSeq.IperlCheckCmd);
// retVal.Add(GenesisCommunicationForm.UpdateBothQ2FactorsTestRLOnlyStr);
// retVal.Add(GenesisCommunicationForm.UpdateBothQ2FactorsTestLROnlyStr);
// retVal.Add(GenesisCommunicationForm.UpdateQ2CorrectionsStr);
// retVal.Add(GenesisCommunicationForm.ConditnlUpdateQ2CorrectionsStr);
// retVal.Add(GenesisCommunicationForm.ConditnlUpdateQ2CorrRLStr);
// retVal.Add(GenesisCommunicationForm.ConditnlUpdateQ2CorrLRStr);
// retVal.Add("Q2 corrected from Q2adj");
// retVal.Add("Q2 correction check Q2bc Q2ac");
// retVal.Add(GenesisCommunicationForm.SetActiveModeStr);
// retVal.Add(GenesisCommunicationForm.SetIdleModeStr);
// retVal.Add("---");
// retVal.Add(GenesisCommunicationForm.Reset2HzCorrectionStr);
// retVal.Add(GenesisCommunicationForm.Write2HzCorrectionStr);
// retVal.Add(GenesisCommunicationForm.DewaReworkRLStr);
// retVal.Add(GenesisCommunicationForm.DewaReworkLRStr);
// retVal.Add(GenesisCommunicationForm.StartTestingSealedMetersStr);
// retVal.Add(GenesisCommunicationForm.EndTestingSealedMetersStr);
// retVal.Add(string.Format("{0} if enabled", GenesisCommunicationForm.ReadConfigurationStr));
// retVal.Add(string.Format("{0} 80", GenesisCommunicationForm.SetTestModeStr));
// retVal.Add("iPerl_check prevWorkStep direction q2factors");
// for (ConditionID id = ConditionID.A; id < ConditionID.Count; id++)
// {
// retVal.Add(string.Format(SequenceConditionOp.ConditionNameFmt, id));
// }
return retVal;
}

View File

@ -4653,4 +4653,18 @@
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\GciBridgeClient.cs" />
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\IGciBridgeClient.cs" />
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\common\LedState.cs" />
<Compile Include="Rig\TestMethods\GenesisCommunication\GenesisCommunicationForm.cs" />
<Compile Include="Rig\TestMethods\GenesisCommunication\GenesisCommunicationForm.designer.cs" />
<EmbeddedResource Include="Rig\TestMethods\GenesisCommunication\GenesisCommunicationForm.resx" />
</ItemGroup>
<ItemGroup>
<Compile Include="Rig\TestMethods\GenesisCommunication\CommCompletedEventArgs.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Rig\TestMethods\GenesisCommunication\GenesisCalibrationFactors.cs" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,179 @@
using System;
using System.Data.SQLite;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Results.Entities;
using Results.Entities.helpers;
using GenesisCalibrationFactors = TBF.Rig.TestMethods.GenesisCommunication.GenesisCalibrationFactors;
namespace TBFTests
{
[TestClass]
public class GenesisRecoveryTests
{
[TestMethod]
public void TextFieldsPreserveConfiguredFactors()
{
double[] factors; string error;
Assert.IsTrue(GenesisCalibrationFactors.TryParse("17969", "17969", "17969", out factors, out error));
CollectionAssert.AreEqual(new double[] { 17969, 17969, 17969 }, factors);
Assert.IsTrue(GenesisCalibrationFactors.TryParse(" 17969 ", "18000", "19000", out factors, out error));
CollectionAssert.AreEqual(new double[] { 17969, 18000, 19000 }, factors);
}
[TestMethod]
public void IncompleteOrInvalidFactorsAreRejectedBeforeWriting()
{
foreach (var invalid in new[] { null, "", "0", "-1", "65536", "NaN", "1.5", "bad" })
{
double[] factors; string error;
Assert.IsFalse(GenesisCalibrationFactors.TryParse("17969", invalid, "17969", out factors, out error));
Assert.IsNull(factors);
StringAssert.Contains(error, "Text2");
}
}
[TestMethod]
public void EmptyLegacyConfigurationKeepsDefault()
{
double[] factors; string error;
Assert.IsTrue(GenesisCalibrationFactors.TryParse(null, " ", "", out factors, out error));
CollectionAssert.AreEqual(new double[] { 15625, 15625, 15625 }, factors);
}
[TestMethod]
public void MultipleMetersHaveIndependentStableChannelRecords()
{
var test = new TestRslt();
var first = new WaterMeter { WMPosition = 1 };
var second = new WaterMeter { WMPosition = 2 };
var a = test.GetCalibrationFactors(first);
var b = test.GetCalibrationFactors(second);
a[0].BaseCalibFactor = 17969;
b[0].BaseCalibFactor = 19000;
Assert.AreEqual(6, test.CalibFactorResultsToSave.Count);
Assert.AreSame(a[0], test.GetCalibrationFactors(first)[0]);
Assert.AreEqual(17969, a[0].BaseCalibFactor);
Assert.AreEqual(19000, b[0].BaseCalibFactor);
for (int i = 0; i < 3; i++) Assert.AreEqual(i + 1, b[i].CalibFactorIndex);
}
[TestMethod]
public void GenesisFactoryAndProcedureActivitiesAreAvailable()
{
var factory = TBF.Rig.TbfComponents.CmpntFactoryFromClassName("TestMethods.GenesisCommunication");
Assert.IsNotNull(factory);
var config = factory.DefaultConfig() as TBF.Rig.TestMethods.GenesisCommunication.TestMethodCfg;
Assert.IsNotNull(config);
Assert.AreEqual(10, config.NrThreads);
var parameters = new TBF.Rig.TestMethods.GenesisCommunication.iPerlCommunicationParams(true);
CollectionAssert.Contains(new System.Collections.Generic.List<string>(parameters.ParamValues(0)), "Prepare Q3 Calibration Slot");
Assert.IsNotNull(TBF.Rig.TbfComponents.CmpntFactoryFromClassName("TestMethods.iPerlCommunication"));
}
[TestMethod]
public void MappedCalibrationRecordsRoundTripForTwoMeters()
{
string path = Path.Combine(Path.GetTempPath(), "genesis-roundtrip-" + Guid.NewGuid() + ".sqlite");
var previousType = Results.DB.DbType;
var previousConnection = Results.DB.ConnectionString;
var previousFactory = Results.DB.SessionFactory;
try
{
Results.DB.DbType = Common.DBType.SQLite;
Results.DB.ConnectionString = path;
using (var factory = Results.DB.CreateSessionFactory(true))
{
int testId;
using (var session = factory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var test = new TestRslt();
session.Save(test);
testId = test.Id;
for (int meter = 1; meter <= 2; meter++)
foreach (var factor in test.GetCalibrationFactors(new WaterMeter { WMPosition = meter }))
{
factor.BaseCalibFactor = 17969 + meter;
factor.CalculatedCalibFactor = 18000 + meter;
factor.Stored = true;
factor.IsCalibFactorValid = true;
session.Save(factor);
}
transaction.Commit();
}
DatabaseMigrationHelper.EnsureSchema(Common.DBType.SQLite, path);
using (var session = factory.OpenSession())
{
var rows = TestRsltCalibFactorHelper.GetByTestRsltId(session, testId);
Assert.AreEqual(6, rows.Count);
foreach (var row in rows)
{
Assert.AreEqual(17969 + row.WaterMeterPosition, row.BaseCalibFactor);
Assert.IsTrue(row.Stored);
Assert.IsTrue(row.IsCalibFactorValid);
}
}
}
}
finally
{
Results.DB.DbType = previousType;
Results.DB.ConnectionString = previousConnection;
Results.DB.SessionFactory = previousFactory;
SQLiteConnection.ClearAllPools();
if (File.Exists(path)) File.Delete(path);
}
}
// This test creates a temporary schema at runtime; no IDE data source exists.
// ReSharper disable SqlResolve
[TestMethod]
public void SQLiteEnsureCreatesAndUpgradesWithoutLosingExistingData()
{
string path = Path.Combine(Path.GetTempPath(), "genesis-migration-" + Guid.NewGuid() + ".sqlite");
try
{
using (var connection = new SQLiteConnection("Data Source=" + path))
{
connection.Open();
Execute(connection, "CREATE TABLE WaterMeterData(Id INTEGER PRIMARY KEY)");
Execute(connection, "CREATE TABLE WaterMeter(Id INTEGER PRIMARY KEY, CalibFactorNominal REAL NOT NULL DEFAULT 4096)");
Execute(connection, "CREATE TABLE MeterTestRslt(Id INTEGER PRIMARY KEY, FlipMode INT NULL)");
Execute(connection, "INSERT INTO WaterMeter(Id, CalibFactorNominal) VALUES(1, 17969)");
Execute(connection, "INSERT INTO MeterTestRslt(Id, FlipMode) VALUES(1, 7)");
// Simulate a partially migrated database from a previous special build.
Execute(connection, "CREATE TABLE TestRsltCalibFactor(Id INTEGER PRIMARY KEY, TestRsltId INT)");
Execute(connection, "INSERT INTO TestRsltCalibFactor(Id, TestRsltId) VALUES(1, 12)");
}
DatabaseMigrationHelper.EnsureSchema(Common.DBType.SQLite, path);
DatabaseMigrationHelper.EnsureSchema(Common.DBType.SQLite, path);
using (var connection = new SQLiteConnection("Data Source=" + path))
{
connection.Open();
Assert.AreEqual(17969d, Convert.ToDouble(Scalar(connection, "SELECT CalibFactorNominal FROM WaterMeter WHERE Id=1")));
Assert.AreEqual(7L, Convert.ToInt64(Scalar(connection, "SELECT FlipMode FROM MeterTestRslt WHERE Id=1")));
Assert.AreEqual(0L, Convert.ToInt64(Scalar(connection, "SELECT Q3Channel FROM WaterMeter WHERE Id=1")));
Assert.AreEqual(12L, Convert.ToInt64(Scalar(connection, "SELECT TestRsltId FROM TestRsltCalibFactor WHERE Id=1")));
Execute(connection, "UPDATE TestRsltCalibFactor SET WaterMeterPosition=2, CalibFactorIndex=3, BaseCalibFactor=17969, IsCalibFactorValid=1, Stored=1 WHERE Id=1");
Assert.AreEqual(17969L, Convert.ToInt64(Scalar(connection, "SELECT BaseCalibFactor FROM TestRsltCalibFactor WHERE WaterMeterPosition=2 AND CalibFactorIndex=3")));
Assert.AreEqual(0L, Convert.ToInt64(Scalar(connection, "SELECT COUNT(*) FROM MeterTestCalibFactorRslt")));
}
}
finally { SQLiteConnection.ClearAllPools(); if (File.Exists(path)) File.Delete(path); }
}
// ReSharper restore SqlResolve
private static void Execute(SQLiteConnection connection, string sql)
{
using (var command = connection.CreateCommand()) { command.CommandText = sql; command.ExecuteNonQuery(); }
}
private static object Scalar(SQLiteConnection connection, string sql)
{
using (var command = connection.CreateCommand()) { command.CommandText = sql; return command.ExecuteScalar(); }
}
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')" />
<PropertyGroup>
@ -63,6 +63,13 @@
<Reference Include="Moq, Version=4.20.70.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.20.70\lib\net462\Moq.dll</HintPath>
</Reference>
<Reference Include="NHibernate">
<HintPath>..\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite, Version=1.0.119.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\lib\net46\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
@ -207,10 +214,12 @@
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.10\build\net46\MSTest.TestAdapter.targets'))" />
</Target>
@ -222,4 +231,11 @@
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup><Compile Include="GenesisRecoveryTests.cs" /></ItemGroup>
<!-- Project dependencies may copy an older SQLite interop DLL with a newer timestamp. -->
<Target Name="EnsureMatchingSQLiteInterop" AfterTargets="Build">
<Copy SourceFiles="@(SQLiteInteropFiles)"
DestinationFiles="@(SQLiteInteropFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="5.1.1" targetFramework="net472" />
<package id="JetBrains.Annotations" version="2023.3.0" targetFramework="net472" />
@ -14,4 +14,7 @@
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
<package id="log4net" version="2.0.15" targetFramework="net472" />
<package id="NHibernate" version="4.0.4.4000" targetFramework="net48" />
<package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.119.0" targetFramework="net48" />
<package id="System.Data.SQLite.Core" version="1.0.119.0" targetFramework="net48" />
</packages>