using Cognex.VisionPro;
using CSScripting;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using Team.FFFeederService.Interfaces;
using TeamAAS_VP.Core.PLCs;
using TeamAAS_VP.Core.ScrewDriver;
using TeamAAS_VP.Enums;
using TeamAAS_VP.Events;
using TeamAAS_VP.Interfaces;
using TeamAAS_VP.Models;
using TeamAAS_VP.Resources.Languages;
using TeamAAS_VP.ViewModels;
using TeamAAS_VP.ViewModels.Home;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace TeamAAS_VP.Core
{
public class Management : BindableBase
{
#region 字段
IRegionManager _regionManager;
IEventAggregator _eventAggregator;
IContainerProvider _container;
IConfigService _configService;
IRobotService _robotService;
ICameraService _cameraService;
IFeederService _feederService;
IPlcService _plcService;
ILightManagerService _lightManagerService;
IProductService _productService;
ICalibrationService _calibrationService;
IRemoteCommandService _remoteCommandService;
ISystemDatabaseService _systemDatabaseService;
IMesService _mesService;
Timer yieldtimer;
private DateTime StartTime = DateTime.Now;
///
/// 产品主sn
///
string ProductMainSN = "";
string wo = "";
#endregion
#region 属性
public string[] CsvData = new string[50];
public int[] ResultData = new int[200];
public string code = "";
List lockResultsAll = new List();//一个产品的总结果
private ObservableCollection _Renders;
private double _CTtime;
public int ResultDataCount;
private bool _ShowMes_Query;
///
/// 显示查询结果
///
public bool ShowMes_Query
{
get { return _ShowMes_Query; }
set { SetProperty(ref _ShowMes_Query, value); }
}
private bool _ShowMes_Result;
///
/// 显示上传结果
///
public bool ShowMes_Result
{
get { return _ShowMes_Result; }
set { SetProperty(ref _ShowMes_Result, value); }
}
///
/// ct
///
public double CTtime
{
get { return _CTtime; }
set { SetProperty(ref _CTtime, value); }
}
///
/// 显示界面
///
public ObservableCollection Renders
{
get { return _Renders; }
set { SetProperty(ref _Renders, value); }
}
private ProductModel _CurrentProduct;
///
/// 当前产品
///
public ProductModel CurrentProduct
{
get { return _CurrentProduct; }
set { SetProperty(ref _CurrentProduct, value); }
}
public BgCommunicate BgCommunicate { get; private set; }
public BgModbusTcpCommunicate BgModbusTcpCommunicate { get; private set; }
private ObservableCollection _Status = new ObservableCollection();
///
/// 状态栏集合
///
public ObservableCollection Status
{
get { return _Status; }
set { SetProperty(ref _Status, value); }
}
private Int64 _TotalQuantity;
///
/// 总产量
///
public Int64 TotalQuantity
{
get { return _TotalQuantity; }
set { SetProperty(ref _TotalQuantity, value); }
}
private Int64 _TotalQuantityToday;
///
/// 当天的总产量
///
public Int64 TotalQuantityToday
{
get { return _TotalQuantityToday; }
set { SetProperty(ref _TotalQuantityToday, value); }
}
private Int64 _CurrentUPH;
///
/// 当前的UPH
///
public Int64 CurrentUPH
{
get { return _CurrentUPH; }
set { SetProperty(ref _CurrentUPH, value); }
}
private Int64 _NgNumber;
///
/// 当前的NG数量
///
public Int64 NgNumber
{
get { return _NgNumber; }
set { SetProperty(ref _NgNumber, value); }
}
private double _Yield;
///
/// 当前的NG数量
///
public double Yield
{
get { return _Yield; }
set { SetProperty(ref _Yield, value); }
}
private XYD_ScrewDriver _ScrewDriver;
public XYD_ScrewDriver ScrewDriver
{
get { return _ScrewDriver; }
set { SetProperty(ref _ScrewDriver, value); }
}
public Dictionary BackupObject { get; set; } = new Dictionary();
#endregion
#region 命令
#endregion
#region 事件
#endregion
public Management(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IConfigService configService,
IRobotService robotService, ICameraService cameraService, IFeederService feederService, IPlcService plcService, IProductService productService,
ICalibrationService calibrationService, IRemoteCommandService remoteCommandService, ISystemDatabaseService systemDatabaseService, ILightManagerService lightManagerService, IMesService mesService)
{
_regionManager = regionManager;
_eventAggregator = ea;
_container = container;
_configService = configService;
_robotService = robotService;
_cameraService = cameraService;
_feederService = feederService;
_plcService = plcService;
_calibrationService = calibrationService;
yieldtimer = new Timer(DoYieldTime, null, 10000, 1000);
Renders = new ObservableCollection();
_configService = configService;
_productService = productService;
_remoteCommandService = remoteCommandService;
_systemDatabaseService = systemDatabaseService;
_lightManagerService = lightManagerService;
_mesService = mesService;
}
#region 初始化硬件模块
///
/// 初始化Feeder
///
///
public async Task<(bool IsSucceed, string Msg)> InitFeeders()
{
var feeders = _configService.GetAllFeeders();
StringBuilder sb = new StringBuilder();
foreach (var item in feeders)
{
_feederService.CreateFeeder(item.Id, item.FeederNo, item.FeederName, item.IP, item.Port, item.FeederBrand);
var feeder = _feederService.GetFeeder(item.Id);
Status.Add(new StatusInfo(item.Id, item.FeederName + $"{Lang.未连接}", new SolidColorBrush(Colors.Red)));
try
{
feeder.FeederConnectionStatusChanged += Management_FeederConnectionStatusChanged;
await feeder.ConnectAsync(); //连接Feeder
//SendTaskMessage($"{item.FeederName}已连接!", MessageLevel.Debug);
}
catch (Exception ex)
{
sb.AppendLine($"{item.FeederName}:{Lang.断开连接}![{ex.Message}]");
SendTaskMessage($"{item.FeederName}{Lang.断开连接}!", MessageLevel.Alarm);
}
}
if (sb.Length == 0)
{
return (true, "");
}
else
{
return (false, sb.ToString());
}
}
///
/// 初始化机器人
///
///
public async Task<(bool IsSucceed, string Msg)> InitRobots()
{
var robots = _configService.GetAllRobots();
StringBuilder sb = new StringBuilder();
foreach (var item in robots)
{
_robotService.CreateRobot(item.Id, item);
try
{
Status.Add(new StatusInfo(item.Id, item.RobotName + $"{Lang.未连接}", new SolidColorBrush(Colors.Red)));
var robot = _robotService.GetRobot(item.Id);
robot.ReceivedEvent += Management_ReceivedEvent;
robot.SendEvent += Management_SendEvent;
robot.ConnectedEvent += Management_ConnectedEvent;
robot.DisconnectedEvent += Management_DisconnectedEvent;
await robot.ConnectAsync(); //连接Robot
SendTaskMessage($"{item.RobotName}{Lang.已连接}!", MessageLevel.Debug);
}
catch (Exception ex)
{
sb.AppendLine($"{item.RobotName}:{Lang.断开连接}![{ex.Message}]");
SendTaskMessage($"{item.RobotName}{Lang.断开连接}!", MessageLevel.Alarm);
}
}
if (sb.Length == 0)
{
return (true, "");
}
else
{
return (false, sb.ToString());
}
}
///
/// 初始化PLC
///
///
public async Task<(bool IsSucceed, string Msg)> InitPlc()
{
var plcs = _configService.GetAllPlcs();
StringBuilder sb = new StringBuilder();
foreach (var item in plcs)
{
try
{
_plcService.CreatePlc(item.Id, item);
var plc = _plcService.GetPlc(item.Id);
Status.Add(new StatusInfo(item.Id, item.Name + $"{Lang.未连接}", new SolidColorBrush(Colors.Red)));
plc.ConnectChangedEvent += Management_PlcConnectChangedEvent;
await plc.ConnectAsync(); //连接PLC
//SendTaskMessage($"{item.Name}{Lang.已连接}!", MessageLevel.Debug);
}
catch (Exception ex)
{
sb.AppendLine($"{item.Name}:{Lang.断开连接}![{ex.Message}]");
SendTaskMessage($"{item.Name}{Lang.断开连接}!", MessageLevel.Alarm);
}
}
try
{
await WriteSystemParameterToPlcAsync(_configService.GetSystemConfiguration());
RegisterPlcMonitorAddress();
}
catch (Exception ex)
{
LogHelper.WriteLogError("为PLC写入系统参数和订阅变量时出错", ex);
}
if (sb.Length == 0)
{
return (true, "");
}
else
{
return (false, sb.ToString());
}
}
///
/// 初始化相机
///
///
public async Task<(bool IsSucceed, string Msg)> InitCameras()
{
var cameras = _configService.GetAllCameras();
StringBuilder sb = new StringBuilder();
foreach (var item in cameras)
{
if (item.DisplatConfigs != null)
{
foreach (var item1 in item.DisplatConfigs)
{
Renders.Add(new ShowRender() { Id = item1.Id, DisplayName = item1.DisplayName });
}
}
_cameraService.CreateCamera(item.Id, item);
try
{
var camera = _cameraService.GetCamera(item.Id);
Status.Add(new StatusInfo(item.Id, item.CameraName + $"{Lang.未连接}", new SolidColorBrush(Colors.Red)));
camera.CameraConnectChangedEvent += Management_CameraConnectChangedEvent;
camera.ImageCallbackEvent += Camera_ImageCallbackEvent;
try
{
if (await camera.OpenDeviceAsync())
{
SendTaskMessage($"{item.CameraName}{Lang.已连接}!", MessageLevel.Debug);
}
else
{
SendTaskMessage($"{item.CameraName}{Lang.连接失败}!", MessageLevel.Alarm);
sb.AppendLine($"{item.CameraName}:{Lang.连接失败}!");
}
}
catch (Exception ex)
{
SendTaskMessage($"{item.CameraName}{ex.Message}!", MessageLevel.Alarm);
sb.AppendLine($"{item.CameraName}:{ex.Message}!");
}
}
catch (Exception ex)
{
SendTaskMessage($"{item.CameraName}{Lang.连接失败}!", MessageLevel.Alarm);
sb.AppendLine($"{item.CameraName}:{Lang.连接失败}!:{ex.Message}");
}
}
_container.Resolve().Renders = Renders;
if (sb.Length == 0)
{
return (true, "");
}
else
{
return (false, sb.ToString());
}
}
private void Camera_ImageCallbackEvent(ICogImage arg1, TimeSpan arg2, string arg3, Guid cameraId)
{
var camera = _configService.GetCamera(cameraId);
SendTaskMessage($"相机[{camera.CameraName}]图像接收完成!", MessageLevel.Info);
//if (camera.CameraNo == 1)
//{
// ImageData[1] = 1;
//}
//else if (camera.CameraNo == 2)
//{
// ImageData[2] = 1;
//}
//else if (camera.CameraNo == 3)
//{
// ImageData[3] = 1;
// ImageData[4] = 1;
//}
//_eventAggregator.GetEvent().Publish(new ShowRender()
//{
// CameraName = camera.CameraName,
// Id = cameraId,
// Image = arg1,
// Graphic = null,
// Record = null,
// Result = false,
// IsShow = true,
//});
// 通知等待方:该相机新图到达
//SignalImageArrived(cameraId, arg1);
}
///
/// 初始化光源控制器
///
///
public async Task<(bool IsSucceed, string Msg)> InitLightControllers()
{
var lightcontrollers = _configService.GetAllLightControllers();
StringBuilder sb = new StringBuilder();
foreach (var item in lightcontrollers)
{
try
{
var lishtCtr = await _lightManagerService.RegisterControllerAsync(item.Id, item);
//var lightcontroller = _cameraService.GetLightController(item.Id);
//await lightcontroller.ConnectAsync(); //连接光源控制器
//SendTaskMessage($"{item.LightControllerName}{Lang.已连接}!", MessageLevel.Debug);
}
catch (Exception ex)
{
//sb.AppendLine($"{item.LightControllerName}:{Lang.断开连接}![{ex.Message}]");
//SendTaskMessage($"{item.LightControllerName}{Lang.断开连接}!", MessageLevel.Alarm);
}
}
if (lightcontrollers.Count > 0)
{
var result = await _lightManagerService.ConnectAllAsync();
if (result)
{
return (true, "");
}
else
{
return (false, "Light Controller Connect Failed!");
}
}
return (true, "");
//if (sb.Length == 0)
//{
// return (true, "");
//}
//else
//{
// return (false, sb.ToString());
//}
}
///
/// 初始化后台TCP服务器通讯
///
public void InitBgTcp()
{
var config = _configService.GetBgTcp();
try
{
BgCommunicate = new BgCommunicate(config);
BgCommunicate.ConnectedEvent += BgCommunicate_ConnectedEvent;
BgCommunicate.DisconnectedEvent += BgCommunicate_DisconnectedEvent;
BgCommunicate.ReceivedEvent += BgCommunicate_ReceivedEvent;
BgCommunicate.SendEvent += BgCommunicate_SendEvent;
BgCommunicate.StartListening();
SendTaskMessage($"{Lang.已开启监听端口}:{config.Port}", MessageLevel.Debug);
}
catch (Exception ex)
{
SendTaskMessage($"{Lang.未开启监听端口}:{config.Port}", MessageLevel.Error);
LogHelper.WriteLogError("开启后台服务器通讯时出错!", ex);
}
}
///
/// 初始化后台ModbusTCP从站
///
public void InitModbusTcp()
{
try
{
var config = _configService.GetBgModbusTcp();
BgModbusTcpCommunicate = new BgModbusTcpCommunicate(config);
if (config.IsEnabled)
{
BgModbusTcpCommunicate.Listen();
SendTaskMessage($"Start Modbus Tcp Slave:{BgModbusTcpCommunicate.IP}:{BgModbusTcpCommunicate.Port}:{BgModbusTcpCommunicate.SlaveID}", MessageLevel.Debug);
}
}
catch (Exception ex)
{
SendTaskMessage($"No Start Modbus Tcp Slave:{ex.Message}", MessageLevel.Alarm);
LogHelper.WriteLogError("开启后台Modbus TCP通讯时出错!", ex);
}
}
///
/// 初始化后台脚本
///
public void InitBackgroundcript()
{
try
{
if (!Directory.Exists(FilePath.BackgroundScriptPath))
{
Directory.CreateDirectory(FilePath.BackgroundScriptPath);
}
try
{
string[] files = Directory.GetFiles(FilePath.BackgroundScriptPath);
List ScriptFilesCollection = new List();
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string fileExtension = Path.GetExtension(file);
if (fileExtension == ".cs")
{
ScriptFilesCollection.Add(file);
}
}
foreach (var item in ScriptFilesCollection)
{
try
{
string script = FileHelper.ReadFile(item);
SendTaskMessage($"{Lang.执行脚本}:{item}", MessageLevel.Info);
Task.Factory.StartNew(() =>
{
ScriptHelper.ExecuteScriptingAsync(script, _regionManager, _eventAggregator, _container, rst =>
{
if (!rst.Item1)
{
foreach (var err in rst.Item2)
{
SendTaskMessage($"{Lang.后台脚本出错}:{err}", MessageLevel.Error);
}
}
});
});
}
catch (Exception ex)
{
LogHelper.WriteLogError($"开启脚本时出错:{item}", ex);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("读取本地脚本文件列表时出错", ex);
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("开启后台脚本时出错!", ex);
}
}
///
/// 初始化电批
///
///
public async Task InitScrewDriver()
{
try
{
var screwDriverConfig = _configService.GetScrewDriverConfig();
ScrewDriver = new XYD_ScrewDriver(screwDriverConfig.IPAdress, screwDriverConfig.Port);
Status.Add(new StatusInfo(ScrewDriver.Id, "电批未连接", new SolidColorBrush(Colors.Red)));
ScrewDriver.ConnectStateChangedEvent += ScrewDriver_ConnectStateChangedEvent;
ScrewDriver.SendTimeout = screwDriverConfig.SendTimeout;
screwDriverConfig.ReceiveTimeout = screwDriverConfig.ReceiveTimeout;
var isConnected = await ScrewDriver.ConnectAsync();
if (isConnected)
{
SendTaskMessage($"电批已连接", MessageLevel.Debug);
}
else
{
SendTaskMessage($"电批连接失败", MessageLevel.Error);
}
}
catch (Exception ex)
{
SendTaskMessage($"电批连接失败:{ex.Message}", MessageLevel.Alarm);
LogHelper.WriteLogError("连接电批时出错!", ex);
}
}
#endregion
#region 机器人指令执行
public Dictionary RobotTCPCollection = new Dictionary();
///
/// 机器人TCP接收
///
///
///
///
private async void Management_ReceivedEvent(Guid robotid, object arg2, TouchSocket.Sockets.ReceivedDataEventArgs e)
{
try
{
if (!RobotTCPCollection.ContainsKey(robotid))
RobotTCPCollection.Add(robotid, new CancellationTokenSource());
else
{
if (RobotTCPCollection[robotid].IsCancellationRequested)
{
RobotTCPCollection[robotid] = new CancellationTokenSource();
}
}
var robot = await _robotService.GetRobotAsync(robotid);
//从服务器收到信息。但是一般byteBlock和requestInfo会根据适配器呈现不同的值。
var buffer = e.ByteBlock.Span.ToString(robot.GetEncoding());
SendTaskMessage($"{robot.Name}Received:{buffer}", MessageLevel.Info);
var _ = _remoteCommandService.ExecuteAsync(buffer, RobotTCPCollection[robotid].Token, async msg =>
{
try
{
if (robot.ConnectType == TCPConnectType.Client)
{
if (robot.IsConnected)
{
await robot.SendAsync($"{msg}");
}
}
else
{
var cient = (ITcpSessionClient)arg2;
if (cient.Online)
{
await robot.SendAsync(cient, $"{msg}");
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("TCP发送数据时出错!", ex);
SendTaskMessage(ex.Message, MessageLevel.Alarm);
}
});
}
catch (Exception ex)
{
LogHelper.WriteLogError("处理机器人接收的命令时出错!", ex);
SendTaskMessage(ex.Message, MessageLevel.Alarm);
}
}
#endregion
#region 机器人&Feeder&相机连接状态事件
///
/// 机器人发送事件
///
///
///
///
///
private void Management_SendEvent(Guid robotid, object arg2, string arg3)
{
var r = _robotService.GetRobot(robotid);
SendTaskMessage($"{r.Name}Send:{arg3}", MessageLevel.Info);
}
///
/// 机器人断开连接时
///
///
///
///
///
private void Management_DisconnectedEvent(Guid robotid, object arg2, ClosedEventArgs arg3)
{
if (RobotTCPCollection.ContainsKey(robotid))
{
RobotTCPCollection[robotid].Cancel();
}
var r = _configService.GetRobot(robotid);
if (r.ConnectType == TCPConnectType.Server)
{
ITcpSessionClient socketClient = arg2 as ITcpSessionClient;
SendTaskMessage($"{r.RobotName}[{socketClient.Id}:{socketClient.IP}]{Lang.断开连接}!", MessageLevel.Error);
var robot = _robotService.GetRobot(robotid);
if (robot.TcpService.Count < 1)
{
var sta = Status.FirstOrDefault(s => s.ID == robotid);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{r.RobotName}{Lang.未连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
}
}
else
{
SendTaskMessage($"{r.RobotName}{Lang.断开连接}!", MessageLevel.Error);
var sta = Status.FirstOrDefault(s => s.ID == robotid);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{r.RobotName}{Lang.断开连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
}
}
///
/// 机器人连接成功时
///
///
///
///
///
private void Management_ConnectedEvent(Guid robotid, object arg2, ConnectedEventArgs arg3)
{
var r = _configService.GetRobot(robotid);
if (r.ConnectType == TCPConnectType.Server)
{
ITcpSessionClient socketClient = arg2 as ITcpSessionClient;
SendTaskMessage($"{r.RobotName}[{socketClient.Id}:{socketClient.IP}]{Lang.已连接}!", MessageLevel.Debug);
var robot = _robotService.GetRobot(robotid);
if (robot.TcpService.Count > 0)
{
var sta = Status.FirstOrDefault(s => s.ID == robotid);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{r.RobotName}{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
}
}
else
{
SendTaskMessage($"{r.RobotName}{Lang.已连接}!", MessageLevel.Debug);
var sta = Status.FirstOrDefault(s => s.ID == robotid);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{r.RobotName}{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
}
}
///
/// Feeder连接状态改变时
///
///
///
private void Management_FeederConnectionStatusChanged(object sender, bool state)
{
IFeeder feeder = sender as IFeeder;
var sta = Status.FirstOrDefault(s => s.ID == feeder.Id);
if (state)
{
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{feeder.Name}{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
SendTaskMessage($"{feeder.Name}{Lang.已连接}!", MessageLevel.Debug);
}
else
{
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{feeder.Name}{Lang.未连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
SendTaskMessage($"{feeder.Name}{Lang.断开连接}!", MessageLevel.Error);
}
}
///
/// 相机连接或者断开时
///
///
///
private void Management_CameraConnectChangedEvent(Guid id, bool state)
{
var sta = Status.FirstOrDefault(s => s.ID == id);
var camera = _configService.GetCamera(id);
if (sta != null && camera != null)
{
if (state)
{
App.Current.Dispatcher.Invoke(new Action(() =>
{
sta.Message = $"{camera.CameraName}{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
}
else
{
App.Current.Dispatcher.Invoke(new Action(() =>
{
sta.Message = $"{camera.CameraName}{Lang.断开连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
}
}
}
///
/// PLC连接状态改变事件
///
///
///
private void Management_PlcConnectChangedEvent(object sender, bool isconnected)
{
IPlc plc = sender as IPlc;
var sta = Status.FirstOrDefault(s => s.ID == plc.Id);
if (plc.IsConnected)
{
SendTaskMessage($"{plc.Name}{Lang.已连接}!", MessageLevel.Debug);
if (sta == null) return;
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{plc.Name}{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
}
else
{
SendTaskMessage($"{plc.Name}{Lang.断开连接}!", MessageLevel.Error);
if (sta == null) return;
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"{plc.Name}{Lang.未连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
}
}
///
/// 电批连接状态改变时
///
///
///
private void ScrewDriver_ConnectStateChangedEvent(object screwDevice, bool state)
{
try
{
XYD_ScrewDriver screwDriver = screwDevice as XYD_ScrewDriver;
if (state)
{
SendTaskMessage($"电批{Lang.已连接}!", MessageLevel.Debug);
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"电批{Lang.已连接}";
sta.Background = new SolidColorBrush(Colors.Green);
}));
}
else
{
SendTaskMessage($"电批{Lang.未连接}!", MessageLevel.Error);
var sta = Status.FirstOrDefault(s => s.ID == screwDriver.Id);
App.Current.Dispatcher.Invoke(new
Action(() =>
{
sta.Message = $"电批{Lang.未连接}";
sta.Background = new SolidColorBrush(Colors.Red);
}));
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("电批连接状态改变时出错了", ex);
}
}
#endregion
#region 后台服务器通讯事件
private void BgCommunicate_SendEvent(ITcpSessionClient client, string msg)
{
SendTaskMessage($"{Lang.服务器}[{client.ServicePort}] Send To {Lang.客户端}[{client.Id}:{client.IP}]:{msg}", MessageLevel.Info);
}
public Dictionary BgCommunicateollection = new Dictionary();
private async void BgCommunicate_ReceivedEvent(ITcpSessionClient client, string msg)
{
try
{
if (!BgCommunicateollection.ContainsKey(client.Id))
{
BgCommunicateollection.Add(client.Id, new CancellationTokenSource());
}
SendTaskMessage($"{Lang.服务器}[{client.ServicePort}]ReceiveFor{Lang.客户端}[{client.Id}:{client.IP}]:{msg}", MessageLevel.Info);
var _ = _remoteCommandService.ExecuteAsync(msg, BgCommunicateollection[client.Id].Token, async response =>
{
try
{
if (!client.Online)
{
return;
}
await BgCommunicate.SendAsync(client, $"{response}");
}
catch (Exception ex)
{
LogHelper.WriteLogError("后台TCP发送数据时出错!", ex);
SendTaskMessage(ex.Message, MessageLevel.Alarm);
}
});
}
catch (Exception ex)
{
LogHelper.WriteLogError("处理后台服务器接收的命令时出错!", ex);
SendTaskMessage(ex.Message, MessageLevel.Alarm);
}
}
private void BgCommunicate_DisconnectedEvent(ITcpSessionClient client, ClosedEventArgs e)
{
SendTaskMessage($"{Lang.服务器}[{client.ServicePort}]{Lang.客户端}[{client.Id}:{client.IP}]{Lang.断开连接}!", MessageLevel.Alarm);
if (BgCommunicateollection.ContainsKey(client.Id))
{
BgCommunicateollection[client.Id].Cancel();
}
}
private void BgCommunicate_ConnectedEvent(ITcpSessionClient client, ConnectedEventArgs e)
{
SendTaskMessage($"{Lang.服务器}[{client.ServicePort}]{Lang.客户端}[{client.Id}:{client.IP}]{Lang.连接成功}!", MessageLevel.Debug);
}
#endregion
#region PLC
///
/// 将系统参数写入PLC
///
///
///
public async Task WriteSystemParameterToPlcAsync(SystemConfiguration systemConfiguration)
{
var addressConfig = _configService.GetPlcAddresses();
var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
if (plc == null || !plc.IsConnected) return;
Dictionary nodeValues = new Dictionary();
nodeValues.Add(addressConfig.Out_WorkMode.Address, (Int16)systemConfiguration.WorkMode);
nodeValues.Add(addressConfig.Out_PickPointNum.Address, (Int16)systemConfiguration.PickPointNum);
nodeValues.Add(addressConfig.Out_DowmCameraNum.Address, (Int16)systemConfiguration.DowmCameraNum);
nodeValues.Add(addressConfig.Out_UpCameraPickNum.Address, (Int16)systemConfiguration.UpCameraPickNum);
nodeValues.Add(addressConfig.Out_UpCameraPutNum.Address, (Int16)systemConfiguration.UpCameraPutNum);
nodeValues.Add(addressConfig.Out_UPCameracheckNum.Address, (Int16)systemConfiguration.UPCameracheckNum);
nodeValues.Add(addressConfig.Out_FixedCameraPickNum.Address, (Int16)systemConfiguration.FixedCameraPickNum);
nodeValues.Add(addressConfig.Out_FixedCameraPutNum.Address, (Int16)systemConfiguration.FixedCameraPutNum);
nodeValues.Add(addressConfig.Out_FixedCameracheckNum.Address, (Int16)systemConfiguration.FixedCameracheckNum);
var res = await plc.WriteNodesAsync(nodeValues);
}
///
/// 注册需要监控的PLC地址
///
public void RegisterPlcMonitorAddress()
{
var addressConfig = _configService.GetPlcAddresses();
var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
if (plc == null || !plc.IsConnected) return;
//PLC地址数组
List monitorNodeIds = new List()
{
addressConfig.In_DowmCameraExe.Address,
addressConfig.In_UpCameraPickExe.Address,
addressConfig.In_UpCameraPutExe.Address,
addressConfig.In_UPCameracheckExe.Address,
addressConfig.In_FixedCameraPickExe.Address,
addressConfig.In_FixedCameraPutExe.Address,
addressConfig.In_FixedCameracheckExe.Address,
addressConfig.In_WorkStart.Address,
addressConfig.In_WorkDone.Address,
addressConfig.In_MesCheck.Address,
addressConfig.In_RequestPosition.Address,
};
for (int i = 0; i < 10; i++)
{
monitorNodeIds.Add(string.Format(addressConfig.In_MesCheck.Address, i));
}
//订阅PLC地址变化
plc.SubscribeNodes("AutoSensor", monitorNodeIds, PlcCommandTrigger);
}
///
/// 写入点位信息给PLC
///
///
public async Task WritePositionToPlcAsync()
{
var addressConfig = _configService.GetPlcAddresses();
var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
if (plc == null || !plc.IsConnected) return;
var current = _productService.GetCurrentProduct();
if (current == null) return;
if (current.PickCameraPoints != null && current.PickCameraPoints.Count > 0)
{
foreach (var item in current.PickCameraPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_PickCamera, plc);
}
}
if (current.PickPoints != null && current.PickPoints.Count > 0)
{
foreach (var item in current.PickPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_Pick, plc);
}
}
if (current.SecPosCameraPoints != null && current.SecPosCameraPoints.Count > 0)
{
foreach (var item in current.SecPosCameraPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_SecPosCamera, plc);
}
}
if (current.ScrewCameraPoints != null && current.ScrewCameraPoints.Count > 0)
{
foreach (var item in current.ScrewCameraPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_ScrewCamera, plc);
}
}
//if (current.ScrewPoints != null && current.ScrewPoints.Count > 0)
//{
// foreach (var item in current.ScrewPoints)
// {
// await item.WriteToPlcAddress(addressConfig.Out_Screw, plc);
// }
// await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)current.ScrewPoints.Count);
//}
if (current.CheckCameraPoints != null && current.CheckCameraPoints.Count > 0)
{
foreach (var item in current.CheckCameraPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_CheckCamera, plc);
}
}
if (current.AoiPoints != null && current.AoiPoints.Count > 0)
{
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickNum.Address, (Int16)current.AoiPoints.Count);
foreach (var item in current.AoiPoints)
{
await item.WriteToPlcAddress(addressConfig.Out_AoiCamera, plc);
}
}
else
{
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickNum.Address, 0);
}
}
PointF[] DowmCameraResults = new PointF[10];
PointF[] UpCameraPutResults = new PointF[10];
bool _LastDowmCameraExe = false;
bool _LastScrewTeachExe = false;
bool _LastUpCameraPickExe = false;
bool _LastUpCameraPutExe = false;
bool _LastUPCameracheckExe = false;
bool _LastFixedCameraPickExe = false;
bool _LastFixedCameraPutExe = false;
bool _LastFixedCameracheckExe = false;
Int16 _LastWorkStart = 0;
Int16 _LastWorkDone = 0;
Int16 _LastRequestPosition = 0;
Int16[] _LastMesCheck = new Int16[10];
Int16 _LastPickINC = 0;
DateTime[] _LastMesCheckTime = new DateTime[10];
List> _PrcTaskList = new List>();
private readonly object _stateLock = new object();
///
/// PLC命令触发时
///
///
private async void PlcCommandTrigger((string key, string nodeId, object value) tuple)
{
try
{
if (tuple.key != "AutoSensor")
{
return;
}
var addressConfig = _configService.GetPlcAddresses();
var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
if (plc == null || !plc.IsConnected) return;
// 获取当前产品
var currentProduct = _productService.GetCurrentProduct();
if (currentProduct == null)
{
return;
}
////获取产品编码
//_productService.CurrentProductCode = currentProduct.Name;
//string productCode = plc.ReadNode(addressConfig.In_Code.Address);
////如果产品编码为空,则以当前的时间戳作为编码
//if (string.IsNullOrEmpty(productCode))
//{
// productCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
//}
// 写入3D相机长度
if (addressConfig.In_UPCameracheckExe.Address.Contains(tuple.nodeId))
{
if (tuple.value is bool state)
{
if (_LastUPCameracheckExe != state)
{
_LastUPCameracheckExe = state;
}
else
{
return;
}
if (state)
{
SendTaskMessage($"写入3D相机长度...", MessageLevel.Debug);
//相机的编号
//Int16 cameraIndex = plc.ReadNode(addressConfig.In_FixedCameracheckNum.Address);
// 读取相机编号
Int16 cameraIndex = plc.ReadNode(addressConfig.In_FixedCameracheckNum.Address);
SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
// 找到对应编号的 PlcPoint
var targetPoint = currentProduct.AoiPoints?.FirstOrDefault(p => p.Number == cameraIndex);
if (targetPoint == null)
{
SendTaskMessage($"未找到 AOI 点位,编号:{cameraIndex}", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)2);
return;
}
SetBatchPoints(new int[] { targetPoint.Camera_Data1, targetPoint.Camera_Data2, targetPoint.Camera_Data3, targetPoint.Camera_Data4 });
await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)1);
}
else
{
SendTaskMessage($"写入3D相机长度信号已关闭", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)0);
}
}
}
// 发送点位个数
else if (addressConfig.In_RequestPosition.Address.Contains(tuple.nodeId))
{
if (tuple.value is Int16 state)
{
if (_LastRequestPosition != state)
{
_LastRequestPosition = state;
}
else
{
return;
}
if (state == 1)
{
var current = _productService.GetCurrentProduct();
if (current == null) return;
await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)1);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickNum.Address, (Int16)current.AoiPoints.Count);
}
else
{
SendTaskMessage($"多相机坐标合并请求已结束或被取消,state={state}", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)0);
}
}
}
// 固定相机检测拍照
else if (addressConfig.In_FixedCameracheckExe.Address.Contains(tuple.nodeId))
{
if (tuple.value is bool state)
{
if (_LastFixedCameracheckExe != state)
{
_LastFixedCameracheckExe = state;
}
else
{
return;
}
if (state)
{
LockResult lockResult = new LockResult();
lockResult.TimeStart = DateTime.Now;
SendTaskMessage($"触发固定相机检测拍照...", MessageLevel.Debug);
// 读取相机编号
Int16 cameraIndex = plc.ReadNode(addressConfig.In_FixedCameracheckNum.Address);
SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
// 找到对应编号的 PlcPoint
var targetPoint = currentProduct.AoiPoints?.FirstOrDefault(p => p.Number == cameraIndex);
if (targetPoint == null)
{
SendTaskMessage($"未找到 AOI 点位,编号:{cameraIndex}", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameracheckStatus.Address, (Int16)2);
return;
}
// 收集要执行的流程 id(仅添加大于0的)
var procIds = new List();
try
{
if (targetPoint.CameraProcedureId1 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId1);
}
catch { }
try
{
if (targetPoint.CameraProcedureId2 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId2);
}
catch { }
try
{
if (targetPoint.CameraProcedureId3 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId3);
}
catch { }
try
{
if (targetPoint.CameraProcedureId4 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId4);
}
catch { }
try
{
if (targetPoint.CameraProcedureId5 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId5);
}
catch { }
try
{
if (targetPoint.CameraProcedureId6 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId6);
}
catch { }
try
{
if (targetPoint.CameraProcedureId7 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId7);
}
catch { }
try
{
if (targetPoint.CameraProcedureId8 != Guid.Empty) procIds.Add(targetPoint.CameraProcedureId8);
}
catch { }
if (procIds.Count == 0)
{
SendTaskMessage($"Point#{cameraIndex} 未配置任何视觉流程 (CameraProcedureId1/2/3)", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
return;
}
var cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures == null || cameraProcedures.Count == 0)
{
SendTaskMessage($"当前产品未配置 CameraProcedures,无法执行视觉流程", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
return;
}
if (cameraIndex == currentProduct.PhotoCount)
{
_PrcTaskList.Clear();
lock (_stateLock)
{
lockResultsAll.Clear();
}
App.Current.Dispatcher.Invoke(() =>
{
_eventAggregator.GetEvent().Publish();
});
}
var sysConfig = _configService.GetSystemConfiguration();
if (sysConfig.CodeUse==true && cameraIndex == 1)
{
var cts = new CancellationTokenSource();
// CameraProcedureId 存储的是具体的视觉流程 Id(ProcedureModel.Id),
// 需要在所有 CameraProcedures 的 ProcedureModels 中查找匹配的流程。
ProcedureModel selectedProcedure = null;
try
{
cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures != null)
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == targetPoint.CameraProcedureId1);
if (selectedProcedure != null) break;
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
SendTaskMessage($"未找到 AOI 点位对应的视觉流程,Point#{cameraIndex} ProcedureId={targetPoint.CameraProcedureId1}", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
return;
}
if (selectedProcedure.Id == currentProduct.FixedDownCameraProcedureId && sysConfig.TurnOnAllLightUse == true)
{
await _remoteCommandService.SetLightBeforePhoto(selectedProcedure);
}
var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint2(selectedProcedure, null, null, cts.Token);
if (visionResult.IsSucceed)
{
code = visionResult.X.ToUpper();
SendTaskMessage($"扫码成功,SN:{code}", MessageLevel.Info);
//这里缺少从MES获取产品配方的内容,需要补充
_LastMesCheckTime[0] = (await _mesService.GetServerTimeAsync(code, 2)).Now;
LogHelper.WriteLogMes($"【mes开始QUERY】");
SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
//(bool isSuccess, string response) = await _mesService.StationGetAsync(code, "", 2);//询问mes
(bool isSuccess, string response) = await _mesService.StationGetExAsync(code, "", 2);//基于电池的SN获取产品SN,询问mes
if (isSuccess)
{
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
string ProductMainSN_Temp = "";
LogHelper.WriteLogMes($"询问mes成功");
SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
if (response != "MES功能未启用!")
{
string[] item = response.Split('\n');
if (item[2].Contains("sn="))
{
ProductMainSN_Temp = item[2].Replace("sn=", "");
SendTaskMessage($"sn:{ProductMainSN_Temp}", MessageLevel.Info);
}
}
LogHelper.WriteLogMes($"询问mes成功");
SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
//20260214,特别版(电池组装)
(bool isSuccess2, string response2) = await _mesService.StationGetAsync(ProductMainSN_Temp, "", 2);//询问mes
if (isSuccess2)
{
LogHelper.WriteLogMes($"询问mes成功");
SendTaskMessage($"询问mes成功:{response2}", MessageLevel.Debug);
if (response2 != "MES功能未启用!")
{
string[] item = response2.Split('\n');
if (item[3].Contains("sn="))
{
ProductMainSN = item[3].Replace("sn=", "");
_productService.CurrentProductCode = ProductMainSN;
SendTaskMessage($"产品主sn:{ProductMainSN}", MessageLevel.Info);
}
if (item[5].Contains("wo="))
{
wo = item[5].Replace("wo=", "");
SendTaskMessage($"产品主wo:{wo}", MessageLevel.Info);
}
}
LogHelper.WriteLogMes($"第二次询问mes成功");
SendTaskMessage($"第二次询问mes成功:{response2}", MessageLevel.Debug);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
}
else
{
LogHelper.WriteLogMes($"第二次询问mes失败");
SendTaskMessage($"第二次询问mes失败:{response2}", MessageLevel.Error);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)3);
}
}
else
{
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)3);
LogHelper.WriteLogMes($"询问mes失败");
SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
}
}
else
{
SendTaskMessage($"扫码失败", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)3);
}
return;
}
if (sysConfig.CodeUse2 == true && cameraIndex == 1)
{
var cts = new CancellationTokenSource();
// CameraProcedureId 存储的是具体的视觉流程 Id(ProcedureModel.Id),
// 需要在所有 CameraProcedures 的 ProcedureModels 中查找匹配的流程。
ProcedureModel selectedProcedure = null;
try
{
cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures != null)
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == targetPoint.CameraProcedureId1);
if (selectedProcedure != null) break;
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
SendTaskMessage($"未找到 AOI 点位对应的视觉流程,Point#{cameraIndex} ProcedureId={targetPoint.CameraProcedureId1}", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
return;
}
var ctsAll = new CancellationTokenSource();
if (selectedProcedure.Id == currentProduct.FixedDownCameraProcedureId && sysConfig.TurnOnAllLightUse == true)
{
await _remoteCommandService.SetLightBeforePhoto(selectedProcedure);
}
var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint2(selectedProcedure, null, null, ctsAll.Token);
if (visionResult.IsSucceed)
{
code = visionResult.X;
ProductMainSN = visionResult.X;
SendTaskMessage($"扫码成功,SN:{code}", MessageLevel.Info);
//这里缺少从MES获取产品配方的内容,需要补充
_LastMesCheckTime[0] = (await _mesService.GetServerTimeAsync(code, 2)).Now;
//_LastMesCheckTime[1] = DateTime.Now;
LogHelper.WriteLogMes($"【mes开始QUERY】");
SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
(bool isSuccess, string response) = await _mesService.StationGetAsync(code, "", 2);//询问mes
if (isSuccess)
{
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
LogHelper.WriteLogMes($"询问mes成功");
SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
if (response != "MES功能未启用!")
{
string[] items = response.Split('\n');
if (items[3].Contains("sn="))
{
ProductMainSN = items[3].Replace("sn=", "");
_productService.CurrentProductCode = ProductMainSN;
}
SendTaskMessage($"产品主sn:{ProductMainSN}", MessageLevel.Info);
if (items[5].Contains("wo="))
{
wo = items[5].Replace("wo=", "");
}
SendTaskMessage($"产品wo:{wo}", MessageLevel.Info);
}
LogHelper.WriteLogMes($"【mes结束QUERY】");
SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
return;
}
else
{
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)3);
LogHelper.WriteLogMes($"询问mes失败");
SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
}
}
else
{
SendTaskMessage($"扫码失败", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)3);
}
return;
}
foreach (var prcId in procIds)
{
if (Is3D(prcId))
{
_PrcTaskList.Add(ExecuteProcedureAsync(cameraIndex, prcId));
}
else
{
//2d相机时,需要先等待图像采集完成
var imageData = await GrabImage(cameraIndex, prcId);
if (imageData.IsSucceed)
{
_PrcTaskList.Add(ExecuteProcedureAsync(cameraIndex, prcId, imageData.imges));
}
else
{
SendTaskMessage($"图像采集失败!{cameraIndex}: {prcId}", MessageLevel.Alarm);
}
}
}
//如果最后一个拍照点,则需要等待前面所有的拍照处理完成
if (cameraIndex == currentProduct.PhotoCountStop)
{
//等待所有的图像处理流程处理完成
var results = await Task.WhenAll(_PrcTaskList);
//结果输出
bool resultFlog = true;
foreach (var item in results)
{
if (!item.IsSucceed || item.Result == null)
{
resultFlog = false;
}
else
{
foreach (var item_1 in item.Result)
{
if (!item_1)
{
resultFlog = false;
break;
}
}
}
}
//全部OK
if (resultFlog)
{
SendTaskMessage($"检测执行成功", MessageLevel.Debug);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
}
//存在NG
else
{
SendTaskMessage($"检测执行失败", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)2);
}
}
else
{
//直接放行,执行下一个检测点
//SendTaskMessage($"流程执行成功", MessageLevel.Info);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
}
}
else
{
SendTaskMessage($"触发固定相机检测拍照信号已关闭", MessageLevel.Alarm);
await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)0);
}
}
}
// 过站检查
else
{
for (int i = 0; i < 10; i++)
{
if (string.Format(addressConfig.In_MesCheck.Address, i).Contains(tuple.nodeId))
{
if (tuple.value is Int16 state)
{
if (_LastMesCheck[i] != state)
{
_LastMesCheck[i] = state;
}
else
{
return;
}
var sysConfig = _configService.GetSystemConfiguration();
if (sysConfig.CodeUse == true && state == 1)
{
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
return;
}
if (sysConfig.CodeUse2 == true && state == 1)
{
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
return;
}
if (sysConfig.CodeUse == false && sysConfig.CodeUse2 == false)
{
code = plc.ReadNode(string.Format(addressConfig.In_Code.Address, i));
}
var homeview = _container.Resolve();
//过站检查
if (state == 1)
{
//这里缺少从MES获取产品配方的内容,需要补充
_LastMesCheckTime[i] = (await _mesService.GetServerTimeAsync(code, 2)).Now;
LogHelper.WriteLogMes($"【mes开始QUERY】");
SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
ShowMes_Query = false;
(bool isSuccess, string response) = await _mesService.StationGetAsync(code, "", 2);//询问mes
if (i == 0)
{
SendTaskMessage($"收到当前过站检查请求(当站是否生产)...", MessageLevel.Debug);
}
else
{
SendTaskMessage($"收到{i}过站检查请求(当站是否生产)...", MessageLevel.Debug);
}
if (isSuccess)
{
string[] item = response.Split('\n');
//获取产品主sn和wo用于后续上传数据使用
string snItem = item.FirstOrDefault(f => f.Contains("sn="));
if (snItem != null)
{
ProductMainSN = snItem.Replace("sn=", "").Trim();
if (i == 0)
{
_productService.CurrentProductCode = ProductMainSN;
}
SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
}
string woItem = item.FirstOrDefault(f => f.Contains("wo="));
if (woItem != null)
{
wo = woItem.Replace("wo=", "").Trim();
SendTaskMessage($"工单信息:{wo[i]}", MessageLevel.Info);
}
ShowMes_Query = true;
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
LogHelper.WriteLogMes($"【mes结束QUERY】");
SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
return;
}
else
{
//产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
LogHelper.WriteLogMes($"询问mes失败");
SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
}
LogHelper.WriteLogMes($"【mes结束QUERY】");
SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
}
// 上传本站数据
else if (state == 2)
{
//获取当前工位的配置
var stationConfig = _configService.GetDeviceInfo();
List DFC = new List();
SendTaskMessage($"收到{i}上传本站数据请求...", MessageLevel.Debug);
//这里缺少上传MES的本站数据结果及开始和结束时间,需要补充
//从服务器中获取当前时间
var serverTimeResult = await _mesService.GetServerTimeAsync(code, 2);
double ct = serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds;
if (i == 0)
{
CTtime = ct;
}
//读取产品结果
Int16 resultIndex = plc.ReadNode(string.Format(addressConfig.In_Result.Address, i));
if (homeview.IsResultTrue == false)
{
resultIndex = 1;
}
//Int16 resultIndex = 1;
//目前只记录当前站
if (i == 0)
await _systemDatabaseService.RecordProductionAsync(new ProductionRecord()
{
ProductName = currentProduct.Name,
ProductCode = code,
DeviceId = i,
DeviceName = "",
Category = resultIndex == 1 ? "OK" : "NG",
Quantity = 1,
Remark = $"TotalSeconds:{DateTime.UtcNow.Subtract(_LastMesCheckTime[i]).TotalSeconds.ToString("F2")}",
});
LogHelper.WriteLogMes($"【mes开始ADD】");
SendTaskMessage($"mes开始ADD", MessageLevel.Info);
StringBuilder submitData = new StringBuilder();
foreach (var item in lockResultsAll)
{
submitData.Append($"{item.PhotoName}-{item.ResultData}");
}
ShowMes_Result = resultIndex == 1 ? true : false;
//(bool isSuccess, string response) = await _mesService.SubmitGetAsync(ProductMainSN, "", MesData.Replace("--", "-"), resultIndex == 1 ? true : false, _LastMesCheckTime[i], DateTime.UtcNow);
(bool isSuccess, string response) = await _mesService.SubmitGetAsync(ProductMainSN, "", submitData.ToString(), resultIndex == 1 ? true : false, _LastMesCheckTime[i], serverTimeResult.Now);
if (isSuccess)
{
LogHelper.WriteLogMes($"上传mes成功");
SendTaskMessage($"上传mes成功", MessageLevel.Debug);
//ProductMainSN = "";
}
else
{
LogHelper.WriteLogMes($"上传mes失败");
SendTaskMessage($"上传mes失败", MessageLevel.Error);
//ProductMainSN = "";
}
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
//是否保存当前的产品记录至CSV?
if (stationConfig.SaveCsv)
{
//判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
if (!string.IsNullOrEmpty(stationConfig.SaveCsvPath))
{
foreach (var item in lockResultsAll)
{
DFC.Add(new DataFormCtq
{
PPID = ProductMainSN,
PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
CTQ_NAME = item.PhotoName,
CTQ_VALUE = item.ResultData.Replace(",", ";"),
CTQ_LSL = item.DownLimit,
CTQ_USL = item.UpLimit,
PROCESS_END_TIME = serverTimeResult.Now.ToString(),
SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
REVISION = stationConfig.DataInfo.REVISION,
WO = wo,
MFG_LOT = stationConfig.DataInfo.MFG_LOT,
MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
PROCESS_OUTCOME = item.PhotoPassed == "OK" ? "PASS" : "FAIL",
PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
CTQ_UNIT_OF_MEASURE = "mm",
ERROR_MESSAGE = item.PhotoPassed == "OK" ? "" : $"{item.PhotoName} OOS",
PD_ATTR_01= "xxxxxxxx1",
PD_ATTR_02 = item.MidLimit,
PD_ATTR_03 = "",
PD_ATTR_04 = "",
PD_ATTR_05 = ""
});
}
bool recordResult = RecordStationResult(i, DFC, ProductMainSN, serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
if (recordResult)
{
SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存成功", MessageLevel.Debug);
}
else
{
SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存失败", MessageLevel.Error);
}
}
else
{
SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存路径,无法保存产品记录", MessageLevel.Error);
}
}
else
{
SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存产品记录", MessageLevel.Debug);
}
//WriteProductLog(lockResultsAll, code, CTtime);
lock (_stateLock)
{
lockResultsAll.Clear();
}
ProductMainSN = "";
LogHelper.WriteLogMes($"【mes结束ADD】");
SendTaskMessage($"mes结束ADD", MessageLevel.Info);
}
else
{
SendTaskMessage($"{i}过站检查信号:state={state},处理为默认状态", MessageLevel.Alarm);
await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)0);
}
}
}
}
}
}
catch (Exception ex)
{
SendTaskMessage(ex.Message, MessageLevel.Error);
}
}
///
/// 异步执行流程拍照
///
///
///
///
private Task<(bool IsSucceed, bool[] Result, string Message)> ExecuteProcedureAsync(int pointIndex, Guid procedureId)
{
return Task.Run(async () =>
{
List results = new List();
// 获取当前产品
var currentProduct = _productService.GetCurrentProduct();
if (currentProduct == null)
{
return (false, null, "当前产品为空,未加载产品!");
}
var cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures == null || cameraProcedures.Count == 0)
{
SendTaskMessage($"当前产品未配置 CameraProcedures,无法执行视觉流程", MessageLevel.Alarm);
return (false, null, $"当前产品未配置 CameraProcedures,无法执行视觉流程");
}
var ctsAll = new CancellationTokenSource();
try
{
ProcedureModel selectedProcedure = null;
try
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == procedureId);
if (selectedProcedure != null) break;
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
SendTaskMessage($"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={pointIndex}", MessageLevel.Alarm);
return (false, null, $"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={procedureId}");
}
SendTaskMessage($"开始执行 AOI 流程 (Point#{pointIndex}) 流程Id={pointIndex}", MessageLevel.Debug);
try
{
//1. 执行拍照,图像处理
var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint1(selectedProcedure, null, null, ctsAll.Token);
if (visionResult.Count == 0)
{
SendTaskMessage("Count值为0", MessageLevel.Alarm);
return (false, null, $"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={procedureId}");
}
//2. 结果分析
for (int i = 1; i <= visionResult.Count; i++)
{
LockResult lockResult1 = new LockResult();
//if (pointIndex == currentProduct.PhotoCount && selectedProcedure.Id == currentProduct.FixedUpCamera1ProcedureId && i == 1)
//{
// lockResult1.Number = 1;
//}
string[] strpoints1 = visionResult.Items[i].Split(',');
lockResult1.PhotoName = strpoints1[0];
lockResult1.ResultData = strpoints1[1];
lockResult1.PhotoCode = ProductMainSN;
var globalParam = currentProduct.GlobalParamListCollection.FirstOrDefault(p => p.Name == strpoints1[0]);
if (globalParam != null)
{
lockResult1.UpLimit = globalParam.Param1;
lockResult1.DownLimit = globalParam.Param2;
lockResult1.MidLimit = globalParam.Param5;
string ResData = strpoints1[1];
if (ResData.Contains("NA"))
{
ResData = "-1000";
}
string[] body = ResData.Split(";");
bool resultflog = true;
foreach (var item in body)
{
if (Convert.ToDouble(item) >= Convert.ToDouble(globalParam.Param2) && Convert.ToDouble(item) <= Convert.ToDouble(globalParam.Param1))
{
}
else
{
resultflog = false;
}
}
if (resultflog)
{
lockResult1.PhotoPassed = "OK";
results.Add(true);
}
else
{
lockResult1.PhotoPassed = "NG";
results.Add(false);
}
}
lock (_stateLock)
{
lockResultsAll.Add(lockResult1);
}
App.Current.Dispatcher.Invoke(() =>
{
_eventAggregator.GetEvent().Publish(lockResult1);
});
}
//排序
//lock (_stateLock)
//{
// var bf1 = lockResultsAll.OrderBy(p => p.Number);
// lockResultsAll = new List(bf1);
//}
}
catch (Exception ex)
{
LogHelper.WriteLogError("执行 AOI 视觉流程时出错", ex);
SendTaskMessage($"执行 AOI 视觉流程异常: {ex.Message}", MessageLevel.Alarm);
}
return (true, results.ToArray(), $"成功");
}
catch (Exception ex)
{
LogHelper.WriteLogError("处理固定相机检测拍照时出错", ex);
return (false, null, $"处理固定相机检测拍照时出错");
}
});
}
///
/// 异步执行流程拍照
///
///
///
///
private Task<(bool IsSucceed, bool[] Result, string Message)> ExecuteProcedureAsync(int pointIndex, Guid procedureId, ICogImage[] images)
{
return Task.Run(async () =>
{
List results = new List();
// 获取当前产品
var currentProduct = _productService.GetCurrentProduct();
if (currentProduct == null)
{
return (false, null, "当前产品为空,未加载产品!");
}
var cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures == null || cameraProcedures.Count == 0)
{
SendTaskMessage($"当前产品未配置 CameraProcedures,无法执行视觉流程", MessageLevel.Alarm);
return (false, null, $"当前产品未配置 CameraProcedures,无法执行视觉流程");
}
var ctsAll = new CancellationTokenSource();
try
{
ProcedureModel selectedProcedure = null;
try
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == procedureId);
if (selectedProcedure != null) break;
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
SendTaskMessage($"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={pointIndex}", MessageLevel.Alarm);
return (false, null, $"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={procedureId}");
}
SendTaskMessage($"开始执行 AOI 流程 (Point#{pointIndex}) 流程Id={pointIndex}", MessageLevel.Debug);
try
{
var sysConfig = _configService.GetSystemConfiguration();
if (selectedProcedure.Id == currentProduct.MoveDownCameraLockPhotoProcedureId && sysConfig.TurnOffAllLightUse == true)
{
await _remoteCommandService.TurnOffLightAfterPhoto(selectedProcedure);
}
//1. 执行拍照,图像处理
var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint1(selectedProcedure, images, null, null, ctsAll.Token);
if (visionResult.Count == 0)
{
SendTaskMessage("Count值为0", MessageLevel.Alarm);
return (false, null, $"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={procedureId}");
}
//2. 结果分析
for (int i = 1; i <= visionResult.Count; i++)
{
LockResult lockResult1 = new LockResult();
//if (pointIndex == currentProduct.PhotoCount && selectedProcedure.Id == currentProduct.FixedUpCamera1ProcedureId && i == 1)
//{
// lockResult1.Number = 1;
// lock (_stateLock)
// {
// lockResultsAll.Clear();
// }
//}
string[] strpoints1 = visionResult.Items[i].Split(',');
lockResult1.PhotoName = strpoints1[0];
lockResult1.ResultData = strpoints1[1];
lockResult1.PhotoCode = ProductMainSN;
var globalParam = currentProduct.GlobalParamListCollection.FirstOrDefault(p => p.Name == strpoints1[0]);
if (globalParam != null)
{
lockResult1.UpLimit = globalParam.Param1;
lockResult1.DownLimit = globalParam.Param2;
lockResult1.MidLimit = globalParam.Param5;
string ResData = strpoints1[1];
if (ResData.Contains("NA"))
{
ResData = "-1000";
}
string[] body = ResData.Split(";");
bool resultflog = true;
foreach (var item in body)
{
if (Convert.ToDouble(item) >= Convert.ToDouble(globalParam.Param2) && Convert.ToDouble(item) <= Convert.ToDouble(globalParam.Param1))
{
}
else
{
resultflog = false;
}
}
if (resultflog)
{
lockResult1.PhotoPassed = "OK";
results.Add(true);
}
else
{
lockResult1.PhotoPassed = "NG";
results.Add(false);
}
}
lock (_stateLock)
{
lockResultsAll.Add(lockResult1);
}
App.Current.Dispatcher.Invoke(() =>
{
_eventAggregator.GetEvent().Publish(lockResult1);
});
}
////排序
//lock (_stateLock)
//{
// var bf1 = lockResultsAll.OrderBy(p => int.Parse(p.PhotoName));
// lockResultsAll = new List(bf1);
//}
}
catch (Exception ex)
{
LogHelper.WriteLogError("执行 AOI 视觉流程时出错", ex);
SendTaskMessage($"执行 AOI 视觉流程异常: {ex.Message}", MessageLevel.Alarm);
}
return (true, results.ToArray(), $"成功");
}
catch (Exception ex)
{
LogHelper.WriteLogError("处理固定相机检测拍照时出错", ex);
return (false, null, $"处理固定相机检测拍照时出错");
}
});
}
///
/// 是否是3D相机
///
///
///
private bool Is3D(Guid procedureId)
{
// 获取当前产品
var currentProduct = _productService.GetCurrentProduct();
if (currentProduct == null)
{
return false;
}
var cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures == null || cameraProcedures.Count == 0)
{
return false;
}
ProcedureModel selectedProcedure = null;
try
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == procedureId);
if (selectedProcedure != null) break;
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
return false;
}
var camera = _cameraService.GetCamera(selectedProcedure.CameraId);
if (camera == null)
{
return false;
}
return camera.Is3D;
}
///
/// 2D相机先采集图像
///
///
///
private async Task<(bool IsSucceed, ICogImage[] imges, string Message)> GrabImage(int pointIndex, Guid procedureId)
{
// 获取当前产品
var currentProduct = _productService.GetCurrentProduct();
if (currentProduct == null)
{
return (false, null, "当前产品为空,未加载产品!");
}
var cameraProcedures = currentProduct.CameraProcedures;
if (cameraProcedures == null || cameraProcedures.Count == 0)
{
SendTaskMessage($"当前产品未配置 CameraProcedures,无法执行视觉流程", MessageLevel.Alarm);
return (false, null, $"当前产品未配置 CameraProcedures,无法执行视觉流程");
}
try
{
ProcedureModel selectedProcedure = null;
try
{
foreach (var cp in cameraProcedures)
{
if (cp?.ProcedureModels == null) continue;
selectedProcedure = cp.ProcedureModels.FirstOrDefault(pm => pm.Id == procedureId);
if (selectedProcedure != null) break;
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("查找 AOI 点位对应视觉流程时出错", ex);
}
if (selectedProcedure == null)
{
SendTaskMessage($"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={pointIndex}", MessageLevel.Alarm);
return (false, null, $"未找到 AOI 点位对应的视觉流程,Point#{pointIndex} ProcedureId={procedureId}");
}
SendTaskMessage($"开始执行 AOI 流程 (Point#{pointIndex}) 流程Id={pointIndex}", MessageLevel.Debug);
try
{
var sysConfig = _configService.GetSystemConfiguration();
if (selectedProcedure.Id == currentProduct.FixedDownCameraProcedureId && sysConfig.TurnOnAllLightUse == true)
{
await _remoteCommandService.SetLightBeforePhoto(selectedProcedure);
}
//1. 执行拍照
return await _remoteCommandService.ExecuteGrabImageAsync(selectedProcedure);
}
catch (Exception ex)
{
LogHelper.WriteLogError("执行 AOI 视觉图像采集时出错", ex);
SendTaskMessage($"执行 AOI 视觉图像采集时出错: {ex.Message}", MessageLevel.Alarm);
}
return (false, null, $"图像采集失败");
}
catch (Exception ex)
{
LogHelper.WriteLogError("处理固定相机检测拍照时出错", ex);
return (false, null, $"处理固定相机检测拍照时出错");
}
}
///
/// 为所有相机设置批处理点数(会调用具体相机实现的 SetBatchPoints)
///
///
public void SetBatchPoints(int CameraNum, int points)
{
try
{
if (points == 0 || points < 0)
{
return;
}
var cameras = _cameraService.GetCameraByNumber(CameraNum);
if (cameras == null) return;
try
{
// 优先针对已知的 SSZNCamera 类型直接调用
if (cameras is TeamAAS_VP.Core.Cameras.SSZNCamera sszn)
{
sszn.CameraRevFinish = false;
sszn.SetBatchPoints(points);
}
}
catch (Exception ex)
{
LogHelper.WriteLogError($"SetBatchPoints to camera {cameras?.Name} failed", ex);
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("SetBatchPoints failed", ex);
}
}
public void SetBatchPoints(int[] CameraSpoints)
{
try
{
for (int i = 0; i < CameraSpoints.Length; i++)
{
SetBatchPoints(i + 1, CameraSpoints[i]);
}
}
catch (Exception ex)
{
LogHelper.WriteLogError("SetBatchPoints failed", ex);
}
}
#endregion
#region 方法
private void SendTaskMessage(string msg, MessageLevel level)
{
App.Current.Dispatcher.Invoke(() =>
{
_eventAggregator.GetEvent().Publish(new Models.MessageStruct() { Message = msg, level = level });
});
}
private async void DoYieldTime(object state)
{
try
{
//获取当前产品
CurrentProduct= _productService.GetCurrentProduct();
var currentproduct = _productService.GetCurrentProduct();
if (currentproduct == null) return;
TotalQuantity = await _systemDatabaseService.GetOverallProductionAsync(currentproduct.Name);
TotalQuantityToday = await _systemDatabaseService.GetTodayProductionAsync(currentproduct.Name);
CurrentUPH = await _systemDatabaseService.GetLastHourProductionAsync(currentproduct.Name);
NgNumber = await _systemDatabaseService.GetNGProductionAsync (currentproduct.Name);
Yield = ((double)TotalQuantityToday - (double)NgNumber) / (double)TotalQuantityToday * 100;
}
catch (Exception)
{
}
}
#region vm启动检测
///
/// 杀死所有VM有关进程
///
public void KillVMProcess()
{
KillProcess("VisionMasterServerApp");
KillProcess("VisionMaster");
KillProcess("VmModuleProxy.exe");
KillProcess("vServerApp.exe");
}
///
/// 杀死指定进程名的进程
///
///
public void KillProcess(string strKillName)
{
foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
{
if (p.ProcessName.Contains(strKillName))
{
try
{
p.Kill();
p.WaitForExit();
}
catch (Exception ex)
{
LogHelper.WriteLogError($"杀死进程:{strKillName}时失败!", ex);
}
}
}
}
#endregion
///
/// 记录工位的结果,其他工位要存储的数据项按照键值对集合的形式传入,键为数据项名称,值为数据项的值
///
///
///
///
///
///
///
///
///
private bool RecordStationResult(int stationIndex, IEnumerable dfcs, string productMainSN, double ct, DateTime timestamp, string savePath, bool isFirstEnter = true)
{
try
{
//获取当前工位的配置
var stationConfig = _configService.GetDeviceInfo();
if (stationConfig == null) return false;
//如果保存路径为空,则不保存
if (string.IsNullOrEmpty(savePath)) return false;
string fullPath = savePath;
//如果保存路径是一个文件路径,则直接保存,否则按照工位和日期进行保存
if (File.Exists(savePath) || Path.HasExtension(savePath))
{
fullPath = savePath;
//如果路径不存在,则创建
// 创建目录
string directory = Path.GetDirectoryName(fullPath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
else
{
//结果保存至CSV文件,文件名格式:savePath\yyyy-MM\工位编号_工位名称_yyyy-MM-dd.csv
string datePath = timestamp.ToString("yyyy-MM") + "\\";
string dirPath = Path.Combine(savePath, datePath);
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
string fileName = $"{stationIndex}_{stationConfig.DeviceName}_{timestamp.ToString("yyyy-MM-dd")}.csv";
fullPath = Path.Combine(dirPath, fileName);
}
StringBuilder sb = new StringBuilder();
if (!File.Exists(fullPath))
{
sb.Append("PPID,PROCESS_NAME,PROCESS_START_TIME,CTQ_NAME,CTQ_VALUE,CTQ_LSL,CTQ_USL,PROCESS_END_TIME,SUPPLIER_NAME,COMMODITY_TYPE,REVISION,WO#,MFG_LOT#," +
"MFG_ASSY_LINE,PROCESS_OUTCOME,PROCESS_MACHINE_ID,CTQ_UNIT_OF_MEASURE,ERROR_MESSAGE,PD_ATTR_01,PD_ATTR_02,PD_ATTR_03,PD_ATTR_04,PD_ATTR_05");
sb.AppendLine();
}
if (dfcs == null || dfcs.Count() == 0)
{
return false;
}
foreach (var dfc in dfcs)
{
sb.Append($"{dfc.PPID},{dfc.PROCESS_NAME},{dfc.PROCESS_START_TIME},{dfc.CTQ_NAME},{dfc.CTQ_VALUE},{dfc.CTQ_LSL},{dfc.CTQ_USL},{dfc.PROCESS_END_TIME},{dfc.SUPPLIER_NAME},{dfc.COMMODITY_TYPE},{dfc.REVISION},{dfc.WO},{dfc.MFG_LOT},{dfc.MFG_ASSY_LINE},{dfc.PROCESS_OUTCOME},{dfc.PROCESS_MACHINE_ID},{dfc.CTQ_UNIT_OF_MEASURE},{dfc.ERROR_MESSAGE},{dfc.PD_ATTR_01},{dfc.PD_ATTR_02},{dfc.PD_ATTR_03},{dfc.PD_ATTR_04},{dfc.PD_ATTR_05}");
sb.AppendLine();
}
// 使用 StreamWriter 以追加模式打开文件
StreamWriter sw = new StreamWriter(fullPath, true, Encoding.UTF8);
sw.Write(sb.ToString());
sw.Close();
sw.Dispose();
return true;
}
catch (Exception ex)
{
if (!isFirstEnter)
{
return false;
}
LogHelper.WriteLogError("记录其他工位结果时出错!", ex);
//我希望在这里生成一个临时文件来保存这次的记录,因为如果本地文件被打开时可能会导致无法写入,如果不保存的话可能会丢失这次的记录,所以我想在这里生成一个临时文件来保存这次的记录
//生成临时文件的路径,格式为savePath\yyyy-MM\工位编号_yyyy-MM-dd_temp\工位编号_yyyy-MM-dd_HH-mm-ss-fff_temp.csv
string datePath = timestamp.ToString("yyyy-MM") + "\\";
string tempDirPath = Path.Combine(savePath, datePath, $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd")}_temp");
string tempFileName = $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd_HH-mm-ss-fff")}_temp.csv";
RecordStationResult(stationIndex, dfcs, productMainSN, ct, timestamp, tempFileName, false);
return false;
}
}
#endregion
// 用于等待“指定相机的下一张图到达”
private readonly object _imageSyncLock = new object();
private readonly Dictionary> _nextImageTcsByCamera =
new Dictionary>();
private Task PrepareNextImageWait(Guid cameraId)
{
lock (_imageSyncLock)
{
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
_nextImageTcsByCamera[cameraId] = tcs;
return tcs.Task;
}
}
public async Task SignalImageArrived(Guid cameraId, ICogImage image)
{
await Task.Delay(500);
TaskCompletionSource tcs = null;
lock (_imageSyncLock)
{
_nextImageTcsByCamera.TryGetValue(cameraId, out tcs);
}
tcs?.TrySetResult(image);
}
public async Task WaitNextImageAsync(Guid cameraId, int timeoutMs, CancellationToken token)
{
var waitTask = PrepareNextImageWait(cameraId);
var completed = await Task.WhenAny(waitTask, Task.Delay(timeoutMs, token)).ConfigureAwait(false);
if (completed != waitTask) return null;
return await waitTask.ConfigureAwait(false);
}
//public async Task WaitImageFlagAsync(int cameraNo, int timeoutMs, CancellationToken token)
//{
// if (cameraNo < 0 || cameraNo >= ImageData.Length)
// {
// SendTaskMessage($"等待相机图像失败:CameraNo={cameraNo} 越界", MessageLevel.Alarm);
// return false;
// }
// var start = DateTime.UtcNow;
// while (ImageData[cameraNo] == 0)
// {
// token.ThrowIfCancellationRequested();
// if ((DateTime.UtcNow - start).TotalMilliseconds >= timeoutMs)
// {
// SendTaskMessage($"等待相机图像超时:CameraNo={cameraNo} Timeout={timeoutMs}ms", MessageLevel.Alarm);
// return false;
// }
// await Task.Delay(100, token).ConfigureAwait(false);
// }
// return true;
//}
}
}