| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567 |
- 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;
- /// <summary>
- /// 产品主sn
- /// </summary>
- string ProductMainSN = "";
- string wo = "";
- #endregion
- #region 属性
- public string[] CsvData = new string[50];
- public int[] ResultData = new int[200];
- public string code = "";
- List<LockResult> lockResultsAll = new List<LockResult>();//一个产品的总结果
- private ObservableCollection<ShowRender> _Renders;
- private double _CTtime;
- public int ResultDataCount;
- private bool _ShowMes_Query;
- /// <summary>
- /// 显示查询结果
- /// </summary>
- public bool ShowMes_Query
- {
- get { return _ShowMes_Query; }
- set { SetProperty(ref _ShowMes_Query, value); }
- }
- private bool _ShowMes_Result;
- /// <summary>
- /// 显示上传结果
- /// </summary>
- public bool ShowMes_Result
- {
- get { return _ShowMes_Result; }
- set { SetProperty(ref _ShowMes_Result, value); }
- }
- /// <summary>
- /// ct
- /// </summary>
- public double CTtime
- {
- get { return _CTtime; }
- set { SetProperty(ref _CTtime, value); }
- }
- /// <summary>
- /// 显示界面
- /// </summary>
- public ObservableCollection<ShowRender> Renders
- {
- get { return _Renders; }
- set { SetProperty(ref _Renders, value); }
- }
- private ProductModel _CurrentProduct;
- /// <summary>
- /// 当前产品
- /// </summary>
- 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<StatusInfo> _Status = new ObservableCollection<StatusInfo>();
- /// <summary>
- /// 状态栏集合
- /// </summary>
- public ObservableCollection<StatusInfo> Status
- {
- get { return _Status; }
- set { SetProperty(ref _Status, value); }
- }
- private Int64 _TotalQuantity;
- /// <summary>
- /// 总产量
- /// </summary>
- public Int64 TotalQuantity
- {
- get { return _TotalQuantity; }
- set { SetProperty(ref _TotalQuantity, value); }
- }
- private Int64 _TotalQuantityToday;
- /// <summary>
- /// 当天的总产量
- /// </summary>
- public Int64 TotalQuantityToday
- {
- get { return _TotalQuantityToday; }
- set { SetProperty(ref _TotalQuantityToday, value); }
- }
- private Int64 _CurrentUPH;
- /// <summary>
- /// 当前的UPH
- /// </summary>
- public Int64 CurrentUPH
- {
- get { return _CurrentUPH; }
- set { SetProperty(ref _CurrentUPH, value); }
- }
- private Int64 _NgNumber;
- /// <summary>
- /// 当前的NG数量
- /// </summary>
- public Int64 NgNumber
- {
- get { return _NgNumber; }
- set { SetProperty(ref _NgNumber, value); }
- }
- private double _Yield;
- /// <summary>
- /// 当前的NG数量
- /// </summary>
- 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<string, object> BackupObject { get; set; } = new Dictionary<string, object>();
- #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<ShowRender>();
- _configService = configService;
- _productService = productService;
- _remoteCommandService = remoteCommandService;
- _systemDatabaseService = systemDatabaseService;
- _lightManagerService = lightManagerService;
- _mesService = mesService;
- }
- #region 初始化硬件模块
- /// <summary>
- /// 初始化Feeder
- /// </summary>
- /// <returns></returns>
- 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());
- }
- }
- /// <summary>
- /// 初始化机器人
- /// </summary>
- /// <returns></returns>
- 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());
- }
- }
- /// <summary>
- /// 初始化PLC
- /// </summary>
- /// <returns></returns>
- 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());
- }
- }
- /// <summary>
- /// 初始化相机
- /// </summary>
- /// <returns></returns>
- 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<ShowVisionRenderViewModel>().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<RenderUpdateNotification>().Publish(new ShowRender()
- //{
- // CameraName = camera.CameraName,
- // Id = cameraId,
- // Image = arg1,
- // Graphic = null,
- // Record = null,
- // Result = false,
- // IsShow = true,
- //});
- // 通知等待方:该相机新图到达
- //SignalImageArrived(cameraId, arg1);
- }
- /// <summary>
- /// 初始化光源控制器
- /// </summary>
- /// <returns></returns>
- 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());
- //}
- }
- /// <summary>
- /// 初始化后台TCP服务器通讯
- /// </summary>
- 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);
- }
- }
- /// <summary>
- /// 初始化后台ModbusTCP从站
- /// </summary>
- 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);
- }
- }
- /// <summary>
- /// 初始化后台脚本
- /// </summary>
- public void InitBackgroundcript()
- {
- try
- {
- if (!Directory.Exists(FilePath.BackgroundScriptPath))
- {
- Directory.CreateDirectory(FilePath.BackgroundScriptPath);
- }
- try
- {
- string[] files = Directory.GetFiles(FilePath.BackgroundScriptPath);
- List<string> ScriptFilesCollection = new List<string>();
- 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);
- }
- }
- /// <summary>
- /// 初始化电批
- /// </summary>
- /// <returns></returns>
- 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<Guid, CancellationTokenSource> RobotTCPCollection = new Dictionary<Guid, CancellationTokenSource>();
- /// <summary>
- /// 机器人TCP接收
- /// </summary>
- /// <param name="arg1"></param>
- /// <param name="arg2"></param>
- /// <param name="arg3"></param>
- 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&相机连接状态事件
- /// <summary>
- /// 机器人发送事件
- /// </summary>
- /// <param name="arg1"></param>
- /// <param name="arg2"></param>
- /// <param name="arg3"></param>
- /// <exception cref="NotImplementedException"></exception>
- private void Management_SendEvent(Guid robotid, object arg2, string arg3)
- {
- var r = _robotService.GetRobot(robotid);
- SendTaskMessage($"{r.Name}Send:{arg3}", MessageLevel.Info);
- }
- /// <summary>
- /// 机器人断开连接时
- /// </summary>
- /// <param name="arg1"></param>
- /// <param name="arg2"></param>
- /// <param name="arg3"></param>
- /// <exception cref="NotImplementedException"></exception>
- 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);
- }));
- }
- }
- /// <summary>
- /// 机器人连接成功时
- /// </summary>
- /// <param name="arg1"></param>
- /// <param name="arg2"></param>
- /// <param name="arg3"></param>
- /// <exception cref="NotImplementedException"></exception>
- 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);
- }));
- }
- }
- /// <summary>
- /// Feeder连接状态改变时
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="state"></param>
- 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);
- }
- }
- /// <summary>
- /// 相机连接或者断开时
- /// </summary>
- /// <param name="id"></param>
- /// <param name="state"></param>
- 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);
- }));
- }
- }
- }
- /// <summary>
- /// PLC连接状态改变事件
- /// </summary>
- /// <param name="plc"></param>
- /// <param name="isconnected"></param>
- 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);
- }));
- }
- }
- /// <summary>
- /// 电批连接状态改变时
- /// </summary>
- /// <param name="screwDevice"></param>
- /// <param name="state"></param>
- 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<string, CancellationTokenSource> BgCommunicateollection = new Dictionary<string, CancellationTokenSource>();
- 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
- /// <summary>
- /// 将系统参数写入PLC
- /// </summary>
- /// <param name="systemConfiguration"></param>
- /// <returns></returns>
- 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<string, object> nodeValues = new Dictionary<string, object>();
- 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);
- }
- /// <summary>
- /// 注册需要监控的PLC地址
- /// </summary>
- public void RegisterPlcMonitorAddress()
- {
- var addressConfig = _configService.GetPlcAddresses();
- var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
- if (plc == null || !plc.IsConnected) return;
- //PLC地址数组
- List<string> monitorNodeIds = new List<string>()
- {
- 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);
- }
- /// <summary>
- /// 写入点位信息给PLC
- /// </summary>
- /// <returns></returns>
- 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<Task<(bool IsSucceed, bool[] Result, string Message)>> _PrcTaskList = new List<Task<(bool IsSucceed, bool[] Result, string Message)>>();
- private readonly object _stateLock = new object();
- /// <summary>
- /// PLC命令触发时
- /// </summary>
- /// <param name="tuple"></param>
- 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<string>(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<Int16>(addressConfig.In_FixedCameracheckNum.Address);
- // 读取相机编号
- Int16 cameraIndex = plc.ReadNode<Int16>(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<Int16>(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<Guid>();
- 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<LockResetNotification>().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>(string.Format(addressConfig.In_Code.Address, i));
- }
- var homeview = _container.Resolve<HomeViewModel>();
-
- //过站检查
- 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<DataFormCtq> DFC = new List<DataFormCtq>();
- 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<Int16>(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);
- }
- }
- /// <summary>
- /// 异步执行流程拍照
- /// </summary>
- /// <param name="pointIndex"></param>
- /// <param name="procedureId"></param>
- /// <returns></returns>
- private Task<(bool IsSucceed, bool[] Result, string Message)> ExecuteProcedureAsync(int pointIndex, Guid procedureId)
- {
- return Task.Run(async () =>
- {
- List<bool> results = new List<bool>();
- // 获取当前产品
- 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<LockFinishNotification>().Publish(lockResult1);
- });
- }
- //排序
- //lock (_stateLock)
- //{
- // var bf1 = lockResultsAll.OrderBy(p => p.Number);
- // lockResultsAll = new List<LockResult>(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, $"处理固定相机检测拍照时出错");
- }
- });
- }
- /// <summary>
- /// 异步执行流程拍照
- /// </summary>
- /// <param name="pointIndex"></param>
- /// <param name="procedureId"></param>
- /// <returns></returns>
- private Task<(bool IsSucceed, bool[] Result, string Message)> ExecuteProcedureAsync(int pointIndex, Guid procedureId, ICogImage[] images)
- {
- return Task.Run(async () =>
- {
- List<bool> results = new List<bool>();
- // 获取当前产品
- 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<LockFinishNotification>().Publish(lockResult1);
- });
- }
- ////排序
- //lock (_stateLock)
- //{
- // var bf1 = lockResultsAll.OrderBy(p => int.Parse(p.PhotoName));
- // lockResultsAll = new List<LockResult>(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, $"处理固定相机检测拍照时出错");
- }
- });
- }
- /// <summary>
- /// 是否是3D相机
- /// </summary>
- /// <param name="procedureId"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 2D相机先采集图像
- /// </summary>
- /// <param name="procedureId"></param>
- /// <returns></returns>
- 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, $"处理固定相机检测拍照时出错");
- }
- }
- /// <summary>
- /// 为所有相机设置批处理点数(会调用具体相机实现的 SetBatchPoints)
- /// </summary>
- /// <param name="points"></param>
- 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<TaskMessageNotification>().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启动检测
- /// <summary>
- /// 杀死所有VM有关进程
- /// </summary>
- public void KillVMProcess()
- {
- KillProcess("VisionMasterServerApp");
- KillProcess("VisionMaster");
- KillProcess("VmModuleProxy.exe");
- KillProcess("vServerApp.exe");
- }
- /// <summary>
- /// 杀死指定进程名的进程
- /// </summary>
- /// <param name="strKillName"></param>
- 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
- /// <summary>
- /// 记录工位的结果,其他工位要存储的数据项按照键值对集合的形式传入,键为数据项名称,值为数据项的值
- /// </summary>
- /// <param name="stationIndex"></param>
- /// <param name="dfcs"></param>
- /// <param name="productMainSN"></param>
- /// <param name="ct"></param>
- /// <param name="timestamp"></param>
- /// <param name="savePath"></param>
- /// <param name="isFirstEnter"></param>
- /// <returns></returns>
- private bool RecordStationResult(int stationIndex, IEnumerable<DataFormCtq> 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<Guid, TaskCompletionSource<ICogImage>> _nextImageTcsByCamera =
- new Dictionary<Guid, TaskCompletionSource<ICogImage>>();
- private Task<ICogImage> PrepareNextImageWait(Guid cameraId)
- {
- lock (_imageSyncLock)
- {
- var tcs = new TaskCompletionSource<ICogImage>(TaskCreationOptions.RunContinuationsAsynchronously);
- _nextImageTcsByCamera[cameraId] = tcs;
- return tcs.Task;
- }
- }
- public async Task SignalImageArrived(Guid cameraId, ICogImage image)
- {
- await Task.Delay(500);
- TaskCompletionSource<ICogImage> tcs = null;
- lock (_imageSyncLock)
- {
- _nextImageTcsByCamera.TryGetValue(cameraId, out tcs);
- }
- tcs?.TrySetResult(image);
- }
- public async Task<ICogImage> 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<bool> 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;
- //}
- }
- }
|