This commit is contained in:
meelstorm
2025-10-02 14:14:11 +02:00
parent 63afb2dcfb
commit 44748f2855
9 changed files with 193 additions and 99 deletions

View File

@@ -1,7 +1,33 @@
using System.Xml; using System.Xml;
using Hawkeye.VisionBuilder.Workflow; using Hawkeye.VisionBuilder.Workflow;
var files = Directory.GetFiles(AppContext.BaseDirectory, "*.hrcp", SearchOption.TopDirectoryOnly); // Check if directory argument is provided
if (args.Length == 0)
{
Console.WriteLine("Usage: RecipeConverter.exe <directory>");
Console.WriteLine("Example: RecipeConverter.exe C:\\MyRecipes");
return;
}
string targetDirectory = args[0];
// Validate directory exists
if (!Directory.Exists(targetDirectory))
{
Console.WriteLine($"Error: Directory '{targetDirectory}' does not exist.");
return;
}
var files = Directory.GetFiles(targetDirectory, "*.hrcp", SearchOption.TopDirectoryOnly);
if (files.Length == 0)
{
Console.WriteLine($"No *.hrcp files found in directory '{targetDirectory}'");
return;
}
Console.WriteLine($"Found {files.Length} recipe file(s) in '{targetDirectory}'");
foreach (var file in files) foreach (var file in files)
{ {
try try
@@ -10,7 +36,12 @@ foreach (var file in files)
var f = File.OpenRead(file); var f = File.OpenRead(file);
WorkflowList list = new WorkflowList(); WorkflowList list = new WorkflowList();
list.Load(new BinaryReader(f), new OperationDiscoveryService(list)); list.Load(new BinaryReader(f), new OperationDiscoveryService(list));
list.SaveJSON(Path.GetFileNameWithoutExtension(file)+".jhrcp");
// Save the converted file in the same directory as the source
string outputPath = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(file) + ".jhrcp");
list.SaveJSON(outputPath);
Console.WriteLine($"Saved: {outputPath}");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -41,6 +41,7 @@ namespace Inspectron.Camera.UEye
{ {
uEye.Defines.ColorMode mode; uEye.Defines.ColorMode mode;
_camera.PixelFormat.Get(out mode); _camera.PixelFormat.Get(out mode);
int channels = 0; int channels = 0;
if (mode == uEye.Defines.ColorMode.Mono8) if (mode == uEye.Defines.ColorMode.Mono8)
@@ -53,7 +54,7 @@ namespace Inspectron.Camera.UEye
} }
else if (mode == uEye.Defines.ColorMode.BGRA8Packed) else if (mode == uEye.Defines.ColorMode.BGRA8Packed)
{ {
channels = 3; channels = 4;
} }
else else
{ {
@@ -68,8 +69,17 @@ namespace Inspectron.Camera.UEye
Byte[] u8img; Byte[] u8img;
_camera.Memory.CopyToArray(idx, out u8img); _camera.Memory.CopyToArray(idx, out u8img);
Mat mat = new Mat(size.Height,pitch, MatType.CV_8UC(channels));
mat.SetArray(u8img); // Warning! This will work only if pitch == width * channels
if (pitch != size.Width * channels)
{
throw new Exception("pitch must be equal to width * channels");
}
Mat mat = new Mat(size.Height, size.Width,MatType.CV_8UC3);
// copy data to mat
System.Runtime.InteropServices.Marshal.Copy(u8img, 0, mat.Data, u8img.Length);
return mat; return mat;
} }
@@ -88,14 +98,13 @@ namespace Inspectron.Camera.UEye
} }
uEye.Types.SensorInfo info = new uEye.Types.SensorInfo(); uEye.Types.SensorInfo info = new uEye.Types.SensorInfo();
_camera.Information.GetSensorInfo(out info); _camera.Information.GetSensorInfo(out info);
Console.WriteLine($"Camera {cameraIdx} opened: {info.SensorName} ({info.SensorID})"); Log.Information($"Camera {cameraIdx} opened: {info.SensorName} ({info.SensorID})");
_camera.Parameter.Load(); _camera.Parameter.Load();
Console.WriteLine($"Camera {cameraIdx} parameters loaded"); Log.Information($"Camera {cameraIdx} parameters loaded");
_camera.Trigger.Set(uEye.Defines.TriggerMode.Continuous); _camera.Trigger.Set(uEye.Defines.TriggerMode.Continuous);
statusRet = _camera.Memory.Allocate(); statusRet = _camera.Memory.Allocate();
Console.WriteLine("Memory allocated");
if (statusRet != uEye.Defines.Status.Success) if (statusRet != uEye.Defines.Status.Success)
{ {
throw new Exception("Allocate Memory failed"); throw new Exception("Allocate Memory failed");

View File

@@ -16,5 +16,9 @@
<Private>false</Private> <Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\VisionBuilder.UI.Statistics\VisionBuilder.UI.Statistics.csproj" >
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,6 @@
using VisionBuilder.UI.Common; using Serilog;
using VisionBuilder.UI.Common;
using VisionBuilder.UI.Statistics;
namespace B24SiemensPlugin; namespace B24SiemensPlugin;
@@ -6,13 +8,15 @@ public class SiemensCameraModule: IVisionBuilderModule
{ {
private readonly SingleCameraVM _singleCameraVm; private readonly SingleCameraVM _singleCameraVm;
private readonly B24SiemensSettings _settings; private readonly B24SiemensSettings _settings;
private readonly VisionBuilderStatistics _statistics;
private SiemensServer _server; private SiemensServer _server;
public SiemensCameraModule(SingleCameraVM singleCameraVm,B24SiemensSettings settings) public SiemensCameraModule(SingleCameraVM singleCameraVm,B24SiemensSettings settings, VisionBuilderStatistics statistics)
{ {
_singleCameraVm = singleCameraVm; _singleCameraVm = singleCameraVm;
_settings = settings; _settings = settings;
_statistics = statistics;
} }
public void InitializeModule() public void InitializeModule()
@@ -32,6 +36,11 @@ public class SiemensCameraModule: IVisionBuilderModule
} }
private PLCPacket _server_OnPLCPacket(PLCPacket packet) private PLCPacket _server_OnPLCPacket(PLCPacket packet)
{ {
if (_singleCameraVm.SynchronizationContext == null)
{
Log.Warning("Synchronization context is null, cannot update UI from PLC packet.");
return packet;
}
packet.KameraStart= _singleCameraVm.IsRunning; packet.KameraStart= _singleCameraVm.IsRunning;
var recipe = GetMapping(packet.Materialnummer); var recipe = GetMapping(packet.Materialnummer);
var selectedRecipe = _singleCameraVm.SelectedRecipe; var selectedRecipe = _singleCameraVm.SelectedRecipe;
@@ -45,7 +54,7 @@ public class SiemensCameraModule: IVisionBuilderModule
{ {
_singleCameraVm.ProcessRecipeSelectionVm(vm); _singleCameraVm.ProcessRecipeSelectionVm(vm);
}, null); }, null);
_statistics.Metadata = packet.Materialnummer.ToString();
} }
} }

View File

@@ -14,4 +14,6 @@ public class ImageProcessedEvent:IEvent
public bool HasError { get; set; } public bool HasError { get; set; }
public List<string> ErrorNames { get; set; } public List<string> ErrorNames { get; set; }
public TimeSpan AnalysisTime { get; set; } public TimeSpan AnalysisTime { get; set; }
public TimeSpan AcquisitionTime { get; set; }
public TimeSpan SleepTime { get; set; }
} }

View File

@@ -27,13 +27,19 @@ public abstract class BaseRecognitionControl: IRecognitionControl
public void SetRecipe(RecipeData recipe) public void SetRecipe(RecipeData recipe)
{ {
lock (_lock)
{
// error if running // error if running
if (IsRunning) if (IsRunning)
{ {
throw new InvalidOperationException("Cannot change recipe while recognition is running."); throw new InvalidOperationException("Cannot change recipe while recognition is running.");
} }
_currentRecipe = recipe; _currentRecipe = recipe;
} }
}
public bool IsRunning { get; set; } public bool IsRunning { get; set; }
public bool IsPaused { get; set; } public bool IsPaused { get; set; }
@@ -44,17 +50,24 @@ public abstract class BaseRecognitionControl: IRecognitionControl
private DateTime _startTime; private DateTime _startTime;
object _lock = new object();
public void Start() public void Start()
{ {
lock (_lock)
{
if (_currentRecipe == null) if (_currentRecipe == null)
{ {
throw new InvalidOperationException("No recipe set."); throw new InvalidOperationException("No recipe set.");
} }
if (IsRunning) if (IsRunning)
{ {
throw new InvalidOperationException("Recognition is already running."); throw new InvalidOperationException("Recognition is already running.");
} }
_loadingService.StartLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}..."); _loadingService.StartLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
Initialize(_currentRecipe); Initialize(_currentRecipe);
_startTime = DateTime.Now; _startTime = DateTime.Now;
@@ -85,6 +98,9 @@ public abstract class BaseRecognitionControl: IRecognitionControl
}); });
_loadingService.StopLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}..."); _loadingService.StopLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
}
} }
protected abstract void Initialize(RecipeData currentRecipe); protected abstract void Initialize(RecipeData currentRecipe);
@@ -94,9 +110,14 @@ public abstract class BaseRecognitionControl: IRecognitionControl
protected abstract (Mat originalImage, Mat analysisImage, TimeSpan processingTime, TimeSpan acquisitionTime, string[] errorNames)? ProcessImage(CancellationToken token); protected abstract (Mat originalImage, Mat analysisImage, TimeSpan processingTime, TimeSpan acquisitionTime, string[] errorNames)? ProcessImage(CancellationToken token);
public void Stop() public void Stop()
{
lock (_lock)
{ {
if (!IsRunning) if (!IsRunning)
return; return;
_loadingService.StartLoading($"Stopping {_settings.CameraName}"); _loadingService.StartLoading($"Stopping {_settings.CameraName}");
_cts?.Cancel(); _cts?.Cancel();
try try
@@ -130,16 +151,23 @@ public abstract class BaseRecognitionControl: IRecognitionControl
_loadingService.StopLoading($"Stopping {_settings.CameraName}"); _loadingService.StopLoading($"Stopping {_settings.CameraName}");
IsPaused = false; // ensure paused is reset IsPaused = false; // ensure paused is reset
} }
}
public void Pause() public void Pause()
{
lock (_lock)
{ {
IsPaused = true; IsPaused = true;
} }
}
public void Resume() public void Resume()
{
lock (_lock)
{ {
IsPaused = false; IsPaused = false;
} }
}
int _errorsInSequence = 0; int _errorsInSequence = 0;
@@ -161,10 +189,13 @@ public abstract class BaseRecognitionControl: IRecognitionControl
{ {
return; return;
} }
int sleepTime=0;
if (processed.Value.processingTime.Milliseconds < _settings.MinimumProcessingTime) if (processed.Value.processingTime.Milliseconds < _settings.MinimumProcessingTime)
{ {
Thread.Sleep(_settings.MinimumProcessingTime - (int)processed.Value.processingTime.Milliseconds);
sleepTime = _settings.MinimumProcessingTime - (int)processed.Value.processingTime.Milliseconds;
Log.Debug("Sleeping for {sleepTime}",sleepTime);
Thread.Sleep(sleepTime);
} }
if (processed.Value.errorNames.Length > 0) if (processed.Value.errorNames.Length > 0)
@@ -185,6 +216,8 @@ public abstract class BaseRecognitionControl: IRecognitionControl
SessionStart = _startTime, SessionStart = _startTime,
RecipeName = _currentRecipe.RecipeName, RecipeName = _currentRecipe.RecipeName,
AnalysisTime = processed.Value.processingTime - processed.Value.acquisitionTime, AnalysisTime = processed.Value.processingTime - processed.Value.acquisitionTime,
AcquisitionTime = processed.Value.acquisitionTime,
SleepTime = TimeSpan.FromMilliseconds(sleepTime),
ErrorNames = processed.Value.errorNames.ToList(), ErrorNames = processed.Value.errorNames.ToList(),
HasError = processed.Value.errorNames.Length > 0, HasError = processed.Value.errorNames.Length > 0,
ImageSource = _settings.CameraName, ImageSource = _settings.CameraName,
@@ -195,7 +228,7 @@ public abstract class BaseRecognitionControl: IRecognitionControl
var swProcessed = Stopwatch.StartNew(); var swProcessed = Stopwatch.StartNew();
ImageProcessed(processingResult); ImageProcessed(processingResult);
swProcessed.Stop(); swProcessed.Stop();
Log.Information($"ImageProcessed event handled in {swProcessed.ElapsedMilliseconds} ms"); Log.Information("ImageProcessed event handled in {processed} ms", swProcessed.ElapsedMilliseconds);
} }

View File

@@ -57,8 +57,8 @@ namespace VisionBuilder.UI.Common
public bool CanStop => IsRunning; public bool CanStop => IsRunning;
public bool CanStart => !IsRunning && SelectedRecipe!=null; public bool CanStart => !IsRunning && SelectedRecipe!=null;
public bool CanPause => (IsRunning && !IsPaused)&&_uiConfiguration.ShowPauseButton; public bool CanPause => (IsRunning && !IsPaused);
public bool CanResume => (IsRunning && IsPaused) && _uiConfiguration.ShowPauseButton; public bool CanResume => (IsRunning && IsPaused);
@@ -129,15 +129,16 @@ namespace VisionBuilder.UI.Common
CurrentRecipeName = SelectedRecipe?.RecipeName ?? "Select recipe"; CurrentRecipeName = SelectedRecipe?.RecipeName ?? "Select recipe";
} }
[RelayCommand(CanExecute = nameof(CanStart))] [RelayCommand(CanExecute = nameof(CanStart))]
public async Task Start() public async Task Start()
{ {
IsRunning = true; IsRunning = true;
await Task.Run(() => await Task.Run(() => { _recognitionControl.Start(); });
{
_recognitionControl.Start();
});
_handlingEnabled = true; _handlingEnabled = true;
} }

View File

@@ -48,6 +48,11 @@ namespace VisionBuilder.UI.Statistics
private void _recognitionControl_SessionEnded(SessionEndedEvent obj) private void _recognitionControl_SessionEnded(SessionEndedEvent obj)
{ {
if (_csvStatistics == null)
{
Log.Warning("Session ended but CSV statistics is null, nothing to do.");
return;
}
var endedAt = obj.SessionEnded; var endedAt = obj.SessionEnded;
_endTime = endedAt; _endTime = endedAt;
Log.Information("Start processing statistics"); Log.Information("Start processing statistics");

View File

@@ -8,7 +8,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>Inspectron icon-512.ico</ApplicationIcon> <ApplicationIcon>Inspectron icon-512.ico</ApplicationIcon>
<Deterministic>false</Deterministic> <Deterministic>false</Deterministic>
<Version>1.0.6</Version> <Version>1.0.7</Version>
</PropertyGroup> </PropertyGroup>