| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348 |
- using Cognex.VisionPro.ToolBlock;
- 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.IO.Compression;
- using System.Linq;
- using System.Net.Sockets;
- 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.Models.PLC;
- using TeamAAS_VP.Models.Torque;
- using TeamAAS_VP.Resources.Languages;
- using TouchSocket.Core;
- using TouchSocket.SerialPorts;
- using TouchSocket.Sockets;
- using Timer = System.Threading.Timer;
- 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;
- SerialPortClient client;
- // Pressure collection
- /// <summary>
- /// 压力采集信号控制CTS
- /// </summary>
- private CancellationTokenSource _pressureCts;
- /// <summary>
- /// 压力采集超时CTS
- /// </summary>
- private CancellationTokenSource _pressureTimeoutCts;
- /// <summary>
- /// 压力采集CTS
- /// </summary>
- private CancellationTokenSource _pressureLinkedCts;
- /// <summary>
- /// 压力数据集合
- /// </summary>
- private List<(DateTime Timestamp, float Value)> _pressureSamples = new List<(DateTime, float)>();
- /// <summary>
- /// 采样间隔毫秒
- /// </summary>
- private int _pressureSampleIntervalMs = 50; //采样间隔毫秒
- /// <summary>
- /// 超时自动停止秒数
- /// </summary>
- private int _pressureMaxDurationSeconds = 30; //超时自动停止秒数
- List<LockResult> lockResultsAll = new List<LockResult>();//一个产品的总结果
- string productSn = "";//产品sn
- DateTime StartScrewTime = DateTime.Now;//开始锁附的时间
- #endregion
- #region 属性
- private ObservableCollection<ShowRender> _Renders;
- /// <summary>
- /// 显示界面
- /// </summary>
- public ObservableCollection<ShowRender> Renders
- {
- get { return _Renders; }
- set { SetProperty(ref _Renders, 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 _ThrowNumber;
- /// <summary>
- /// 抛料数
- /// </summary>
- public Int64 ThrowNumber
- {
- get { return _ThrowNumber; }
- set { SetProperty(ref _ThrowNumber, value); }
- }
- private Int64 _NgNumber;
- /// <summary>
- /// ng数量
- /// </summary>
- public Int64 NgNumber
- {
- get { return _NgNumber; }
- set { SetProperty(ref _NgNumber, value); }
- }
- private double _Yield;
- /// <summary>
- /// 良率
- /// </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>();
- private string _SignalValue = "0";
- /// <summary>
- /// 扭力测量仪获取的最大值
- /// </summary>
- public string SignalValue
- {
- get { return _SignalValue; }
- set { SetProperty(ref _SignalValue, value); }
- }
- private NumberStatistics _NumStatistics;
- /// <summary>
- /// 数量(批头、吸嘴、供料器)
- /// </summary>
- public NumberStatistics NumStatistics
- {
- get { return _NumStatistics; }
- set { SetProperty(ref _NumStatistics, value); }
- }
- private double _CTtime;
- /// <summary>
- /// ct
- /// </summary>
- public double CTtime
- {
- get { return _CTtime; }
- set { SetProperty(ref _CTtime, value); }
- }
- private bool _TorqueStatus = false;
- public bool TorqueStatus
- {
- get { return _TorqueStatus; }
- set { _TorqueStatus = value; }
- }
- private ObservableCollection<DataFormCtq> _dfc = new ObservableCollection<DataFormCtq>();
- /// <summary>
- /// CTQ数据集合
- /// </summary>
- public ObservableCollection<DataFormCtq> DFC
- {
- get { return _dfc; }
- set { SetProperty(ref _dfc, value); }
- }
- private ObservableCollection<ProductModel> _ProductList;
- public ObservableCollection<ProductModel> ProductList
- {
- get { return _ProductList; }
- set { SetProperty(ref _ProductList, value); }
- }
- #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>();
- _productService = productService;
- _remoteCommandService = remoteCommandService;
- _systemDatabaseService = systemDatabaseService;
- _lightManagerService = lightManagerService;
- _mesService = mesService;
- }
- #region 读取配置参数
- public async Task ReadConfig()
- {
- await ReadNumber();
- }
- /// <summary>
- /// 读取数量配置
- /// </summary>
- public async Task ReadNumber()
- {
- try
- {
- NumStatistics = new NumberStatistics();
- var latestHeadChangeRecord = await _systemDatabaseService.GetLatestHeadChangeRecordAsync();
- if (latestHeadChangeRecord != null)
- {
- NumStatistics.HeaderNum = latestHeadChangeRecord.CurrentLockCount;
- }
- var latestNozzleChangeRecord = await _systemDatabaseService.GetLatestNozzleChangeRecordAsync();
- if (latestNozzleChangeRecord != null)
- {
- NumStatistics.NozzleNum = latestNozzleChangeRecord.CurrentLockCount;
- }
- NumStatistics.Feeder1Num = _configService.GetRemainingCountByFeederNumber(1);
- NumStatistics.Feeder2Num = _configService.GetRemainingCountByFeederNumber(2);
- }
- catch (Exception ex)
- {
- NumStatistics = new NumberStatistics();
- LogHelper.WriteLogError("加载数量配置文件时出错!", ex);
- }
- }
- #endregion
- #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(Lang.为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)
- {
- try
- {
- //Renders.Add(new ShowRender() { Id = item.Id, CameraName = item.CameraName });
- _cameraService.CreateCamera(item.Id, item);
- var camera = _cameraService.GetCamera(item.Id);
- Status.Add(new StatusInfo(item.Id, item.CameraName + $"{Lang.未连接}", new SolidColorBrush(Colors.Red)));
- camera.CameraConnectChangedEvent += Management_CameraConnectChangedEvent;
- 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());
- }
- }
- /// <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(Lang.开启后台服务器通讯时出错, 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(Lang.开启后台ModbusTCP通讯时出错, 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(string.Format(Lang.开启脚本时出错0, item), ex);
- }
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError(Lang.读取本地脚本文件列表时出错, ex);
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError(Lang.开启后台脚本时出错, 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, Lang.电批未连接, new SolidColorBrush(Colors.Red)));
- ScrewDriver.ConnectStateChangedEvent += ScrewDriver_ConnectStateChangedEvent;
- ScrewDriver.SendTimeout = screwDriverConfig.SendTimeout;
- screwDriverConfig.ReceiveTimeout = screwDriverConfig.ReceiveTimeout;
- var isConnected = await ScrewDriver.ConnectAsync();
- if (isConnected)
- {
- SendTaskMessage(Lang.电批已连接, MessageLevel.Debug);
- }
- else
- {
- SendTaskMessage(Lang.电批连接失败, MessageLevel.Error);
- }
- }
- catch (Exception ex)
- {
- SendTaskMessage(string.Format(Lang.电批连接失败0, ex.Message), MessageLevel.Alarm);
- LogHelper.WriteLogError(Lang.连接电批时出错, ex);
- }
- }
- /// <summary>
- /// 初始化扭力测量仪
- /// </summary>
- /// <returns></returns>
- public async Task InitSignal()
- {
- var torqueConfig = _configService.GetTorqueReaderConfig();
- if (torqueConfig != null)
- {
- try
- {
- var port = FileHelper.ReadJsonFile<TorqueProduceModel>(FilePath.TorqueReaderConfigurationPath);
- if (string.IsNullOrEmpty(port.TorqueMeasureSerialPort))
- {
- client = new TouchSocket.SerialPorts.SerialPortClient();
- client.Connecting = (client1, e) => { return EasyTask.CompletedTask; };//即将连接到端口
- client.Connected = (client1, e) => { return EasyTask.CompletedTask; };//成功连接到端口
- client.Closing = (client1, e) => { return EasyTask.CompletedTask; };//即将从端口断开连接。此处仅主动断开才有效。
- client.Closed = (client1, e) => { return EasyTask.CompletedTask; };//从端口断开连接,当连接不成功时不会触发。
- client.Received = async (c, e) =>
- {
- //await Console.Out.WriteLineAsync(Encoding.UTF8.GetString(e.ByteBlock.Buffer));
- await Console.Out.WriteLineAsync(e.ByteBlock.Span.ToString(Encoding.ASCII));
- };
- client.Received = Sp_DataReceived;
- await client.SetupAsync(new TouchSocketConfig()
- .SetSerialPortOption(new SerialPortOption()
- {
- BaudRate = torqueConfig.BaudRate,//波特率
- DataBits = torqueConfig.DataBits,//数据位
- Parity = torqueConfig.Parity,//校验位
- PortName = torqueConfig.PortName,//COM
- StopBits = torqueConfig.StopBits//停止位
- })
- .SetSerialDataHandlingAdapter(() => new PeriodPackageAdapter() { CacheTimeout = TimeSpan.FromMilliseconds(100) })
- );
- await client.ConnectAsync();
- }
- else
- {
- SendTaskMessage("请设置扭力测量仪串口!", MessageLevel.Error);
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("初始化扭力测量仪时出错!", ex);
- SendTaskMessage("初始化扭力测量仪时出错!" + ex.Message, MessageLevel.Error);
- }
- }
- else
- {
- TorqueSerialPortConfig config = new TorqueSerialPortConfig();
- FileHelper.WriteJsonFile(config, FilePath.TorqueReaderConfigurationPath);
- }
- }
- #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(Lang.TCP发送数据时出错, ex);
- SendTaskMessage(ex.Message, MessageLevel.Alarm);
- }
- });
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError(Lang.处理机器人接收的命令时出错, 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 async 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);
- }));
- try
- {
- await WriteSystemParameterToPlcAsync(_configService.GetSystemConfiguration());
- await WritePositionToPlcAsync();
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("PLC连接成功时,写入系统参数和点位信息时出错!", ex);
- }
- }
- 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(Lang.电批连接状态改变时出错了, 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(Lang.后台TCP发送数据时出错, ex);
- SendTaskMessage(ex.Message, MessageLevel.Alarm);
- }
- });
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError(Lang.处理后台服务器接收的命令时出错, 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);
- }
- /// <summary>
- /// 扭力测量仪接收信息
- /// </summary>
- /// <param name="client"></param>
- /// <param name="e"></param>
- /// <returns></returns>
- private async Task Sp_DataReceived(ISerialPortClient client, ReceivedDataEventArgs e)
- {
- try
- {
- string poname = client.MainSerialPort.PortName;
- string data = e.ByteBlock.Span.ToString(Encoding.ASCII);
- await Console.Out.WriteLineAsync(data);
- string response = data.Split('\r')[0];
- SendTaskMessage($"{poname}Receive:{response}", MessageLevel.Info);
- SignalValue = "";
- SignalValue = response;
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("扭力测量仪接收信息时出错!", ex);
- SendTaskMessage("扭力测量仪接收信息时出错!" + ex.Message, MessageLevel.Error);
- Thread.Sleep(50);
- }
- }
- #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);
- nodeValues.Add(addressConfig.Out_ScrewTeachNum.Address, (Int16)systemConfiguration.ScrewTeachNum);
- 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,
- addressConfig.In_QrCodePhotoRequest.Address,
- addressConfig.In_ScrewTeachExe.Address,
- addressConfig.In_PickINC.Address,
- addressConfig.In_Throw.Address,
- };
- var systemconfig = _configService.GetSystemConfiguration();
- for (int i = 0; i < 10; i++)
- {
- if (systemconfig.DoubleSoftMode && i == 1)
- {
- continue;
- }
- 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, item.Feeder);
- }
- }
- 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)
- {
- int index = 0;
- foreach (var item in current.ScrewCameraPoints)
- {
- //根据使用的点位进行排序
- if (item.IsUse)
- {
- index++;
- await item.WriteToPlcAddress(addressConfig.Out_ScrewCamera, plc, index);
- }
- }
- }
- if (current.ScrewPoints != null && current.ScrewPoints.Count > 0)
- {
- int index = 0;
- foreach (var item in current.ScrewPoints)
- {
- if (item.IsUse)
- {
- index++;
- await item.WriteToPlcAddressEx(addressConfig.Out_Screw, plc, index);
- }
- }
- await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)index);
- }
- if (current.CheckCameraPoints != null && current.CheckCameraPoints.Count > 0)
- {
- int index = 0;
- foreach (var item in current.CheckCameraPoints)
- {
- if (item.IsUse)
- {
- index++;
- await item.WriteToPlcAddress(addressConfig.Out_CheckCamera, plc, index);
- }
- }
- }
- if (current.QrCodePoints != null && current.QrCodePoints.Count > 0)
- {
- foreach (var item in current.QrCodePoints)
- {
- await item.WriteToPlcAddress(addressConfig.Out_QrCodeCamera, plc);
- }
- }
- }
- 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;
- bool _LastThrowExe = false;
- Int16 _LastWorkStart = 0;
- Int16 _LastWorkDone = 0;
- Int16 _LastRequestPosition = 0;
- Int16 _LastQrCodePhotoRequest = 0;
- Int16[] _LastMesCheck = new Int16[10];
- Int16 _LastPickINC = 0;
- DateTime[] _LastMesCheckTime = new DateTime[10];
- string[] ProductMainSN { get; set; } = new string[10];//产品主sn
- string[] model_num { get; set; } = new string[10];//产品model_num
- string[] wo { get; set; } = new string[10];//产品wo
- string[] color { get; set; } = new string[10];//产品color
- Dictionary<string, string> dataToMes = new Dictionary<string, string>();//上传mes的数据
- List<string> resultToMes = new List<string>();//上传mes的数据
- /// <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 = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, 0));
- ////如果产品编码为空,则以当前的时间戳作为编码
- //if (string.IsNullOrEmpty(_productService.CurrentProductCode))
- //{
- // _productService.CurrentProductCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
- //}
- // 触发下相机拍照
- if (addressConfig.In_DowmCameraExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastDowmCameraExe != state)
- {
- _LastDowmCameraExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发下相机拍照, MessageLevel.Debug);
- //相机的编号
- Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
- // 获取流程
- var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
- if (process == null)
- {
- SendTaskMessage(string.Format(Lang.固定向上相机1视觉流程流程ID0, currentProduct.FixedUpCamera1ProcedureId), MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
- return;
- }
- // 获取机器人当前坐标
- var robot = _robotService.GetAllRobots().FirstOrDefault();
- if (robot == null)
- {
- SendTaskMessage(Lang.未找到机器人无法执行上相机锁附组装拍照视觉任务, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
- return;
- }
- var currentPosition = robot.GetRobotPos();
- // 执行视觉任务
- var _cts = new CancellationTokenSource();
- ImageParameters imgPara = new ImageParameters();
- imgPara.SNCode = productSn;
- var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token, cameraIndex, null, imgPara);
- if (visionResult.IsSucceed)
- {
- //披头偏差
- float offsetX = (float)(visionResult.X - currentPosition.X);
- float offsetY = (float)(visionResult.Y - currentPosition.Y);
- DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
- await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
- return;
- }
- else
- {
- await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
- return;
- }
- }
- else
- {
- SendTaskMessage(Lang.触发下相机拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)0);
- }
- }
- }
- // 触发下相机拍照披头
- if (addressConfig.In_ScrewTeachExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastScrewTeachExe != state)
- {
- _LastScrewTeachExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发下相机拍照, MessageLevel.Debug);
- //相机的编号
- Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
- // 获取流程
- var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
- if (process == null)
- {
- SendTaskMessage(string.Format(Lang.固定向上相机1视觉流程流程ID0, currentProduct.FixedUpCamera1ProcedureId), MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
- return;
- }
- // 获取机器人当前坐标
- var robot = _robotService.GetAllRobots().FirstOrDefault();
- if (robot == null)
- {
- SendTaskMessage(Lang.未找到机器人无法执行上相机锁附组装拍照视觉任务, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
- return;
- }
- var currentPosition = robot.GetRobotPos();
- // 执行视觉任务
- var _cts = new CancellationTokenSource();
- ImageParameters imgPara = new ImageParameters();
- imgPara.SNCode = productSn;
- var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token, cameraIndex, null, imgPara);
- if (visionResult.IsSucceed)
- {
- //披头偏差
- float offsetX = (float)(visionResult.X - currentPosition.X);
- float offsetY = (float)(visionResult.Y - currentPosition.Y);
- DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
- await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)1);
- return;
- }
- else
- {
- await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
- return;
- }
- }
- else
- {
- SendTaskMessage(Lang.触发下相机拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)0);
- }
- }
- }
- // 触发上相机取料拍照
- else if (addressConfig.In_UpCameraPickExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastUpCameraPickExe != state)
- {
- _LastUpCameraPickExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发上相机取料拍照, MessageLevel.Debug);
- //相机的编号
- //Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPickNum.Address);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage(Lang.触发上相机取料拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)0);
- }
- }
- }
- // 上相机锁附/组装拍照
- else if (addressConfig.In_UpCameraPutExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastUpCameraPutExe != state)
- {
- _LastUpCameraPutExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发上相机锁附组装拍照, MessageLevel.Debug);
- //相机的编号
- Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPutNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
- //视觉流程ID
- Guid procedureId = currentProduct.MoveDownCameraLockPhotoProcedureId;
- List<PlcPoint> plcPoints = new List<PlcPoint>();
- foreach (var item in currentProduct.ScrewCameraPoints)
- {
- if (item.IsUse)
- {
- plcPoints.Add(item);
- }
- }
- //获取锁付拍照的点位
- var pos = plcPoints[cameraIndex - 1];
- if (pos != null)
- {
- procedureId = pos.VisionProcessID;
- }
- // 获取流程
- var process = _productService.GetCurrentProductProcedureModelById(procedureId);
- if (process == null)
- {
- SendTaskMessage(string.Format(Lang.未找到上相机锁附组装拍照对应的视觉流程流程ID0, procedureId), MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
- return;
- }
- // 获取机器人当前坐标
- var robot = _robotService.GetAllRobots().FirstOrDefault();
- if (robot == null)
- {
- SendTaskMessage(Lang.未找到机器人无法执行上相机锁附组装拍照视觉任务, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
- return;
- }
- var currentPosition = robot.GetRobotPos();
- // 执行视觉任务
- var _cts = new CancellationTokenSource();
- ImageParameters imgPara = new ImageParameters();
- imgPara.SNCode = productSn;
- var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token, cameraIndex, null, imgPara);
- if (visionResult.IsSucceed)
- {
- //是拍一个锁一个还是拍两个点锁所有
- var systemConfig = _configService.GetSystemConfiguration();
- //拍1打1
- if (systemConfig.WorkMode == 1)
- {
- UpCameraPutResults[1] = new PointF((float)visionResult.X, (float)visionResult.Y);
- }
- else
- {
- UpCameraPutResults[cameraIndex] = new PointF((float)visionResult.X, (float)visionResult.Y);
- }
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
- }
- else
- {
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
- }
- }
- else
- {
- SendTaskMessage(Lang.触发上相机锁附组装拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)0);
- }
- }
- }
- // 上相机检测拍照
- else if (addressConfig.In_UPCameracheckExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastUPCameracheckExe != state)
- {
- _LastUPCameracheckExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发上相机检测拍照, MessageLevel.Debug);
- //相机的编号
- Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UPCameracheckNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
- //获取锁付拍照的点位
- List<PlcPoint> plcPoints = new List<PlcPoint>();
- foreach (var item in currentProduct.CheckCameraPoints)
- {
- if (item.IsUse)
- {
- plcPoints.Add(item);
- }
- }
- //视觉流程ID
- Guid procedureId = Guid.Empty;
- //获取锁付拍照的点位
- var pos = plcPoints[cameraIndex - 1];
- if (pos != null)
- {
- procedureId = pos.VisionProcessID;
- }
- // 获取流程
- var process = _productService.GetCurrentProductProcedureModelById(procedureId);
- if (process == null)
- {
- SendTaskMessage(string.Format("未找到点位:{0}的视觉流程:{1}", cameraIndex, procedureId), MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)2);
- return;
- }
- // 获取机器人当前坐标
- var robot = _robotService.GetAllRobots().FirstOrDefault();
- if (robot == null)
- {
- SendTaskMessage("未找到机器人无法执行 上相机检测拍照视觉任务", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
- return;
- }
- var currentPosition = robot.GetRobotPos();
- // 执行视觉任务
- var _cts = new CancellationTokenSource();
- var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token, cameraIndex, null, null);
- if (visionResult.IsSucceed)
- {
- await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)1);
- SendTaskMessage($"点位{cameraIndex}检测OK", MessageLevel.Debug);
- }
- else
- {
- await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)2);
- SendTaskMessage($"点位{cameraIndex}检测NG", MessageLevel.Error);
- }
- }
- else
- {
- SendTaskMessage(Lang.触发上相机检测拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_UPCameracheckStatus.Address, (Int16)0);
- }
- }
- }
- // 固定相机取料拍照
- else if (addressConfig.In_FixedCameraPickExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastFixedCameraPickExe != state)
- {
- _LastFixedCameraPickExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发固定相机取料拍照, MessageLevel.Debug);
- //相机的编号
- //Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_FixedCameraPickNum.Address);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage(Lang.触发固定相机取料拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPickStatus.Address, (Int16)0);
- }
- }
- }
- // 固定相机锁附/组装拍照
- else if (addressConfig.In_FixedCameraPutExe.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastFixedCameraPutExe != state)
- {
- _LastFixedCameraPutExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage(Lang.触发固定相机锁附组装拍照, MessageLevel.Debug);
- //相机的编号
- //Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_FixedCameraPutNum.Address);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPutStatus.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage(Lang.触发固定相机锁附组装拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameraPutStatus.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)
- {
- SendTaskMessage(Lang.触发固定相机检测拍照, MessageLevel.Debug);
- //相机的编号
- //Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_FixedCameracheckNum.Address);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameracheckStatus.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage(Lang.触发固定相机检测拍照信号已关闭, MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_FixedCameracheckStatus.Address, (Int16)0);
- }
- }
- }
- // 开始锁付
- else if (addressConfig.In_WorkStart.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is Int16 state)
- {
- if (_LastWorkStart != state)
- {
- _LastWorkStart = state;
- }
- else
- {
- return;
- }
- if (state == 1)
- {
- SendTaskMessage(Lang.收到开始锁付信号, MessageLevel.Debug);
- StartScrewTime = DateTime.Now;
- //位置编号
- Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, positionIndex), MessageLevel.Info);
- // 开始采集压力值
- StartPressureCollection(currentProduct.Name, _productService.CurrentProductCode, positionIndex);
- }
- else
- {
- SendTaskMessage(Lang.开始锁付信号已关闭, MessageLevel.Alarm);
- // 关闭时的处理(如需)可放在这里
- }
- }
- }
- // 停止锁付
- else if (addressConfig.In_WorkDone.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is Int16 state)
- {
- if (_LastWorkDone != state)
- {
- _LastWorkDone = state;
- }
- else
- {
- return;
- }
- if (state == 1 || state == 2)
- {
- if (TorqueStatus)
- {
- }
- SendTaskMessage(Lang.收到停止锁付信号, MessageLevel.Debug);
- //位置编号
- Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, positionIndex), MessageLevel.Info);
- //获取当前锁付点
- var screwPoint = currentProduct.ScrewPoints.FirstOrDefault(p => p.Number == positionIndex);
- //获取当前的机器人点位
- var robot = _robotService.GetAllRobots().FirstOrDefault();
- var currentPosition = robot.GetRobotPos();
- //读取压力值
- float pressure = plc.ReadNode<float>(addressConfig.In_PressureValue.Address);
- //当前用户名
- string currentUserName = _systemDatabaseService.GetCurrentUser().UserName;
- //吸嘴最后一次的记录
- var nozzleRecord = await _systemDatabaseService.GetLatestNozzleChangeRecordAsync();
- //最后一次的吸嘴编号
- string nozzleNumber = nozzleRecord != null ? nozzleRecord.NozzleBatchNumber : "N/A";
- //披头最后一次的记录
- var headRecord = await _systemDatabaseService.GetLatestHeadChangeRecordAsync();
- //最后一次的披头编号
- string headNumber = headRecord != null ? headRecord.HeadBatchNumber : "N/A";
- await Task.Delay(60);
- //获取电批结果
- bool isSucced = ScrewDriver.GetData();
- LockResult lockResult = new LockResult();
- lockResult.ScrewdriverGetDataSucceed = isSucced;
- lockResult.Number = positionIndex;
- lockResult.LockPassed = ScrewDriver.Success;
- lockResult.ProductName = currentProduct.Name;
- lockResult.ProductNumber = _productService.CurrentProductCode;
- lockResult.LockTurns = (float)ScrewDriver.Truns;
- lockResult.LockTorque = (float)ScrewDriver.TorqueValue;
- lockResult.LockDuration = (float)ScrewDriver.FinalTime;
- lockResult.ScrewdriverProgramNumber = ScrewDriver.ProgramNumber;
- lockResult.ResultDetails = ScrewDriver.ErrorInfo;
- lockResult.Pressure = pressure;
- lockResult.TargetTorqueUpperLimit = ScrewDriver.TargetTorqueUpperLimit;
- lockResult.TargetTorqueLowerLimit = ScrewDriver.TargetTorqueLowerLimit;
- lockResult.TargetTurnsUpperLimit = ScrewDriver.TargetTurnsUpperLimit / 360;
- lockResult.TargetTurnsLowerLimit = ScrewDriver.TargetTurnsLowerLimit / 360;
- lockResult.TargetLockSpeed = ScrewDriver.TargetLockSpeed;
- lockResult.PositionX = currentPosition.X;
- lockResult.PositionY = currentPosition.Y;
- lockResult.StartPositionZ = screwPoint.Z_Position_Start;
- lockResult.EndPositionZ = currentPosition.Z;
- lockResult.LockDescentSpeed = screwPoint.Z_Velocity_Stop;
- lockResult.FeederNumber = screwPoint != null ? screwPoint.Feeder : 0;
- lockResult.NozzleNumber = nozzleNumber;
- lockResult.HeadNumber = headNumber;
- lockResult.OperatorName = currentUserName;
- lockResult.ProductImagePath = "";
- lockResult.WaveDatas = ScrewDriver.WaveDatas;
- //获取系统参数
- var systemConfig = _configService.GetSystemConfiguration();
- //判断是否保存锁付曲线
- if (systemConfig.IsSaveScrewCurve)
- {
- //锁付曲线的保存路径为:systemConfig.ScrewCurvePath//年月//年月日//配方名//产品SN//产品SN+螺丝索引
- string datePath = DateTime.Now.ToString("yyyy-MM") + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\";
- string dirPath = System.IO.Path.Combine(systemConfig.ScrewCurvePath, datePath, currentProduct.Name, lockResult.ProductNumber);
- if (!Directory.Exists(dirPath))
- {
- Directory.CreateDirectory(dirPath);
- }
- string curveFileName = $"{lockResult.ProductNumber}-{lockResult.Number}.png";
- //锁付CSV保存路径
- string curveFileFullPath = System.IO.Path.Combine(dirPath, $"{lockResult.ProductNumber}-{lockResult.Number}.csv");
- //锁付曲线保存路径
- lockResult.LockCurveImagePath = System.IO.Path.Combine(dirPath, curveFileName);
- var _ = lockResult.SaveToCsvAsync(curveFileFullPath);
- }
- if (lockResult.Number == 1)
- {
- dataToMes.Clear();
- resultToMes.Clear();
- lockResultsAll.Clear();
- }
- //基于当前的锁付结果和产品的规格参数判断锁付结果是否合格
- var stationConfig = _configService.GetDeviceInfo(0);
- bool torqueRes = false, turnRes = false, pressureRes = false;
- bool lastRes = false;//默认不合格,只有当扭力、圈数、压力都在设定的上下限范围内时,才判定为锁付合格
- if (lockResult.LockTorque >= lockResult.TargetTorqueLowerLimit && lockResult.LockTorque <= lockResult.TargetTorqueUpperLimit)
- {
- torqueRes = true;
- }
- if (lockResult.Pressure >= stationConfig.DataInfo.CTQ_LSL_Pressure && lockResult.Pressure <= stationConfig.DataInfo.CTQ_USL_Pressure)
- {
- pressureRes = true;
- }
- if (lockResult.LockTurns >= lockResult.TargetTurnsLowerLimit && lockResult.LockTurns <= lockResult.TargetTurnsUpperLimit)
- {
- turnRes = true;
- }
- if (torqueRes == true && turnRes == true && pressureRes == true)//当扭力、圈数、压力都在设定的上下限范围内时,才判定为锁付合格
- {
- lastRes = true;
- }
- dataToMes.Add($"Torque{lockResult.Number}", $"{lockResult.LockTorque:F2}");
- dataToMes.Add($"Turn{lockResult.Number}", $"{lockResult.LockTurns:F2}");
- dataToMes.Add($"Pressure{lockResult.Number}", $"{lockResult.Pressure:F2}");
- //dataToMes.Add($"LastResult{lockResult.Number}", $"{lastRes}");
- if (!lastRes)//如果不合格,则在MES结果中添加"Screw{lockResult.Number}_Fail"
- {
- resultToMes.Add($"Screw{lockResult.Number}_Fail");
- }
- SendTaskMessage($"螺丝序号:{lockResult.Number},扭力:{lockResult.LockTorque},压力:{lockResult.Pressure},圈数:{lockResult.LockTurns}", MessageLevel.Info);
- lockResultsAll.Add(lockResult);
- App.Current.Dispatcher.Invoke(() =>
- {
- _eventAggregator.GetEvent<LockFinishNotification>().Publish(lockResult);
- });
- //记录锁付结果至数据库
- await _systemDatabaseService.RecordLockResultAsync(lockResult);
- //披头数量+1
- NumStatistics.HeaderNum = await _systemDatabaseService.IncrementLatestHeadLockCountAsync(currentUserName);
- //吸嘴数量+1
- NumStatistics.NozzleNum = await _systemDatabaseService.IncrementLatestNozzleLockCountAsync(currentUserName);
- await plc.WriteNodeAsync(addressConfig.In_WorkDone.Address, (Int16)0);
- // 停止采集压力并保存
- await StopAndSavePressureCollectionAsync(currentProduct.Name, _productService.CurrentProductCode, positionIndex);
- }
- else
- {
- SendTaskMessage(Lang.停止锁付信号已关闭, MessageLevel.Alarm);
- }
- }
- }
- // 多相机坐标合并
- 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)
- {
- SendTaskMessage(Lang.收到多相机坐标合并请求开始合并, MessageLevel.Debug);
- //位置编号
- Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
- //是拍一个锁一个还是拍两个点锁所有
- var systemConfig = _configService.GetSystemConfiguration();
- //拍1打1
- if (systemConfig.WorkMode == 1)
- {
- List<PlcPoint> plcPoints = new List<PlcPoint>();
- foreach (var item in currentProduct.ScrewPoints)
- {
- if (item.IsUse)
- {
- plcPoints.Add(item);
- }
- }
- var point = plcPoints[positionIndex - 1];
- if (point == null)
- {
- SendTaskMessage($"点:{positionIndex}不存在", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)2);
- return;
- }
- point = point.Clone();
- point.X_Position = UpCameraPutResults[1].X + DowmCameraResults[1].X;
- point.Y_Position = UpCameraPutResults[1].Y + DowmCameraResults[1].Y;
- SendTaskMessage($"点:{positionIndex},{point.X_Position:F3},{point.Y_Position:F4}", MessageLevel.Info);
- await point.WriteToPlcAddress(addressConfig.Out_Screw, plc, positionIndex);
- }
- //拍1打所有
- else if (systemConfig.WorkMode == 2)
- {
- //根据UpCameraPutResults[]中的索引1、2,和拍照点对应的Local下的坐标,从创建Local坐标系
- PointF worldP1 = new PointF(UpCameraPutResults[1].X, UpCameraPutResults[1].Y);
- PointF worldP2 = new PointF(UpCameraPutResults[2].X, UpCameraPutResults[2].Y);
- PointF localP1 = new PointF(currentProduct.ScrewCameraLocalPos1.X_Position, currentProduct.ScrewCameraLocalPos1.Y_Position);
- PointF localP2 = new PointF(currentProduct.ScrewCameraLocalPos2.X_Position, currentProduct.ScrewCameraLocalPos2.Y_Position);
- CoordinateTransformer local = new CoordinateTransformer(worldP1, worldP2, localP1, localP2);
- for (int i = 0; i < currentProduct.ScrewPoints.Count; i++)
- {
- var localPoint = new PointF(currentProduct.ScrewPoints[i].X_Position + currentProduct.ScrewPoints[i].X_Offset,
- currentProduct.ScrewPoints[i].Y_Position + currentProduct.ScrewPoints[i].Y_Offset);
- var worldPoint = local.ToOldCoord(localPoint.X, localPoint.Y);
- var point = currentProduct.ScrewPoints[i].Clone();
- //锁付点位在Local中已经加了偏移,这里写回PLC时需要将偏移清零,否则写入PLC端时会重复计算偏移
- point.X_Offset = 0;
- point.Y_Offset = 0;
- point.X_Position = (float)worldPoint[0];
- point.Y_Position = (float)worldPoint[1];
- SendTaskMessage($"点:{i},{point.X_Position:F3},{point.Y_Position:F4}", MessageLevel.Info);
- await point.WriteToPlcAddress(addressConfig.Out_Screw, plc);
- }
- await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)currentProduct.ScrewPoints.Count);
- }
- await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage(string.Format(Lang.多相机坐标合并请求已结束或被取消state0, state), MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)0);
- }
- }
- }
- // PLC请求二维码拍照位置
- else if (addressConfig.In_QrCodePhotoRequest.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is Int16 state)
- {
- if (_LastQrCodePhotoRequest != state)
- {
- _LastQrCodePhotoRequest = state;
- }
- else
- {
- return;
- }
- if (state == 1)
- {
- SendTaskMessage("收到PLC二维码拍照位置请求", MessageLevel.Debug);
- if (currentProduct.QrCodePoints == null || currentProduct.QrCodePoints.Count == 0)
- {
- SendTaskMessage("未找到示教后的二维码拍照点位", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- return;
- }
- var qrpoint = currentProduct.QrCodePoints[0];
- //发送点位
- bool SendSuccess = await qrpoint.WriteToPlcAddress(addressConfig.Out_QrCodeCamera, plc);
- if (SendSuccess)
- {
- SendTaskMessage("二维码拍照点位发送成功", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)1);
- Guid qrCodeProcedureId = currentProduct.QrCodeProcedureId;
- if (qrCodeProcedureId == Guid.Empty)
- {
- // 如果没有配置二维码视觉流程,直接返回成功
- SendTaskMessage("未配置二维码视觉流程,跳过扫码", MessageLevel.Info);
- return;
- }
- }
- else
- {
- SendTaskMessage("二维码拍照点位发送失败", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- }
- }
- else
- {
- SendTaskMessage("二维码拍照点位发送信号已关闭", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)0);
- }
- }
- }
- // 螺丝供料器螺丝递减
- else if (addressConfig.In_PickINC.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is Int16 state)
- {
- if (_LastPickINC != state)
- {
- _LastPickINC = state;
- }
- else
- {
- return;
- }
- if (state != 0)
- {
- SendTaskMessage($"螺丝供料器...", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.In_PickINC.Address, (Int16)0);
- var feeders = _configService.GetRemainingCountByFeederNumber(state);
- if (state == 1)
- {
- NumStatistics.Feeder1Num = _configService.DecrementScrewCountByFeederNumber(feeders);
- }
- else if (state == 2)
- {
- NumStatistics.Feeder2Num = _configService.DecrementScrewCountByFeederNumber(feeders);
- }
- }
- }
- }
- // 抛料计数
- else if (addressConfig.In_Throw.Address.Contains(tuple.nodeId))
- {
- if (tuple.value is bool state)
- {
- if (_LastThrowExe != state)
- {
- _LastThrowExe = state;
- }
- else
- {
- return;
- }
- if (state)
- {
- SendTaskMessage("收到抛料信号", MessageLevel.Info);
- await _systemDatabaseService.RecordThrowNumberAsync(new ThrowRecord()
- {
- DayTime = DateTime.Now,
- ThrowCount = 1
- });
- }
- }
- }
- // 过站检查
- 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 systemConfig = _configService.GetSystemConfiguration();
- string code = "";
- //plc启用的模式
- bool models = plc.ReadNode<bool>(addressConfig.Cam_code_mode.Address);
- if (models && state == 1)
- {
- //拍照读码
- SendTaskMessage(Lang.触发上相机锁附组装拍照, MessageLevel.Debug);
- //相机的编号
- Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPutNum.Address);
- SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
- Guid qrCodeProcedureId = currentProduct.QrCodeProcedureId;
- //视觉流程ID
- var qrCodeProcess = _productService.GetCurrentProductProcedureModelById(qrCodeProcedureId);
- if (qrCodeProcess == null)
- {
- SendTaskMessage($"未找到二维码视觉流程,流程ID: {qrCodeProcedureId}", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- return;
- }
- SendTaskMessage($"开始执行二维码扫码视觉流程", MessageLevel.Debug);
- var _cts = new CancellationTokenSource();
- await _remoteCommandService.SetLightBeforePhoto(qrCodeProcess);
- var qrCodeResult = _remoteCommandService.ExecutePhoto(i + 1, qrCodeProcess, out CogToolBlockTerminalCollection outputCollection);
- if (qrCodeResult && outputCollection.Contains("QR"))
- {
- code = outputCollection["QR"].Value as string;
- code = code.ToUpper();
- if (!string.IsNullOrEmpty(code))
- {
- if (systemConfig.IsBasePartCodeChooseScrew)//是否基于零件码,判断是不是当站要打的螺丝
- {
- var val = CheckCode(code, systemConfig.ChooseScrewModel);
- if (val)
- {
- SendTaskMessage($"是当站螺丝:{code}", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage($"不是当站螺丝:{code}", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- return;
- }
- }
- SendTaskMessage($"二维码扫码成功:{code}", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)1);
- }
- else
- {
- SendTaskMessage("二维码扫码失败", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- return;
- }
- }
- else
- {
- code = "";
- SendTaskMessage("二维码扫码失败", MessageLevel.Alarm);
- await plc.WriteNodeAsync(addressConfig.Out_QrCodePhotoResault.Address, (Int16)2);
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- return;
- }
- }
- else
- {
- code = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, i));
- }
- productSn = code;
- //询问mes
- if (state == 1)
- {
- if (_configService.GetDeviceInfo().EnableMES)
- {
- if (i == 0)
- {
- SendTaskMessage($"收到当前过站检查请求(当站是否生产)...", MessageLevel.Debug);
- }
- else
- {
- SendTaskMessage($"收到{i}过站检查请求(当站是否生产)...", MessageLevel.Debug);
- }
- _LastMesCheckTime[i] = DateTime.Now;
- LogHelper.WriteLogMes($"【mes开始QUERY】");
- SendTaskMessage($"mes开始QUERY", MessageLevel.Info);
- dataToMes.Clear();
- if (systemConfig.IsBasePartCodeGetSN)//是否基于零件码,判断是否过站
- {
- SendTaskMessage($"基于零件码,判断是否过站", MessageLevel.Debug);
- (bool isSuccess, string response) = await _mesService.StationGetExAsync(code, "", 2);//基于电池的SN获取产品SN,询问mes
- if (isSuccess)
- {
- string ProductMainSN_Temp = "";
- LogHelper.WriteLogMes($"询问mes成功");
- SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
- 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);
- item = response2.Split('\n');
- if (item[1].Contains("color="))
- {
- color[i] = item[1].Replace("color=", "");
- SendTaskMessage($"产品color:{color[i]}", MessageLevel.Info);
- }
- if (item[3].Contains("model_num="))
- {
- model_num[i] = item[3].Replace("model_num=", "");
- SendTaskMessage($"产品model_num:{model_num[i]}", MessageLevel.Info);
- }
- if (item[4].Contains("sn="))
- {
- ProductMainSN[i] = item[4].Replace("sn=", "");
- SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
- _productService.CurrentProductCode = ProductMainSN[i];
- _eventAggregator.GetEvent<DelaySaveImageNotification>().Publish(true);//通知界面延迟保存图片,等待MES查询结果返回,避免图片和数据不同步
- }
- if (item[5].Contains("wo="))
- {
- wo[i] = item[5].Replace("wo=", "");
- SendTaskMessage($"产品主wo:{wo[i]}", MessageLevel.Info);
- }
- LogHelper.WriteLogMes($"第二次询问mes成功");
- SendTaskMessage($"第二次询问mes成功:{response2}", MessageLevel.Debug);
- //切换产品
- if (i == 0)//i=0时才会切换产品
- {
- var q = await _systemDatabaseService.QueryProductFromMesAsync(model_num[i], color[i]);
- if (!string.IsNullOrEmpty(q))
- {
- ProductList = new ObservableCollection<ProductModel>(_productService.GetAllProducts());
- Guid productId = Guid.Empty;
- foreach (var itt in ProductList)
- {
- if (itt.Name == q)
- {
- productId = itt.ID;
- break;
- }
- }
- if (currentProduct.ID != productId)
- {
- //切换产品
- _productService.LoadProduct(productId);
- _productService.SetCurrentProduct(productId);
- await WritePositionToPlcAsync();
- SendTaskMessage($"切换产品成功", MessageLevel.Debug);
- }
- }
- }
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
- }
- else
- {
- LogHelper.WriteLogMes($"第二次询问mes失败");
- SendTaskMessage($"第二次询问mes失败:{response2}", MessageLevel.Error);
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- }
- }
- else
- {
- LogHelper.WriteLogMes($"询问mes失败");
- SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- }
- }
- else //直接基于RFID询问是否过站
- {
- SendTaskMessage($"基于RFID询问是否过站", MessageLevel.Debug);
- (bool isSuccess, string response) = await _mesService.StationGetAsync(code, "", 2);//询问mes
- if (isSuccess)
- {
- LogHelper.WriteLogMes($"询问mes成功");
- SendTaskMessage($"询问mes成功:{response}", MessageLevel.Debug);
- var item = response.Split('\n');
- if (item[1].Contains("color="))
- {
- color[i] = item[1].Replace("color=", "");
- SendTaskMessage($"产品color:{color[i]}", MessageLevel.Info);
- }
- if (item[3].Contains("model_num="))
- {
- model_num[i] = item[3].Replace("model_num=", "");
- SendTaskMessage($"产品model_num:{model_num[i]}", MessageLevel.Info);
- }
- if (item[4].Contains("sn="))
- {
- ProductMainSN[i] = item[4].Replace("sn=", "");
- SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
- _productService.CurrentProductCode = ProductMainSN[i];
- _eventAggregator.GetEvent<DelaySaveImageNotification>().Publish(true);//通知界面延迟保存图片,等待MES查询结果返回,避免图片和数据不同步
- }
- if (item[5].Contains("wo="))
- {
- wo[i] = item[5].Replace("wo=", "");
- SendTaskMessage($"产品主wo:{wo[i]}", MessageLevel.Info);
- }
- //切换产品
- if (i == 0)//i=0时才会切换产品
- {
- var q = await _systemDatabaseService.QueryProductFromMesAsync(model_num[i], color[i]);
- if (!string.IsNullOrEmpty(q))
- {
- ProductList = new ObservableCollection<ProductModel>(_productService.GetAllProducts());
- Guid productId = Guid.Empty;
- foreach (var itt in ProductList)
- {
- if (itt.Name == q)
- {
- productId = itt.ID;
- break;
- }
- }
- if (currentProduct.ID != productId)
- {
- //切换产品
- _productService.LoadProduct(productId);
- _productService.SetCurrentProduct(productId);
- await WritePositionToPlcAsync();
- SendTaskMessage($"切换产品成功", MessageLevel.Debug);
- }
- }
- }
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
- }
- else
- {
- LogHelper.WriteLogMes($"询问mes失败");
- SendTaskMessage($"询问mes失败:{response}", MessageLevel.Error);
- //产品发生改变并且供料器发生了变化时,需要通知PLC进行取料更改
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)2);
- }
- }
- LogHelper.WriteLogMes($"【mes结束QUERY】");
- SendTaskMessage($"mes结束QUERY", MessageLevel.Info);
- }
- else
- {
- ProductMainSN[i] = DateTime.Now.ToString("yyyyMMddHHmmssfff");
- if (i == 0)
- {
- _productService.CurrentProductCode = ProductMainSN[i];
- _eventAggregator.GetEvent<DelaySaveImageNotification>().Publish(true);//通知界面延迟保存图片,等待MES查询结果返回,避免图片和数据不同步
- }
- LogHelper.WriteLogMes($"【未启用mes】");
- SendTaskMessage($"未启用mes", MessageLevel.Info);
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)1);
- }
- }
- // 上传本站数据
- else if (state == 2)
- {
- if (_configService.GetDeviceInfo().EnableMES == true)
- {
- DFC.Clear();
- //获取当前工位的配置
- var stationConfig = _configService.GetDeviceInfo(0);
- SendTaskMessage($"收到{i}:{stationConfig.DeviceName}上传本站数据请求...", MessageLevel.Debug);
- //从服务器中获取当前时间
- LogHelper.WriteLogMes($"【从服务器中获取当前时间】");
- SendTaskMessage($"从服务器中获取当前时间", MessageLevel.Info);
- var serverTimeResult = await _mesService.GetServerTimeAsync(i, code, 2);
- //这里缺少上传MES的本站数据结果及开始和结束时间,需要补充
- if (i == 0)
- {
- CTtime = serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds;
- _eventAggregator.GetEvent<DelaySaveImageNotification>().Publish(false);//通知界面延迟保存图片,等待MES查询结果返回,避免图片和数据不同步
- }
- //读取产品结果
- Int16 resultIndex = plc.ReadNode<Int16>(string.Format(addressConfig.In_Result.Address, i));
- //目前只记录当前站
- if (i == 0)
- await _systemDatabaseService.RecordProductionAsync(new ProductionRecord()
- {
- ProductName = currentProduct.Name,
- ProductCode = ProductMainSN[i],
- DeviceId = i,
- DeviceName = "",
- Category = resultIndex == 1 ? "OK" : "NG",
- Quantity = 1,
- Remark = $"TotalSeconds:{serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds.ToString("F2")}",
- });
- LogHelper.WriteLogMes($"【mes开始ADD】");
- SendTaskMessage($"mes开始ADD", MessageLevel.Info);
- //上传mes
- //这里现在上传的结果都是锁付站的,如果存在其他附属站的数据需要上传时,将不适用,要根据实际情况进行调整
- //(bool isSuccess, string response) = await _mesService.SubmitGetAsync(ProductMainSN[i], "", dataToMes, resultIndex == 1 ? true : false, _LastMesCheckTime[i], serverTimeResult.Now);
- (bool isSuccess, string response) = await _mesService.SubmitGetExAsync(ProductMainSN[i], "", dataToMes, resultToMes, _LastMesCheckTime[i], serverTimeResult.Now);
- if (isSuccess)
- {
- LogHelper.WriteLogMes($"上传mes成功");
- SendTaskMessage($"上传mes成功", MessageLevel.Debug);
- }
- else
- {
- LogHelper.WriteLogMes($"上传mes失败");
- SendTaskMessage($"上传mes失败", MessageLevel.Error);
- }
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
- //是否保存当前的产品记录至CSV?
- if (stationConfig.SaveCsv)
- {
- //判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
- if (!string.IsNullOrEmpty(stationConfig.SaveCsvPath))
- {
- bool recordResult = false;
- if (i == 0)
- {
- foreach (var lockResult in lockResultsAll)
- {
- bool torqueRes, turnRes, pressureRes;
- if (lockResult.LockTorque >= lockResult.TargetTorqueLowerLimit && lockResult.LockTorque <= lockResult.TargetTorqueUpperLimit)
- {
- torqueRes = true;
- }
- else torqueRes = false;
- if (lockResult.Pressure >= stationConfig.DataInfo.CTQ_LSL_Pressure && lockResult.Pressure <= stationConfig.DataInfo.CTQ_USL_Pressure)
- {
- pressureRes = true;
- }
- else pressureRes = false;
- if (lockResult.LockTurns >= lockResult.TargetTurnsLowerLimit && lockResult.LockTurns <= lockResult.TargetTurnsUpperLimit)
- {
- turnRes = true;
- }
- else turnRes = false;
- DFC.Add(new DataFormCtq
- {
- PPID = ProductMainSN[i],
- ScrewNum = lockResult.Number,
- PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
- PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
- CTQ_NAME = "Torque",
- CTQ_VALUE = lockResult.LockTorque,
- CTQ_LSL = lockResult.TargetTorqueLowerLimit,
- CTQ_USL = lockResult.TargetTorqueUpperLimit,
- PROCESS_END_TIME = serverTimeResult.Now.ToString(),
- SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
- COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
- REVISION = stationConfig.DataInfo.REVISION,
- WO = wo[i],
- MFG_LOT = stationConfig.DataInfo.MFG_LOT,
- MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
- PROCESS_OUTCOME = torqueRes ? "PASS" : "FAIL",
- PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
- CTQ_UNIT_OF_MEASURE = "kgf.cm",
- ERROR_MESSAGE = torqueRes ? "" : "Torque_Spec OOS"
- });
- DFC.Add(new DataFormCtq
- {
- PPID = ProductMainSN[i],
- ScrewNum = lockResult.Number,
- PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
- PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
- CTQ_NAME = "Turn",
- CTQ_VALUE = lockResult.LockTurns,
- CTQ_LSL = lockResult.TargetTurnsLowerLimit,
- CTQ_USL = lockResult.TargetTurnsUpperLimit,
- PROCESS_END_TIME = serverTimeResult.Now.ToString(),
- SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
- COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
- REVISION = stationConfig.DataInfo.REVISION,
- WO = wo[i],
- MFG_LOT = stationConfig.DataInfo.MFG_LOT,
- MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
- PROCESS_OUTCOME = turnRes ? "PASS" : "FAIL",
- PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
- CTQ_UNIT_OF_MEASURE = "圈",
- ERROR_MESSAGE = turnRes ? "" : "Turn_Spec OOS"
- });
- DFC.Add(new DataFormCtq
- {
- PPID = ProductMainSN[i],
- ScrewNum = lockResult.Number,
- PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
- PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
- CTQ_NAME = "Pressure",
- CTQ_VALUE = lockResult.Pressure,
- CTQ_LSL = stationConfig.DataInfo.CTQ_LSL_Pressure,
- CTQ_USL = stationConfig.DataInfo.CTQ_USL_Pressure,
- PROCESS_END_TIME = serverTimeResult.Now.ToString(),
- SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
- COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
- REVISION = stationConfig.DataInfo.REVISION,
- WO = wo[i],
- MFG_LOT = stationConfig.DataInfo.MFG_LOT,
- MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
- PROCESS_OUTCOME = pressureRes ? "PASS" : "FAIL",
- PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
- CTQ_UNIT_OF_MEASURE = "N",
- ERROR_MESSAGE = pressureRes ? "" : "Pressure_Spec OOS"
- });
- }
- }
- recordResult = RecordStationResult(i, DFC, ProductMainSN[i], serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
- if (recordResult)
- {
- SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存成功", MessageLevel.Debug);
- //上传数据
- try
- {
- DateTime dt = DateTime.Now;
- string filename = $"{ProductMainSN[i]}_{dt.ToString("yyyyMMddHHmmss")}";
- var device = _configService.GetDeviceInfo();
- (bool isSuc, string resp) = await _mesService.SendFtpFileAsync(ProductMainSN[i], filename);
- if (isSuc)
- {
- LogHelper.WriteLogMes($"上传数据成功");
- SendTaskMessage($"上传数据成功", MessageLevel.Debug);
- string filePath = $"D:\\image\\Recored\\{dt.ToString("yyyy-MM")}\\{dt.ToString("MM-dd")}\\{currentProduct.Name}\\{ProductMainSN[i]}";
- //复制csv
- string source_csv = $"{stationConfig.SaveCsvPath}\\{dt.ToString("yyyy-MM")}\\{i}_{stationConfig.DeviceName}_{dt.ToString("yyyy-MM-dd")}.csv";
- string target_csv = Path.Combine(filePath, Path.GetFileName(source_csv)); ;
- File.Copy(source_csv, target_csv, true);
- //复制log
- string source_log = $"..\\Log\\LogInfo\\{dt.ToString("yyyy-MM")}\\{dt.ToString("yyyy-MM-dd")}.txt";
- string target_log = Path.Combine(filePath, Path.GetFileName(source_log));
- File.Copy(source_log, target_log, true);
- CompressionImage(filePath, filename, device.Station, device.FixtureId);
- }
- else
- {
- LogHelper.WriteLogMes($"上传数据失败");
- SendTaskMessage($"上传数据失败", MessageLevel.Error);
- }
- }
- catch (Exception ex)
- {
- SendTaskMessage($"上传数据时出错:{ex.Message}", MessageLevel.Error);
- LogHelper.WriteLogError($"上传数据时出错", ex);
- }
- }
- else
- {
- SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存失败", MessageLevel.Error);
- }
- }
- else
- {
- SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存路径,无法保存产品记录", MessageLevel.Error);
- }
- }
- else
- {
- SendTaskMessage($"{i}:{stationConfig.DeviceName}工位未配置保存产品记录", MessageLevel.Debug);
- }
- WriteProductLog(lockResultsAll, ProductMainSN[i], CTtime);
- LogHelper.WriteLogMes($"【mes结束ADD】");
- SendTaskMessage($"mes结束ADD", MessageLevel.Info);
- }
- else
- {
- await plc.WriteNodeAsync(addressConfig.Out_ScrewFeederIsChanged.Address, (Int16)1); //不发生改变
- await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
- }
- }
- 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);
- }
- }
- #endregion
- #region 方法
- public void SendTaskMessage(string msg, MessageLevel level)
- {
- App.Current.Dispatcher.Invoke(() =>
- {
- _eventAggregator.GetEvent<TaskMessageNotification>().Publish(new Models.MessageStruct() { Message = msg, level = level });
- });
- }
- #region Pressure collection helpers
- /// <summary>
- /// 开始采集压力值
- /// </summary>
- /// <param name="productName">配方名称</param>
- /// <param name="productCode">产品编号</param>
- /// <param name="positionIndex">锁付点编号</param>
- private void StartPressureCollection(string productName, string productCode, int positionIndex)
- {
- try
- {
- // cancel existing if any
- _pressureCts?.Cancel();
- _pressureTimeoutCts?.Cancel();
- _pressureLinkedCts?.Dispose();
- _pressureSamples?.Clear();
- _pressureCts = new CancellationTokenSource();
- _pressureTimeoutCts = new CancellationTokenSource();
- // timeout after configured seconds
- _pressureTimeoutCts.CancelAfter(TimeSpan.FromSeconds(_pressureMaxDurationSeconds));
- // link tokens so either stop or timeout cancels
- _pressureLinkedCts = CancellationTokenSource.CreateLinkedTokenSource(_pressureCts.Token, _pressureTimeoutCts.Token);
- var token = _pressureLinkedCts.Token;
- var addressConfig = _configService.GetPlcAddresses();
- var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
- if (plc == null || !plc.IsConnected) return;
- Task.Run(async () =>
- {
- SendTaskMessage($"Pressure collection started for position {positionIndex}", MessageLevel.Debug);
- while (!token.IsCancellationRequested)
- {
- try
- {
- float pressure = plc.ReadNode<float>(addressConfig.In_PressureValue.Address);
- lock (_pressureSamples)
- {
- _pressureSamples.Add((DateTime.Now, pressure));
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("采集压力值时出错", ex);
- }
- await Task.Delay(_pressureSampleIntervalMs);
- }
- // if cancelled due to timeout
- if (_pressureTimeoutCts.IsCancellationRequested && !_pressureCts.IsCancellationRequested)
- {
- SendTaskMessage("Pressure collection timed out, saving collected data.", MessageLevel.Alarm);
- await StopAndSavePressureCollectionAsync(productName, productCode, positionIndex);
- }
- }, token);
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("StartPressureCollection error", ex);
- }
- }
- /// <summary>
- /// 停止采集并保存压力数据
- /// </summary>
- /// <param name="productName"></param>
- /// <param name="productCode"></param>
- /// <param name="positionIndex"></param>
- /// <returns></returns>
- private async Task StopAndSavePressureCollectionAsync(string productName, string productCode, int positionIndex)
- {
- try
- {
- // cancel sampling
- _pressureCts?.Cancel();
- // allow worker to observe cancel
- await Task.Delay(50);
- List<(DateTime Timestamp, float Value)> snapshot;
- lock (_pressureSamples)
- {
- snapshot = new List<(DateTime, float)>(_pressureSamples);
- }
- if (snapshot.Count == 0)
- {
- SendTaskMessage("No pressure samples collected.", MessageLevel.Info);
- return;
- }
- // save to file under configured path
- try
- {
- //获取系统参数
- var systemConfig = _configService.GetSystemConfiguration();
- //判断是否保存锁付曲线
- if (systemConfig.IsSaveScrewCurve)
- {
- string basePath = systemConfig?.ScrewCurvePath ?? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
- string datePath = DateTime.Now.ToString("yyyy-MM") + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\";
- string dirPath = Path.Combine(basePath, datePath, productName ?? "UnknownProduct", productCode ?? DateTime.Now.ToString("yyyyMMddHHmmssfff"));
- if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
- string fileName = $"pressure-{productCode}-{positionIndex}-{DateTime.Now.ToString("HHmmss")}.csv";
- string fullPath = Path.Combine(dirPath, fileName);
- var sb = new StringBuilder();
- sb.AppendLine("Timestamp,Value");
- foreach (var s in snapshot)
- {
- sb.AppendLine($"{s.Timestamp:O},{s.Value}");
- }
- File.WriteAllText(fullPath, sb.ToString());
- SendTaskMessage($"Pressure samples saved to {fullPath}", MessageLevel.Debug);
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("保存压力采样文件时出错", ex);
- SendTaskMessage("保存压力采样文件时出错: " + ex.Message, MessageLevel.Error);
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("StopAndSavePressureCollectionAsync error", ex);
- }
- finally
- {
- try
- {
- _pressureLinkedCts?.Cancel();
- _pressureLinkedCts?.Dispose();
- _pressureTimeoutCts?.Dispose();
- _pressureCts?.Dispose();
- _pressureSamples?.Clear();
- }
- catch { }
- }
- }
- #endregion
- private async void DoYieldTime(object state)
- {
- try
- {
- //获取当前产品
- 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);
- //
- ThrowNumber = await _systemDatabaseService.GetThrowNumberAsync();
- NgNumber = await _systemDatabaseService.GetNGProductionAsync(currentproduct.Name);
- Yield = ((double)TotalQuantityToday - (double)NgNumber) / (double)TotalQuantityToday * 100;
- }
- catch (Exception)
- {
- }
- }
- /// <summary>
- /// 判断是否符合当站
- /// </summary>
- /// <param name="data"></param>
- /// <param name="checkData"></param>
- /// <returns></returns>
- private bool CheckCode(string data, string checkData)
- {
- try
- {
- if (data.Length != checkData.Length)
- {
- var len = checkData.Length - data.Length;
- LogHelper.WriteLogMes($"判断是否符合当站失败,字符长度差{len}");
- SendTaskMessage($"判断是否符合当站失败,字符长度差{len}", MessageLevel.Error);
- return false;
- }
- int count = checkData.Length;
- for (int i = 0; i < count; i++)
- {
- if (checkData[i] == '*')//不需要检测的部分
- {
- continue;
- }
- if (data[i] != checkData[i])//有值不一致
- {
- LogHelper.WriteLogMes($"判断是否符合当站失败,第{i}个字符,不一致");
- SendTaskMessage($"判断是否符合当站失败,第{i}个字符,不一致", MessageLevel.Error);
- return false;
- }
- }
- return true;
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogMes($"判断是否符合当站失败,{ex}");
- SendTaskMessage($"判断是否符合当站失败,{ex}", MessageLevel.Error);
- return false;
- }
- }
- #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(string.Format(Lang.杀死进程0时失败, strKillName), ex);
- }
- }
- }
- }
- #endregion
- #region 产品锁付记录进行存储
- /// <summary>
- /// 产品锁付记录进行存储
- /// </summary>
- /// <param name="result">结果</param>
- public void WriteProductLog(List<LockResult> lockResults, string rfid, double ct)
- {
- try
- {
- string result = "";//产品的总结果
- foreach (var item in lockResults)
- {
- result = "OK";
- if (!item.LockPassed)
- {
- result = "NG";
- break;
- }
- }
- DateTime dt = DateTime.Now;
- int number = lockResults.Count;//螺丝数量
- string path = $"D:\\Data\\生产数据\\{dt.ToString("yyyy-MM")}\\{dt.ToString("yyyy-MM-dd")}.csv";
- StringBuilder sb = new StringBuilder();
- //具体的ct需要优化
- sb.Append($"{dt.ToString("yyyy-MM-dd HH:mm:ss")},{lockResults[0].ProductName},{Math.Round(ct, 3)},{rfid},{result},{lockResults[number - 1].NozzleNumber},{lockResults[number - 1].HeadNumber},");
- foreach (var item in lockResults)
- {
- try
- {
- string res = "";
- if (item.LockPassed)
- {
- res = "Pass";
- }
- else res = "Fail";
- sb.Append($"{res},{item.ResultDetails},{item.LockTorque},{item.TargetTorqueUpperLimit},{item.TargetTorqueLowerLimit},{item.LockTurns},{item.TargetTurnsUpperLimit},{item.TargetTurnsLowerLimit},{item.Pressure},{item.PositionX},{item.PositionY},{item.StartPositionZ},{item.EndPositionZ},{item.LockDescentSpeed},");
- }
- catch (Exception)
- {
- sb.Append($",,,,,,,,,,,,,,");
- }
- }
- //========================
- if (!Directory.Exists(Path.GetDirectoryName(path))) //判断文件夹是否
- {
- Directory.CreateDirectory(Path.GetDirectoryName(path)); //创建文件夹
- }
- if (File.Exists(path))
- {
- // 使用 StreamWriter 以追加模式打开文件
- StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
- sw.WriteLine(sb.ToString().TrimEnd(','));
- sw.Close();
- sw.Dispose();
- }
- else
- {
- StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
- StringBuilder sb1 = new StringBuilder();
- StringBuilder sb_up = new StringBuilder();
- StringBuilder sb_down = new StringBuilder();
- sb1.Append("时间,产品名称,CT,RFID,产品结果,吸嘴数量,披头数量,");
- for (int i = 0; i < number; i++)
- {
- sb1.Append($"螺丝{i + 1}结果,螺丝{i + 1}结果详情,螺丝{i + 1}扭矩,螺丝{i + 1}扭矩上限,螺丝{i + 1}扭矩下限,螺丝{i + 1}圈数,螺丝{i + 1}圈数上限,螺丝{i + 1}圈数下限,螺丝{i + 1}压力值,螺丝{i + 1}锁附X,螺丝{i + 1}锁附Y,螺丝{i + 1}开始位置Z,螺丝{i + 1}结束位置Z,螺丝{i + 1}锁附下降速度,");
- }
- sw.WriteLine(sb1.ToString().TrimEnd(','));
- sw.WriteLine(sb.ToString().TrimEnd(','));
- sw.Close();
- sw.Dispose();
- }
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError("写入产品记录时出错!", ex);
- }
- lockResultsAll.Clear();
- }
- /// <summary>
- /// 记录当前工位的锁付结果
- /// </summary>
- /// <param name="stationIndex"></param>
- /// <param name="lockResults"></param>
- /// <param name="productMainSN"></param>
- /// <param name="ct"></param>
- /// <param name="timestamp"></param>
- /// <param name="savePath"></param>
- /// <param name="isSingleLine">是否将所有螺丝的锁付结果一行显示,还是每颗螺丝单独一行显示,默认所有颗螺丝单独一行显示</param>
- /// <returns></returns>
- private bool RecordLockResult(int stationIndex, List<LockResult> lockResults, string productMainSN, double ct, DateTime timestamp, string savePath, bool isSingleLine = true, bool isFirstEnter = true)
- {
- try
- {
- //获取当前工位的配置
- var stationConfig = _configService.GetDeviceInfo(stationIndex);
- if (stationConfig == null) return false;
- //如果保存路径为空,则不保存
- if (string.IsNullOrEmpty(savePath)) return false;
- //如果锁付结果列表为空,则不保存
- if (lockResults == null || lockResults.Count == 0) 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))
- {
- if (isSingleLine)
- {
- //将所有螺丝的锁付结果一行显示,列名格式:时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号1,锁付结果1,锁付圈数1,锁付扭矩1,锁付时长1,电批程序编号1,结果详情1,压力值1,扭矩上限1,扭矩下限1,圈数上限1,圈数下限1,电批锁付速度1,锁附X1,锁附Y1,开始位置Z1,结束位置Z1,锁附下降速度1,螺丝供料器编号,...(依次类推直到螺丝编号n)
- sb.Append("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,");
- for (int i = 0; i < lockResults.Count; i++)
- {
- sb.Append($"螺丝编号{i + 1},锁付结果{i + 1},锁付圈数{i + 1},锁付扭矩{i + 1},锁付时长{i + 1},电批程序编号{i + 1},结果详情{i + 1},压力值{i + 1}," +
- $"扭矩上限{i + 1},扭矩下限{i + 1},圈数上限{i + 1},圈数下限{i + 1},电批锁付速度{i + 1},锁附X{i + 1},锁附Y{i + 1},开始位置Z{i + 1},结束位置Z{i + 1},锁附下降速度{i + 1},螺丝供料器编号{i + 1},");
- }
- sb.Append("吸嘴编号,披头编号,操作员姓名");
- }
- else
- {
- sb.Append("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号,锁付结果,锁付圈数,锁付扭矩,锁付时长,电批程序编号,结果详情,压力值," +
- "扭矩上限,扭矩下限,圈数上限,圈数下限,电批锁付速度,锁附X,锁附Y,开始位置Z,结束位置Z,锁附下降速度,螺丝供料器编号,吸嘴编号,披头编号,操作员姓名");
- }
- sb.AppendLine();
- }
- if (isSingleLine)
- {
- //将所有螺丝的锁付结果一行显示,列名格式:时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,螺丝编号1,锁付结果1,锁付圈数1,锁付扭矩1,锁付时长1,电批程序编号1,结果详情1,压力值1,扭矩上限1,扭矩下限1,圈数上限1,圈数下限1,电批锁付速度1,锁附X1,锁附Y1,开始位置Z1,结束位置Z1,锁附下降速度1,螺丝供料器编号,...(依次类推直到螺丝编号n)
- sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},{lockResults[0].ProductName},{lockResults[0].ProductNumber},");
- for (int i = 0; i < lockResults.Count; i++)
- {
- var item = lockResults[i];
- sb.Append($"螺丝{i + 1},{item.LockPassed},{item.LockTurns},{item.LockTorque},{item.LockDuration},{item.ScrewdriverProgramNumber}," +
- $"{item.ResultDetails},{item.Pressure},{item.TargetTorqueUpperLimit},{item.TargetTorqueLowerLimit},{item.TargetTurnsUpperLimit},{item.TargetTurnsLowerLimit},{item.TargetLockSpeed}," +
- $"{item.PositionX},{item.PositionY},{item.StartPositionZ},{item.EndPositionZ},{item.LockDescentSpeed},{item.FeederNumber},");
- }
- sb.Append($"{lockResults[lockResults.Count - 1].NozzleNumber},{lockResults[lockResults.Count - 1].HeadNumber},{lockResults[lockResults.Count - 1].OperatorName}");
- sb.AppendLine();
- }
- else
- {
- foreach (var item in lockResults)
- {
- sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},{item.ProductName},{item.ProductNumber},{item.Number},{item.LockPassed},{item.LockTurns},{item.LockTorque},{item.LockDuration},{item.ScrewdriverProgramNumber}," +
- $"{item.ResultDetails},{item.Pressure},{item.TargetTorqueUpperLimit},{item.TargetTorqueLowerLimit},{item.TargetTurnsUpperLimit},{item.TargetTurnsLowerLimit},{item.TargetLockSpeed}," +
- $"{item.PositionX},{item.PositionY},{item.StartPositionZ},{item.EndPositionZ},{item.LockDescentSpeed},{item.FeederNumber},{item.NozzleNumber},{item.HeadNumber},");
- 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";
- RecordLockResult(stationIndex, lockResults, productMainSN, ct, timestamp, tempFileName, isSingleLine, false);
- return false;
- }
- }
- /// <summary>
- /// 记录其他工位的结果,其他工位要存储的数据项按照键值对集合的形式传入,键为数据项名称,值为数据项的值
- /// </summary>
- /// <param name="stationIndex"></param>
- /// <param name="dataItems"></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 RecordOtherStationResult(int stationIndex, Dictionary<string, string> dataItems, string productMainSN, double ct, DateTime timestamp, string savePath, bool isFirstEnter = true)
- {
- try
- {
- //获取当前工位的配置
- var stationConfig = _configService.GetDeviceInfo(stationIndex);
- if (stationConfig == null) return false;
- // 获取当前产品
- var currentProduct = _productService.GetCurrentProduct();
- if (currentProduct == 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("时间,产品主SN,CT,工位编号,工位名称,配方名称,配方编号,");
- foreach (var item in dataItems)
- {
- sb.Append($"{item.Key},");
- }
- sb.AppendLine();
- }
- sb.Append($"{timestamp:yyyy-MM-dd HH:mm:ss},{productMainSN},{Math.Round(ct, 3)},{stationIndex},{stationConfig.DeviceName},{currentProduct.Name},{currentProduct.NumberCode},");
- foreach (var item in dataItems)
- {
- sb.Append($"{item.Value},");
- }
- 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";
- RecordOtherStationResult(stationIndex, dataItems, productMainSN, ct, timestamp, tempFileName, false);
- return false;
- }
- }
- /// <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(stationIndex);
- 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,Screw_Number,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");
- sb.AppendLine();
- }
- if (dfcs == null || dfcs.Count() == 0)
- {
- return false;
- }
- foreach (var dfc in dfcs)
- {
- sb.Append($"{dfc.PPID},{dfc.ScrewNum},{dfc.PROCESS_NAME},{dfc.PROCESS_START_TIME},{dfc.CTQ_NAME},{dfc.CTQ_VALUE:F3},{dfc.CTQ_LSL:F3},{dfc.CTQ_USL:F3},{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}");
- 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
- #region 写log
- TxtFile mesLog = new TxtFile($"D:\\Data\\Mes记录", "");
- public void MesMessage(string msg)
- {
- mesLog.WriteLine("== " + msg + "\r\n");
- }
- TxtFile infoLog = new TxtFile($"D:\\Data\\运行日志", "");
- public void InfoMessage(string msg)
- {
- infoLog.WriteLine("== " + msg + "\r\n");
- }
- #endregion
- #region 压缩图片文件夹
- /// <summary>
- /// 压缩文件
- /// </summary>
- /// <param name="sourcePath">原路径</param>
- /// <param name="zipname">压缩后文件的名称</param>
- /// <param name="station">mes中的station</param>
- /// <param name="fixid">mes中的fixtureID</param>
- public async void CompressionImage(string sourcePath, string zipname, string station, string fixid)
- {
- string zipPath = "";
- try
- {
- SendTaskMessage($"开始压缩文件", MessageLevel.Info);
- await Task.Run(() =>
- {
- zipPath = $"Z:\\{station}\\{fixid}\\{DateTime.Now.ToString("yyyyMMdd")}\\{zipname}.zip";//生成的zip文件路径
- string path = $"Z:\\{station}\\{fixid}\\{DateTime.Now.ToString("yyyyMMdd")}";
- if (!Directory.Exists(path))
- {
- Directory.CreateDirectory(path);
- }
- ZipFile.CreateFromDirectory(sourcePath, zipPath);
- });
- }
- catch (Exception ex)
- {
- LogHelper.WriteLogError($"压缩文件时出错", ex);
- }
- }
- #endregion
- #endregion
- }
- }
|