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.
905 lines
36 KiB
C#
905 lines
36 KiB
C#
///
|
|
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
using Common;
|
|
using Config.Entities;
|
|
using Results.Resources;
|
|
|
|
namespace Results.Entities
|
|
{
|
|
public enum ResultCode
|
|
{
|
|
None = 0,
|
|
|
|
Bit16 = (1 << 16),
|
|
Bit17 = (1 << 17),
|
|
Bit18 = (1 << 18),
|
|
Bit19 = (1 << 19),
|
|
RfidErrorCodeMask = (Bit16 | Bit17 | Bit18 | Bit19), /// RFID comm. err. (the first encounetered error is stored)
|
|
|
|
Bit20 = (1 << 20),
|
|
Bit21 = (1 << 21),
|
|
Bit22 = (1 << 22),
|
|
Bit23 = (1 << 23),
|
|
RfidErrorTestIdMask = (Bit20 | Bit21 | Bit22 | Bit23), /// RFID comm. err. (the first encounetered error is stored)
|
|
|
|
MissingOptoData = (1 << 24),
|
|
OptoDataWithZeroFlow = (1 << 25),
|
|
OptoErrorCodeMask = (MissingOptoData | OptoDataWithZeroFlow), /// Opto comm. err. (the first encounetered error is stored)
|
|
|
|
Bit26 = (1 << 26),
|
|
Bit27 = (1 << 27),
|
|
Bit28 = (1 << 28),
|
|
Bit29 = (1 << 29),
|
|
Bit30 = (1 << 30),
|
|
Bit31 = (1 << 31),
|
|
}
|
|
|
|
|
|
public class WaterMeter
|
|
{
|
|
public virtual int Id { get; protected set; }
|
|
public virtual string SerialNr { get; set; } /// S/N _or_ S/N of the main meter of a compound meter _or_ PCB Number of an iPerl water meter
|
|
public virtual string SerialNrAux { get; set; } /// S/N of the aux. meter of a compound meter _or_ eRegister PCB Number of a 640 water meter
|
|
public virtual string RadioAddress { get; set; }
|
|
public virtual string PurchaseOrder { get; set; }
|
|
public virtual int YearOfProduction { get; set; }
|
|
public virtual int WMPosition { get; set; } /// 1-based water meter position
|
|
public virtual string EndState { get; set; } /// End state (of the main water meter)
|
|
public virtual string EndStateAux { get; set; } /// End state of the auxiliary water meter
|
|
public virtual double QRise { get; set; } /// [m3/h] detected Q_rise of a composed meter or 'sensitivity' of a single meter
|
|
public virtual double QFall { get; set; } /// [m3/h] detected Q_fall of a composed meter
|
|
public virtual long ErrorFlags { get; set; } /// bitfield : bit14=E15, bit15=E16
|
|
public virtual long InfoFlags { get; set; } /// bitfield : bit14=E15, bit15=E16
|
|
public virtual bool Passed { get; set; }
|
|
public virtual int ResultCode { get; set; }
|
|
public virtual string ArchivePath { get; set; }
|
|
public virtual string Remark { get; set; }
|
|
|
|
#if IPERL
|
|
public virtual double OrigCalibFactor { get; set; } /// Original iPerl calibration factor used during the test
|
|
public virtual double CalibFactor { get; set; } /// iPerl calibration factor used during the test
|
|
public virtual double CalibFactorNominal { get; set; } /// Raw calibration factor representing 100 % for this test result
|
|
public virtual double CalibFactorPercentage
|
|
{
|
|
get
|
|
{
|
|
double nominalCalibFactor = CalibFactorNominal > 0.0 ? CalibFactorNominal : 4096.0;
|
|
return CalibFactor * 100.0 / nominalCalibFactor;
|
|
}
|
|
}
|
|
public virtual double CalibFactorCorrectionPercentage
|
|
{
|
|
get { return CalibFactorPercentage - 100.0; }
|
|
}
|
|
public virtual double OrigCalibFactorLNA{ get; set; } /// Original iPerl LNA calibration factor used during the test
|
|
public virtual double CalibFactorLNA { get; set; } /// iPerl LNA calibration factor used during the test
|
|
public virtual double Q2ErrWOCorrection { get; set; }
|
|
public virtual int Q2CorrRL { get; set; } /// iPerl Q2 correction for the R-flow written to iPerl
|
|
public virtual int Q2CorrLR { get; set; } /// iPerl Q2 correction for the L-flow written to iPerl
|
|
public virtual int Q2CorrFlowRight { get; set; } /// 1 = right to left
|
|
public virtual double Diff2Hz8Hz { get; set; }
|
|
public virtual bool Hz2CorrectionDone { get; set; } /// true = iPerl Q2 correction was done
|
|
public virtual int Hz2Correction { get; set; } /// iPerl Q2 correction used during the test
|
|
public virtual string FWVersion { get; set; }
|
|
#endif
|
|
#if TURA_SPECIAL
|
|
/// <summary>
|
|
/// Data from a production test bench (in case of tests on iPerl special)
|
|
/// </summary>
|
|
public virtual int PaletteNr { get; set; }
|
|
public virtual int UmkartonNr { get; set; }
|
|
public virtual string ProdTestBench { get; set; }
|
|
public virtual int ProdWMPosition { get; set; }
|
|
public virtual string ProdUserName { get; set; }
|
|
public virtual string ProdPurchaseOrder { get; set; }
|
|
public virtual bool ProdPassed { get; set; }
|
|
public virtual int ProdResultCode { get; set; }
|
|
public virtual int ProdQ2CorrRL { get; set; } /// iPerl Q2 correction for the R-flow written to iPerl
|
|
public virtual int ProdQ2CorrLR { get; set; } /// iPerl Q2 correction for the L-flow written to iPerl
|
|
#endif
|
|
|
|
///
|
|
/// Mapped to database only when ORACLE_DB is defined
|
|
///
|
|
public virtual int AssignedSerialNr { get; set; }
|
|
public virtual string Prefix { get; set; }
|
|
public virtual string Suffix { get; set; }
|
|
public virtual string CompleteSerialNr { get; set; }
|
|
public virtual string OriRadioAddress { get; set; } /// Not mapped to DB !!! Original radio address of a 640 water meter (albatrosID)
|
|
public virtual int WMTypeRevision { get; set; }
|
|
public virtual int Pruefindex { get; set; } /// >=1 ... pruefindex, 0 ... unknown (no reading from DB yet)
|
|
public virtual int HydrPruefung { get; set; }
|
|
public virtual object RawTestInfos { get; set; } /// IList<SensusTestInfo> fetched from Oracle at the beginning of the cycle, not mapped to DB !!!
|
|
public virtual object CompleteTestInfos { get; set; } /// SensusTestInfo[] obtained as a best match at the beginning of the cycle, not mapped to DB !!!
|
|
|
|
///
|
|
/// Not mapped to database
|
|
///
|
|
public virtual string Workflow { get; set; } /// Not mapped to DB !!! Production tracing workflow name
|
|
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; }
|
|
|
|
///
|
|
/// Wrappers
|
|
///
|
|
public virtual string GetEndStateAux() { return Compound() ? EndStateAux : string.Empty; }
|
|
public virtual void SetEndStateAux(string s) { if (Compound()) EndStateAux = s; }
|
|
|
|
public virtual string GetStartState() { return Compound() ? string.Empty : EndStateAux; }
|
|
public virtual void SetStartState(string s) { if (!Compound()) EndStateAux = s; }
|
|
|
|
public virtual string ProductName() { return WaterMeterData.ProductName; }
|
|
public virtual string Producer() { return WaterMeterData.Producer; }
|
|
public virtual string MetrologicalClass() { return WaterMeterData.MetrologicalClass; }
|
|
public virtual string ApprovalInfo() { return WaterMeterData.ApprovalInfo; }
|
|
public virtual FlowNames Qnames() { return (FlowNames)WaterMeterData.Qnames; }
|
|
public virtual double Q4_Qmax() { return WaterMeterData.Q4_Qmax; }
|
|
public virtual double Q3_Qn() { return WaterMeterData.Q3_Qn; }
|
|
public virtual double Q2_Qt() { return WaterMeterData.Q2_Qt; }
|
|
public virtual double Q1_Qmin() { return WaterMeterData.Q1_Qmin; }
|
|
public virtual double ErrLimHiQ() { return WaterMeterData.ErrLimHiQ; }
|
|
public virtual double ErrLimLoQ() { return WaterMeterData.ErrLimLoQ; }
|
|
|
|
public virtual bool Compound() { return WaterMeterData.Compound; }
|
|
public virtual bool HeatMeter() { return WaterMeterData.HeatMeter; }
|
|
|
|
public virtual string ProducerAux() { return WaterMeterData.ProducerAux; }
|
|
public virtual double Q3_Qn_Aux() { return WaterMeterData.Q3_Qn_Aux; }
|
|
public virtual string MetrologicalClassAux() { return WaterMeterData.MetrologicalClassAux; }
|
|
public virtual string ApprovalInfoAux() { return WaterMeterData.ApprovalInfoAux; }
|
|
|
|
public virtual int BatchNr() { return Batch.BatchNr; }
|
|
public virtual int BenchId() { return Batch.TestBenchId; }
|
|
public virtual string ProcedureName() { return Batch.ProcedureName; }
|
|
public virtual int ProcedureRevision() { return Batch.ProcedureRevision; }
|
|
public virtual DateTime StartTime() { return Batch.StartTime; }
|
|
public virtual DateTime EndTime() { return Batch.EndTime; }
|
|
|
|
public virtual IList<MeterTestRslt> RegularMeterTestRslts()
|
|
{
|
|
IList<MeterTestRslt> rslt = new List<MeterTestRslt>();
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if ((mtr.Name().Length > 0 && mtr.Name()[0] != '[') || !mtr.Name().Contains("]")) rslt.Add(mtr);
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
public virtual IList<MeterTestRslt> AutoMeterTestRslts(string param)
|
|
{
|
|
int len = param.Length;
|
|
IList<MeterTestRslt> rslt = new List<MeterTestRslt>();
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Name().Length > len + 1 && mtr.Name()[0] == '[' && mtr.Name().IndexOf(param) == 1 && mtr.Name()[len + 1] == ']')
|
|
{
|
|
rslt.Add(mtr);
|
|
}
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
public virtual long ErrorFlagsFromTests()
|
|
{
|
|
long errorFlags = 0;
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && mtr.TestDone) errorFlags |= mtr.TestRslt.ErrorFlags;
|
|
}
|
|
return errorFlags;
|
|
}
|
|
|
|
public virtual long ErrorFlagsFromTestsAndWM()
|
|
{
|
|
return ErrorFlagsFromTests() | ErrorFlags;
|
|
}
|
|
|
|
public virtual long ErrorFlagsFromTestsAndWMByFlag(ErrorFlagMask errorFlagsQuestion)
|
|
{
|
|
long errorFlagsMask = (long)errorFlagsQuestion;
|
|
return ErrorFlagsFromTests() & errorFlagsMask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert combined errorFlags of all tests to string
|
|
/// </summary>
|
|
/// <returns>ErrorFlags string</returns>
|
|
public virtual string ErrorFlagsStr()
|
|
{
|
|
string eFlags = Utils.ErrorFlagsStr(ErrorFlagsFromTestsAndWM());
|
|
#if LANG_PL
|
|
return string.IsNullOrEmpty(eFlags) ? "brak" : eFlags;
|
|
#else
|
|
return eFlags;
|
|
#endif
|
|
}
|
|
|
|
public virtual long InfoFlagsFromTests()
|
|
{
|
|
long infoFlags = 0;
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && mtr.TestDone) infoFlags |= mtr.TestRslt.InfoFlags;
|
|
}
|
|
return infoFlags;
|
|
}
|
|
|
|
public virtual long InfoFlagsFromTestsAndWM()
|
|
{
|
|
return InfoFlagsFromTests() | InfoFlags;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert combined errorFlags of all tests to string
|
|
/// </summary>
|
|
/// <returns>ErrorFlags string</returns>
|
|
public virtual string InfoFlagsStr()
|
|
{
|
|
return Utils.ErrorFlagsStr(InfoFlagsFromTestsAndWM());
|
|
}
|
|
|
|
public virtual string PassedOrErrorFlagsStr()
|
|
{
|
|
string eFlags = Utils.ErrorFlagsStr(ErrorFlagsFromTestsAndWM());
|
|
return string.IsNullOrEmpty(eFlags) ? (WaterMeterData.Text4 + PassedColorStr(null)) : eFlags;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert failed tests and combined errorFlags of all tests to string
|
|
/// </summary>
|
|
/// <returns>ErrorFlagsEx string</returns>
|
|
public virtual string ErrorFlagsStrEx()
|
|
{
|
|
StringBuilder errFlgsStr = new StringBuilder();
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && mtr.TestDone && !mtr.Passed)
|
|
{
|
|
errFlgsStr.Append(mtr.Name());
|
|
errFlgsStr.Append(" ");
|
|
}
|
|
}
|
|
|
|
errFlgsStr.Append(Utils.ErrorFlagsStr(ErrorFlagsFromTestsAndWM()));
|
|
|
|
return errFlgsStr.ToString();
|
|
}
|
|
|
|
public virtual bool PassedFromTests()
|
|
{
|
|
bool passed = (ErrorFlagsFromTestsAndWM() == 0);
|
|
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && (!mtr.Passed || !mtr.TestDone))
|
|
{
|
|
passed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return passed;
|
|
}
|
|
|
|
public virtual bool PassedFromTestsE15()
|
|
{
|
|
//TODO BUMI this will just let us is E15
|
|
bool passed = (ErrorFlagsFromTestsAndWMByFlag(ErrorFlagMask.E15) == 0);
|
|
|
|
//TODO BUMI Check This may be not needed ?
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && (!mtr.TestDone))
|
|
{
|
|
passed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return passed;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Three state test results and/or water meter result (Algeria PT25 requirement).
|
|
/// NearlyOK means error is within error limits not narrowed by uncertainty
|
|
/// OK: Uncertainty + ErrLimLo <= error <= ErrLimHi - Uncertainty
|
|
/// NearlyOK: not OK but stil ErrLimLo <= error <= ErrLimHi
|
|
/// Nok: otherwise
|
|
/// </summary>
|
|
public virtual ThreeState ThreeStateFromTests()
|
|
{
|
|
ThreeState result = ThreeState.OK;
|
|
if (ErrorFlagsFromTestsAndWM() != 0) result = ThreeState.Nok;
|
|
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate())
|
|
{
|
|
if(!mtr.TestDone || mtr.Error < mtr.ErrLimLo() || mtr.Error > mtr.ErrLimHi())
|
|
{
|
|
/// Test was not done or completely failed (was outside broader error limits)
|
|
result = ThreeState.Nok;
|
|
}
|
|
else if (result == ThreeState.OK && (mtr.Error < mtr.ErrLimLo() + mtr.Uncertainty() || mtr.Error > mtr.ErrLimHi() - mtr.Uncertainty()))
|
|
{
|
|
/// So far the water meter was OK, but this test was outside narrow error limits (= limits shrinked by Uncertainty)
|
|
result = ThreeState.NearlyOK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public virtual bool CompletedFromTests()
|
|
{
|
|
bool completed = true;
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Evaluate() && !mtr.TestDone)
|
|
{
|
|
completed = false;
|
|
break;
|
|
}
|
|
}
|
|
return completed;
|
|
}
|
|
|
|
|
|
public virtual string PassedColorStr(string yesNoFormatOrEmpty)
|
|
{
|
|
if (string.IsNullOrEmpty(yesNoFormatOrEmpty))
|
|
{
|
|
return Utils.PassedColorStr(Passed, true);
|
|
}
|
|
else
|
|
{
|
|
string[] yesNo = yesNoFormatOrEmpty.Split(new char[] { '~' });
|
|
return Passed ? yesNo[0] : ((yesNo.Length >= 2) ? yesNo[1] : Results.Resources.Strings.No);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
/// Not mapped to the database
|
|
///
|
|
public virtual bool Disabled { get; set; } /// true = Disabled water meters (not saved into DB)
|
|
|
|
|
|
public virtual MeterTestRslt GetMeterTestRslt(string testName)
|
|
{
|
|
return GetMeterTestRslt(testName, CompoundMeterId.SingleOrCompound);
|
|
}
|
|
|
|
public virtual MeterTestRslt GetMeterTestRslt(string testName, CompoundMeterId meterId)
|
|
{
|
|
if (string.IsNullOrEmpty(testName)) return null;
|
|
if (Disabled) return null;
|
|
|
|
string testNameL = testName.ToLower();
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.Name().ToLower().Equals(testNameL))
|
|
{
|
|
if (mtr.CompoundMeterId == (byte)meterId)
|
|
{
|
|
return mtr;
|
|
}
|
|
else if (meterId == CompoundMeterId.SingleOrCompound && mtr.CompoundMeterId == (byte)CompoundMeterId.Single)
|
|
{
|
|
return mtr;
|
|
}
|
|
else if (meterId == CompoundMeterId.SingleOrCompound && mtr.CompoundMeterId == (byte)CompoundMeterId.Compound)
|
|
{
|
|
return mtr;
|
|
}
|
|
else if (meterId == CompoundMeterId.SingleOrCompound && mtr.CompoundMeterId == (byte)CompoundMeterId.HeatMeterEnergy)
|
|
{
|
|
return mtr;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public virtual TestRslt GetTestRslt(string testName)
|
|
{
|
|
MeterTestRslt mtr = GetMeterTestRslt(testName);
|
|
if (mtr != null) return mtr.TestRslt;
|
|
return null;
|
|
}
|
|
|
|
public virtual bool TryGetTestRslt(string testName, out TestRslt testRslt)
|
|
{
|
|
MeterTestRslt mtr = GetMeterTestRslt(testName);
|
|
if (mtr != null)
|
|
{
|
|
testRslt = mtr.TestRslt;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
testRslt = null;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public virtual TestData GetTestData(string testName)
|
|
{
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.TestRslt.TestData.Name == testName)
|
|
{
|
|
return mtr.TestRslt.TestData;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public virtual bool TryGetTestData(string testName, out TestData testData)
|
|
{
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if (mtr.TestRslt.TestData.Name == testName)
|
|
{
|
|
testData = mtr.TestRslt.TestData;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
testData = null;
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor, initializes a list, used as a base for other constructors
|
|
/// </summary>
|
|
public WaterMeter()
|
|
{
|
|
MeterTestRslts = new List<MeterTestRslt>();
|
|
|
|
AssignedSerialNr = 0;
|
|
Prefix = string.Empty;
|
|
Suffix = string.Empty;
|
|
CompleteSerialNr = string.Empty;
|
|
WMTypeRevision = 0;
|
|
Pruefindex = 0;
|
|
HydrPruefung = 0;
|
|
RawTestInfos = null;
|
|
CompleteTestInfos = null;
|
|
|
|
Workflow = string.Empty;
|
|
ErrorFlags = 0;
|
|
InfoFlags = 0;
|
|
LastRecordIsNok = false;
|
|
|
|
/// Initialize strings
|
|
SerialNr = string.Empty;
|
|
SerialNrAux = string.Empty;
|
|
RadioAddress = string.Empty;
|
|
PurchaseOrder = string.Empty;
|
|
EndState = string.Empty;
|
|
EndStateAux = string.Empty;
|
|
ArchivePath = string.Empty;
|
|
Remark = string.Empty;
|
|
#if IPERL
|
|
FWVersion = string.Empty;
|
|
#endif
|
|
#if TURA_SPECIAL
|
|
ProdUserName = string.Empty;
|
|
ProdPurchaseOrder = string.Empty;
|
|
#endif
|
|
#if IPERL
|
|
FWVersion = string.Empty;
|
|
#endif
|
|
PrintLabel = true;
|
|
Q3Channel = 0; //No Q3 calibration by default
|
|
}
|
|
|
|
|
|
public virtual void CopyContentFrom(WaterMeter src)
|
|
{
|
|
if (src == null) return;
|
|
|
|
SerialNr = src.SerialNr;
|
|
SerialNrAux = src.SerialNrAux;
|
|
RadioAddress = src.RadioAddress;
|
|
PurchaseOrder = src.PurchaseOrder;
|
|
YearOfProduction = src.YearOfProduction;
|
|
WMPosition = src.WMPosition;
|
|
EndState = src.EndState;
|
|
EndStateAux = src.EndStateAux;
|
|
QRise = src.QRise;
|
|
QFall = src.QFall;
|
|
ErrorFlags = src.ErrorFlags;
|
|
InfoFlags = src.InfoFlags;
|
|
Passed = src.Passed;
|
|
ResultCode = src.ResultCode;
|
|
ArchivePath = src.ArchivePath;
|
|
Remark = src.Remark;
|
|
#if IPERL
|
|
OrigCalibFactor = src.OrigCalibFactor;
|
|
CalibFactor = src.CalibFactor;
|
|
CalibFactorNominal = src.CalibFactorNominal;
|
|
OrigCalibFactorLNA = src.OrigCalibFactorLNA;
|
|
CalibFactorLNA = src.CalibFactorLNA;
|
|
Q2ErrWOCorrection = src.Q2ErrWOCorrection;
|
|
Q2CorrRL = src.Q2CorrRL;
|
|
Q2CorrLR = src.Q2CorrLR;
|
|
Q2CorrFlowRight = src.Q2CorrFlowRight;
|
|
Diff2Hz8Hz = src.Diff2Hz8Hz;
|
|
Hz2CorrectionDone = src.Hz2CorrectionDone;
|
|
Hz2Correction = src.Hz2Correction;
|
|
FWVersion = src.FWVersion;
|
|
#endif
|
|
#if TURA_SPECIAL
|
|
PaletteNr = src.PaletteNr;
|
|
UmkartonNr = src.UmkartonNr;
|
|
ProdTestBench = src.ProdTestBench;
|
|
ProdWMPosition = src.ProdWMPosition;
|
|
ProdUserName = src.ProdUserName;
|
|
ProdPurchaseOrder = src.ProdPurchaseOrder;
|
|
ProdPassed = src.ProdPassed;
|
|
ProdResultCode = src.ProdResultCode;
|
|
ProdQ2CorrRL = src.ProdQ2CorrRL;
|
|
ProdQ2CorrLR = src.ProdQ2CorrLR;
|
|
#endif
|
|
AssignedSerialNr = src.AssignedSerialNr;
|
|
Prefix = src.Prefix;
|
|
Suffix = src.Suffix;
|
|
CompleteSerialNr = src.CompleteSerialNr;
|
|
OriRadioAddress = src.OriRadioAddress;
|
|
WMTypeRevision = src.WMTypeRevision;
|
|
Pruefindex = src.Pruefindex;
|
|
HydrPruefung = src.HydrPruefung;
|
|
RawTestInfos = src.RawTestInfos; /// Not mapped to DB
|
|
CompleteTestInfos = src.CompleteTestInfos; /// Not mapped to DB
|
|
|
|
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)
|
|
{
|
|
MeterTestRslt srcMtr = src.GetMeterTestRslt(mtr.Name(), (CompoundMeterId)mtr.CompoundMeterId);
|
|
if (srcMtr != null)
|
|
{
|
|
mtr.CopyContentFrom(srcMtr);
|
|
mtr.TestRslt.CopyContentFrom(srcMtr.TestRslt);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder(80);
|
|
#if IPERL
|
|
sb.AppendFormat("PCB:{0} S/N:{1} ", SerialNr, SerialNrAux);
|
|
#else
|
|
sb.AppendFormat("S/N:{0} ", SerialNr);
|
|
#endif
|
|
|
|
foreach (var tr in MeterTestRslts) sb.AppendFormat(" {0}:{1}%", tr.Name(), tr.Error.ToString("F2"));
|
|
sb.AppendFormat(" test start: {0} {1} batch={2}", StartTime().ToShortDateString(), StartTime().ToShortTimeString(), BatchNr());
|
|
return sb.ToString();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get decorated test names for a specified watermeter
|
|
/// </summary>
|
|
/// <param name="wMtr">Watermeter results entity</param>
|
|
/// <returns>A list of strings</returns>
|
|
public virtual IList<string> GetAllDecoratedTestNames()
|
|
{
|
|
IList<string> testNames = new List<string>();
|
|
|
|
if (MeterTestRslts != null)
|
|
{
|
|
foreach (var mtr in MeterTestRslts)
|
|
{
|
|
if ((mtr.CompoundMeterId == (byte)CompoundMeterId.Single || mtr.CompoundMeterId == (byte)CompoundMeterId.Compound || mtr.CompoundMeterId == (byte)CompoundMeterId.HeatMeterEnergy)
|
|
&& (mtr.Q3Channel != 0 ||
|
|
(mtr.TestDone
|
|
&& (mtr.Publish() != Publish.Never)
|
|
&& (mtr.Publish() != Publish.Internal))))
|
|
{
|
|
testNames.Add(mtr.Name());
|
|
}
|
|
}
|
|
}
|
|
|
|
return testNames;
|
|
}
|
|
|
|
|
|
static readonly System.Drawing.Color NotCompletedColor = System.Drawing.Color.White;
|
|
static readonly System.Drawing.Color OkColor = System.Drawing.Color.LightGreen;
|
|
static readonly System.Drawing.Color NokColor = System.Drawing.Color.LightPink;
|
|
static readonly System.Drawing.Color RejectColor = System.Drawing.Color.Magenta;
|
|
static readonly System.Drawing.Color ProductionErrorColor = System.Drawing.Color.RoyalBlue;
|
|
static readonly System.Drawing.Color WrongDirectionColor = System.Drawing.Color.Gold;
|
|
static readonly System.Drawing.Color WrongQ2FactorsColor = System.Drawing.Color.Red;
|
|
|
|
/// <summary>
|
|
/// Get color for highlighting results and an apporpriate text message.
|
|
/// </summary>
|
|
/// <param name="wMtr">Water meter results entity</param>
|
|
/// <param name="message">Appropriate message</param>
|
|
/// <returns>Color for results</returns>
|
|
public virtual System.Drawing.Color GetColorOfResults(bool maxRepeatsExceeded, out string message)
|
|
{
|
|
bool wmtrCompleted = CompletedFromTests();
|
|
bool wmtrPassed = PassedFromTests();
|
|
|
|
if ((ErrorFlags & (int)ErrorFlagMask.E28) != 0)
|
|
{
|
|
message = Strings.Previous_step_is_missing_or_NOK;
|
|
return ProductionErrorColor;
|
|
}
|
|
else if ((ErrorFlags & (int)ErrorFlagMask.E27) != 0)
|
|
{
|
|
message = Strings.Wrong_iPerl_counting_direction;
|
|
return WrongDirectionColor;
|
|
}
|
|
else if ((ErrorFlags & (int)ErrorFlagMask.E26) != 0)
|
|
{
|
|
message = Strings.Invalid_Q2_correction_factors;
|
|
return WrongQ2FactorsColor;
|
|
}
|
|
else if (wmtrPassed)
|
|
{
|
|
/// Water meter passed (therefore is was also completed)
|
|
message = Strings.Passed;
|
|
return OkColor;
|
|
}
|
|
else if (wmtrCompleted)
|
|
{
|
|
/// Water meter was completed but did not pass => Failed
|
|
if (maxRepeatsExceeded)
|
|
{
|
|
message = Strings.Test_repetition_count_exceeded_upper_limit;
|
|
return RejectColor;
|
|
}
|
|
else
|
|
{
|
|
message = Strings.Failed;
|
|
return NokColor;
|
|
}
|
|
}
|
|
else if (Disabled)
|
|
{
|
|
/// Water meter was not completed yet => did not pass, did not fail
|
|
message = Strings.This_position_is_disabled;
|
|
return NotCompletedColor;
|
|
}
|
|
else
|
|
{
|
|
/// Water meter was not completed yet => did not pass, did not fail
|
|
message = Strings.Test_in_progress;
|
|
return NotCompletedColor;
|
|
}
|
|
}
|
|
|
|
public virtual void WriteBinary(BinaryWriter writer, IList<WaterMeterData> savedWMDatas)
|
|
{
|
|
writer.Write(Id);
|
|
writer.Write((SerialNr != null) ? SerialNr : string.Empty);
|
|
writer.Write((SerialNrAux != null) ? SerialNrAux : string.Empty);
|
|
writer.Write((RadioAddress != null) ? RadioAddress : string.Empty);
|
|
writer.Write((PurchaseOrder != null) ? PurchaseOrder : string.Empty);
|
|
writer.Write(YearOfProduction);
|
|
writer.Write(WMPosition);
|
|
writer.Write((EndState != null) ? EndState : string.Empty);
|
|
writer.Write((EndStateAux != null) ? EndStateAux : string.Empty);
|
|
writer.Write(QRise);
|
|
writer.Write(QFall);
|
|
writer.Write(ErrorFlags);
|
|
writer.Write(InfoFlags);
|
|
writer.Write(Passed);
|
|
writer.Write(ResultCode);
|
|
writer.Write((ArchivePath != null) ? ArchivePath : string.Empty);
|
|
writer.Write((Remark != null) ? Remark : string.Empty);
|
|
#if IPERL
|
|
writer.Write(OrigCalibFactor);
|
|
writer.Write(CalibFactor);
|
|
writer.Write(OrigCalibFactorLNA);
|
|
writer.Write(CalibFactorLNA);
|
|
writer.Write(Q2ErrWOCorrection);
|
|
writer.Write(Q2CorrRL);
|
|
writer.Write(Q2CorrLR);
|
|
writer.Write(Q2CorrFlowRight);
|
|
writer.Write(Diff2Hz8Hz);
|
|
writer.Write(Hz2CorrectionDone);
|
|
writer.Write(Hz2Correction);
|
|
writer.Write((FWVersion != null) ? FWVersion : string.Empty);
|
|
#endif
|
|
#if TURA_SPECIAL
|
|
writer.Write(PaletteNr);
|
|
writer.Write(UmkartonNr);
|
|
writer.Write((ProdTestBench != null) ? ProdTestBench : string.Empty);
|
|
writer.Write(ProdWMPosition);
|
|
writer.Write((ProdUserName != null) ? ProdUserName : string.Empty);
|
|
writer.Write((ProdPurchaseOrder != null) ? ProdPurchaseOrder : string.Empty);
|
|
writer.Write(ProdPassed);
|
|
writer.Write(ProdResultCode);
|
|
writer.Write(ProdQ2CorrRL);
|
|
writer.Write(ProdQ2CorrLR);
|
|
#endif
|
|
writer.Write(AssignedSerialNr);
|
|
writer.Write((Prefix != null) ? Prefix : string.Empty);
|
|
writer.Write((Suffix != null) ? Suffix : string.Empty);
|
|
writer.Write((CompleteSerialNr != null) ? CompleteSerialNr : string.Empty);
|
|
writer.Write((OriRadioAddress != null) ? OriRadioAddress : string.Empty);
|
|
writer.Write(WMTypeRevision);
|
|
writer.Write(Pruefindex);
|
|
writer.Write(HydrPruefung);
|
|
|
|
/// Write RawTestInfos
|
|
IList<Output.SensusTestInfo> rawTestInfos = RawTestInfos as IList<Output.SensusTestInfo>;
|
|
writer.Write((rawTestInfos != null) ? rawTestInfos.Count : 0);
|
|
if (rawTestInfos != null)
|
|
{
|
|
for (int i = 0; i < rawTestInfos.Count; i++) rawTestInfos[i].WriteBinary(writer);
|
|
}
|
|
|
|
/// Write CompleteTestInfos
|
|
Output.SensusTestInfo[] completeTestInfos = CompleteTestInfos as Output.SensusTestInfo[];
|
|
writer.Write((completeTestInfos != null) ? completeTestInfos.Length : 0);
|
|
if (completeTestInfos != null)
|
|
{
|
|
for (int i = 0; i < completeTestInfos.Length; i++) completeTestInfos[i].WriteBinary(writer);
|
|
}
|
|
|
|
writer.Write(Workflow);
|
|
writer.Write(LastRecordIsNok);
|
|
writer.Write(PrintLabel);
|
|
|
|
/// Save WaterMeterData or WaterMeterData.Id
|
|
if (WaterMeterData != null && savedWMDatas != null && !savedWMDatas.Contains(WaterMeterData))
|
|
{
|
|
writer.Write(true);
|
|
WaterMeterData.WriteBinary(writer);
|
|
savedWMDatas.Add(WaterMeterData);
|
|
}
|
|
else
|
|
{
|
|
writer.Write(false);
|
|
}
|
|
|
|
/// Write MeterTestRslts
|
|
int meterTestRsltsCount = MeterTestRslts != null ? MeterTestRslts.Count : 0;
|
|
writer.Write(meterTestRsltsCount);
|
|
for (int i = 0; i < meterTestRsltsCount; i++)
|
|
{
|
|
MeterTestRslts[i].WriteBinary(writer);
|
|
}
|
|
}
|
|
|
|
public virtual void ReadBinary(BinaryReader reader, IList<WaterMeterData> wmDatasRetrievedSoFar, IList<TestRslt> testRslts)
|
|
{
|
|
Id = reader.ReadInt32();
|
|
SerialNr = reader.ReadString();
|
|
SerialNrAux = reader.ReadString();
|
|
RadioAddress = reader.ReadString();
|
|
PurchaseOrder = reader.ReadString();
|
|
YearOfProduction = reader.ReadInt32();
|
|
WMPosition = reader.ReadInt32();
|
|
EndState = reader.ReadString();
|
|
EndStateAux = reader.ReadString();
|
|
QRise = reader.ReadDouble();
|
|
QFall = reader.ReadDouble();
|
|
ErrorFlags = reader.ReadInt64();
|
|
InfoFlags = reader.ReadInt64();
|
|
Passed = reader.ReadBoolean();
|
|
ResultCode = reader.ReadInt32();
|
|
ArchivePath = reader.ReadString();
|
|
Remark = reader.ReadString();
|
|
#if IPERL
|
|
OrigCalibFactor = reader.ReadDouble();
|
|
CalibFactor = reader.ReadDouble();
|
|
OrigCalibFactorLNA = reader.ReadDouble();
|
|
CalibFactorLNA = reader.ReadDouble();
|
|
Q2ErrWOCorrection = reader.ReadDouble();
|
|
Q2CorrRL = reader.ReadInt32();
|
|
Q2CorrLR = reader.ReadInt32();
|
|
Q2CorrFlowRight = reader.ReadInt32();
|
|
Diff2Hz8Hz = reader.ReadDouble();
|
|
Hz2CorrectionDone = reader.ReadBoolean();
|
|
Hz2Correction = reader.ReadInt32();
|
|
FWVersion = reader.ReadString();
|
|
#endif
|
|
#if TURA_SPECIAL
|
|
PaletteNr = reader.ReadInt32();
|
|
UmkartonNr = reader.ReadInt32();
|
|
ProdTestBench = reader.ReadString();
|
|
ProdWMPosition = reader.ReadInt32();
|
|
ProdUserName = reader.ReadString();
|
|
ProdPurchaseOrder = reader.ReadString();
|
|
ProdPassed = reader.ReadBoolean();
|
|
ProdResultCode = reader.ReadInt32();
|
|
ProdQ2CorrRL = reader.ReadInt32();
|
|
ProdQ2CorrLR = reader.ReadInt32();
|
|
#endif
|
|
AssignedSerialNr = reader.ReadInt32();
|
|
Prefix = reader.ReadString();
|
|
Suffix = reader.ReadString();
|
|
CompleteSerialNr = reader.ReadString();
|
|
OriRadioAddress = reader.ReadString();
|
|
WMTypeRevision = reader.ReadInt32();
|
|
Pruefindex = reader.ReadInt32();
|
|
HydrPruefung = reader.ReadInt32();
|
|
|
|
/// Read RawTestInfos
|
|
int rawTestInfosCount = reader.ReadInt32();
|
|
IList<Output.SensusTestInfo> rawTestInfos = new List<Output.SensusTestInfo>();
|
|
for (int i = 0; i < rawTestInfosCount; i++)
|
|
{
|
|
Output.SensusTestInfo ti = new Output.SensusTestInfo();
|
|
ti.ReadBinary(reader);
|
|
rawTestInfos.Add(ti);
|
|
}
|
|
RawTestInfos = rawTestInfos;
|
|
|
|
/// Read CompleteTestInfos
|
|
int completeTestInfosLen = reader.ReadInt32();
|
|
Output.SensusTestInfo[] completeTestInfos = new Output.SensusTestInfo[completeTestInfosLen];
|
|
for (int i = 0; i < completeTestInfosLen; i++)
|
|
{
|
|
Output.SensusTestInfo ti = new Output.SensusTestInfo();
|
|
ti.ReadBinary(reader);
|
|
completeTestInfos[i] = ti;
|
|
}
|
|
CompleteTestInfos = completeTestInfos;
|
|
|
|
Workflow = reader.ReadString();
|
|
LastRecordIsNok = reader.ReadBoolean();
|
|
PrintLabel = reader.ReadBoolean();
|
|
|
|
/// Retrieve TestData
|
|
if (reader.ReadBoolean())
|
|
{
|
|
(WaterMeterData = new WaterMeterData()).ReadBinary(reader);
|
|
if (wmDatasRetrievedSoFar != null) wmDatasRetrievedSoFar.Add(WaterMeterData);
|
|
}
|
|
else
|
|
{
|
|
WaterMeterData = null;
|
|
foreach (var wmd in wmDatasRetrievedSoFar)
|
|
{
|
|
WaterMeterData = wmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// Read MeterTestRslts
|
|
int meterTestRsltsCount = reader.ReadInt32();
|
|
MeterTestRslts = new List<MeterTestRslt>();
|
|
for (int i = 0; i < meterTestRsltsCount; i++)
|
|
{
|
|
MeterTestRslt mtr = new MeterTestRslt();
|
|
mtr.WaterMeter = this;
|
|
mtr.ReadBinary(reader, testRslts);
|
|
MeterTestRslts.Add(mtr);
|
|
}
|
|
}
|
|
}
|
|
}
|