diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 11a8ac88c..44cc42bb6 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.9.2142.13")] -[assembly: AssemblyFileVersion("3.9.2142.13")] +[assembly: AssemblyVersion("3.9.2142.19")] +[assembly: AssemblyFileVersion("3.9.2142.19")] diff --git a/TBF/Resources/Strings.Designer.cs b/TBF/Resources/Strings.Designer.cs index 0715fe51c..2fb34f8b2 100644 --- a/TBF/Resources/Strings.Designer.cs +++ b/TBF/Resources/Strings.Designer.cs @@ -4307,6 +4307,15 @@ namespace TBF.Resources { } } + /// + /// Looks up a localized string similar to Project number. + /// + internal static string Project_number { + get { + return ResourceManager.GetString("Project_number", resourceCulture); + } + } + /// /// Looks up a localized string similar to Prompt. /// diff --git a/TBF/Resources/Strings.cs.resx b/TBF/Resources/Strings.cs.resx index 08532570d..295ec3d55 100644 --- a/TBF/Resources/Strings.cs.resx +++ b/TBF/Resources/Strings.cs.resx @@ -1752,4 +1752,7 @@ Napětí + + Projtové číslo + \ No newline at end of file diff --git a/TBF/Resources/Strings.de.resx b/TBF/Resources/Strings.de.resx index 0b7dc0842..588038bb6 100644 --- a/TBF/Resources/Strings.de.resx +++ b/TBF/Resources/Strings.de.resx @@ -2217,4 +2217,7 @@ Spannung + + Projektnummer + \ No newline at end of file diff --git a/TBF/Resources/Strings.es.resx b/TBF/Resources/Strings.es.resx index 067be8ac8..c036312c9 100644 --- a/TBF/Resources/Strings.es.resx +++ b/TBF/Resources/Strings.es.resx @@ -120,4 +120,7 @@ Activity in Spanish + + Número de proyecto + \ No newline at end of file diff --git a/TBF/Resources/Strings.fr.resx b/TBF/Resources/Strings.fr.resx index 5c9376790..d4fa5769c 100644 --- a/TBF/Resources/Strings.fr.resx +++ b/TBF/Resources/Strings.fr.resx @@ -2016,4 +2016,7 @@ Tension + + Numéro de projet + \ No newline at end of file diff --git a/TBF/Resources/Strings.it.resx b/TBF/Resources/Strings.it.resx index 5f8df07f1..4fdac482d 100644 --- a/TBF/Resources/Strings.it.resx +++ b/TBF/Resources/Strings.it.resx @@ -1785,4 +1785,7 @@ Voltaggio + + Numero del progetto + \ No newline at end of file diff --git a/TBF/Resources/Strings.pl.resx b/TBF/Resources/Strings.pl.resx index 11f889945..5a351ca4b 100644 --- a/TBF/Resources/Strings.pl.resx +++ b/TBF/Resources/Strings.pl.resx @@ -1692,4 +1692,7 @@ Napięcie + + Numer projektu + \ No newline at end of file diff --git a/TBF/Resources/Strings.resx b/TBF/Resources/Strings.resx index acd994b62..ecbc4fb1f 100644 --- a/TBF/Resources/Strings.resx +++ b/TBF/Resources/Strings.resx @@ -949,6 +949,9 @@ Purchase order + + Project number + Ambient humidity diff --git a/TBF/Resources/Strings.ro.resx b/TBF/Resources/Strings.ro.resx index 70267a5dd..69c5fd0ea 100644 --- a/TBF/Resources/Strings.ro.resx +++ b/TBF/Resources/Strings.ro.resx @@ -837,4 +837,7 @@ Voltage + + Numărul proiectului + \ No newline at end of file diff --git a/TBF/Resources/Strings.ru.resx b/TBF/Resources/Strings.ru.resx index 005d5a1fc..c823348c7 100644 --- a/TBF/Resources/Strings.ru.resx +++ b/TBF/Resources/Strings.ru.resx @@ -1605,4 +1605,7 @@ Voltage + + Номер проекта + \ No newline at end of file diff --git a/TBF/Resources/Strings.sk.resx b/TBF/Resources/Strings.sk.resx index 4fc61a8a2..257d50212 100644 --- a/TBF/Resources/Strings.sk.resx +++ b/TBF/Resources/Strings.sk.resx @@ -241,4 +241,7 @@ Cesty + + Číslo projektu + \ No newline at end of file diff --git a/TBF/Rig/DataEntry/Combined/EntryForm.cs b/TBF/Rig/DataEntry/Combined/EntryForm.cs index 7f3860fd5..eb4a64af8 100644 --- a/TBF/Rig/DataEntry/Combined/EntryForm.cs +++ b/TBF/Rig/DataEntry/Combined/EntryForm.cs @@ -109,6 +109,7 @@ namespace TBF.Rig.DataEntry.Combined /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/DEItem.cs b/TBF/Rig/DataEntry/DEItem.cs index a338c9130..a07e26c37 100644 --- a/TBF/Rig/DataEntry/DEItem.cs +++ b/TBF/Rig/DataEntry/DEItem.cs @@ -66,6 +66,7 @@ namespace TBF.Rig.DataEntry Start, End, Both, + Collect, } /// diff --git a/TBF/Rig/DataEntry/HeatMeters12/EntryForm.cs b/TBF/Rig/DataEntry/HeatMeters12/EntryForm.cs index 52830370c..572280835 100644 --- a/TBF/Rig/DataEntry/HeatMeters12/EntryForm.cs +++ b/TBF/Rig/DataEntry/HeatMeters12/EntryForm.cs @@ -124,6 +124,7 @@ namespace TBF.Rig.DataEntry.HeatMeters12 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/HeatMeters6/EntryForm.cs b/TBF/Rig/DataEntry/HeatMeters6/EntryForm.cs index 13d9a6d62..97965e1f4 100644 --- a/TBF/Rig/DataEntry/HeatMeters6/EntryForm.cs +++ b/TBF/Rig/DataEntry/HeatMeters6/EntryForm.cs @@ -123,6 +123,7 @@ namespace TBF.Rig.DataEntry.HeatMeters6 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/S620/EntryForm.cs b/TBF/Rig/DataEntry/S620/EntryForm.cs index 7fd06bf80..d3d562f4d 100644 --- a/TBF/Rig/DataEntry/S620/EntryForm.cs +++ b/TBF/Rig/DataEntry/S620/EntryForm.cs @@ -117,6 +117,7 @@ namespace TBF.Rig.DataEntry.S620 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/Single/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Single/EntryFormNoStartEnd.cs index b4ea70111..7aba67818 100644 --- a/TBF/Rig/DataEntry/Single/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Single/EntryFormNoStartEnd.cs @@ -109,6 +109,7 @@ namespace TBF.Rig.DataEntry.Single /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/Standard12/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Standard12/EntryFormNoStartEnd.cs index 9bb357c07..fa208c85a 100644 --- a/TBF/Rig/DataEntry/Standard12/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Standard12/EntryFormNoStartEnd.cs @@ -109,6 +109,7 @@ namespace TBF.Rig.DataEntry.Standard12 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/Standard24/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Standard24/EntryFormNoStartEnd.cs index d351d98c6..d7a0d5572 100644 --- a/TBF/Rig/DataEntry/Standard24/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Standard24/EntryFormNoStartEnd.cs @@ -122,6 +122,8 @@ namespace TBF.Rig.DataEntry.Standard24 this.waterMeters = waterMeters; return this; } + + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/Standard48/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Standard48/EntryFormNoStartEnd.cs index 5b57d3949..1a784a1d6 100644 --- a/TBF/Rig/DataEntry/Standard48/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Standard48/EntryFormNoStartEnd.cs @@ -109,6 +109,7 @@ namespace TBF.Rig.DataEntry.Standard48 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/Standard6/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Standard6/EntryFormNoStartEnd.cs index a05b7c7b1..642c64b9a 100644 --- a/TBF/Rig/DataEntry/Standard6/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Standard6/EntryFormNoStartEnd.cs @@ -105,6 +105,7 @@ namespace TBF.Rig.DataEntry.Standard6 /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/StandardCamera/EntryForm.cs b/TBF/Rig/DataEntry/StandardCamera/EntryForm.cs index 56f82b663..4a714b4ff 100644 --- a/TBF/Rig/DataEntry/StandardCamera/EntryForm.cs +++ b/TBF/Rig/DataEntry/StandardCamera/EntryForm.cs @@ -186,6 +186,7 @@ namespace TBF.Rig.DataEntry.StandardCamera /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.cs index b269c63b9..fe93ee1c8 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.cs @@ -108,8 +108,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder }; enabledComboBoxesN = new List(); - - + completed = false; StartForceCloseHandler(); } @@ -169,6 +168,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void CycleBeginningForm_Load(object sender, EventArgs e) { Localize(); + CreateTooltipToInfoAboutLock(); if (orderGroupBox.Visible) { @@ -191,6 +191,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder enabledComboBoxes.Add(comboBoxes[i]); enabledComboBoxesN.Add(comboNumbers[i]); } + foreach (ComboBox cbxN in enabledComboBoxesN) { cbxN.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.comboBoxNX_KeyPress); @@ -214,7 +215,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder void Localize() { Text = Strings.Data; - orderGroupBox.Text = Strings.Purchase_order; + orderGroupBox.Text = Strings.Project_number; for (int i = 0; i < textBoxesCount; i++) { labels[i].Text = Strings.Serial_number + " " + (i + 1).ToString(); @@ -290,6 +291,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } lastComboBoxSerialNo = 0; + EnableOrderCheckBox(true); } @@ -1349,6 +1351,22 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void buttonChooseBox_Click(object sender, EventArgs e) { Choose(); + EnableOrderCheckBox(false); + } + + private void EnableOrderCheckBox(bool enable) + { + if (orderComboBox.Text != null && !orderComboBox.Text.IsEmpty()) + { + orderComboBox.Enabled = enable; + //set Tooltip on + toolTip.Active = !enable; + } + else if (orderComboBox.Text != null && orderComboBox.Text.IsEmpty()) + { + orderComboBox.Enabled = true; + toolTip.Active = false; + } } @@ -1522,9 +1540,10 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder //enable behaviour type bool addOnEndOnly = false; - int countOfFreeBoxes = addOnEndOnly ? (enabledComboBoxes.Count - (LastOccupiedBox()+1)) : CountFreeBoxes(); + int countOfFreeBoxes = + addOnEndOnly ? (enabledComboBoxes.Count - (LastOccupiedBox() + 1)) : CountFreeBoxes(); - if (countOfFreeBoxes /// Process all KeyPress included in list of enabledComboBoxesN /// @@ -2356,16 +2375,17 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder e.Handled = true; // Mark the event as handled (optional) //Jump focus on Box purchaseBoxComboBox.Focus(); - }else if (e.KeyChar == '-') + } + else if (e.KeyChar == '-') { e.Handled = true; // Mark the event as handled (optional) //Do nothing - highest element } } - + private void ProcessKeyPressBox(object sender, KeyPressEventArgs e) { - if (e.KeyChar == '+' ) + if (e.KeyChar == '+') { e.Handled = true; // Mark the event as handled (optional) //Jump focus on Firs comboBoxN1 / buttonChooseBox if is visible @@ -2377,30 +2397,31 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder { comboBoxN1.Focus(); } - - }else if (e.KeyChar == '-') + } + else if (e.KeyChar == '-') { e.Handled = true; // Mark the event as handled (optional) //Jump focus on Firs comboBoxN1 orderComboBox.Focus(); } } - + private void ProcessKeyPressButton(object sender, KeyPressEventArgs e) { - if (e.KeyChar == '+' ) + if (e.KeyChar == '+') { e.Handled = true; // Mark the event as handled (optional) //Jump focus on Firs comboBoxN1 comboBoxN1.Focus(); - }else if (e.KeyChar == '-') + } + else if (e.KeyChar == '-') { e.Handled = true; // Mark the event as handled (optional) //Jump focus on Firs comboBoxN1 purchaseBoxComboBox.Focus(); } } - + private void orderComboBox_KeyPress(object sender, KeyPressEventArgs e) { ProcessKeyPressOrder(sender, e); @@ -2416,6 +2437,64 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder ProcessKeyPressButton(sender, e); } - + // Create a ToolTip object (this can also be done via the designer) + private ToolTip toolTip = new ToolTip(); + + private void CreateTooltipToInfoAboutLock() + { + // Set the ToolTip for the disabled CheckBox + toolTip.SetToolTip(orderComboBox, " If is Locked by Order items! To unlock use button Clear, please!"); + + toolTip.AutoPopDelay = 5000; // The time (in milliseconds) the tooltip stays visible + toolTip.InitialDelay = 500; // The time (in milliseconds) before the tooltip appears + toolTip.ReshowDelay = 500; // The time (in milliseconds) before subsequent tooltips appear + toolTip.ShowAlways = true; // Ensures the tooltip shows even when the control is disabled + toolTip.Active = true; + } + + private void orderComboBox_Click(object sender, EventArgs e) + { + if (orderComboBox.Enabled == false && orderGroupBox.Enabled == true) + { + MessageBox.Show(this, + "To unlock use button Clear, please!", + "Locked by Order items!", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + } + + private void orderComboBox_MouseMove(object sender, MouseEventArgs e) + { + /*ComboBox comboBox = sender as ComboBox; + if (comboBox != null && comboBox.Enabled == false) + { + toolTip.Show("To unlock use button Clear, please!", comboBox, 0, comboBox.Height); + }*/ + } + + private void orderComboBox_MouseLeave(object sender, EventArgs e) + { + /* ComboBox comboBox = sender as ComboBox; + if (comboBox != null && comboBox.Enabled == false) + { + toolTip.Hide(comboBox); + }*/ + } + + private void orderGroupBox_MouseHover(object sender, EventArgs e) + { + /* // Get the mouse position in screen coordinates + Point mousePositionInScreen = Cursor.Position; + // Check if the mouse is over the disabled ComboBox + if (mousePositionInScreen != null && orderComboBox.Enabled == false && + orderComboBox.Bounds.Contains(mousePositionInScreen)) + { + toolTip.Show("To unlock use button Clear, please!", orderComboBox, 0, orderComboBox.Height); + //toolTip.Hide(comboBox); + } + else if (orderComboBox.Enabled == false) + { + toolTip.Hide(orderComboBox); + }*/ + } } } \ No newline at end of file diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.designer.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.designer.cs index 66686d173..4849bf31c 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.designer.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/CycleBeginningForm.designer.cs @@ -250,6 +250,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder this.orderGroupBox.ForeColor = System.Drawing.Color.Black; this.orderGroupBox.Name = "orderGroupBox"; this.orderGroupBox.TabStop = false; + this.orderGroupBox.MouseHover += new System.EventHandler(this.orderGroupBox_MouseHover); // // buttonChooseBox // @@ -273,7 +274,10 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder resources.ApplyResources(this.orderComboBox, "orderComboBox"); this.orderComboBox.Name = "orderComboBox"; this.orderComboBox.SelectedIndexChanged += new System.EventHandler(this.orderComboBox_SelectedIndexChanged); + this.orderComboBox.Click += new System.EventHandler(this.orderComboBox_Click); this.orderComboBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.orderComboBox_KeyPress); + this.orderComboBox.MouseLeave += new System.EventHandler(this.orderComboBox_MouseLeave); + this.orderComboBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.orderComboBox_MouseMove); // // clearButton // diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs index 830e64f38..d91447a33 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs @@ -113,14 +113,20 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder public string TestStartImgName(int wmNr0, string testName) { - if (waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) return string.Empty; + if (waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) + { + return string.Format("{0}-start.bmp", testName).Replace(' ','_'); + } return string.Format("{0}-start.bmp", testName).Replace(' ','_'); } public string TestEndImgName(int wmNr0, string testName) { - if (waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) return string.Empty; + if (waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) + { + return string.Format("{0}-end.bmp", testName).Replace(' ','_'); + } return string.Format("{0}-end.bmp", testName).Replace(' ','_'); } @@ -133,6 +139,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder TestStartStates, TestEndStates, DeferredTestEval, + TestBothStates, } CurrentOp currentOp; @@ -187,6 +194,25 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + /// + /// this will be used for collect data on the end = no working as START/END but as both + /// + /// + /// + /// + /// + /// + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, + double errLimHi) + { + currentOp = CurrentOp.TestBothStates; + this.regReaders = regReaders; + this.refVolume = refVolume; + this.errLimLo = errLimLo; + this.errLimHi = errLimHi; + return this; + } + /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) { @@ -245,6 +271,17 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder refVolume, errLimLo, errLimHi); modelessDlg.Show(); } + + void OpenTestBothStatesDlg(EntryForm myRef) + { + log.Debug("-- OpenTestBothStatesDlg --"); + string ocrMessage; + var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage); + myRef.modelessDlg = new TestStartEndForm(TBF.Data.WMsCount, myRef.regReaders, ocr, ocrMessage, myRef.OcrStream, + startImages, wmStartState, wmStartStateStr, endImages, disabled, + refVolume, errLimLo, errLimHi, true); + modelessDlg.Show(); + } /// void OpenDeferredTestEvalDlg(EntryForm myRef) { @@ -323,17 +360,21 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } break; - case CurrentOp.TestStartStates: - Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestStartStatesDlg), this); - break; + case CurrentOp.TestStartStates: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestStartStatesDlg), this); + break; - case CurrentOp.TestEndStates: - Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestEndStatesDlg), this); - break; + case CurrentOp.TestEndStates: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestEndStatesDlg), this); + break; - case CurrentOp.DeferredTestEval: - Program.MainWnd.Invoke(new EntryFormDlgt(OpenDeferredTestEvalDlg), this); - break; + case CurrentOp.TestBothStates: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestBothStatesDlg), this); + break; + + case CurrentOp.DeferredTestEval: + Program.MainWnd.Invoke(new EntryFormDlgt(OpenDeferredTestEvalDlg), this); + break; } } @@ -409,6 +450,20 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder wmEndState[i] = dlg.WMEndState[i]; } } + } + else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestBothStates) + { + /// Fixed start/stop: test end + TestStartEndForm dlg = (modelessDlg as TestStartEndForm); + if (dlg != null) + { + for (int i = 0; i < dlg.WaterMetersCount; i++) + { + wmStartState[i] = dlg.WMStartState[i]; + wmStartStateStr[i] = dlg.WMStartStateStr[i]; + wmEndState[i] = dlg.WMEndState[i]; + } + } } else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.DeferredTestEval) { diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs index c4de19515..e1edd16a4 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs @@ -222,6 +222,30 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder ConstructorCommon(regReaders); } + + /// + /// Constructor to fill in end states + /// + /// Number of water meters + /// Array with register reader components + /// Cognex wrapper object performing OCR or null + /// Array with paths to end images + /// Array with start states in default volume units (liters) + /// Information entered on test start + /// Information from CycleBeginningForm about availability of water meters + /// Reference volume, it is used to verify the end state, show/hide exclamation if necessary + /// Error limit low, it is used to verify the end state, show/hide exclamation if necessary + /// Error limit high, it is used to verify the end state, show/hide exclamation if necessary + public TestStartEndForm(int waterMetersCount, IRegReader[] regReaders, OcrVidi ocrVidi, string ocrMessage, string streamName, + string[] startImages, double[] wmStartState, string[] wmStartStateStr, string[] endImages, + bool[] disabled, double refVolume, double errLimLo, double errLimHi, Boolean both) + : this(waterMetersCount, regReaders, ocrVidi, ocrMessage, + streamName, + startImages, endImages, disabled, + refVolume, errLimLo, errLimHi) + { + mode = both? Tst.Both : Tst.Collect; + } /// /// Constructor for deferred evaluation, to fill in both start- and end-states @@ -338,6 +362,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder switch (mode) { case Tst.Start: + checkBoxEnableStartBox.Visible = false; if ((disabled != null && wmPos <= disabled.Length && disabled[wmPos - 1]) || (regReaders != null && wmPos <= regReaders.Length && regReaders[wmPos - 1] == null)) { @@ -346,11 +371,15 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder else { startTextBoxes[i].Enabled = true; + + StartTextBox_EnableHanders(i); + enabledTextBoxes.Add(startTextBoxes[i]); } break; case Tst.End: + checkBoxEnableStartBox.Visible = true; if ((disabled != null && wmPos <= disabled.Length && disabled[wmPos - 1]) || (regReaders != null && wmPos <= regReaders.Length && regReaders[wmPos - 1] == null)) { @@ -359,15 +388,23 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } else { - startTextBoxes[i].Enabled = true; + startTextBoxes[i].Enabled = false; startTextBoxes[i].Text = WMStartStateStr[wmPos - 1]; + StartTextBox_EnableHanders(i); endTextBoxes[i].Enabled = true; enabledTextBoxes.Add(startTextBoxes[i]); enabledTextBoxes.Add(endTextBoxes[i]); + EndTextBox_EnableHanders(i); + UpdateStartTextBoxesByChecker(checkBoxEnableStartBox.Checked); } break; + case Tst.Collect: + checkBoxEnableStartBox.Visible = false; + // Fall-through to the next case by explicitly calling Tst.Both logic + goto case Tst.Both; case Tst.Both: + checkBoxEnableStartBox.Visible = false; if ((disabled != null && wmPos <= disabled.Length && disabled[wmPos - 1]) || (regReaders != null && wmPos <= regReaders.Length && regReaders[wmPos - 1] == null)) { @@ -380,9 +417,12 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder endTextBoxes[i].Enabled = true; enabledTextBoxes.Add(startTextBoxes[i]); enabledTextBoxes.Add(endTextBoxes[i]); + StartTextBox_EnableHanders(i); + EndTextBox_EnableHanders(i); } break; } + } } @@ -414,7 +454,27 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } } - private void TestStartEndForm_FormClosed(object sender, FormClosedEventArgs e) + /// + /// Enables the event handlers for the StartTextBox control. + /// + /// The index of the StartTextBox control. + private void StartTextBox_EnableHanders(int i) + { + startTextBoxes[i].AcceptsTabChanged += new System.EventHandler(this.startTextBoxX_AcceptsTabChanged); + startTextBoxes[i].TextChanged += new System.EventHandler(this.startTextBoxX_TextChanged); + startTextBoxes[i].KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.startTextBoxX_KeyPress); + startTextBoxes[i].MouseDown += new System.Windows.Forms.MouseEventHandler(this.startTextBoxX_MouseDown); + } + + private void EndTextBox_EnableHanders(int i) + { + endTextBoxes[i].AcceptsTabChanged += new System.EventHandler(this.endTextBoxX_AcceptsTabChanged); + endTextBoxes[i].TextChanged += new System.EventHandler(this.endTextBoxX_TextChanged); + endTextBoxes[i].KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.endTextBoxX_KeyPress); + endTextBoxes[i].MouseDown += new System.Windows.Forms.MouseEventHandler(this.endTextBoxX_AcceptsTabChanged); + } + + private void TestStartEndForm_FormClosed(object sender, FormClosedEventArgs e) { if (imageProcessingThread != null && imageProcessingThread.IsAlive) { @@ -635,6 +695,24 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// Make an exclamation mark visible if out of range. /// Similar event handler is implemented for all endTextBoxes (1..24). /// + + private void startTextBoxX_TextChanged(object sender, EventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + var physPos = PhysPos(clickedTextBox, startTextBoxes); + + if (physPos < 0) + { + return; + } + + UpdateExclamation(physPos); + } + } + private void startTextBox1_TextChanged(object sender, EventArgs e) { UpdateExclamation(0); } private void startTextBox2_TextChanged(object sender, EventArgs e) { UpdateExclamation(1); } private void startTextBox3_TextChanged(object sender, EventArgs e) { UpdateExclamation(2); } @@ -660,6 +738,23 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void startTextBox23_TextChanged(object sender, EventArgs e) { UpdateExclamation(22); } private void startTextBox24_TextChanged(object sender, EventArgs e) { UpdateExclamation(23); } + private void endTextBoxX_TextChanged(object sender, EventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + var physPos = PhysPos(clickedTextBox, startTextBoxes); + + if (physPos < 0) + { + return; + } + + UpdateExclamation(physPos); + } + } + private void endTextBox1_TextChanged(object sender, EventArgs e) { UpdateExclamation(0); } private void endTextBox2_TextChanged(object sender, EventArgs e) { UpdateExclamation(1); } private void endTextBox3_TextChanged(object sender, EventArgs e) { UpdateExclamation(2); } @@ -687,7 +782,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// void UpdateExclamation(int uiCtrlPos) /// uiCtrlPos = 0 .. TextBoxesCount-1 { - exclamations[uiCtrlPos].Visible = false; + //exclamations[uiCtrlPos].Visible = false; /*if ((mode == Tst.End) || (mode == Tst.Both)) { @@ -718,6 +813,16 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } + private void startTextBoxX_KeyPress(object sender, KeyPressEventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + ProcKeyPress(sender, e, clickedTextBox); + } + } + private void startTextBox1_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, startTextBox1); } private void startTextBox2_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, startTextBox2); } private void startTextBox3_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, startTextBox3); } @@ -743,6 +848,16 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void startTextBox23_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, startTextBox23); } private void startTextBox24_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, startTextBox24); } + + private void endTextBoxX_KeyPress(object sender, KeyPressEventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + ProcKeyPress(sender, e, clickedTextBox); + } + } private void endTextBox1_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, endTextBox1); } private void endTextBox2_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, endTextBox2); } private void endTextBox3_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, endTextBox3); } @@ -791,7 +906,13 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder if (enabledTextBoxes[i] == currentFocusOwner) { /// Change focus to the next enabled text box - var currentTextBox = enabledTextBoxes[(i + 1) % enabledTextBoxes.Count]; + int nextItem = i + 1; + var currentTextBox = enabledTextBoxes[(nextItem) % enabledTextBoxes.Count]; + if (currentTextBox.Enabled == false) // Try get next - new behaviour - disable start boxes + { + + currentTextBox = enabledTextBoxes[(nextItem + 1) % enabledTextBoxes.Count]; + } currentTextBox.Focus(); /// Load the respective image @@ -821,6 +942,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } + private void startTextBox1_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 0); } private void startTextBox2_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 1); } private void startTextBox3_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 2); } @@ -845,6 +967,57 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void startTextBox22_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 21); } private void startTextBox23_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 22); } private void startTextBox24_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.Start, 23); } + + private void startTextBoxX_AcceptsTabChanged(object sender, EventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + var physPos = PhysPos(clickedTextBox, startTextBoxes); + + if (physPos < 0) + { + return; + } + + LoadImage(sender, Tst.Start, physPos); + } + } + + private void startTextBoxX_MouseDown(object sender, MouseEventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + var physPos = PhysPos(clickedTextBox, startTextBoxes); + + if (physPos < 0) + { + return; + } + + LoadImage(sender, Tst.Start, physPos); + } + } + + private int PhysPos(TextBox clickedTextBox, TextBox[] textBoxes) + { + int physPos = -1; + for (int i =0; i< textBoxes.Length; i++) + { + + if (textBoxes[i].Equals(clickedTextBox)) + { + physPos = i; + } + } + + return physPos; + } + + private void startTextBox1_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.Start, 0); } private void startTextBox2_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.Start, 1); } private void startTextBox3_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.Start, 2); } @@ -870,6 +1043,23 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void startTextBox23_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.Start, 22); } private void startTextBox24_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.Start, 23); } + + private void endTextBoxX_AcceptsTabChanged(object sender, EventArgs e) + { + // Cast the sender object to TextBox + TextBox clickedTextBox = sender as TextBox; + if (clickedTextBox != null) + { + var physPos = PhysPos(clickedTextBox, startTextBoxes); + + if (physPos < 0) + { + return; + } + + LoadImage(sender, Tst.End, physPos); + } + } private void endTextBox1_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 0); } private void endTextBox2_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 1); } private void endTextBox3_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 2); } @@ -1108,6 +1298,33 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder pictureBox1.Image = tempBmp; } + + private void checkBoxEnableStartBox_CheckStateChanged(object sender, EventArgs e) + { + CheckBox checkBox = sender as CheckBox; + bool EnableStartBox = false; + if (checkBox != null) + { + if (checkBox.Visible == false) + { + return; + } + + EnableStartBox = checkBox.Checked; + UpdateStartTextBoxesByChecker(EnableStartBox); + } + } + + private void UpdateStartTextBoxesByChecker(bool EnableStartBox) + { + foreach(TextBox startTextBox in startTextBoxes) + { + if (startTextBox.Visible && enabledTextBoxes.Contains(startTextBox)) + { + startTextBox.Enabled = EnableStartBox; + } + } + } } } diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.designer.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.designer.cs index 3dca08f43..5c8c28ae7 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.designer.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.designer.cs @@ -232,6 +232,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder this.startTextBox25 = new System.Windows.Forms.TextBox(); this.endTextBox25 = new System.Windows.Forms.TextBox(); this.label25 = new System.Windows.Forms.Label(); + this.checkBoxEnableStartBox = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.SuspendLayout(); // @@ -2784,6 +2785,17 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder this.label25.Text = "25"; this.label25.Visible = false; // + // checkBoxEnableStartBox + // + this.checkBoxEnableStartBox.Font = new System.Drawing.Font("Verdana", 12F); + this.checkBoxEnableStartBox.Location = new System.Drawing.Point(1351, 45); + this.checkBoxEnableStartBox.Name = "checkBoxEnableStartBox"; + this.checkBoxEnableStartBox.Size = new System.Drawing.Size(409, 67); + this.checkBoxEnableStartBox.TabIndex = 204; + this.checkBoxEnableStartBox.Text = "Enable Start Boxes"; + this.checkBoxEnableStartBox.UseVisualStyleBackColor = true; + this.checkBoxEnableStartBox.CheckStateChanged += new System.EventHandler(this.checkBoxEnableStartBox_CheckStateChanged); + // // TestStartEndForm // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); @@ -2791,6 +2803,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder this.AutoScroll = true; this.BackColor = System.Drawing.Color.DarkGray; this.ClientSize = new System.Drawing.Size(2061, 1295); + this.Controls.Add(this.checkBoxEnableStartBox); this.Controls.Add(this.exclamation48); this.Controls.Add(this.startTextBox48); this.Controls.Add(this.endTextBox48); @@ -3005,8 +3018,8 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder this.PerformLayout(); } + private System.Windows.Forms.CheckBox checkBoxEnableStartBox; - private System.Windows.Forms.TextBox startTextBox35; diff --git a/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs index 7775ffb26..008af64fa 100644 --- a/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs +++ b/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs @@ -195,6 +195,7 @@ namespace TBF.Rig.DataEntry.Uni { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowDeferredTestEvalFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/DataEntry/iPerl/EntryForm.cs b/TBF/Rig/DataEntry/iPerl/EntryForm.cs index 7f918e8b4..51f3dbd92 100644 --- a/TBF/Rig/DataEntry/iPerl/EntryForm.cs +++ b/TBF/Rig/DataEntry/iPerl/EntryForm.cs @@ -100,6 +100,7 @@ namespace TBF.Rig.DataEntry.iPerl /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/GenericDevices/IHasWMStatesForm.cs b/TBF/Rig/GenericDevices/IHasWMStatesForm.cs index 1f9fb5956..057b33d0e 100644 --- a/TBF/Rig/GenericDevices/IHasWMStatesForm.cs +++ b/TBF/Rig/GenericDevices/IHasWMStatesForm.cs @@ -40,5 +40,11 @@ namespace TBF.Rig.GenericDevices /// /// Operation to be used in the sequence IOperation ShowTestEndFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi); + + /// + /// Displays form at the end of all tests the test to enter water meter start start. + /// + /// Operation to be used in the sequence + IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi); } } diff --git a/TBF/Rig/GenericDevices/IRestAPIAdapter.cs b/TBF/Rig/GenericDevices/IRestAPIAdapter.cs new file mode 100644 index 000000000..9f2e61619 --- /dev/null +++ b/TBF/Rig/GenericDevices/IRestAPIAdapter.cs @@ -0,0 +1,7 @@ +namespace TBF.Rig.GenericDevices +{ + public interface IRestAPIAdapter : TBF.Rig.Generic.IComponent + { + string Path { get; } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/ApiMessageOp.cs b/TBF/Rig/Network/RestAPI/ApiMessageOp.cs new file mode 100644 index 000000000..5a6210802 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/ApiMessageOp.cs @@ -0,0 +1,99 @@ +using System; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using TBF.Rig.GenericDevices; +using TBF.Rig.Network.RestAPI.facade; + +namespace TBF.Rig.Network.RestAPI +{ + public class ApiMessageOp : IOperation + { + private static readonly HttpClient httpClient = new HttpClient(); + private HttpRequestMessage httpRequest; + private bool isFinished = false; + private int timeoutCounter = 0; + private Event holdEvent = Event.Starting; + + private IRestAPIAdapter restApiAdapter; + private ApiDataLoad apiDataLoad; + + public ApiMessageOp(IRestAPIAdapter restApiAdapter, ApiDataLoad apiDataLoad) + { + this.restApiAdapter = restApiAdapter; + this.apiDataLoad = apiDataLoad; + } + + + public void Start() + { + httpRequest = new HttpRequestMessage(HttpMethod.Post, restApiAdapter.Path); // An exemplar URL is used here + holdEvent = Event.Starting; + } + + public Event Run() + { + if (isFinished) + { + return Event.Done; + } + + if (timeoutCounter >= 3000) + { + return Event.Abort; + } + + /** + * send asynchro request only one time and wait to result or timeout + */ + if (holdEvent != Event.Starting) + { + return holdEvent; + } + + //I must have what to send and where to send + if (!(restApiAdapter == null || apiDataLoad == null)) + { + httpRequest.Content = new StringContent(apiDataLoad.getJsonRequestBody(), Encoding.UTF8, "application/json"); + + _ = SendRequestAsync(); + + holdEvent = Event.Busy; + return holdEvent; + } + + holdEvent = Event.Error; + return holdEvent; + } + + private async Task SendRequestAsync() + { + try + { + var response = await httpClient.SendAsync(httpRequest); + if (response.IsSuccessStatusCode) + { + isFinished = true; + holdEvent = Event.Done; + } + else + { + timeoutCounter += 1000; + await Task.Delay(1000); // Counting timeout + } + } + catch (Exception) + { + timeoutCounter += 1000; + await Task.Delay(1000); // Counting timeout + holdEvent = Event.Error; + } + } + + public void Stop() + { + httpClient.Dispose(); + holdEvent = Event.Done; + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/Factory.cs b/TBF/Rig/Network/RestAPI/Factory.cs new file mode 100644 index 000000000..93cb6fba7 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/Factory.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Config.Entities; +using TBF.Rig.Generic; + +namespace TBF.Rig.Network.RestAPI +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(8); } } + public override string ToString() { return ClassName; } + + public IComponent DummyComponent() { return new RestAPIAdapter(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new RestAPIAdapter(cfg); } + + public IComponentCfg DefaultConfig() { return new RestAPIadapterCfg(this.GetType().Namespace.Substring(8), this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(RestAPIadapterCfg.Serializer, component, this); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/RestAPIAdapter.cs b/TBF/Rig/Network/RestAPI/RestAPIAdapter.cs new file mode 100644 index 000000000..ad5f81fce --- /dev/null +++ b/TBF/Rig/Network/RestAPI/RestAPIAdapter.cs @@ -0,0 +1,35 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.Net; +using log4net; +using TBF.Rig.GenericDevices; + +namespace TBF.Rig.Network.RestAPI +{ + public class RestAPIAdapter : ComponentBase, GenericDevices.IRestAPIAdapter + { + private static readonly ILog log = LogManager.GetLogger(typeof(RestAPIAdapter)); + public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } + + readonly RestAPIadapterCfg restApIadapterCfg; + + private string path; + public string Path { get => path; } + + + public RestAPIAdapter() { } + + public RestAPIAdapter(Generic.IComponentCfg cfg) + : base(cfg) + { + restApIadapterCfg = cfg as RestAPIadapterCfg; + log.Warn(this.ToString()); + } + + public override void Initialize() + { + path = restApIadapterCfg.Path; + } + } +} diff --git a/TBF/Rig/Network/RestAPI/RestAPIadapterCfg.cs b/TBF/Rig/Network/RestAPI/RestAPIadapterCfg.cs new file mode 100644 index 000000000..801fd48a9 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/RestAPIadapterCfg.cs @@ -0,0 +1,44 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using Config.Entities; +using TBF.Rig.Generic; +using TBF.Rig.GenericDevices; + +namespace TBF.Rig.Network.RestAPI +{ + public class RestAPIadapterCfg : ComponentCfgBase, Generic.IComponentCfg + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RestAPIadapterCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl(IList cmpntEntities) { return new RestApiCfgCtrl(); } + + + public string Description; /// Description string of the selected network adapter + public string Path; // path to Ftp + public string Trigger; + + /// Private parameterless constructor invoked by all other (public) constructors NetFtpadapterCfg() {} + + public RestAPIadapterCfg(string name, IComponentFactory factory) + : this() + { + Name = name; + Factory = factory; + ParentName = string.Empty; + } + + protected RestAPIadapterCfg() + { + } + + public string ToString(int i) + { + return string.Format("Name={0}, Description={1}", Name, Description); + } + } +} diff --git a/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.cs b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.cs new file mode 100644 index 000000000..a26579f10 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.cs @@ -0,0 +1,107 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Common; +using Config.Entities; +using TBF.Rig.Generic; + +namespace TBF.Rig.Network.RestAPI +{ + public partial class RestApiCfgCtrl : UserControl, IComponentCfgCtrl + { + public bool ShowMore { get { return false; } } + + RestAPIadapterCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as RestAPIadapterCfg; + Redraw(); + } + } + + public RestApiCfgCtrl() + { + InitializeComponent(); + nameTextBox.Enabled = false; + textBoxFtpDir.Enabled = false; + } + + private void EntryFormCfgCtrl_Load(object sender, EventArgs e) + { + if (ParentForm == null) return; /// Return is executed when tab page is open in Designer + if (config == null) return; /// Control was not loaded, settings were not changed + + Localize(); + + Redraw(); + } + + void Redraw() + { + classNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + textBoxFtpDir.Text = config.Path; + } + + void Localize() + { + } + + public void Closing() + { + } + + public void Unlock() + { + nameTextBox.Enabled = true; + textBoxFtpDir.Enabled = true; + } + + // Define the regex pattern for HTTP or HTTPS URLs + private static string urlPattern = @"^(http|https):\/\/([a-zA-Z0-9\.-]+)(:[0-9]+)?(\/[a-zA-Z0-9\._\-~]+)*\/?$"; + + public CfgUpdateFlags VerifyCfg(ref string message) + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + + // Create regex object + Regex regex = new Regex(urlPattern); + + if (!regex.IsMatch(textBoxFtpDir.Text)) + { + flags = CfgUpdateFlags.Error; + message += Environment.NewLine + "Invalid 'URL'"; + } + + return flags; + } + + public CfgUpdateFlags UpdateCfg() + { + CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd; + + if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + + /// Network adapter + string strAdapter = textBoxFtpDir.Text; + int iDash = strAdapter.IndexOf(" - "); + config.Description = iDash < 0 ? "" : strAdapter.Substring(iDash + 3); + + config.Path = textBoxFtpDir.Text; + + return flags; + } + + } +} diff --git a/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.designer.cs b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.designer.cs new file mode 100644 index 000000000..7e9ce2237 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.designer.cs @@ -0,0 +1,122 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +namespace TBF.Rig.Network.RestAPI +{ + partial class RestApiCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.classNameLabel = new System.Windows.Forms.Label(); + this.adapterLabel = new System.Windows.Forms.Label(); + this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components); + this.textBoxFtpDir = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit(); + this.SuspendLayout(); + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(152, 77); + this.nameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(169, 26); + this.nameTextBox.TabIndex = 5; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(14, 82); + this.nameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(51, 20); + this.nameLabel.TabIndex = 4; + this.nameLabel.Text = "Name"; + // + // classNameLabel + // + this.classNameLabel.AutoSize = true; + this.classNameLabel.Location = new System.Drawing.Point(147, 37); + this.classNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.classNameLabel.Name = "classNameLabel"; + this.classNameLabel.Size = new System.Drawing.Size(125, 20); + this.classNameLabel.TabIndex = 3; + this.classNameLabel.Text = "ComonentName"; + // + // adapterLabel + // + this.adapterLabel.AutoSize = true; + this.adapterLabel.Location = new System.Drawing.Point(14, 123); + this.adapterLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.adapterLabel.Name = "adapterLabel"; + this.adapterLabel.Size = new System.Drawing.Size(66, 20); + this.adapterLabel.TabIndex = 6; + this.adapterLabel.Text = "Adapter"; + // + // errorProvider1 + // + this.errorProvider1.ContainerControl = this; + // + // textBoxFtpDir + // + this.textBoxFtpDir.Location = new System.Drawing.Point(151, 120); + this.textBoxFtpDir.Name = "textBoxFtpDir"; + this.textBoxFtpDir.Size = new System.Drawing.Size(373, 26); + this.textBoxFtpDir.TabIndex = 7; + // + // RestApiCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.textBoxFtpDir); + this.Controls.Add(this.adapterLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.classNameLabel); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "RestApiCfgCtrl"; + this.Size = new System.Drawing.Size(675, 462); + this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load); + ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + } + + private System.Windows.Forms.ErrorProvider errorProvider1; + private System.Windows.Forms.TextBox textBoxFtpDir; + + #endregion + + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label classNameLabel; + private System.Windows.Forms.Label adapterLabel; + } +} diff --git a/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.resx b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.resx new file mode 100644 index 000000000..3ee7035cb --- /dev/null +++ b/TBF/Rig/Network/RestAPI/RestApiCfgCtrl.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/facade/ApiDataLoad.cs b/TBF/Rig/Network/RestAPI/facade/ApiDataLoad.cs new file mode 100644 index 000000000..26e50a474 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/facade/ApiDataLoad.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using log4net; +using Newtonsoft.Json; +using Results.Entities; + +namespace TBF.Rig.Network.RestAPI.facade +{ + public class ApiDataLoad + { + [JsonIgnore] private Results.BatchResults batchResults; + [JsonIgnore] private static readonly ILog log = LogManager.GetLogger(typeof(RestAPIAdapter)); + + public ApiDataLoad(Results.BatchResults batchResults) + { + this.batchResults = batchResults; + } + + public String getJsonRequestBody() + { + try + { + List watermeterList = new List(); + if (batchResults.Batch != null && batchResults.Batch.WaterMeters != null) + { + for (int i = 0; i < batchResults.Batch.WaterMeters.Count; i++) + { + if (batchResults.Batch.WaterMeters[i] != null && !batchResults.Batch.WaterMeters[i].Disabled) + { + watermeterList.Add(toFacaseWaterMeter(batchResults.Batch.WaterMeters[i])); + } + } + } + + //do json from results + string jsonRequestBody = JsonConvert.SerializeObject(watermeterList, Formatting.Indented); + log.Debug("JSON to send in API: " + jsonRequestBody); + return jsonRequestBody; + } + catch (Exception ex) + { + log.Error("getJsonRequestBody()", ex); + Console.WriteLine(ex); + } + + return ""; + } + + // Assuming toFacaseWaterMeter method exists + private WaterMeter toFacaseWaterMeter(Results.Entities.WaterMeter meter) + { + try + { + WaterMeter waterMeter = new WaterMeter(); + // logic to convert WaterMeter data to facase class + waterMeter.WaterMeterID = meter.Id; + waterMeter.Passed = meter.Passed; + waterMeter.Remark = meter.Remark; + waterMeter.ArchivePath = meter.ArchivePath; + waterMeter.EndState = meter.EndState; + waterMeter.OrderName = meter.PurchaseOrder; + waterMeter.QFall = meter.QFall; + waterMeter.QRise = meter.QRise; + waterMeter.RadioAddress = meter.RadioAddress; + waterMeter.ResultCode = meter.ResultCode; + waterMeter.SerialNo = meter.SerialNr; + waterMeter.WmPosition = meter.WMPosition; + waterMeter.EndStateAux = meter.EndStateAux; + waterMeter.SerialNrAux = meter.SerialNrAux; + waterMeter.YearOfProduction = meter.YearOfProduction; + + //TODO BUMI implemet - Data from purchase + waterMeter.OrderID = null; + waterMeter.BoxId = ""; + + //convert next objects + waterMeter.WaterMeterData = toFacaseWaterMeterData(meter.WaterMeterData); + waterMeter.Batch = toFacadeBatch(meter.Batch); + + waterMeter.TestResultsList = toFacasetoFacaseWaterMeterData(meter); + + + return waterMeter; // Update this line as per implementation + } + catch (Exception e) + { + log.Error("toFacaseWaterMeter()", e); + return null; + } + } + + private Batch toFacadeBatch(Results.Entities.Batch meterBatch) + { + try + { + Batch facadeBatch = null; + if (meterBatch != null) + { + facadeBatch = new Batch(); + + facadeBatch.Id = meterBatch.Id; + facadeBatch.BatchNr = meterBatch.BatchNr; + facadeBatch.TestBenchId = meterBatch.TestBenchId; + facadeBatch.ProgramVersion = meterBatch.ProgramVersion; + facadeBatch.UserName = meterBatch.UserName; + facadeBatch.UserNumber = meterBatch.UserNumber; + facadeBatch.ProcedureName = meterBatch.ProcedureName; + facadeBatch.ProcedureRevision = meterBatch.ProcedureRevision; + facadeBatch.Remark = meterBatch.Remark; + facadeBatch.Counter6 = meterBatch.Counter6; + facadeBatch.Counter7 = meterBatch.Counter7; + facadeBatch.Counter8 = meterBatch.Counter8; + facadeBatch.Counter9 = meterBatch.Counter9; + facadeBatch.Counter10 = meterBatch.Counter10; + facadeBatch.StartTime = meterBatch.StartTime; + facadeBatch.EndTime = meterBatch.EndTime; + facadeBatch.Dirty = meterBatch.Dirty; + facadeBatch.RsltsSent = meterBatch.RsltsSent; + facadeBatch.RsltsPrinted = meterBatch.RsltsPrinted; + } + + return facadeBatch; + } + catch (Exception ex) + { + log.Error("toFacadeBatch()", ex); + return null; + } + } + + private WaterMeterData toFacaseWaterMeterData(Results.Entities.WaterMeterData meterWaterMeterData) + { + try + { + WaterMeterData waterMeterData = null; + + if (meterWaterMeterData != null) + { + waterMeterData = new WaterMeterData(); + + waterMeterData.Id = meterWaterMeterData.Id; + waterMeterData.ProductName = meterWaterMeterData.ProductName; + waterMeterData.Producer = meterWaterMeterData.Producer; + waterMeterData.Dn = meterWaterMeterData.DN; + waterMeterData.L = meterWaterMeterData.L; + waterMeterData.Mounting = + meterWaterMeterData.Mounting + .ToString(); // Assuming Mounting is an enum or has a valid ToString implementation + waterMeterData.Q4Qmax = meterWaterMeterData.Q4_Qmax; + waterMeterData.Q3Qn = meterWaterMeterData.Q3_Qn; + waterMeterData.Q2Qt = meterWaterMeterData.Q2_Qt; + waterMeterData.Q1Qmin = meterWaterMeterData.Q1_Qmin; + waterMeterData.MetrologicalClass = meterWaterMeterData.MetrologicalClass; + waterMeterData.Certificate = meterWaterMeterData.Certificate; + waterMeterData.Compound = meterWaterMeterData.Compound; + waterMeterData.Medium = meterWaterMeterData.Medium.ToString(); + waterMeterData.ApprovalInfo = meterWaterMeterData.ApprovalInfo; + waterMeterData.MaxAdmissiblePressure = + meterWaterMeterData.MaxAdmissiblePressure + .ToString(); // Assuming Register is an enum or has a valid ToString implementation + waterMeterData.TemperatureClass = meterWaterMeterData.TemperatureClass.ToString(); + waterMeterData.ApprovalInfoAux = meterWaterMeterData.ApprovalInfoAux; + waterMeterData.PulsesPerLtr = meterWaterMeterData.PulsesPerLtr; + waterMeterData.ProducerAux = meterWaterMeterData.ProducerAux; + waterMeterData.Q3QnAux = meterWaterMeterData.Q3_Qn_Aux; + waterMeterData.MetrologicalClassAux = meterWaterMeterData.MetrologicalClassAux; + waterMeterData.PressureLossClass = meterWaterMeterData.PressureLossClass.ToString(); + waterMeterData.FlowProfileSensitivityClass = + meterWaterMeterData.FlowProfileSensitivityClass.ToString(); + } + + return waterMeterData; + } + catch (Exception ex) + { + log.Error("toFacaseWaterMeterData()", ex); + return null; + } + } + + private List toFacasetoFacaseWaterMeterData(Results.Entities.WaterMeter meter) + { + List testResultsList = new List(); + + IList regularMeterTestRslts = meter.RegularMeterTestRslts(); + foreach (MeterTestRslt meterTestRslt in regularMeterTestRslts) + { + if (meterTestRslt != null && meterTestRslt.TestDone) + { + TestResults testResults = new TestResults(meterTestRslt); + testResultsList.Add(testResults); + } + } + + return testResultsList; + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/facade/Batch.cs b/TBF/Rig/Network/RestAPI/facade/Batch.cs new file mode 100644 index 000000000..07786867b --- /dev/null +++ b/TBF/Rig/Network/RestAPI/facade/Batch.cs @@ -0,0 +1,36 @@ +using System; + +namespace TBF.Rig.Network.RestAPI.facade +{ + /// + /// Represents the information transfer between a Water Meter and the Server side. This class contains the batch-related information. + /// + public class Batch + { + public int Id { get; set; } + public int? BatchNr { get; set; } + public int? TestBenchId { get; set; } + public string ProgramVersion { get; set; } + public string UserName { get; set; } + public int? UserNumber { get; set; } + public string ProcedureName { get; set; } + public int? ProcedureRevision { get; set; } + public string ProtocolTitle { get; set; } + public string Remark { get; set; } + public double? Custom1 { get; set; } + public double? Custom2 { get; set; } + public double? Custom3 { get; set; } + public int? Counter6 { get; set; } + public int? Counter7 { get; set; } + public int? Counter8 { get; set; } + public int? Counter9 { get; set; } + public int? Counter10 { get; set; } + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public bool? Dirty { get; set; } + public bool? RsltsSent { get; set; } + public bool? RsltsPrinted { get; set; } + + public Batch() { } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/facade/TestResults.cs b/TBF/Rig/Network/RestAPI/facade/TestResults.cs new file mode 100644 index 000000000..b3bd40fc7 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/facade/TestResults.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Results.Entities; + +namespace TBF.Rig.Network.RestAPI.facade +{ + /// + /// Results information transfer - Representing results output based on Water Meter to Server side. + /// + public class TestResults + { + public float? Temp_LN_ME { get; set; } // Calculated + + public double? Mass { get; set; } // Calculated + + // in Sec + public double? TestTime { get; set; } + public double? Q_v_r { get; set; } + + public double? Vol_Rm { get; set; } + + public float? Press_UP_ME { get; set; } + + public DateTime? TimestampEnd { get; set; } + + public DateTime? TimestampStart { get; set; } + public double? Start_volume { get; set; } + public double? End_volume { get; set; } + + public double? ErrorRel { get; set; } + + public string TestName { get; set; } // Collapsed 3 parameters + + public TestResults() + { + } + + public TestResults(MeterTestRslt meterTestRslt) + { + if (meterTestRslt == null) + { + return; + } + + Results.Entities.TestData testData = meterTestRslt.TestData(); + Results.Entities.TestRslt testRslt = meterTestRslt.TestRslt; + + if (testRslt != null) + { + SetTemp_LN_ME_DB(testRslt.TempUpMean, testRslt.TempDownMean); + SetMass_DB(testRslt.MassEnd, testRslt.MassStart); + TestTime = testRslt.TestTime; + SetQ_v_r_DB(testRslt.Flow); // in m3/hr => l/hr + Press_UP_ME = testRslt.PressUpMean; + + if (testData != null) + { + TestName = Results.Utils.GetTestName(testData.Name, testData.Repeats, testRslt.RepetitionNr); + } + } + + Vol_Rm = meterTestRslt.VolumeRef; + Start_volume = meterTestRslt.VolumeStart; + End_volume = meterTestRslt.VolumeEnd; + ErrorRel = meterTestRslt.Error; + + + if (meterTestRslt.Batch() != null) + { + TimestampEnd = meterTestRslt.Batch().EndTime; + TimestampStart = meterTestRslt.Batch().StartTime; + } + } + + + public void SetTemp_LN_ME_DB(float tempUpMean, float tempDownMean) + { + Temp_LN_ME = (tempUpMean + tempDownMean) / 2; + } + + + public void SetMass_DB(double massEnd, double massStart) + { + Mass = massEnd - massStart; + } + + + public void SetQ_v_r_DB(double q_v_r) + { + Q_v_r = q_v_r * 1000; // m3/hr => l/hr + } + + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/facade/WaterMeter.cs b/TBF/Rig/Network/RestAPI/facade/WaterMeter.cs new file mode 100644 index 000000000..e5d558ce3 --- /dev/null +++ b/TBF/Rig/Network/RestAPI/facade/WaterMeter.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace TBF.Rig.Network.RestAPI.facade +{ + /// + /// WaterMeter class represents a water meter output to the server side. It contains various properties related to the water meter. + /// This class serves as a model object for the water meter. + /// + public class WaterMeter + { + public int? OrderID { get; set; } + public string OrderName { get; set; } + public string BoxId { get; set; } + public string SerialNo { get; set; } + + public int? WaterMeterID { get; set; } + public bool? Passed { get; set; } + public string SerialNrAux { get; set; } + public string RadioAddress { get; set; } + public int? YearOfProduction { get; set; } + public int? WmPosition { get; set; } + + public string EndState { get; set; } + public string EndStateAux { get; set; } + public double? QRise { get; set; } + public double? QFall { get; set; } + public int? ResultCode { get; set; } + public string ArchivePath { get; set; } + public string Remark { get; set; } + + public WaterMeterData WaterMeterData { get; set; } + public Batch Batch { get; set; } + + public List TestResultsList { get; set; } + + public WaterMeter() { } + } +} \ No newline at end of file diff --git a/TBF/Rig/Network/RestAPI/facade/WaterMeterData.cs b/TBF/Rig/Network/RestAPI/facade/WaterMeterData.cs new file mode 100644 index 000000000..3a4c4ed3d --- /dev/null +++ b/TBF/Rig/Network/RestAPI/facade/WaterMeterData.cs @@ -0,0 +1,41 @@ +namespace TBF.Rig.Network.RestAPI.facade +{ + /// + /// The WaterMeterData class represents the server-side data representation for a Water Meter Data. + /// It contains various attributes and their corresponding getter and setter methods. + /// + public class WaterMeterData + { + public int Id { get; set; } + public string ProductName { get; set; } + public string Producer { get; set; } + public double? Dn { get; set; } + public double? L { get; set; } + public string Mounting { get; set; } + public double? Q4Qmax { get; set; } + public double? Q3Qn { get; set; } + public double? Q2Qt { get; set; } + public double? Q1Qmin { get; set; } + public string MetrologicalClass { get; set; } + public string TemperatureClass { get; set; } + public string PressureLossClass { get; set; } + public string MaxAdmissiblePressure { get; set; } + public string FlowProfileSensitivityClass { get; set; } + public string ApprovalInfo { get; set; } + public string Certificate { get; set; } + public double? PulsesPerLtr { get; set; } + public string ProducerAux { get; set; } + public double? Q3QnAux { get; set; } + public string MetrologicalClassAux { get; set; } + public string ApprovalInfoAux { get; set; } + public string Medium { get; set; } + public string Text1 { get; set; } + public string Text2 { get; set; } + public string Text3 { get; set; } + public string Text4 { get; set; } + public string Text5 { get; set; } + public bool? Compound { get; set; } + + public WaterMeterData() { } + } +} \ No newline at end of file diff --git a/TBF/Rig/RegisterReaders/KPackE/DataEntryForRadio/EntryForm.cs b/TBF/Rig/RegisterReaders/KPackE/DataEntryForRadio/EntryForm.cs index 7c260ecf0..b88f90518 100644 --- a/TBF/Rig/RegisterReaders/KPackE/DataEntryForRadio/EntryForm.cs +++ b/TBF/Rig/RegisterReaders/KPackE/DataEntryForRadio/EntryForm.cs @@ -108,6 +108,7 @@ namespace TBF.Rig.RegisterReaders.KPackE.DataEntryForRadio /// null (not implemented) public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList waterMeters, bool isCondOp) { return null; } + public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; } /// Reference to the operation public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi) diff --git a/TBF/Rig/Sequences/MainSeq.cs b/TBF/Rig/Sequences/MainSeq.cs index 374f6581c..b0e80bae6 100644 --- a/TBF/Rig/Sequences/MainSeq.cs +++ b/TBF/Rig/Sequences/MainSeq.cs @@ -13,6 +13,8 @@ using TBF.Rig.Operations; using TBF.Rig.GenericDevices; using TBF.Resources; using TBF.Rig.Generic; +using TBF.Rig.Network.RestAPI; +using TBF.Rig.Network.RestAPI.facade; using TBF.Rig.Output.Printers.GroupPrinting.Single; using TBF.UiBridge; @@ -157,9 +159,12 @@ namespace TBF.Rig.Sequences } /// - /// Main sequence execution + /// Executes the main sequence. /// - public void Execute() + /// + /// This method is used to execute the main sequence. + /// + public void Execute() { IList e = new List(); Selection selection; @@ -871,7 +876,7 @@ namespace TBF.Rig.Sequences * Data Collector AFTER ? if exist, then check collector and test */ bool collectDataAfterTests = false; - TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstComponentImpl(); + TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstSequenceComponentImpl(); int currentTestIx = selsctedTestIx; while (currentTestIx < StateMachine.TestInstances.Length - simultWithEvacuationCount) @@ -1180,7 +1185,7 @@ namespace TBF.Rig.Sequences * Data Collector AFTER ? if exist, then check collector and test */ bool collectDataAfterTests = false; - TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstComponentImpl(); + TBF.Rig.Generic.IComponent collector = TbfComponents.FindFirstSequenceComponentImpl(); ITestMethod testMethod = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethod != null && testMethod.CanTest(StateMachine.Procedure.MetersKind)) @@ -1428,6 +1433,34 @@ namespace TBF.Rig.Sequences goto error; } if (e.Contains(Event.Error)) goto error; + + /// --- REST API via Operation + try + { + //send REST API via Operation + IRestAPIAdapter adapter = TbfComponents.FindFirstComponentImpl() as IRestAPIAdapter; + if (adapter != null) + { + State st = State.Create("MainSeq : Send data via REST API"); + //ProcessData.BatchRslts.Batch + st.AddOperation(new ApiMessageOp(adapter, new ApiDataLoad(ProcessData.BatchRslts))); + st.EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + if (e.Contains(Event.Error)) break; + if (e.Contains(Event.Error)) break; + } while (e.Contains(Event.Busy) && e.Contains(Event.Starting)); + } + } + catch (Exception x) + { + Bridge.OnError(this, string.Format(Strings.Component_0_crashed_Results_not_saved, "API REST")); + log.FatalFormat("API call crashed: {1}", x.Message); + e.Add(Event.ErrorProcessingResults); // operation unsuccessful + } + + /// if (!e.Contains(Event.ErrorProcessingResults)) { diff --git a/TBF/Rig/Sequences/MainSeqUtils.cs b/TBF/Rig/Sequences/MainSeqUtils.cs index 9b41fa856..68720e837 100644 --- a/TBF/Rig/Sequences/MainSeqUtils.cs +++ b/TBF/Rig/Sequences/MainSeqUtils.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using Common; using Config.Entities; +using Results; using TBF.Rig.GenericDevices; using TBF.Rig.Operations; using TBF.Boxes; @@ -684,6 +685,103 @@ namespace TBF.Rig.Sequences } } } + + CopyImagesToNewPath(oriBatch,batchResults); + } + + private void CopyImagesToNewPath(Batch oriBatch, BatchResults batchResults) + { + string ImagesPath = "C:\\TBF\\Images"; + string pathToOriginBatchImagesDir = Path.Combine(ImagesPath, oriBatch.BatchNr.ToString()); + string pathToNewBatchImagesDir = Path.Combine(ImagesPath, batchResults.Batch.BatchNr.ToString()); + string pathToNewBatchImagesTempDir = + Path.Combine(ImagesPath, "Temp\\" + batchResults.Batch.BatchNr.ToString()); + + try + { + CopyDirectory(pathToOriginBatchImagesDir, pathToNewBatchImagesDir); + } + catch (Exception e) + { + log.Error("Restore - Image To New Path Failed! Details:", e); + } + + + try + { + CopyDirectory(pathToOriginBatchImagesDir, pathToNewBatchImagesTempDir); + } + catch (Exception e) + { + log.Error("Restore - Image To New TEMP Path Failed! Details:", e); + } + } + private void CopyImagesToNewPath(Batch oriBatch, BatchResults batchResults, int WMPosition) + { + string ImagesPath = "C:\\TBF\\Images"; + string pathToOriginBatchImagesDir = Path.Combine(ImagesPath, oriBatch.BatchNr.ToString() + "\\" + WMPosition); + string pathToNewBatchImagesTempDir = Path.Combine(ImagesPath, "Temp\\" + batchResults.Batch.BatchNr.ToString() + "\\" + WMPosition); + try + { + CopyDirectory(pathToOriginBatchImagesDir, pathToNewBatchImagesTempDir); + } + catch (Exception e) + { + log.Error("Restore - Image To New Path Failed! Details:", e); + } + } + + public static void CopyDirectory(string sourceDir, string destinationDir, bool overwrite = true) + { + // Check if the source directory exists + if (!Directory.Exists(sourceDir)) + { + log.WarnFormat($"Restore Batch - Source directory not found: {sourceDir}"); + return; + } + + try + { + // If the destination directory doesn't exist, create it + if (!Directory.Exists(destinationDir)) + { + Directory.CreateDirectory(destinationDir); + } + + // Get all the files in the source directory + string[] files = Directory.GetFiles(sourceDir); + + // Copy each file to the destination directory + foreach (string file in files) + { + string fileName = Path.GetFileName(file); + string destFile = Path.Combine(destinationDir, fileName); + + // Copy the file to the destination + File.Copy(file, destFile, overwrite); + } + } + catch (Exception e) + { + log.Error("Copy of dir and Files is no succesfull!",e); + } + + try + { + // Optionally, handle subdirectories + string[] directories = Directory.GetDirectories(sourceDir); + foreach (string subDir in directories) + { + string subDirName = Path.GetFileName(subDir); + string destSubDir = Path.Combine(destinationDir, subDirName); + + // Recursively copy subdirectory + CopyDirectory(subDir, destSubDir, overwrite); + } + }catch (Exception e) + { + log.Error("Copy of sub dirs no successful!",e); + } } void CollectSimultSteps() diff --git a/TBF/Rig/TbfComponents.cs b/TBF/Rig/TbfComponents.cs index a367b0ebe..4ef66b2d9 100644 --- a/TBF/Rig/TbfComponents.cs +++ b/TBF/Rig/TbfComponents.cs @@ -83,6 +83,7 @@ namespace TBF.Rig new Network.Camera.RoiForFixedStart.Factory(), new Network.Camera.RoiForFixedStartKeyence.Factory(), new Network.Comet.Ambient.Factory(), + new Network.RestAPI.Factory(), new Output.DB.ProductionTracing.Factory(), new Output.DB.SaveDiverterCorrections.Factory(), new Output.DB.SaveFlowmeterCorrections.Factory(), @@ -342,7 +343,7 @@ namespace TBF.Rig return FindComponent(name, StateMachine.Components); } - public static IComponent FindFirstComponentImpl(IList components) where T : class, ISequence + public static IComponent FindFirstSequenceComponentImpl(IList components) where T : class, ISequence { foreach (var component in components) { @@ -354,12 +355,29 @@ namespace TBF.Rig return null; } - public static IComponent FindFirstComponentImpl() where T : class, ISequence + public static IComponent FindFirstSequenceComponentImpl() where T : class, ISequence + { + return FindFirstSequenceComponentImpl(StateMachine.Components); + } + + public static IComponent FindFirstComponentImpl(IList components) where T : class, IComponent + { + foreach (var component in components) + { + if (component is T) + { + return component; + } + } + return null; + } + + public static IComponent FindFirstComponentImpl() where T : class, IComponent { return FindFirstComponentImpl(StateMachine.Components); } - public static IComponent FindFirstComponentImpl() + public static IComponent FindFirstSequenceComponentImpl() { foreach (var component in StateMachine.Components) { diff --git a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs index 271d4d81c..8744b9349 100644 --- a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs +++ b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs @@ -8,10 +8,13 @@ using System.Threading; using log4net; using Common; using Config.Entities; +using FluentNHibernate.Conventions; using TBF.Boxes; using TBF.Resources; using TBF.Rig.Generic; using TBF.Rig.GenericDevices; +using TBF.Rig.Network.RestAPI; +using TBF.Rig.Operations; using TBF.Rig.Sequences; using TBF.UiBridge; @@ -1076,9 +1079,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance { meterRslt.RegReaderType = (int)regReader.RegisterReaderType; meterRslt.PulsesPerLiter = regReader.PulsesPerLtr; - meterRslt.VolumeStart = regReader.BeginWMState; /// [l] - meterRslt.VolumeEnd = regReader.EndWMState; /// [l] - meterRslt.VolumeMeter = Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart); /// [l] + meterRslt.VolumeStart = 0.0d;//regReader.BeginWMState; /// [l] + meterRslt.VolumeEnd = 0.0d;//regReader.EndWMState; /// [l] + meterRslt.VolumeMeter = 0.0d;//Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart); /// [l] meterRslt.VolumeRef = tstRslt.VolumeCTV; /// [l] meterRslt.PulsesMeter = meterRslt.VolumeMeter; meterRslt.PulsesMaster = tstRslt.PulsesMaster; @@ -1139,15 +1142,15 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance if (volumeRslt != null && volumeRegReader != null) { volumeRslt.PulsesPerLiter = volumeRegReader.PulsesPerLtr; - volumeRslt.VolumeStart = volumeRegReader.BeginWMState; - volumeRslt.VolumeEnd = volumeRegReader.EndWMState; + volumeRslt.VolumeStart = 0.0d;//volumeRegReader.BeginWMState; + volumeRslt.VolumeEnd = 0.0d;//volumeRegReader.EndWMState; volumeRslt.VolumeMeter = volumeRslt.VolumeEnd - volumeRslt.VolumeStart; volumeRslt.VolumeRef = tstRslt.VolumeCTV; volumeRslt.PulsesMeter = volumeRslt.VolumeMeter; volumeRslt.PulsesMaster = tstRslt.PulsesMaster; /// <----------------- ??? volumeRslt.TestTime = tstRslt.TestTime; - volumeRslt.Error = Formulas.ErrorFromVolumes(volumeRslt.VolumeMeter, volumeRslt.VolumeRef); + volumeRslt.Error = 100.0d;//Formulas.ErrorFromVolumes(volumeRslt.VolumeMeter, volumeRslt.VolumeRef); volumeRslt.Passed = !heatMetersTestParams.EvaluateVolume || ((volumeRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty) && (volumeRslt.Error <= test.GetErrLimHi(tstRslt.VolumeCTV, tstRslt.TestTime) - test.Uncertainty) && @@ -1159,14 +1162,14 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance if (energyRslt != null && energyRegReader != null && dataEntryCmpnt is GenericDevices.IHasHeatMtrStatesForm) { volumeRslt.PulsesPerLiter = energyRegReader.PulsesPerLtr; - energyRslt.VolumeStart = (dataEntryCmpnt as GenericDevices.IHasHeatMtrStatesForm).EnergyStartState(i); - energyRslt.VolumeEnd = (dataEntryCmpnt as GenericDevices.IHasHeatMtrStatesForm).EnergyEndState(i); + energyRslt.VolumeStart = 0.0d;//(dataEntryCmpnt as GenericDevices.IHasHeatMtrStatesForm).EnergyStartState(i); + energyRslt.VolumeEnd = 0.0d;//(dataEntryCmpnt as GenericDevices.IHasHeatMtrStatesForm).EnergyEndState(i); energyRslt.VolumeMeter = energyRslt.VolumeEnd - energyRslt.VolumeStart; energyRslt.VolumeRef = tstRslt.RefEnergy; energyRslt.PulsesMeter = energyRslt.VolumeMeter; energyRslt.PulsesMaster = tstRslt.PulsesMaster; /// <----------------- ??? - energyRslt.Error = Formulas.ErrorFromVolumes(energyRslt.VolumeMeter, energyRslt.VolumeRef); + energyRslt.Error = 100.0d;//Formulas.ErrorFromVolumes(energyRslt.VolumeMeter, energyRslt.VolumeRef); energyRslt.Passed = (energyRslt.Error >= heatMetersTestParams.ErrorLimitLo) && (energyRslt.Error <= heatMetersTestParams.ErrorLimitHi) && (tstRslt.ErrorFlags == 0); @@ -1191,14 +1194,14 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance { meterRslt.RegReaderType = (int)regReader.RegisterReaderType; meterRslt.PulsesPerLiter = regReader.PulsesPerLtr; - meterRslt.VolumeStart = regReader.BeginWMState; - meterRslt.VolumeEnd = regReader.EndWMState; - meterRslt.VolumeMeter = Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart); + meterRslt.VolumeStart = 0.0d;//regReader.BeginWMState; + meterRslt.VolumeEnd = 0.0d;//regReader.EndWMState; + meterRslt.VolumeMeter = 0.0d;//Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart); meterRslt.VolumeRef = tstRslt.VolumeCTV; /// liter meterRslt.PulsesMeter = meterRslt.VolumeMeter; meterRslt.PulsesMaster = tstRslt.PulsesMaster; meterRslt.TestTime = tstRslt.TestTime; - meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef); + meterRslt.Error = 100.0d;//Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef); meterRslt.Passed = (meterRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty) && (meterRslt.Error <= test.GetErrLimHi(tstRslt.VolumeCTV, tstRslt.TestTime) - test.Uncertainty) && (tstRslt.ErrorFlags == 0); diff --git a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs index 92bd2e471..a555d2210 100644 --- a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs +++ b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs @@ -10,6 +10,7 @@ using Config.Entities; using TBF.Boxes; using TBF.Resources; using TBF.Rig.GenericDevices; +using TBF.Rig.Network.RestAPI; using TBF.Rig.Sequences; using TBF.UiBridge; @@ -115,7 +116,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvanceCollect State state = State.Create(string.Format("{0}({1}) : Entering the end-state", test.Method, test.Name)); { - state.AddOperation(dataEntryCmpnt.ShowTestEndFormOp(sensPath.RegisterReaders, + state.AddOperation(dataEntryCmpnt.ShowTestCollectFormOp(sensPath.RegisterReaders, 0, test.ErrLimLo + test.Uncertainty, test.ErrLimHi - test.Uncertainty)); } state.AddOperation(checkUiOp) @@ -195,6 +196,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvanceCollect meterRslt.VolumeStart = regReader.BeginWMState; meterRslt.VolumeEnd = regReader.EndWMState; meterRslt.VolumeMeter = Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart); + meterRslt.PulsesMeter = meterRslt.VolumeMeter; meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef); meterRslt.Passed = (meterRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty) diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index ec8ca4794..42eb13944 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -116,6 +116,9 @@ ..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + ..\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll @@ -137,6 +140,7 @@ + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll @@ -625,6 +629,7 @@ + @@ -896,6 +901,21 @@ AmbientCfgCtrl.cs + + + + + + + + + UserControl + + + RestApiCfgCtrl.cs + + + @@ -2898,6 +2918,9 @@ AmbientCfgCtrl.cs + + RestApiCfgCtrl.cs + AskYesNoForm.cs diff --git a/TBF/packages.config b/TBF/packages.config index 7c92e8860..2503ea1ea 100644 --- a/TBF/packages.config +++ b/TBF/packages.config @@ -5,6 +5,7 @@ +