Merge branch 'develop/SLM-PT50' into develop/SLM-PT50-7-2026-merged-smart-cam-slm-mex

This commit is contained in:
Marek Frniak 2026-07-23 08:53:37 +02:00
commit 2953b47d99
7 changed files with 610 additions and 283 deletions

View File

@ -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<string>[] startImageLists = new List<string>[TBF.Data.WMsCount];
private readonly List<string>[] endImageLists = new List<string>[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<string>();
endImageLists[i] = new List<string>();
}
log.FatalFormat("{0} initialized: {1}", Name, this);
}
/// <returns>Reference to the operation</returns>
@ -202,15 +202,19 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder
/// <param name="errLimLo"></param>
/// <param name="errLimHi"></param>
/// <returns></returns>
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
/// <summary>Start this operation</summary>
public void Start()
{
log.WarnFormat( "EntryForm.Start: currentOp={0}, modelessDlg={1}, resultSaved={2}",
currentOp,
modelessDlg == null ? "<null>" : modelessDlg.GetType().FullName,
resultSaved);
resultSaved = false;
switch (currentOp)
{
@ -383,95 +410,80 @@ namespace TBF.Rig.DataEntry.StandartCameraPurchaseOrder
/// <returns>Event.ResultsPrinted</returns>
public Event Run()
{
log.WarnFormat( "EntryForm.Run: currentOp={0}, modelessDlg={1}, completed={2}, resultSaved={3}",
currentOp,
modelessDlg == null ? "<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;
}
/// <summary>Stop this operation</summary>
@ -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]);
}
}
}
}
}

View File

@ -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;
}
/// <summary>
/// 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();
}
/// <summary>
@ -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;
}
/// <summary>
/// load group of images
/// </summary>
/// <param name="baseImageFileName"></param>
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<string> 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 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 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;
}
/// <summary>
/// grouping by time
/// </summary>
@ -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é 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 ---

View File

@ -2337,6 +2337,49 @@ namespace TBF.Rig.Network.Camera.CJMS11
}
}
/// <summary>
/// pouziva LiveStreamOp - pre nahlad
/// </summary>
/// <param name="hiResolution"></param>
public void StartLiveStream(bool hiResolution)
{
if (CameraCfg.DebugLevel == DebugMode.Simulate)
return;
StartLiveStreamListener();
}
/// <summary>
/// pouziva LiveStreamOp - pre ukoncenie nahladu
/// </summary>
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);
}
}
/// <summary>
/// listener for multiple - repetetive image receiving
/// </summary>
@ -2345,12 +2388,7 @@ namespace TBF.Rig.Network.Camera.CJMS11
/// </detail>
/// <param name="localIP"></param>
/// <param name="localPort"></param>
// 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);
}

View File

@ -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;
/// <summary>
/// Events: Event.None or Event.Error
/// </summary>
/// <param name="camera">CLP1611.Camera reference</param>
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);
}
}
}
}

View File

@ -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);

View File

@ -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));
}
}
}

View File

@ -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));
}
}