using Cognex.VisionPro; using MaterialDesignThemes.Wpf; using Prism.Commands; using Prism.Events; using Prism.Ioc; using Prism.Mvvm; using Prism.Regions; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Linq; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using Team.FFFeederService.Interfaces; using TeamAAS_VP; using TeamAAS_VP.Controls; using TeamAAS_VP.Core; using TeamAAS_VP.Data; using TeamAAS_VP.Enums; using TeamAAS_VP.Events; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; using TeamAAS_VP.Models.Lights; using TeamAAS_VP.Resources.Languages; using TeamAAS_VP.Services; using static NPOI.HSSF.Util.HSSFColor; namespace TeamAAS_VP.ViewModels.Product { public class CameraParamsViewModel : BindableBase, IConfirmNavigationRequest { IRegionManager _regionManager; IEventAggregator _eventAggregator; IContainerProvider _container; IDialogService _dialogService; IConfigService _configService; IRobotService _robotService; ICameraService _cameraService; IFeederService _feederService; IProductService _productService; IRemoteCommandService _remoteCommandService; ISystemDatabaseService _systemDatabaseService; ILightManagerService _lightManagerService; // 创建Channel private readonly Channel<(int channel, int brightness)> _brightnessChannel; private CancellationTokenSource _cancellationTokenSource; #region 属性 private ProductModel _SelectProduct; /// /// 选中的产品 /// public ProductModel SelectProduct { get { return _SelectProduct; } set { SetProperty(ref _SelectProduct, value); } } private ProcedureModel _SelectProcedure; /// /// 选中的流程 /// public ProcedureModel SelectProcedure { get { return _SelectProcedure; } set { SetProperty(ref _SelectProcedure, value); } } private bool _IsHaveFeeder=false; public bool IsHaveFeeder { get { return _IsHaveFeeder; } set { SetProperty(ref _IsHaveFeeder, value); } } private bool _IsHaveRobot = false; public bool IsHaveRobot { get { return _IsHaveRobot; } set { SetProperty(ref _IsHaveRobot, value); } } private IRobot _Robot; public IRobot Robot { get { return _Robot; } set { SetProperty(ref _Robot, value); } } private ICamera _Camera; public ICamera Camera { get { return _Camera; } set { SetProperty(ref _Camera, value); } } public IVoiceCoilMotorFeeder Feeder { get; set; } private ICogImage _Image; public ICogImage Image { get { return _Image; } set { SetProperty(ref _Image, value); } } private string _Message; public string Message { get { return _Message; } set { SetProperty(ref _Message, value); } } private float _ExposureTime; /// /// 相机曝光时间 /// public float ExposureTime { get { return _ExposureTime; } set { SetProperty(ref _ExposureTime, value); SelectProcedure.ExposureTime = value; if (Camera != null) { try { Camera.SetExposureTime(value); } catch (Exception) { } } } } private float _Gain; /// /// 相机增益 /// public float Gain { get { return _Gain; } set { SetProperty(ref _Gain, value); SelectProcedure.Gain=value; if (Camera != null) { try { Camera.SetGain(value); } catch (Exception) { } } } } private bool _IsGrap=true; public bool IsGrap { get { return _IsGrap; } set { SetProperty(ref _IsGrap, value); } } #endregion #region 命令 private DelegateCommand _NextCommand; public DelegateCommand NextCommand => _NextCommand ?? (_NextCommand = new DelegateCommand(ExecuteNextCommand)); private DelegateCommand _BackCommand; public DelegateCommand BackCommand => _BackCommand ?? (_BackCommand = new DelegateCommand(ExecuteBackCommand)); private DelegateCommand _LoadedCommand; public DelegateCommand LoadedCommand => _LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand)); private DelegateCommand _LightValueChangedCommand; public DelegateCommand LightValueChangedCommand => _LightValueChangedCommand ?? (_LightValueChangedCommand = new DelegateCommand(ExecuteLightValueChangedCommand)); private DelegateCommand _StartGrabbingCommand; public DelegateCommand StartGrabbingCommand => _StartGrabbingCommand ?? (_StartGrabbingCommand = new DelegateCommand(ExecuteStartGrabbingCommand).ObservesProperty(() => IsGrap)); private DelegateCommand _StopGrabbingCommand; public DelegateCommand StopGrabbingCommand => _StopGrabbingCommand ?? (_StopGrabbingCommand = new DelegateCommand(ExecuteStopGrabbingCommand).ObservesProperty(() => IsGrap)); private DelegateCommand _LightValueAddCommand; public DelegateCommand LightValueAddCommand => _LightValueAddCommand ?? (_LightValueAddCommand = new DelegateCommand(ExecuteLightValueAddCommand)); private DelegateCommand _LightValueSubCommand; public DelegateCommand LightValueSubCommand => _LightValueSubCommand ?? (_LightValueSubCommand = new DelegateCommand(ExecuteLightValueSubCommand)); private DelegateCommand _SetChannelBrightnessCommand; public DelegateCommand SetChannelBrightnessCommand => _SetChannelBrightnessCommand ?? (_SetChannelBrightnessCommand = new DelegateCommand(ExecuteSetChannelBrightnessCommand)); private DelegateCommand _TurnOnCommand; public DelegateCommand TurnOnCommand => _TurnOnCommand ?? (_TurnOnCommand = new DelegateCommand(ExecuteTurnOnCommand)); private DelegateCommand _TurnOffCommand; public DelegateCommand TurnOffCommand => _TurnOffCommand ?? (_TurnOffCommand = new DelegateCommand(ExecuteTurnOffCommand)); #endregion #region 事件 #endregion public CameraParamsViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IDialogService dialogService, IConfigService configService, IRobotService robotService, ICameraService cameraService, IFeederService feederService, IProductService productService, IRemoteCommandService remoteCommandService, ISystemDatabaseService systemDatabaseService, ILightManagerService lightManagerService) { _regionManager = regionManager; _eventAggregator = ea; _container = container; _dialogService = dialogService; _configService = configService; _robotService = robotService; _cameraService = cameraService; _feederService = feederService; _systemDatabaseService = systemDatabaseService; //订阅权限登录事件 _eventAggregator.GetEvent().Subscribe(LoginChange); _productService = productService; _remoteCommandService = remoteCommandService; _lightManagerService = lightManagerService; // 创建有界Channel,容量为1,只保留最新的亮度值 _brightnessChannel = Channel.CreateBounded<(int channel, int brightness)>( new BoundedChannelOptions(1) // 容量为1 { // 当Channel满时,丢弃最旧的值,写入新的值 FullMode = BoundedChannelFullMode.DropOldest, // 允许多个UI线程写入(虽然通常只有一个) SingleWriter = false, // 只有一个消费者读取并发送到设备 SingleReader = true }); _cancellationTokenSource = new CancellationTokenSource(); // 启动消费者任务 StartDeviceConsumer(); } #region 方法 // 消费者:从Channel读取并发送到设备 private async void StartDeviceConsumer() { try { while (await _brightnessChannel.Reader.WaitToReadAsync(_cancellationTokenSource.Token)) { while (_brightnessChannel.Reader.TryRead(out var obj)) { // 实际写入(底层方法可能不支持取消) var success = await _lightManagerService.SetGlobalChannelBrightnessAsync(obj.channel, obj.brightness); } } } catch (OperationCanceledException) { // 正常结束 } finally { _brightnessChannel.Writer.Complete(); } } /// /// 下一步 /// async void ExecuteNextCommand() { SelectProcedure.ExposureTime = ExposureTime; SelectProcedure.Gain = Gain; if (Camera != null) { Camera.StopGrabbing(); Camera.ImageCallbackEvent -= Camera_ImageCallbackEvent; } //判断Toolblock是否存在 if (SelectProcedure.ToolBlock==null) { var view = new WaitingControl(); //show the dialog var task = DialogHost.Show(view, "RootDialog", null, null,null); await _productService.LoadProcedureVisionToolsAsync(SelectProduct.ID, SelectProcedure.CameraId, SelectProcedure.Name); if (DialogHost.IsDialogOpen("RootDialog")) { DialogHost.Close("RootDialog"); } await task; } NavigationParameters param = new NavigationParameters(); param.Add("SelectProduct", SelectProduct); param.Add("SelectedProcedure", SelectProcedure); if (SelectProcedure.VisionModel == Enums.VisionModel.Simple) { _regionManager.RequestNavigate("ProductRegionContext", "SimpleProcedure", param); } else { _regionManager.RequestNavigate("ProductRegionContext", "AdvancedProcedure", param); } } /// /// 上一步 /// void ExecuteBackCommand() { if (Camera != null) { Camera.StopGrabbing(); Camera.ImageCallbackEvent -= Camera_ImageCallbackEvent; } NavigationParameters param = new NavigationParameters(); param.Add("SelectProduct", SelectProduct); param.Add("SelectedProcedure", SelectProcedure); _regionManager.RequestNavigate("ProductRegionContext", "ProcessBasics", param); } async void ExecuteLoadedCommand() { if (_systemDatabaseService.GetCurrentUser().userPart == Enums.UserPart.Operator) { IsAllowEdit = false; } else { IsAllowEdit = true; } } private void Camera_ImageCallbackEvent(ICogImage image,TimeSpan totaltime,string errormessage, Guid id) { Image = image; App.Current.Dispatcher.Invoke(new Action(() => { if (errormessage != null && !string.IsNullOrEmpty(errormessage)) { Message = $"{Lang.耗时}:{totaltime.TotalMilliseconds.ToString("F1")} ms Error:{errormessage}"; } else { Message = $"{Lang.耗时}:{totaltime.TotalMilliseconds.ToString("F1")} ms"; } })); } /// /// 光源亮度调整时 /// async void ExecuteLightValueChangedCommand(double? lightvalue) { try { if (lightvalue == null) return; if (Feeder == null || !Feeder.IsConnected) return; await Feeder.SetLightValueAsync((ushort)lightvalue); } catch (Exception ex) { LogHelper.WriteLogError("产品实时图像界面-Feeder光源亮度更改时出错!", ex); } } /// /// 为指定通道应用亮度设置(仅更新模型并在可能时尝试通知硬件)。 /// /// 要设置的通道配置。 async void ExecuteSetChannelBrightnessCommand(object obj) { try { if (!(obj is Tuple parameter)) return; if (!(parameter.Item1 is ChannelConfig channel)) return; int newValue = (int)parameter.Item2; // 尝试写入Channel(非阻塞) try { // 如果Channel满了(有旧值),DropOldest策略会自动丢弃旧值 await _brightnessChannel.Writer.WriteAsync( (channel.GlobalIndex, newValue), _cancellationTokenSource.Token); } catch (OperationCanceledException) { // 正常取消,无需处理 } catch (ChannelClosedException) { // Channel已关闭 } } catch (Exception ex) { LogHelper.WriteLogError("产品实时图像界面-设置光源通道亮度时出错!", ex); } } /// /// 关闭光源 /// /// async void ExecuteTurnOffCommand(object parameter) { try { if (!(parameter is ChannelConfig channel)) return; await _lightManagerService.TurnOffGlobalChannelAsync(channel.GlobalIndex); } catch (Exception ex) { LogHelper.WriteLogError("关闭通道光源时出错!", ex); } } /// /// 打开光源 /// /// async void ExecuteTurnOnCommand(object parameter) { try { if (!(parameter is ChannelConfig channel)) return; await _lightManagerService.TurnOnGlobalChannelAsync(channel.GlobalIndex); } catch (Exception ex) { LogHelper.WriteLogError("打开通道光源时出错!", ex); } } void ExecuteLightValueSubCommand() { SelectProcedure.LightValue--; } void ExecuteLightValueAddCommand() { SelectProcedure.LightValue++; } /// /// 停止采集 /// void ExecuteStopGrabbingCommand() { IsGrap = false; if (Camera != null) Camera.StopGrabbing(); IsGrap = true; } /// /// 开始采集 /// void ExecuteStartGrabbingCommand() { IsGrap = false; if (Camera != null) Camera.StartGrabbing(); IsGrap = true; } #endregion #region 继承 /// /// 确认导航请求时调用。此方法允许您在导航之前执行一些操作。 /// /// /// public void ConfirmNavigationRequest(NavigationContext navigationContext, Action continuationCallback) { continuationCallback(true); } /// /// 接收导航请求时调用。传入导航参数,包含有关导航目标的信息。 /// /// /// public async void OnNavigatedTo(NavigationContext navigationContext) { try { SelectProduct = navigationContext.Parameters.GetValue("SelectProduct"); SelectProcedure = navigationContext.Parameters.GetValue("SelectedProcedure"); if (SelectProcedure.RobotId != Guid.Empty) { IsHaveRobot = true; Robot = _robotService.GetRobot(SelectProcedure.RobotId); if (Robot != null) { Robot.EnterDebugMode = true; } } else { IsHaveRobot = false; } if (SelectProcedure.FeederId != Guid.Empty) { IsHaveFeeder = true; Feeder = _feederService.GetFeeder(SelectProcedure.FeederId); if (Feeder.IsConnected && !_remoteCommandService.IsExecuting) { await Feeder.OpenLightAsync(); await Feeder.SetLightValueAsync((ushort)SelectProcedure.LightValue); } } else { IsHaveFeeder = false; } Camera = _cameraService.GetCamera(SelectProcedure.CameraId); if (SelectProcedure.ExposureTime == 0) { SelectProcedure.ExposureTime = 5000; } ExposureTime = SelectProcedure.ExposureTime; Gain = SelectProcedure.Gain; if (Camera != null && !_remoteCommandService.IsExecuting) { Camera.SetExposureTime(ExposureTime); Camera.SetGain(Gain); Camera.ImageCallbackEvent += Camera_ImageCallbackEvent; //Camera.Grab(); } } catch (Exception ex) { LogHelper.WriteLogError("相机流程界面进入时出错!", ex); } } /// /// 是否允许导航到此视图模型。 /// /// /// public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } /// /// 导航离开此视图模型时调用。您可以在此处执行清理操作或保存状态。 /// /// public void OnNavigatedFrom(NavigationContext navigationContext) { if (Robot!=null) { Robot.EnterDebugMode = false; } ExecuteStopGrabbingCommand(); } #endregion private bool _IsAllowEdit = false; public bool IsAllowEdit { get { return _IsAllowEdit; } set { SetProperty(ref _IsAllowEdit, value); } } private void LoginChange(Models.User user) { if (user.userPart == Enums.UserPart.Operator) { IsAllowEdit = false; } else { IsAllowEdit = true; } } } }