diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs index 091605cbf..fe7247a0f 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/EntryForm.cs @@ -4,8 +4,8 @@ using System; using System.Collections.Generic; using log4net; -using Common; using TBF.Rig.GenericDevices; +using System.Linq; namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder { @@ -38,32 +38,21 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder public string[] StartImages { get { return startImages; } - set - { - /*if (entryFormCfg.DebugLevel == DebugMode.Simulate ) - { - startImages = new string[] { "C:\\TBF\\Images\\Test\\Image1.jpg", "C:\\TBF\\Images\\Test\\Image2.jpg", - "C:\\TBF\\Images\\Test\\Image3.jpg", "C:\\TBF\\Images\\Test\\Image4.jpg", "C:\\TBF\\Images\\Test\\Image5.jpg", - "C:\\TBF\\Images\\Test\\Image1.jpg", "C:\\TBF\\Images\\Test\\Image2.jpg", "C:\\TBF\\Images\\Test\\Image3.jpg", - "C:\\TBF\\Images\\Test\\Image4.jpg", "C:\\TBF\\Images\\Test\\Image5.jpg", "C:\\TBF\\Images\\Test\\Image1.jpg", - "C:\\TBF\\Images\\Test\\Image2.jpg", "C:\\TBF\\Images\\Test\\Image3.jpg", "C:\\TBF\\Images\\Test\\Image4.jpg", - "C:\\TBF\\Images\\Test\\Image5.jpg", "C:\\TBF\\Images\\Test\\Image1.jpg", "C:\\TBF\\Images\\Test\\Image2.jpg", - "C:\\TBF\\Images\\Test\\Image3.jpg", "C:\\TBF\\Images\\Test\\Image4.jpg", "C:\\TBF\\Images\\Test\\Image5.jpg" }; - } - else*/ - { - startImages = value; - } - } + set { startImages = value; } } - string[] startImages; public string[] EndImages { get { return endImages; } set { endImages = value; } } + + string[] startImages; string[] endImages; + + private readonly List[] startImageLists = new List[TBF.Data.WMsCount]; + + private readonly List[] endImageLists = new List[TBF.Data.WMsCount]; public bool SaveImages { @@ -152,16 +141,27 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder entryFormCfg = cfg as EntryFormCfg; } - public override void Initialize() - { - disabled = new bool[TBF.Data.WMsCount]; - wmStartState = new double[TBF.Data.WMsCount]; - wmStartStateStr = new string[TBF.Data.WMsCount]; - wmEndState = new double[TBF.Data.WMsCount]; - wmCycleEndState = new string[TBF.Data.WMsCount]; - currentOp = CurrentOp.None; - log.FatalFormat("{0} initialized: {1}", Name, this); - } + public override void Initialize() + { + disabled = new bool[TBF.Data.WMsCount]; + wmStartState = new double[TBF.Data.WMsCount]; + wmStartStateStr = new string[TBF.Data.WMsCount]; + wmEndState = new double[TBF.Data.WMsCount]; + wmCycleEndState = new string[TBF.Data.WMsCount]; + + startImages = new string[TBF.Data.WMsCount]; + endImages = new string[TBF.Data.WMsCount]; + + currentOp = CurrentOp.None; + + for (int i = 0; i < TBF.Data.WMsCount; i++) + { + startImageLists[i] = new List(); + endImageLists[i] = new List(); + } + + log.FatalFormat("{0} initialized: {1}", Name, this); + } /// Reference to the operation @@ -202,15 +202,19 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// /// /// - public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, + public IOperation ShowTestCollectFormOp( + IRegReader[] regReaders, + double volumeRef, + double errLimLo, double errLimHi) { if (currentOp != CurrentOp.None) throw new Exception("Sequence error"); currentOp = CurrentOp.TestBothStates; this.regReaders = regReaders; - this.refVolume = refVolume; + this.refVolume = volumeRef; // = refVolume; this.errLimLo = errLimLo; this.errLimHi = errLimHi; + return this; } @@ -255,21 +259,38 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder void OpenTestStartStatesDlg(EntryForm myRef) { log.Debug("-- OpenTestStartStatesDlg --"); - string ocrMessage; - var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage); - myRef.modelessDlg = new TestStartEndForm(TBF.Data.WMsCount, myRef.regReaders, ocr, ocrMessage, myRef.OcrStream, - startImages, disabled); + + log.DebugFormat( "Before TestStartEndForm: TBF.Data.WMsCount={0}, regReaders.Length={1}, startImages.Length={2}, disabled.Length={3}", + TBF.Data.WMsCount, + myRef.regReaders == null ? -1 : myRef.regReaders.Length, + startImages == null ? -1 : startImages.Length, + disabled == null ? -1 : disabled.Length); + + if (startImages != null) + { + for (int i = 0; i < startImages.Length; i++) + { + log.DebugFormat( "startImages[{0}]='{1}'", i, startImages[i]); + } + } + + string ocrMessage; + var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage); + + myRef.modelessDlg = new TestStartEndForm( TBF.Data.WMsCount, myRef.regReaders, ocr, ocrMessage, myRef.OcrStream, startImages, disabled); + modelessDlg.Show(); } /// void OpenTestEndStatesDlg(EntryForm myRef) { - log.Debug("-- OpenTestEndStatesDlg --"); + log.Warn("-- OpenTestEndStatesDlg ENTER --"); 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); + log.Warn("-- OpenTestEndStatesDlg SHOW --"); modelessDlg.Show(); } @@ -340,6 +361,12 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// Start this operation public void Start() { + log.WarnFormat( "EntryForm.Start: currentOp={0}, modelessDlg={1}, resultSaved={2}", + currentOp, + modelessDlg == null ? "" : modelessDlg.GetType().FullName, + resultSaved); + + resultSaved = false; switch (currentOp) { @@ -383,95 +410,80 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder /// Event.ResultsPrinted public Event Run() { + log.WarnFormat( "EntryForm.Run: currentOp={0}, modelessDlg={1}, completed={2}, resultSaved={3}", + currentOp, + modelessDlg == null ? "" : modelessDlg.GetType().FullName, + modelessDlg is IHasCompleted && ((IHasCompleted)modelessDlg).Completed, + resultSaved); + + if ((modelessDlg is IHasCompleted) && !(modelessDlg as IHasCompleted).Completed) { return Event.ModelessFormIsOpen; } - if (!resultSaved) /// This is to save the result only once + if (!resultSaved) { - if ((!entryFormCfg.EnterSerialNrsAtTheEnd && currentOp == CurrentOp.ShowFormAtCycleBeginning) || - (entryFormCfg.EnterSerialNrsAtTheEnd && currentOp == CurrentOp.ShowFormAtCycleEnd)) + try { - CycleBeginningForm dlg = (modelessDlg as CycleBeginningForm); - if (dlg != null) + if ((!entryFormCfg.EnterSerialNrsAtTheEnd && currentOp == CurrentOp.ShowFormAtCycleBeginning) || + (entryFormCfg.EnterSerialNrsAtTheEnd && currentOp == CurrentOp.ShowFormAtCycleEnd)) { - for (int i = 0; i < Math.Min(dlg.WaterMetersCount, waterMeters.Count); i++) - { - if (waterMeters[i] != null) - { - waterMeters[i].Disabled = disabled[i] = dlg.Disabled[i]; - waterMeters[i].SerialNr = dlg.SNText[i]; - if (!entryFormCfg.HideOrder && dlg.PurchaseOrder != null) waterMeters[i].PurchaseOrder = dlg.PurchaseOrder; - } - } - } - } - else if (currentOp == CurrentOp.ShowFormAtCycleEnd) - { - if (modelessDlg is CycleEndForm) - { - CycleEndForm dlg = (modelessDlg as CycleEndForm); - int count = waterMeters.Count; - if ((dlg != null) && (count > dlg.WaterMetersCount)) count = dlg.WaterMetersCount; + CycleBeginningForm dlg = modelessDlg as CycleBeginningForm; - for (int i = 0; i < count; i++) + if (dlg != null) { - if (waterMeters[i] != null) + for (int i = 0; i < Math.Min( dlg.WaterMetersCount, waterMeters.Count); i++) { - /// In case entryFormCfg.ShowCycleEndForm == false dlg would be null, values would be string.Empty - wmCycleEndState[i] = waterMeters[i].EndState = (dlg != null) ? dlg.EndStateText[i] : string.Empty; + if (waterMeters[i] != null) + { + waterMeters[i].Disabled = disabled[i] = dlg.Disabled[i]; + waterMeters[i].SerialNr = dlg.SNText[i]; + + if (!entryFormCfg.HideOrder && dlg.PurchaseOrder != null) + { + waterMeters[i].PurchaseOrder = dlg.PurchaseOrder; + } + } } } } - } - else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestStartStates) - { - /// Fixed start/stop: test start - 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]; - } - } - } - else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestEndStates) - { - /// 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.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) - { - /// Fixed start/stop: deferred test evaluation - TestStartEndForm dlg = (modelessDlg as TestStartEndForm); - if (dlg != null) + else if (currentOp == CurrentOp.ShowFormAtCycleEnd) { + CycleEndForm dlg = modelessDlg as CycleEndForm; + + if (dlg != null) + { + int count = waterMeters.Count; + + if (count > dlg.WaterMetersCount) + { + count = dlg.WaterMetersCount; + } + + for (int i = 0; i < count; i++) + { + if (waterMeters[i] != null) + { + wmCycleEndState[i] = waterMeters[i].EndState = dlg.EndStateText[i]; + } + } + } + } + else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestStartStates) + { + TestStartEndForm dlg = modelessDlg as TestStartEndForm; + + for (int i = 0; i < dlg.WaterMetersCount; i++) + { + wmStartState[i] = dlg.WMStartState[i]; + wmStartStateStr[i] = dlg.WMStartStateStr[i]; + } + } + else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestEndStates) + { + TestStartEndForm dlg = modelessDlg as TestStartEndForm; + for (int i = 0; i < dlg.WaterMetersCount; i++) { wmStartState[i] = dlg.WMStartState[i]; @@ -479,12 +491,39 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder wmEndState[i] = dlg.WMEndState[i]; } } + else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestBothStates) + { + TestStartEndForm dlg = modelessDlg as TestStartEndForm; + + 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) + { + TestStartEndForm dlg = modelessDlg as TestStartEndForm; + for (int i = 0; i < dlg.WaterMetersCount; i++) + { + wmStartState[i] = dlg.WMStartState[i]; + wmStartStateStr[i] = dlg.WMStartStateStr[i]; + wmEndState[i] = dlg.WMEndState[i]; + } + } + + resultSaved = true; + } + finally + { + log.DebugFormat( "EntryForm operation completed: currentOp={0}", currentOp); + modelessDlg = null; + currentOp = CurrentOp.None; } - resultSaved = true; - modelessDlg = null; } - return Event.ModelessFormClosed; /// Form closed + return Event.ModelessFormClosed; } /// Stop this operation @@ -497,5 +536,31 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder } currentOp = CurrentOp.None; } + + public void AddImages(string[] newStartImages, string[] newEndImages) + { + for (int i = 0; i < TBF.Data.WMsCount; i++) + { + if (newStartImages != null && + i < newStartImages.Length && + !string.IsNullOrEmpty(newStartImages[i]) && + System.IO.File.Exists(newStartImages[i]) && + !startImageLists[i].Any( image => string.Equals( image, newStartImages[i], StringComparison.OrdinalIgnoreCase))) + { + startImageLists[i].Add(newStartImages[i]); + } + + if (newEndImages != null && + i < newEndImages.Length && + !string.IsNullOrEmpty(newEndImages[i]) && + System.IO.File.Exists(newEndImages[i]) && + !endImageLists[i].Any( image => string.Equals( image, newEndImages[i], StringComparison.OrdinalIgnoreCase))) + { + endImageLists[i].Add(newEndImages[i]); + } + } + } + + } } diff --git a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs index d94f7471f..4543eaaf5 100644 --- a/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs +++ b/TBF/Rig/DataEntry/StandartCameraPurchaseOrder/TestStartEndForm.cs @@ -179,7 +179,15 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder if (startImages == null || startImages.Length != WaterMetersCount) { - throw new Exception("Invalid 'startImages' argument"); + throw new Exception( + string.Format( + "Invalid 'startImages' argument. startImages.Length={0}, " + + "WaterMetersCount={1}, requestedWaterMetersCount={2}, " + + "regReaders.Length={3}", + startImages == null ? -1 : startImages.Length, + WaterMetersCount, + waterMetersCount, + regReaders == null ? -1 : regReaders.Length)); } this.endImages = new string[WaterMetersCount]; @@ -323,7 +331,7 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder Width = 1420; } - OkButtonPosition(); + PositionBottomControls(); } void OkButtonPosition() @@ -337,6 +345,32 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder ); } } + + private void PositionBottomControls() + { + const int rightMargin = 10; + const int gap = 12; + + // OK vždy úplne vpravo + okButton.Location = new Point( + ClientSize.Width - okButton.Width - rightMargin, + okButton.Location.Y); + + // Checkbox iba v režime End + if (mode == Tst.End) + { + checkBoxEnableStartBox.Location = new Point( + okButton.Left - checkBoxEnableStartBox.Width - gap, + okButton.Top + + (okButton.Height - checkBoxEnableStartBox.Height) / 2); + } + + okButton.Anchor = + AnchorStyles.Bottom | AnchorStyles.Right; + + checkBoxEnableStartBox.Anchor = + AnchorStyles.Bottom | AnchorStyles.Right; + } /// /// Make sure the layout of labels/text boxes on the screen @@ -481,6 +515,8 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder imageProcessingThread = new Thread(new ThreadStart(ImageProcessingThread)); imageProcessingThread.Start(); } + + PositionBottomControls(); } /// @@ -719,14 +755,20 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder Close(); } + /** + * preparation for previous button + */ private void previousButton_Click(object sender, EventArgs e) { - + ShowPreviousImageFromGroup(); } + /** + * preparation for next button + */ private void nextButton_Click(object sender, EventArgs e) { - + ShowNextImageFromGroup(); } @@ -1142,8 +1184,8 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder private void endTextBox20_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 19); } private void endTextBox21_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 20); } private void endTextBox22_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 21); } - private void endTextBox24_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 22); } - private void endTextBox23_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 23); } + private void endTextBox24_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 23); } + private void endTextBox23_AcceptsTabChanged(object sender, EventArgs e) { LoadImage(sender, Tst.End, 22); } private void endTextBox1_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.End, 0); } private void endTextBox2_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.End, 1); } private void endTextBox3_MouseDown(object sender, MouseEventArgs e) { LoadImage(sender, Tst.End, 2); } @@ -1290,77 +1332,92 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder return null; } - + /// /// load group of images /// /// - private void LoadImageGroup( - string baseImageFileName) + private void LoadImageGroup(string baseImageFileName) { currentImageGroup.Clear(); currentImageGroupIndex = 0; if (string.IsNullOrWhiteSpace(baseImageFileName)) { + UpdateImageSwitchControls(); return; } - string fullBaseFileName; - try { - fullBaseFileName = - Path.GetFullPath(baseImageFileName); - } - catch (Exception exc) - { - log.Warn( - $"Cannot create image group from invalid path: " + - $"file='{baseImageFileName}', " + - $"error={exc.Message}"); + /* + * Vstup môže byť napríklad: + * + * C:\Tbf\Images\1667\1\Advance_(1_3)-start.bmp + * + * Preview však musí používať výhradne: + * + * C:\Tbf\Images\Temp\1667\1\Advance_(1_3)-start.bmp + * C:\Tbf\Images\Temp\1667\1\Advance_(1_3)-start_img02_....bmp + * C:\Tbf\Images\Temp\1667\1\Advance_(1_3)-start_img03_....bmp + */ + string tempBaseFileName = + GetTempImageFileName(baseImageFileName); - return; - } + if (string.IsNullOrWhiteSpace(tempBaseFileName)) + { + log.WarnFormat( + "Cannot determine Temp image path from '{0}'.", + baseImageFileName); - string directory = - Path.GetDirectoryName(fullBaseFileName); + UpdateImageSwitchControls(); + return; + } - string baseName = - Path.GetFileNameWithoutExtension(fullBaseFileName); + string tempDirectory = + Path.GetDirectoryName(tempBaseFileName); - string extension = - Path.GetExtension(fullBaseFileName); + string baseName = + Path.GetFileNameWithoutExtension(tempBaseFileName); - if (string.IsNullOrWhiteSpace(directory) || - string.IsNullOrWhiteSpace(baseName)) - { - return; - } + string extension = + Path.GetExtension(tempBaseFileName); - /* - * Pôvodný obrázok pridáme ako prvý. - */ - if (File.Exists(fullBaseFileName)) - { - currentImageGroup.Add(fullBaseFileName); - } + if (string.IsNullOrWhiteSpace(tempDirectory) || + string.IsNullOrWhiteSpace(baseName) || + !Directory.Exists(tempDirectory)) + { + log.DebugFormat( + "Temp image directory does not exist: '{0}'.", + tempDirectory); - if (!Directory.Exists(directory)) - { - return; - } + UpdateImageSwitchControls(); + return; + } - string searchPattern = - $"{baseName}_img*{extension}"; + /* + * Prvý obrázok: + * + * Advance_(1_3)-start.bmp + */ + AddImageToCurrentGroup(tempBaseFileName); + + /* + * Ďalšie obrázky: + * + * Advance_(1_3)-start_img02_20260720_094019_248.bmp + * Advance_(1_3)-start_img03_20260720_094019_847.bmp + */ + string timedPattern = string.Format( + "{0}_img*{1}", + baseName, + extension); - try - { List timedImages = Directory .GetFiles( - directory, - searchPattern, + tempDirectory, + timedPattern, SearchOption.TopDirectoryOnly) .OrderBy(GetTimedImageIndex) .ThenBy( @@ -1370,29 +1427,148 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder foreach (string timedImage in timedImages) { - if (!currentImageGroup.Contains( - timedImage, - StringComparer.OrdinalIgnoreCase)) - { - currentImageGroup.Add(timedImage); - } + AddImageToCurrentGroup(timedImage); } - log.Debug( - $"Image group loaded: " + - $"baseFile='{fullBaseFileName}', " + - $"searchPattern='{searchPattern}', " + - $"imagesCount={currentImageGroup.Count}"); + UpdateImageSwitchControls(); + + log.DebugFormat( + "Temp image group loaded: input='{0}', tempBase='{1}', " + + "pattern='{2}', count={3}, files=[{4}]", + baseImageFileName, + tempBaseFileName, + timedPattern, + currentImageGroup.Count, + string.Join( + ", ", + currentImageGroup.Select(Path.GetFileName))); } catch (Exception exc) { - log.Warn( - $"Cannot load image group: " + - $"baseFile='{fullBaseFileName}', " + - $"pattern='{searchPattern}', " + - $"error={exc.Message}"); + log.WarnFormat( + "Cannot load Temp image group: input='{0}', error={1}", + baseImageFileName, + exc.Message); + + currentImageGroup.Clear(); + currentImageGroupIndex = 0; + UpdateImageSwitchControls(); } } + + private static string GetTempImageFileName( + string imageFileName) + { + if (string.IsNullOrWhiteSpace(imageFileName)) + { + return null; + } + + string fullPath; + + try + { + fullPath = Path.GetFullPath(imageFileName); + } + catch + { + return null; + } + + const string tempRoot = + @"C:\Tbf\Images\Temp"; + + const string imagesRoot = + @"C:\Tbf\Images"; + + /* + * Súbor už smeruje do Temp. + */ + if (fullPath.StartsWith( + tempRoot + Path.DirectorySeparatorChar, + StringComparison.OrdinalIgnoreCase)) + { + return fullPath; + } + + /* + * C:\Tbf\Images\1667\1\file.bmp + * + * zmeníme na: + * + * C:\Tbf\Images\Temp\1667\1\file.bmp + */ + if (fullPath.StartsWith( + imagesRoot + Path.DirectorySeparatorChar, + StringComparison.OrdinalIgnoreCase)) + { + string relativePath = + fullPath.Substring( + imagesRoot.Length + 1); + + return Path.Combine( + tempRoot, + relativePath); + } + + /* + * Neznáma cesta – zachováme iba časť od čísla batchu, + * ak už cesta obsahuje adresár Temp. + */ + int tempIndex = fullPath.IndexOf( + @"\Temp\", + StringComparison.OrdinalIgnoreCase); + + if (tempIndex >= 0) + { + string relativePath = + fullPath.Substring( + tempIndex + @"\Temp\".Length); + + return Path.Combine( + tempRoot, + relativePath); + } + + return null; + } + + private void AddImageToCurrentGroup( + string imageFileName) + { + if (string.IsNullOrWhiteSpace(imageFileName) || + !File.Exists(imageFileName)) + { + return; + } + + bool alreadyAdded = + currentImageGroup.Any( + existingFile => + string.Equals( + existingFile, + imageFileName, + StringComparison.OrdinalIgnoreCase)); + + if (!alreadyAdded) + { + currentImageGroup.Add(imageFileName); + } + } + + private void UpdateImageSwitchControls() + { + bool canSwitch = + currentImageGroup.Count > 1; + + //previousButton.Enabled = canSwitch; + //nextButton.Enabled = canSwitch; + + // previousButton.Visible = canSwitch; + // nextButton.Visible = canSwitch; + } + + /// /// grouping by time /// @@ -1576,20 +1752,35 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder int direction) { if (direction == 0 || - currentImageGroup.Count <= 1) + currentImageGroup.Count == 0) { return; } - int newIndex = - currentImageGroupIndex + direction; - /* - * Cyklické prepínanie: - * - * posledný -> prvý - * prvý -> posledný + * Pred prepnutím odstránime súbory, ktoré už medzitým + * prestali existovať. */ + currentImageGroup.RemoveAll( fileName => !File.Exists(fileName)); + + if (currentImageGroup.Count == 0) + { + currentImageGroupIndex = 0; + UpdateImageSwitchControls(); + LoadImageFile(null); + return; + } + + if (currentImageGroup.Count == 1) + { + currentImageGroupIndex = 0; + UpdateImageSwitchControls(); + LoadImageFile(currentImageGroup[0]); + return; + } + + int newIndex = currentImageGroupIndex + direction; + if (newIndex < 0) { newIndex = @@ -1602,10 +1793,10 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder currentImageGroupIndex = newIndex; - LoadImageFile( - currentImageGroup[currentImageGroupIndex]); - } + LoadImageFile( currentImageGroup[currentImageGroupIndex]); + UpdateImageSwitchControls(); + } // --- mouse events --- diff --git a/TBF/Rig/Network/Camera/CJMS11/Camera.cs b/TBF/Rig/Network/Camera/CJMS11/Camera.cs index 552432ddd..8aec7e28c 100644 --- a/TBF/Rig/Network/Camera/CJMS11/Camera.cs +++ b/TBF/Rig/Network/Camera/CJMS11/Camera.cs @@ -2337,6 +2337,49 @@ namespace TBF.Rig.Network.Camera.CJMS11 } } + /// + /// pouziva LiveStreamOp - pre nahlad + /// + /// + public void StartLiveStream(bool hiResolution) + { + if (CameraCfg.DebugLevel == DebugMode.Simulate) + return; + + StartLiveStreamListener(); + } + + /// + /// pouziva LiveStreamOp - pre ukoncenie nahladu + /// + public void StopLiveStream() + { + if (CameraCfg.DebugLevel == DebugMode.Simulate) + return; + + try + { + liveCts?.Cancel(); + + if (liveStreamTask != null) + { + try + { + liveStreamTask.Wait(1000); + } + catch (AggregateException) + { + // expected after cancellation + } + } + } + catch (Exception ex) + { + log.Error($"{Name}: StopLiveStream failed.", ex); + } + } + + /// /// listener for multiple - repetetive image receiving /// @@ -2345,12 +2388,7 @@ namespace TBF.Rig.Network.Camera.CJMS11 /// /// /// - - // private void StartLiveStreamListener(IPAddress localIP, int localPort) - // { - // liveStreamListenerThread = new Thread(new ThreadStart(LiveStreamListener)); - // liveStreamListenerThread.Start(); - // } + private CancellationTokenSource liveCts; private Task liveStreamTask; @@ -2385,33 +2423,26 @@ namespace TBF.Rig.Network.Camera.CJMS11 try { - log.Debug( - $"Live stream waiting for camera lock: " + - $"cameraIdx={cameraIdx}"); + log.Debug( $"Live stream waiting for camera lock: cameraIdx={cameraIdx}"); - await cameraOperationLock - .WaitAsync(ct) - .ConfigureAwait(false); + await cameraOperationLock .WaitAsync(ct) .ConfigureAwait(false); lockAcquired = true; - log.Debug( - $"Live stream acquired camera lock: " + - $"cameraIdx={cameraIdx}"); + log.Debug( $"Live stream acquired camera lock: cameraIdx={cameraIdx}"); client = await ConnectCameraAsync( - timeoutMs: 3000, - ct: ct, - maxAttempts: 3, - retryDelayMs: 300) - .ConfigureAwait(false); + timeoutMs: 3000, + ct: ct, + maxAttempts: 3, + retryDelayMs: 300) + .ConfigureAwait(false); stream = client.GetStream(); reader = new CameraLineReader( stream, 64 * 1024); - JmsPacket prepare = - await SendCommandAndWaitToAnswerAsync( + JmsPacket prepare = await SendCommandAndWaitToAnswerAsync( stream, reader, CommandM.prepare_camera_, @@ -2425,10 +2456,8 @@ namespace TBF.Rig.Network.Camera.CJMS11 prepare.JmsMessage != null && prepare.JmsMessage.Status == MessageStatus.NACK && - !string.IsNullOrEmpty( - prepare.JmsMessage.Payload) && - prepare.JmsMessage.Payload.Contains( - "OPENED"); + !string.IsNullOrEmpty( prepare.JmsMessage.Payload) && + prepare.JmsMessage.Payload.Contains( "OPENED"); bool prepared = prepare != null && @@ -2447,8 +2476,7 @@ namespace TBF.Rig.Network.Camera.CJMS11 log.Debug( $"Camera already opened for live stream: cameraIdx={cameraIdx}"); } - JmsPacket start = - await SendCommandAndWaitToAnswerAsync( + JmsPacket start = await SendCommandAndWaitToAnswerAsync( stream, reader, CommandM.start_stream_images_, @@ -2469,30 +2497,39 @@ namespace TBF.Rig.Network.Camera.CJMS11 while (!ct.IsCancellationRequested) { - string response = - await reader.ReadLineAsync( - 10000, - ct) - .ConfigureAwait(false); + string response = await reader.ReadLineAsync( 10000, ct).ConfigureAwait(false); if (string.IsNullOrWhiteSpace(response)) - continue; - - JmsPacket packet = - new JmsPacket(response); - - if (packet.JmsMessage == null) - continue; - - if (packet.JmsMessage.Command != - CommandM.grab_image_) { - log.Debug( $"Unexpected packet during live stream: cameraIdx={cameraIdx}, command={packet.JmsMessage.Command}"); continue; } - if (packet.JmsMessage.Status != - MessageStatus.ACK) + JmsPacket packet = new JmsPacket(response); + + if (packet.JmsMessage == null) + { + continue; + } + + /* + * Server môže po spustení streamu poslať ešte jeden + * oneskorený alebo duplicitný ACK start_stream_images. + * Nie je to chyba streamu. + */ + if (packet.JmsMessage.Command == CommandM.start_stream_images_) + { + log.Debug( $"Ignoring delayed start stream response: cameraIdx={cameraIdx}"); + continue; + } + + if (packet.JmsMessage.Command != CommandM.grab_image_) + { + log.Debug( $"Unexpected packet during live stream: cameraIdx={cameraIdx}, " + + $"command={packet.JmsMessage.Command}"); + continue; + } + + if (packet.JmsMessage.Status != MessageStatus.ACK) { log.Warn( $"Live frame returned NACK: cameraIdx={cameraIdx}, payload={packet.JmsMessage.Payload}"); continue; @@ -2508,17 +2545,13 @@ namespace TBF.Rig.Network.Camera.CJMS11 Image image = parsed.Image; if (image == null) + { continue; + } DrawOverlay(image); - OnImageReceived( - this, - cameraIdx, - image, - RoiConfiguration.ImageRotation, - 0, - 1); + OnImageReceived( this, cameraIdx, image, RoiConfiguration.ImageRotation, 0, 1); } } catch (OperationCanceledException) @@ -2527,15 +2560,18 @@ namespace TBF.Rig.Network.Camera.CJMS11 } catch (TimeoutException exc) { + log.Error( $"Live stream timeout: cameraIdx={cameraIdx}, IP={CameraCfg.IPAddressCJMS}, error={exc.Message}"); } catch (SocketException exc) { - log.Error( $"Live stream socket error: cameraIdx={cameraIdx}, IP={CameraCfg.IPAddressCJMS}, socketError={exc.SocketErrorCode}, " + - $"error={exc.Message}"); + + log.Error( $"Live stream socket error: cameraIdx={cameraIdx}, IP={CameraCfg.IPAddressCJMS}, " + + $"socketError={exc.SocketErrorCode}, error={exc.Message}"); } catch (Exception exc) { + log.Error( $"Live stream exception: cameraIdx={cameraIdx}, error={exc.Message}", exc); UiBridge.Bridge.OnImage( cameraIdx, null); } @@ -2607,6 +2643,14 @@ namespace TBF.Rig.Network.Camera.CJMS11 cameraOperationLock.Release(); } + /* + * Dôležité: + * ak stream skončí timeoutom, socket chybou alebo výnimkou, + * UI musí povoliť nový pokus o spustenie. + */ + stopLiveStreamListenerFlag = true; + lockBrich = CameraUICmd.None; + log.Debug( $"Live stream finished: cameraIdx={cameraIdx}"); } } @@ -2656,7 +2700,7 @@ namespace TBF.Rig.Network.Camera.CJMS11 //string command = string.Format("~/userland/build/bin/raspivid -t 0 -cd MJPEG -w {0} -h {1} -fps 30 -b 8000000 -o - | gst-launch-1.0 fdsrc ! \"image/jpeg,framerate=30/1\" ! jpegparse ! rtpjpegpay ! udpsink host={2} port={3}", // wid, hgh, NetAdapter.IPAddress, rtpUdpLocalPort); - return new LiveStreamOp(this, command); + return new LiveStreamOp(this, hiRes); } diff --git a/TBF/Rig/Network/Camera/CJMS11/LiveStreamOp.cs b/TBF/Rig/Network/Camera/CJMS11/LiveStreamOp.cs index b150e46a2..fa7aec2cb 100644 --- a/TBF/Rig/Network/Camera/CJMS11/LiveStreamOp.cs +++ b/TBF/Rig/Network/Camera/CJMS11/LiveStreamOp.cs @@ -10,58 +10,72 @@ namespace TBF.Rig.Network.Camera.CJMS11 { private static readonly ILog log = LogManager.GetLogger(typeof(LiveStreamOp)); - readonly Camera camera; - readonly Telnet.TelnetClient telnet; - readonly string command; + private readonly Camera camera; + private readonly bool hiResolution; + + private bool started; + private Exception startException; + - bool liveStreamCommandSent; /// /// Events: Event.None or Event.Error /// /// CLP1611.Camera reference - public LiveStreamOp(Camera camera, string command) + public LiveStreamOp(Camera camera, bool hiResolution) { this.camera = camera; - this.command = command; + this.hiResolution = hiResolution; } public void Start() { - liveStreamCommandSent = false; + started = false; + startException = null; + + try + { + camera.StartLiveStream(hiResolution); + started = true; + + log.InfoFormat("{0} Live stream started", + camera.Name); + } + catch (Exception ex) + { + startException = ex; + log.Error("Unable to start live stream.", ex); + } } public Event Run() { - if (camera.CameraCfg.DebugLevel == DebugMode.Simulate) return Event.None; + if (camera.CameraCfg.DebugLevel == DebugMode.Simulate) + return Event.None; - log.DebugFormat("Run(): telnet.State = {0}, liveStreamCommandSent = {1}", telnet.State, liveStreamCommandSent); - - if (!liveStreamCommandSent) - { - if (camera.Running && (telnet.State == TelnetClient.TelnetState.Inactive)) - { - telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_STRING, command)); - liveStreamCommandSent = true; - log.WarnFormat("{0} IP={1} command={2}", camera.Name, camera.IPAddress, command); - } - } + if (startException != null) + return Event.Error; return Event.None; } public void Stop() { - if (camera.CameraCfg.DebugLevel == DebugMode.Simulate) return; + if (camera.CameraCfg.DebugLevel == DebugMode.Simulate) + return; - log.DebugFormat("Stop(): telnet.State = {0}, liveStreamCommandSent = {1}", telnet.State, liveStreamCommandSent); - - if (liveStreamCommandSent) + try { - telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_COMMAND, Telnet.TelnetClient.CtrlCCommand)); - log.WarnFormat("{0} IP={1} command=CTRL-C", camera.Name, camera.IPAddress); - } + camera.StopLiveStream(); + + log.InfoFormat("{0} Live stream stopped", + camera.Name); + } + catch (Exception ex) + { + log.Error("Unable to stop live stream.", ex); + } } } } diff --git a/TBF/Rig/Network/Camera/RoiForFixedStartCJMS11/Roi.cs b/TBF/Rig/Network/Camera/RoiForFixedStartCJMS11/Roi.cs index c28c43730..69a11ba79 100644 --- a/TBF/Rig/Network/Camera/RoiForFixedStartCJMS11/Roi.cs +++ b/TBF/Rig/Network/Camera/RoiForFixedStartCJMS11/Roi.cs @@ -137,6 +137,12 @@ namespace TBF.Rig.Network.Camera.RoiForFixedStartCJMS11 { return null; } + + if (NetCamera.CameraCfg.DebugLevel != DebugMode.Simulate && NetCamera.IPAddress == null) + { + log.WarnFormat( "Skipping GrabImageOp for ROI '{0}': camera '{1}' was not detected.", Name, NetCamera.Name); + return null; + } int imageCount = Math.Max(1, RoiPicCount); diff --git a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs index 513deed04..382178bc4 100644 --- a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs +++ b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvance/StandingStartMassCollectionAdvanceSeq.cs @@ -643,10 +643,14 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance (rr as Rig.Network.Camera.RoiForFixedStart.Roi).BeginWMState = dataEntryCmpnt.WMStartState(i); if (rr is Rig.Network.Camera.RoiForFixedStartKeyence.Roi) { - (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).BeginWMState = - dataEntryCmpnt.WMStartState(i); + (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).BeginWMState = dataEntryCmpnt.WMStartState(i); log.DebugFormat("BeginWMState [{0}] -> RoiForFixedStartKeyence.Roi",dataEntryCmpnt.WMStartState(i)); } + if (rr is Rig.Network.Camera.RoiForFixedStartCJMS11.Roi) + { + (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).BeginWMState = dataEntryCmpnt.WMStartState(i); + log.DebugFormat("BeginWMState [{0}] -> RoiForFixedStartCJMS11.Roi",dataEntryCmpnt.WMStartState(i)); + } } } @@ -981,7 +985,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance e = StateMachine.WaitRunDevsRunOps(); if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; } } - while (!e.Contains(Event.TestInProgress/*Event.ModelessFormClosed*/)); + while (!e.Contains(Event.TestInProgress/*Event.ModelessFormClosed*/) && !e.Contains(Event.TestCompleted)); if (heatMetersTestParams != null) @@ -1019,6 +1023,13 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance dataEntryCmpnt.WMEndState(i); log.DebugFormat(" StandingStartMassCollectionAdvanceSeq.cs - EndWMState [{0}] -> RoiForFixedStartKeyence.Roi",dataEntryCmpnt.WMEndState(i)); } + + if (rr is Rig.Network.Camera.RoiForFixedStartCJMS11.Roi) + { + (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).EndWMState = + dataEntryCmpnt.WMEndState(i); + log.DebugFormat(" StandingStartMassCollectionAdvanceSeq.cs - EndWMState [{0}] -> RoiForFixedStartCJMS11.Roi",dataEntryCmpnt.WMEndState(i)); + } } } diff --git a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs index 4192cd75c..882562da3 100644 --- a/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs +++ b/TBF/Rig/TestMethods/StandingStartMassCollectionAdvanceCollect/StandingStartMassCollectionAdvanceCollectSeq.cs @@ -159,20 +159,16 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvanceCollect if (rr is Rig.Network.Camera.RoiForFixedStartKeyence.Roi) { - (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).EndWMState = - dataEntryCmpnt.WMEndState(i); - (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).BeginWMState = - dataEntryCmpnt.WMStartState(i); + (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).EndWMState = dataEntryCmpnt.WMEndState(i); + (rr as Rig.Network.Camera.RoiForFixedStartKeyence.Roi).BeginWMState = dataEntryCmpnt.WMStartState(i); log.DebugFormat(" StandingStartMassCollectionAdvanceSeq.cs - BeginWMState [{0}], EndWMState [{1}] -> RoiForFixedStartKeyence.Roi",dataEntryCmpnt.WMStartState(i),dataEntryCmpnt.WMEndState(i)); } //New camera CJMS11 - supplier Java Microservices, s.r.o if (rr is Rig.Network.Camera.RoiForFixedStartCJMS11.Roi) { - (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).EndWMState = - dataEntryCmpnt.WMEndState(i); - (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).BeginWMState = - dataEntryCmpnt.WMStartState(i); + (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).EndWMState = dataEntryCmpnt.WMEndState(i); + (rr as Rig.Network.Camera.RoiForFixedStartCJMS11.Roi).BeginWMState = dataEntryCmpnt.WMStartState(i); log.DebugFormat(" StandingStartMassCollectionAdvanceSeq.cs - BeginWMState [{0}], EndWMState [{1}] -> RoiForFixedStartCJMS11.Roi",dataEntryCmpnt.WMStartState(i),dataEntryCmpnt.WMEndState(i)); } }