diff --git a/Config/Config.csproj b/Config/Config.csproj index cca307760..afa47fddb 100644 --- a/Config/Config.csproj +++ b/Config/Config.csproj @@ -78,6 +78,7 @@ + diff --git a/Config/Entities/Enums.cs b/Config/Entities/Enums.cs index 0558d7dcd..8048dc7e1 100644 --- a/Config/Entities/Enums.cs +++ b/Config/Entities/Enums.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2017 Sensus Metering Systems +/// Copyright (c) 2013-2018 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -58,7 +58,7 @@ namespace Config.Entities [Description("Remote DB only")] RemoteDBOnly, [Description("Both DB-s, local 1st")] BothDBsLocalFirst, [Description("Both DB-s, remote 1st")] BothDBsRemoteFirst, - Count, + Count } /// diff --git a/Config/Entities/IperlEnums.cs b/Config/Entities/IperlEnums.cs new file mode 100644 index 000000000..ce32d3848 --- /dev/null +++ b/Config/Entities/IperlEnums.cs @@ -0,0 +1,36 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; + +namespace Config.Entities +{ + + public enum Side + { +#if LANG_CS + [Description("Levá")] Left, + [Description("Pravá")] Right, +#else + [Description("Left")] Left, + [Description("Right")] Right, +#endif + Count + } + + public enum FlowDir + { + R_L, + L_R, + Count + } + + public enum OptoHeadState + { + Disabled, + OptoAndDirOK, + OptoNok, + DirNok, + Count + } +} diff --git a/Config/Properties/AssemblyInfo.cs b/Config/Properties/AssemblyInfo.cs index 288d2bd35..22b945181 100644 --- a/Config/Properties/AssemblyInfo.cs +++ b/Config/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.18.982.0")] -[assembly: AssemblyFileVersion("2.18.982.0")] +[assembly: AssemblyVersion("2.18.1082.0")] +[assembly: AssemblyFileVersion("2.18.1082.0")] diff --git a/TBF/BenchControl/BenchInfo/Extended/Component.cs b/TBF/BenchControl/BenchInfo/Extended/Component.cs index 8dddba2c4..2c95e465f 100644 --- a/TBF/BenchControl/BenchInfo/Extended/Component.cs +++ b/TBF/BenchControl/BenchInfo/Extended/Component.cs @@ -30,10 +30,6 @@ namespace TBF.BenchControl.BenchInfo.Extended public string Address5 { get { return myCfg.Address5; } } public RemoteDBUse RemoteDBUse { get { return myCfg.RemoteDBUse; } } -#if ORACLE_DB - public int MaxTestIndex { get { return myCfg.MaxTestIndex; } } /// (MaxPruefindex % 100) value when to reject water meters completely if they are NOK -#endif - public Component() { } diff --git a/TBF/BenchControl/BenchInfo/Extended/ComponentCfg.cs b/TBF/BenchControl/BenchInfo/Extended/ComponentCfg.cs index dbf7efb5c..75d5796b0 100644 --- a/TBF/BenchControl/BenchInfo/Extended/ComponentCfg.cs +++ b/TBF/BenchControl/BenchInfo/Extended/ComponentCfg.cs @@ -33,9 +33,6 @@ namespace TBF.BenchControl.BenchInfo.Extended public string ApprovalDate; public string ApprovedBy; public RemoteDBUse RemoteDBUse; -#if ORACLE_DB - public int MaxTestIndex; /// (MaxPruefindex % 100) value when to reject water meters completely if they are NOK -#endif /// Private parameterless constructor invoked by all other (public) constructors ComponentCfg() {} @@ -67,9 +64,6 @@ namespace TBF.BenchControl.BenchInfo.Extended ApprovedBy = string.Empty; RemoteDBUse = RemoteDBUse.LocalDBOnly; -#if ORACLE_DB - MaxTestIndex = 4; -#endif } string[] paramNames = new string[] @@ -85,9 +79,6 @@ namespace TBF.BenchControl.BenchInfo.Extended "Approval date", "Approved by", "Remote DB use", -#if ORACLE_DB - "Max.test index", -#endif }; public string ParamName(int i) { return paramNames[i]; } public int ParamsCount() { return paramNames.Length; } @@ -126,9 +117,6 @@ namespace TBF.BenchControl.BenchInfo.Extended case 8: return ApprovalDate; case 9: return ApprovedBy; case 10: return RemoteDBUse.ToDescription(); -#if ORACLE_DB - case 11: return MaxTestIndex.ToString(); -#endif default: return string.Empty; } } @@ -165,9 +153,7 @@ namespace TBF.BenchControl.BenchInfo.Extended } } return CfgUpdateFlags.Error; -#if ORACLE_DB - case 11: MaxTestIndex = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd; -#endif + default: return CfgUpdateFlags.None; } } @@ -190,7 +176,6 @@ namespace TBF.BenchControl.BenchInfo.Extended case 9: return true; case 1: - case 11: if (int.TryParse(strValue, out idummy) && (idummy >= 0)) return true; break; case 10: @@ -221,9 +206,6 @@ namespace TBF.BenchControl.BenchInfo.Extended prms.ApprovalDate = this.ApprovalDate; prms.ApprovedBy = this.ApprovedBy; prms.RemoteDBUse = this.RemoteDBUse; -#if ORACLE_DB - prms.MaxTestIndex = this.MaxTestIndex; -#endif } public Config.Entities.IParamsProvider Clone() diff --git a/TBF/BenchControl/BenchInfo/iPerl/Component.cs b/TBF/BenchControl/BenchInfo/iPerl/Component.cs new file mode 100644 index 000000000..c5de0fad6 --- /dev/null +++ b/TBF/BenchControl/BenchInfo/iPerl/Component.cs @@ -0,0 +1,46 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using log4net; +using Config.Entities; +using TBF.BenchControl; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.BenchInfo.iPerl +{ + /// + /// Holds information identifying the test bench. + /// + public class Component : ComponentBase, GenericDevices.IBenchInfo + { + private static readonly ILog log = LogManager.GetLogger(typeof(Component)); + public override string ToString() { return string.Format("BenchInfo.iPerl({0})", Cfg.ToString(1)); } + + readonly ComponentCfg myCfg; + + public string TestBenchName { get { return myCfg.TestBenchName; } } + public int TestBenchId { get { return myCfg.TestBenchId; } } + public string Address1 { get { return myCfg.Address1; } } + public string Address2 { get { return myCfg.Address2; } } + public string Address3 { get { return myCfg.Address3; } } + public string Address4 { get { return myCfg.Address4; } } + public string Address5 { get { return myCfg.Address5; } } + public RemoteDBUse RemoteDBUse { get { return myCfg.RemoteDBUse; } } + public Side Side { get { return myCfg.Side; } } + public int MaxTestIndex { get { return myCfg.MaxTestIndex; } } /// (MaxPruefindex % 100) value when to reject water meters completely if they are NOK + + public Component() + { + } + + public Component(Generic.IComponentCfg cfg) + : base(cfg) + { + myCfg = cfg as ComponentCfg; + log.Debug(this.ToString()); + } + } +} diff --git a/TBF/BenchControl/BenchInfo/iPerl/ComponentCfg.cs b/TBF/BenchControl/BenchInfo/iPerl/ComponentCfg.cs new file mode 100644 index 000000000..4db637b7c --- /dev/null +++ b/TBF/BenchControl/BenchInfo/iPerl/ComponentCfg.cs @@ -0,0 +1,266 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; +using TBF.Resources; + +namespace TBF.BenchControl.BenchInfo.iPerl +{ + /// + /// Holds information identifying the test bench - serializable configuration. + /// + public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ComponentCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); } + + /// + /// Serialized parameters + /// + public string TestBenchName; + public int TestBenchId; + public string Address1; + public string Address2; + public string Address3; + public string Address4; + public string Address5; + public string ApprovalId; + public string ApprovalDate; + public string ApprovedBy; + public RemoteDBUse RemoteDBUse; + public Side Side; + public int MaxTestIndex; /// (MaxPruefindex % 100) value when to reject water meters completely if they are NOK + + /// Private parameterless constructor invoked by all other (public) constructors + ComponentCfg() {} + + public ComponentCfg(string name, IComponentFactory factory) + : this() + { + Factory = factory; + Name = name; + ParentName = string.Empty; + InitializeAll(); + } + + public string ComponentName { get { return Name; } } + + public void InitializeAll() + { + TestBenchName = "1"; + TestBenchId = 1; + + Address1 = string.Empty; + Address2 = string.Empty; + Address3 = string.Empty; + Address4 = string.Empty; + Address5 = string.Empty; + + ApprovalId = string.Empty; + ApprovalDate = string.Empty; + ApprovedBy = string.Empty; + + RemoteDBUse = RemoteDBUse.LocalDBOnly; + Side = Side.Left; + MaxTestIndex = 4; + } + + string[] paramNames = new string[] + { + "Test bench name", + "Test bench ID", + "Address 1", + "Address 2", + "Address 3", + "Address 4", + "Address 5", + "Approval", + "Approval date", + "Approved by", + "Remote DB use", + Strings.Side, + "Max.test index", + }; + public string ParamName(int i) { return paramNames[i]; } + public int ParamsCount() { return paramNames.Length; } + + public IList ParamValues(int i) + { + if (i == 10) + { + IList list = new List(); + for (RemoteDBUse rdbu = 0; rdbu < RemoteDBUse.Count; rdbu++) list.Add(rdbu.ToDescription()); + return list; + } + else if (i == 11) + { + IList list = new List(); + for (Side side = 0; side < Side.Count; side++) list.Add(side.ToDescription()); + return list; + } + else + { + return null; + } + } + + public string ToString(int i) + { + if (i == -1) + { + return string.Format("{0}: Bench name={1}, Bench Id={2}, Procedures={3}", Name, TestBenchName, TestBenchId, RemoteDBUse.ToDescription()); + } + + switch (i) + { + case 0: return TestBenchName; + case 1: return TestBenchId.ToString(); + case 2: return Address1; + case 3: return Address2; + case 4: return Address3; + case 5: return Address4; + case 6: return Address5; + case 7: return ApprovalId; + case 8: return ApprovalDate; + case 9: return ApprovedBy; + case 10: return RemoteDBUse.ToDescription(); + case 11: return Side.ToDescription(); + case 12: return MaxTestIndex.ToString(); + default: return string.Empty; + } + } + + public CfgUpdateFlags UpdateParam(int i, string strValue) + { + switch (i) + { + case 0: TestBenchName = strValue; return CfgUpdateFlags.RestartRqrd; + case 1: TestBenchId = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd; + case 2: Address1 = strValue; return CfgUpdateFlags.RestartRqrd; + case 3: Address2 = strValue; return CfgUpdateFlags.RestartRqrd; + case 4: Address3 = strValue; return CfgUpdateFlags.RestartRqrd; + case 5: Address4 = strValue; return CfgUpdateFlags.RestartRqrd; + case 6: Address5 = strValue; return CfgUpdateFlags.RestartRqrd; + case 7: ApprovalId = strValue; return CfgUpdateFlags.RestartRqrd; + case 8: ApprovalDate = strValue; return CfgUpdateFlags.RestartRqrd; + case 9: ApprovedBy = strValue; return CfgUpdateFlags.RestartRqrd; + + case 10: + for (RemoteDBUse rdbu = 0; rdbu < RemoteDBUse.Count; rdbu++) + { + if (strValue == rdbu.ToDescription()) + { + if (RemoteDBUse != rdbu) + { + RemoteDBUse = rdbu; + return CfgUpdateFlags.RestartRqrd; + } + else + { + return CfgUpdateFlags.None; + } + } + } + return CfgUpdateFlags.Error; + + case 11: + for (Side side = 0; side < Side.Count; side++) + { + if (strValue == side.ToDescription()) + { + if (Side != side) + { + Side = side; + return CfgUpdateFlags.RestartRqrd; + } + else + { + return CfgUpdateFlags.None; + } + } + } + return CfgUpdateFlags.Error; + + case 12: MaxTestIndex = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd; + default: return CfgUpdateFlags.None; + } + } + + public bool ValidateParam(int i, string strValue, out string message) + { + message = string.Empty; + int idummy; + + switch (i) + { + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + return true; + case 1: + case 12: + if (int.TryParse(strValue, out idummy) && (idummy >= 0)) return true; + break; + case 10: + for (RemoteDBUse rdbu = 0; rdbu < RemoteDBUse.Count; rdbu++) + { + if (strValue == rdbu.ToDescription()) return true; + } + return false; + case 11: + for (Side side = 0; side < Side.Count; side++) + { + if (strValue == side.ToDescription()) return true; + } + return false; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(ComponentCfg prms) + { + prms.TestBenchName = this.TestBenchName; + prms.TestBenchId = this.TestBenchId; + prms.Address1 = this.Address1; + prms.Address2 = this.Address2; + prms.Address3 = this.Address3; + prms.Address4 = this.Address4; + prms.Address5 = this.Address5; + prms.ApprovalId = this.ApprovalId; + prms.ApprovalDate = this.ApprovalDate; + prms.ApprovedBy = this.ApprovedBy; + prms.RemoteDBUse = this.RemoteDBUse; + prms.Side = this.Side; + prms.MaxTestIndex = this.MaxTestIndex; + } + + public Config.Entities.IParamsProvider Clone() + { + ComponentCfg pars = new ComponentCfg(); + CopyContentTo(pars); + return pars; + } + + public void UpdateEmbeddedDbEntity() + { + /// Do nothing + } + } +} diff --git a/TBF/BenchControl/BenchInfo/iPerl/ComponentFactory.cs b/TBF/BenchControl/BenchInfo/iPerl/ComponentFactory.cs new file mode 100644 index 000000000..13498dd05 --- /dev/null +++ b/TBF/BenchControl/BenchInfo/iPerl/ComponentFactory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.BenchInfo.iPerl +{ + public class ComponentFactory : IComponentFactory + { + public string ClassName { get { return "BenchInfo.iPerl"; } } + + public void ResetStaticProperties() { Component.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new Component(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new Component(cfg); } + + public IComponentCfg DefaultConfig() { return new ComponentCfg("BenchInfo.iPerl", this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(ComponentCfg.Serializer, component, this); + } + } +} diff --git a/TBF/BenchControl/DataEntry/iPerl/CycleBeginningForm.cs b/TBF/BenchControl/DataEntry/iPerl/CycleBeginningForm.cs index d2de1ad12..d0a272108 100644 --- a/TBF/BenchControl/DataEntry/iPerl/CycleBeginningForm.cs +++ b/TBF/BenchControl/DataEntry/iPerl/CycleBeginningForm.cs @@ -59,13 +59,32 @@ namespace TBF.BenchControl.DataEntry.iPerl orderGroupBox.Text = Strings.Purchase_order; okButton.Text = Strings.OkBtnText; PrepareOrderCombo(orderComboBox); - if (reversedDirection) + + /// + /// Draw an appropriate test bench picture + /// + Config.Entities.Side side = (TBF.BenchControl.Sequences.ProcessData.BenchInfo is BenchInfo.iPerl.Component) + ? (TBF.BenchControl.Sequences.ProcessData.BenchInfo as BenchInfo.iPerl.Component).Side + : Config.Entities.Side.Left; + if (reversedDirection && (side == Config.Entities.Side.Left)) { - pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\reversed_dir.jpg", Program.ExecutableDir, true)); + /// direction L->R (reversed), left side + pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\reversed_dir_left.jpg", Program.ExecutableDir, true)); + } + else if (reversedDirection && (side == Config.Entities.Side.Right)) + { + /// direction L->R (reversed), right side + pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\reversed_dir_right.jpg", Program.ExecutableDir, true)); + } + else if (side == Config.Entities.Side.Right) + { + /// direction R->L (forward), right side + pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\forward_dir_right.jpg", Program.ExecutableDir, true)); } else { - pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\forward_dir.jpg", Program.ExecutableDir, true)); + /// direction R->L (forward), left side + pictureBox.Image = Image.FromFile(string.Format("{0}\\Pictures\\forward_dir_left.jpg", Program.ExecutableDir, true)); } } diff --git a/TBF/BenchControl/GenericDevices/IBenchInfo.cs b/TBF/BenchControl/GenericDevices/IBenchInfo.cs index 3619793ec..182e13113 100644 --- a/TBF/BenchControl/GenericDevices/IBenchInfo.cs +++ b/TBF/BenchControl/GenericDevices/IBenchInfo.cs @@ -19,8 +19,5 @@ namespace TBF.BenchControl.GenericDevices string Address4 { get; } string Address5 { get; } RemoteDBUse RemoteDBUse { get; } -#if ORACLE_DB - int MaxTestIndex { get; } /// (MaxPruefindex % 100) value when to reject water meters completely if they are NOK -#endif } } diff --git a/TBF/BenchControl/TbfComponents.cs b/TBF/BenchControl/TbfComponents.cs index 0766d8a40..a30cefddc 100644 --- a/TBF/BenchControl/TbfComponents.cs +++ b/TBF/BenchControl/TbfComponents.cs @@ -17,7 +17,8 @@ namespace TBF.BenchControl Factories.Add(new BenchInfo.Munich.ComponentFactory()); Factories.Add(new BenchInfo.Extended.ComponentFactory()); - Factories.Add(new Elde.ControlBoardFactory()); + Factories.Add(new BenchInfo.iPerl.ComponentFactory()); + Factories.Add(new Elde.ControlBoardFactory()); Factories.Add(new Elde.CoverTest.Factory()); Factories.Add(new DataEntry.Combined.EntryFormFactory()); Factories.Add(new DataEntry.HeatMeters6.Factory()); diff --git a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs index 74fc4c7b0..8801a3efb 100644 --- a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs +++ b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs @@ -52,6 +52,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication const int Q2CorrFactorsAddrRL = 0x1879; const int Q2CorrFactorsAddrLR = 0x1878; + public static Color DisabledColor = Color.DarkGray; + public static Color OptoAndDirOKColor = Color.Green; + public static Color OptoNokColor = Color.Orange; + public static Color DirNokColor = Color.Red; + private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm)); protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData"); @@ -597,7 +602,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication if (!checkBoxesEditMode && (iperlHeads[i] == null || iperlHeads[i].Disabled)) { checkBoxes[i].Enabled = checkBoxes[i].Checked = ckbState[i] = false; - counters[i].BackColor = Color.DarkGray; + counters[i].BackColor = DisabledColor; messages[i].Text = Strings.Head_was_disabled_by_the_user; } else @@ -618,7 +623,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication for (int i = 0; i < iperlHeads.Count; i++) { iperlHeads[i].FlushedDataCount = 0; - counters[i].BackColor = Color.Red; + counters[i].BackColor = OptoNokColor; } /// @@ -2163,11 +2168,25 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication { if (iperlHeads[i] == null || iperlHeads[i].Disabled) { - counters[i].BackColor = Color.DarkGray; + counters[i].BackColor = DisabledColor; } else { - counters[i].BackColor = (iperlHeads[i].FlushedDataDelta == 0) ? Color.Red : Color.Green; + switch (iperlHeads[i].CheckFlowDirection()) + { + case OptoHeadState.OptoAndDirOK: + counters[i].BackColor = OptoAndDirOKColor; + break; + + case OptoHeadState.DirNok: + counters[i].BackColor = DirNokColor; + break; + + default: + case OptoHeadState.OptoNok: + counters[i].BackColor = OptoNokColor; + break; + } } } diff --git a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs new file mode 100644 index 000000000..409c041bb --- /dev/null +++ b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/FlowDirectionDetection.cs @@ -0,0 +1,102 @@ +/// +/// Copyright (c) 2018 Sensus Slovensko a.s. +/// +using System; +using Config.Entities; + +namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead +{ + public class FlowDirectionDetection + { + readonly int fifoSize = 32; + + Int64[] volumeRawFifo; /// Volume FIFO buffer + Int64[] timestampFifo; /// Timestamp FIFO buffer + /// + int fifoCount; /// Number of valid FIFO items + int fifoIx; /// Index of the next FIFO item + DateTime lastFifoWriteTime; /// Time of the last write to FIFO + + + public FlowDirectionDetection(int fifoSize) + { + this.fifoSize = fifoSize; + volumeRawFifo = new Int64[fifoSize]; + timestampFifo = new Int64[fifoSize]; + ClearFifo(); + } + + + /// + /// Clear FIFO data + /// + public void ClearFifo() + { + fifoCount = 0; + fifoIx = 0; + lastFifoWriteTime = DateTime.MinValue; + } + + + /// + /// Write data to FIFO + /// + /// Volume + /// Time stamp + public void WriteToFifo(Int64 volumeRaw, Int64 timestamp) + { + volumeRawFifo[fifoIx] = volumeRaw; + timestampFifo[fifoIx] = timestamp; + fifoIx = (fifoIx + 1) % fifoSize; + fifoCount = Math.Min(fifoCount + 1, fifoSize); + lastFifoWriteTime = DateTime.Now; + } + + + /// + /// Determine whether there are enough recent FIFO data + /// + /// true when data valid + public bool AreFifoDataValid() + { + return (DateTime.Now.Subtract(lastFifoWriteTime).TotalSeconds <= 2.5) && (fifoCount == fifoSize); + } + + + /// + /// Verify whether the flow direction is correct + /// + /// OptoHeadState.OptoAndDirOK, OptoHeadState.OptoNok or OptoHeadState.DirNok + public OptoHeadState CheckFlowDirection(FlowDir flowDir) + { + if (!AreFifoDataValid()) return OptoHeadState.OptoNok; + + int positiveCount = 0; + int negativeCount = 0; + for (int i = fifoIx; i < fifoIx + fifoSize - 1; i++) + { + if (volumeRawFifo[(i + 1) % fifoSize] - volumeRawFifo[i % fifoSize] > 0) + { + positiveCount++; + } + else if (volumeRawFifo[(i + 1) % fifoSize] - volumeRawFifo[i % fifoSize] < 0) + { + negativeCount++; + } + } + + if ((positiveCount > negativeCount) && flowDir == FlowDir.R_L) + { + return OptoHeadState.OptoAndDirOK; + } + else if ((positiveCount < negativeCount) && flowDir == FlowDir.L_R) + { + return OptoHeadState.OptoAndDirOK; + } + else + { + return OptoHeadState.DirNok; + } + } + } +} diff --git a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index eabf4a988..e3ad8acb1 100644 --- a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2015-2017 Sensus Metering Systems +/// Copyright (c) 2015-2018 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -35,14 +35,15 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead public double PulsesPerLtr { get { return 1000.0; } } public double LtrsPerPulse { get { return 1 / PulsesPerLtr; } } + public float CalibTarget { get { return iperlHeadCfg.ProcParams.CalibTarget; } } + public ushort FactorLimitLo { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitLo; } } + public ushort FactorLimitHi { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitHi; } } + public FlowDir FlowDir { get { return iperlHeadCfg.ProcParams.FlowDir; } } + public LogType LogType { get { return iperlHeadCfg.ProcParams.LogType; } } #if ORACLE_DB public int WMType_ID { get { return iperlHeadCfg.ProcParams.WMType_ID; } } /// Required by Oracle DB public int WMType_Rev { get { return iperlHeadCfg.ProcParams.WMType_Rev; } } /// Required by Oracle DB #endif - public float CalibTarget { get { return iperlHeadCfg.ProcParams.CalibTarget; } } - public ushort FactorLimitLo { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitLo; } } - public ushort FactorLimitHi { get { return (ushort)iperlHeadCfg.ProcParams.FactorLimitHi; } } - public LogType LogType { get { return iperlHeadCfg.ProcParams.LogType; } } /// Properties set by the Begin and the End form public string SerialNr @@ -89,15 +90,18 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead } int resultCode; + /// /// Passed to OptoTelegramRaw.UpdateFromString(...) /// Int64 volumeRawExtLast; Int64 timestampExtLast; + FlowDirectionDetection flowDirectionDetection; public bool PositiveCounting; + /// ConfigStruct of the water meter obtained or updated by iPerlCommunication public ConfigStruct ConfigStruct { @@ -335,7 +339,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead /// Volume of water from the opto telegram /// private Int64 lastVolumeRaw; /// Last read raw volume - private double volumeLtr; /// + private double volumeLtr; private double volumeLtr0; public double VolumeLtrStart { get { return volumeLtrStart; } } /// Test start volume for metrology @@ -384,18 +388,13 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead int lastFlushedDataCount_1; int lastFlushedDataCount; - public int FlushedDataDelta - { - get - { - int retval = Math.Max(flushedDataCount - lastFlushedDataCount, lastFlushedDataCount - lastFlushedDataCount_1); - lastFlushedDataCount_1 = lastFlushedDataCount; - lastFlushedDataCount = flushedDataCount; - return retval; - } - } + public OptoHeadState CheckFlowDirection() + { + return flowDirectionDetection.CheckFlowDirection(FlowDir); + } + /// /// Opto serial port and worker thread related private variables @@ -409,8 +408,10 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead public IperlHead(Generic.IComponentCfg cfg) : base(cfg) - { - ClearData(); + { + flowDirectionDetection = new FlowDirectionDetection(32); /// FIFO size = 32, cca 4 sec. + + ClearData(); iperlHeadCfg = cfg as IperlHeadCfg; @@ -443,7 +444,9 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead Q2CorrRL = 0; optoDataCount = 0; - } + + flowDirectionDetection.ClearFifo(); /// Clear FIFO for flow direction detection + } public void Initialize() { @@ -757,16 +760,18 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead } synchronized = true; } - // CR+LF found and (pos >= OptoTelegramRaw.Length - 2) else if (optoData[optoDataCount].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), optoDataCount, ref volumeRawExtLast, ref timestampExtLast)) { - OptoTelegramRreceived(optoDataCount++, synchronized2); + /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK + flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); + OptoTelegramRreceived(optoDataCount++, synchronized2, volumeRawExtLast, timestampExtLast); synchronized2 = synchronized; allRcvd = allRcvd.Substring(pos + 2); } else { - optoData[optoDataCount].Counter = optoDataCount; + /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) but the telgram was not OK + optoData[optoDataCount].Counter = optoDataCount; optoDataCount++; allRcvd = allRcvd.Substring(pos + 2); } @@ -780,9 +785,10 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead synchronized = true; } // CR+LF found and (pos >= OptoTelegram.Length - 2) - else if (toBeFlushed.UpdateFromStringDummy(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2))) + else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), flushedDataCount, ref volumeRawExtLast, ref timestampExtLast)) { - flushedDataCount++; + flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); + flushedDataCount++; synchronized2 = synchronized; allRcvd = allRcvd.Substring(pos + 2); } @@ -803,13 +809,12 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead } - void OptoTelegramRreceived(int currentIx, bool async) + void OptoTelegramRreceived(int currentIx, bool async, Int64 volumeRawExt, Int64 timestampRawExt) { - OptoTelegramRaw optoTelegram = optoData[currentIx]; telegramIx = currentIx; - lastVolumeRaw = volumeRawExtLast; - lastTimestamp = timestampExtLast; + lastVolumeRaw = volumeRawExt; + lastTimestamp = timestampRawExt; if (volumeLtr == 0 && volumeLtr0 == 0) { @@ -830,8 +835,6 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead { timestampSec = (double)lastTimestamp / 8192.0; } - - //optoDataLogger.InfoFormat("{0} {1} {2} ltr {3} {4}", optoTelegram, lastTimestamp, lastVolumeRaw.ToString("X8"), timestampSec.ToString("F1"), volumeLtr.ToString("F3")); } diff --git a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/ProcParams.cs b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/ProcParams.cs index 4e91817df..259312a49 100644 --- a/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/ProcParams.cs +++ b/TBF/BenchControl/TestMethods/iPerlCommunication/iPerlHead/ProcParams.cs @@ -22,6 +22,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead public float CalibTarget; /// Target error after calibration in [%] public int FactorLimitLo; /// Lower limit for the calibration factor public int FactorLimitHi; /// Upper limit for the calibration factor + public FlowDir FlowDir; /// Initial iPerl flow direction (R_L or L_R) public LogType LogType; #if ORACLE_DB public int WMType_ID; /// Required for Oracle DB: ID_WZTyp in table VT_PRUEFPUNKT_SOLL_SD @@ -35,6 +36,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead CalibTarget = 0; FactorLimitLo = 1000; FactorLimitHi = 8000; + FlowDir = FlowDir.R_L; LogType = LogType.Just_Q1Q2Q3; #if ORACLE_DB WMType_ID = 2; /// Value for iPerl DN15 @@ -48,6 +50,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead "Calib. target [%]", "Calib. factor Lo", "Calib. factor Hi", + "Flow direction", "Log type", #if ORACLE_DB "WMType ID", @@ -66,6 +69,12 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead return retVal; } else if (i == 4) + { + IList retVal = new List(); + for (FlowDir fd = 0; fd < FlowDir.Count; fd++) retVal.Add(fd.ToString()); + return retVal; + } + else if (i == 5) { IList retVal = new List(); for (LogType lt = 0; lt < LogType.Count; lt++) retVal.Add(lt.ToString()); @@ -82,10 +91,11 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead case 1: return CalibTarget.ToString(); case 2: return FactorLimitLo.ToString(); case 3: return FactorLimitHi.ToString(); - case 4: return LogType.ToString(); + case 4: return FlowDir.ToString(); + case 5: return LogType.ToString(); #if ORACLE_DB - case 5: return WMType_ID.ToString(); - case 6: return WMType_Rev.ToString(); + case 6: return WMType_ID.ToString(); + case 7: return WMType_Rev.ToString(); #endif default: return string.Empty; } @@ -105,14 +115,20 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead case 2: FactorLimitLo = int.Parse(strValue); return CfgUpdateFlags.None; case 3: FactorLimitHi = int.Parse(strValue); return CfgUpdateFlags.None; case 4: + for (FlowDir fd = 0; fd < FlowDir.Count; fd++) + { + if (fd.ToString().Equals(strValue)) { FlowDir = fd; return CfgUpdateFlags.None; } + } + break; + case 5: for (LogType lt = 0; lt < LogType.Count; lt++) { if (lt.ToString().Equals(strValue)) { LogType = lt; return CfgUpdateFlags.None; } } break; #if ORACLE_DB - case 5: WMType_ID = int.Parse(strValue); return CfgUpdateFlags.None; - case 6: WMType_Rev = int.Parse(strValue); return CfgUpdateFlags.None; + case 6: WMType_ID = int.Parse(strValue); return CfgUpdateFlags.None; + case 7: WMType_Rev = int.Parse(strValue); return CfgUpdateFlags.None; #endif default: return CfgUpdateFlags.None; } @@ -140,12 +156,14 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead if (int.TryParse(strValue, out iDummy) && iDummy >= 1000 && iDummy <= 8000) return true; break; case 4: + for (FlowDir fd = 0; fd < FlowDir.Count; fd++) if (fd.ToString().Equals(strValue)) return true; + break; + case 5: for (LogType lt = 0; lt < LogType.Count; lt++) if (lt.ToString().Equals(strValue)) return true; break; - #if ORACLE_DB - case 5: /// WMType_ID - case 6: /// WMType_Rev + case 6: /// WMType_ID + case 7: /// WMType_Rev if (int.TryParse(strValue, out iDummy)) return true; break; #endif @@ -164,6 +182,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication.iPerlHead prms.CalibTarget = this.CalibTarget; prms.FactorLimitLo = this.FactorLimitLo; prms.FactorLimitHi = this.FactorLimitHi; + prms.FlowDir = this.FlowDir; prms.LogType = this.LogType; #if ORACLE_DB prms.WMType_ID = this.WMType_ID; diff --git a/TBF/Pictures/forward_dir.jpg b/TBF/Pictures/forward_dir.jpg deleted file mode 100644 index 720d648d7..000000000 Binary files a/TBF/Pictures/forward_dir.jpg and /dev/null differ diff --git a/TBF/Pictures/forward_dir_left.jpg b/TBF/Pictures/forward_dir_left.jpg new file mode 100644 index 000000000..a3f763896 Binary files /dev/null and b/TBF/Pictures/forward_dir_left.jpg differ diff --git a/TBF/Pictures/forward_dir_right.jpg b/TBF/Pictures/forward_dir_right.jpg new file mode 100644 index 000000000..5b964ded6 Binary files /dev/null and b/TBF/Pictures/forward_dir_right.jpg differ diff --git a/TBF/Pictures/reversed_dir.jpg b/TBF/Pictures/reversed_dir.jpg deleted file mode 100644 index ef82a2436..000000000 Binary files a/TBF/Pictures/reversed_dir.jpg and /dev/null differ diff --git a/TBF/Pictures/reversed_dir_left.jpg b/TBF/Pictures/reversed_dir_left.jpg new file mode 100644 index 000000000..70d7a515d Binary files /dev/null and b/TBF/Pictures/reversed_dir_left.jpg differ diff --git a/TBF/Pictures/reversed_dir_right.jpg b/TBF/Pictures/reversed_dir_right.jpg new file mode 100644 index 000000000..1f5d14e60 Binary files /dev/null and b/TBF/Pictures/reversed_dir_right.jpg differ diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index b50528ff5..86668ab4b 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.18.1081.0")] -[assembly: AssemblyFileVersion("2.18.1081.0")] +[assembly: AssemblyVersion("2.18.1082.0")] +[assembly: AssemblyFileVersion("2.18.1082.0")] diff --git a/TBF/Resources/Strings.Designer.cs b/TBF/Resources/Strings.Designer.cs index abbfd0681..c25317ff6 100644 --- a/TBF/Resources/Strings.Designer.cs +++ b/TBF/Resources/Strings.Designer.cs @@ -2058,6 +2058,15 @@ namespace TBF.Resources { } } + /// + /// Looks up a localized string similar to Left. + /// + internal static string Left { + get { + return ResourceManager.GetString("Left", resourceCulture); + } + } + /// /// Looks up a localized string similar to Legalizator. /// @@ -3813,6 +3822,15 @@ namespace TBF.Resources { } } + /// + /// Looks up a localized string similar to Right. + /// + internal static string Right { + get { + return ResourceManager.GetString("Right", resourceCulture); + } + } + /// /// Looks up a localized string similar to ROI Data. /// @@ -4155,6 +4173,15 @@ namespace TBF.Resources { } } + /// + /// Looks up a localized string similar to Side. + /// + internal static string Side { + get { + return ResourceManager.GetString("Side", resourceCulture); + } + } + /// /// Looks up a localized string similar to Simultaneous with next step. /// diff --git a/TBF/Resources/Strings.cs.resx b/TBF/Resources/Strings.cs.resx index 8ab3861e4..58cd4448a 100644 --- a/TBF/Resources/Strings.cs.resx +++ b/TBF/Resources/Strings.cs.resx @@ -1344,4 +1344,13 @@ Mezi opak. - přechod + + Levá + + + Pravá + + + Strana + \ No newline at end of file diff --git a/TBF/Resources/Strings.resx b/TBF/Resources/Strings.resx index 4508958cd..8b14bf556 100644 --- a/TBF/Resources/Strings.resx +++ b/TBF/Resources/Strings.resx @@ -1897,4 +1897,13 @@ Reference mass measurement error + + Left + + + Right + + + Side + \ No newline at end of file diff --git a/TBF/Resources/Strings.sk.resx b/TBF/Resources/Strings.sk.resx index 31721e1d0..daf15a29c 100644 --- a/TBF/Resources/Strings.sk.resx +++ b/TBF/Resources/Strings.sk.resx @@ -147,4 +147,13 @@ Hladina + + Ľavá + + + Pravá + + + Strana + \ No newline at end of file diff --git a/TBF/Screens/ResultsTabPageCtrl.cs b/TBF/Screens/ResultsTabPageCtrl.cs index 9c988cacc..c5fa023cb 100644 --- a/TBF/Screens/ResultsTabPageCtrl.cs +++ b/TBF/Screens/ResultsTabPageCtrl.cs @@ -327,9 +327,9 @@ namespace TBF.Screens Color commonBackColor = wmtrPassed ? Color.LightGreen : (wmtrCompleted ? Color.LightPink : Color.White); #if ORACLE_DB - if (TBF.BenchControl.Sequences.ProcessData.BenchInfo != null) + if (TBF.BenchControl.Sequences.ProcessData.BenchInfo is TBF.BenchControl.BenchInfo.iPerl.Component) { - int maxTrials = TBF.BenchControl.Sequences.ProcessData.BenchInfo.MaxTestIndex; + int maxTrials = (TBF.BenchControl.Sequences.ProcessData.BenchInfo as TBF.BenchControl.BenchInfo.iPerl.Component).MaxTestIndex; if (wmtrCompleted && !wmtrPassed && ((wMtr.Pruefindex % 100) >= maxTrials)) commonBackColor = Color.DarkOrange; } #endif diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 956b3943a..d4e6d068d 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -160,6 +160,9 @@ + + + @@ -1230,6 +1233,7 @@ IperlHeadCfgCtrl.cs + @@ -3081,10 +3085,16 @@ - + Always - + + Always + + + Always + + Always