181 lines
5.7 KiB
C#
181 lines
5.7 KiB
C#
using OrpaonVision.SiteApp.Runtime.Services;
|
||
using System.ComponentModel;
|
||
using System.Runtime.CompilerServices;
|
||
using System.Windows.Media;
|
||
|
||
namespace OrpaonVision.SiteApp.ViewModels
|
||
{
|
||
/// <summary>
|
||
/// 运行端主窗口 ViewModel。
|
||
/// </summary>
|
||
public sealed class MainWindowViewModel : INotifyPropertyChanged
|
||
{
|
||
private readonly ICameraService _cameraService;
|
||
private readonly IInferenceService _inferenceService;
|
||
private readonly IRuleEngineService _ruleEngineService;
|
||
private readonly IRuntimeStateMachineService _runtimeStateMachineService;
|
||
|
||
private string _statusText = "准备就绪。";
|
||
private Brush _statusBrush = Brushes.DarkGreen;
|
||
private string _layerText = "1/1";
|
||
private string _inferenceText = "-";
|
||
private string _decisionText = "-";
|
||
|
||
/// <summary>
|
||
/// 构造函数。
|
||
/// </summary>
|
||
public MainWindowViewModel(
|
||
ICameraService cameraService,
|
||
IInferenceService inferenceService,
|
||
IRuleEngineService ruleEngineService,
|
||
IRuntimeStateMachineService runtimeStateMachineService)
|
||
{
|
||
_cameraService = cameraService;
|
||
_inferenceService = inferenceService;
|
||
_ruleEngineService = ruleEngineService;
|
||
_runtimeStateMachineService = runtimeStateMachineService;
|
||
|
||
RefreshSnapshot();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 状态文本。
|
||
/// </summary>
|
||
public string StatusText
|
||
{
|
||
get => _statusText;
|
||
private set => SetProperty(ref _statusText, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 状态颜色。
|
||
/// </summary>
|
||
public Brush StatusBrush
|
||
{
|
||
get => _statusBrush;
|
||
private set => SetProperty(ref _statusBrush, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前层显示文本。
|
||
/// </summary>
|
||
public string LayerText
|
||
{
|
||
get => _layerText;
|
||
private set => SetProperty(ref _layerText, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 最近一次推理结果。
|
||
/// </summary>
|
||
public string InferenceText
|
||
{
|
||
get => _inferenceText;
|
||
private set => SetProperty(ref _inferenceText, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 最近一次规则判定结果。
|
||
/// </summary>
|
||
public string DecisionText
|
||
{
|
||
get => _decisionText;
|
||
private set => SetProperty(ref _decisionText, value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行一轮采集-推理-规则判定。
|
||
/// </summary>
|
||
public void RunOneCycle()
|
||
{
|
||
var snapshot = _runtimeStateMachineService.GetSnapshot();
|
||
|
||
var captureResult = _cameraService.CaptureFrame();
|
||
if (!captureResult.Succeeded || captureResult.Data is null)
|
||
{
|
||
SetError("相机采图失败。", captureResult.Message);
|
||
return;
|
||
}
|
||
|
||
var predictResult = _inferenceService.Predict(captureResult.Data);
|
||
if (!predictResult.Succeeded || predictResult.Data is null)
|
||
{
|
||
SetError("模型推理失败。", predictResult.Message);
|
||
return;
|
||
}
|
||
|
||
var inference = predictResult.Data;
|
||
InferenceText = $"{inference.Label} (置信度: {inference.Confidence:P0})";
|
||
|
||
var decisionResult = _ruleEngineService.Evaluate(snapshot.CurrentLayer, inference);
|
||
if (!decisionResult.Succeeded || decisionResult.Data is null)
|
||
{
|
||
SetError("规则判定失败。", decisionResult.Message);
|
||
return;
|
||
}
|
||
|
||
var decision = decisionResult.Data;
|
||
DecisionText = $"{decision.Code} - {decision.Message}";
|
||
|
||
StatusBrush = decision.IsPass ? Brushes.DarkGreen : Brushes.OrangeRed;
|
||
StatusText = decision.IsPass ? "当前层判定通过。" : "当前层判定 NG,请人工复核。";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 推进到下一层。
|
||
/// </summary>
|
||
public void MoveToNextLayer()
|
||
{
|
||
var moveResult = _runtimeStateMachineService.MoveToNextLayer();
|
||
if (!moveResult.Succeeded)
|
||
{
|
||
SetError("状态机切层失败。", moveResult.Message);
|
||
return;
|
||
}
|
||
|
||
RefreshSnapshot();
|
||
StatusBrush = Brushes.DarkGreen;
|
||
StatusText = moveResult.Message;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置运行状态。
|
||
/// </summary>
|
||
public void ResetRuntime()
|
||
{
|
||
_runtimeStateMachineService.Reset();
|
||
InferenceText = "-";
|
||
DecisionText = "-";
|
||
RefreshSnapshot();
|
||
StatusBrush = Brushes.DarkGreen;
|
||
StatusText = "运行状态已重置。";
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public event PropertyChangedEventHandler? PropertyChanged;
|
||
|
||
private void RefreshSnapshot()
|
||
{
|
||
var snapshot = _runtimeStateMachineService.GetSnapshot();
|
||
LayerText = $"{snapshot.CurrentLayer}/{snapshot.TotalLayers}";
|
||
}
|
||
|
||
private void SetError(string title, string message)
|
||
{
|
||
StatusBrush = Brushes.OrangeRed;
|
||
StatusText = $"{title} {message}";
|
||
}
|
||
|
||
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||
{
|
||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||
{
|
||
return;
|
||
}
|
||
|
||
field = value;
|
||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||
}
|
||
}
|
||
}
|