using HslCommunication.Core; using Mesnac.Compressor.Entity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Newtonsoft.Json.Linq; using SlnMesnac.Common; using SlnMesnac.Config; using SlnMesnac.Model.domain; using SlnMesnac.Plc; using SlnMesnac.Serilog; using SqlSugar; using System.Collections; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace ConsoleApp { internal class MainCentralControl { private IHost host; // 新增一个标志位,用于表示方法是否正在执行 private static String StationCode; private bool isExecuting = false; private AppConfig _appConfig; private readonly SerilogHelper _logger; private IServiceProvider serviceProvider; private ISqlSugarClient SqlSugarClient; public List plcList; IByteTransform ByteTransform = new ReverseBytesTransform(); public bool isConnect; public string State; private StationInfo _stationInfo; private object _mcValue; //PLC心跳地址 private string _plcHeartBeatAddress; //PLC工作请求地址 private string _workAskAddress; //PLC工作完成放行请求地址 private string _completeAskAddress; public MainCentralControl(IHost host) { this.host = host; _appConfig = host.Services.GetService(); StationCode = _appConfig.StationCode; SqlSugarClient = host.Services.GetRequiredService(); _logger = host.Services.GetRequiredService(); plcList = host.Services.GetRequiredService>(); } public void Start() { init(); StartCheckStatus(); ListeningPlcValue(); _logger.Info("iMES系统启动成功!"); } /// /// 初始化加载PLC地址,不同工位PLC提供的地址不同 /// private void init() { try { switch (StationCode) { case "S130-1": _plcHeartBeatAddress = "D7777"; _completeAskAddress = "D7703"; break; case "S130-2": _plcHeartBeatAddress = "D7777"; _workAskAddress = ""; _completeAskAddress = ""; break; } } catch (Exception ex) { } } /// /// 监听PLC地址值 /// private void ListeningPlcValue() { Task.Run(async () => { while (true) { try { PlcAbsractFactory? Plc = plcList.FirstOrDefault(x => x.ConfigKey == "plc"); if (Plc == null || !Plc.IsConnected) { _logger.Plc(DateTime.Now + "PLC未连接,请检查网络!"); continue; } //读取PLC工作请求,放行请求 switch (StationCode) { case "S130-1": if (Plc.readInt16ByAddress(_completeAskAddress) == 1) { Plc.writeInt16ByAddress(_completeAskAddress, 0); SaveStationDataTask(Plc); } break; case "S130-2": //读取PLC工作请求 if (Plc.readInt16ByAddress(_workAskAddress) == 1) { Plc.writeInt16ByAddress(_workAskAddress, 0); //根据转子码查询上工位是否合格 SelectStationQuality(Plc); } //读取PLC放行请求 if (Plc.readInt16ByAddress(_completeAskAddress) == 1) { Plc.writeInt16ByAddress(_completeAskAddress, 0); //存盘 } break; } } catch (Exception ex) { _logger.Error($"ListeningPlcValue方法异常:" + ex.StackTrace); } finally { Thread.Sleep(1000); } } }); } /// /// 判断数据库表是否已存在条码数据,存在则更新,不存在则插入 /// /// /// private Datastation IsExistData(string ProductBarCode) { Datastation datastation = null; try { SqlSugarClient.Queryable().Any(x => x.Partsns.Contains(ProductBarCode)); datastation = SqlSugarClient.Queryable().First(it => it.Partsns.Contains(ProductBarCode)); if (datastation != null) { return datastation; } return datastation; } catch (Exception ex) { return datastation; } } /// /// S130-1工位存盘 /// /// private async void SaveStationDataTask(PlcAbsractFactory Plc) { try { //主线码 byte[] SemBarCode = Plc.readValueByAddress("D7701", 20); string barcode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII); partsns partsns = new partsns(); partsns.sn.Add(barcode); //数据 string jsonString = StringChange.ModeToJson(partsns); D data1 = new D() { n = "转子压装位置1压力值", t = 0, ng = int.Parse(Plc.readFloatByAddress("D7708").ToString()), v = Plc.readFloatByAddress("D7705").ToString(), min = Plc.readFloatByAddress("D7706").ToString(), max = Plc.readFloatByAddress("D7707").ToString(), }; D data2 = new D() { n = "转子压装位置2压力值", t = 0, ng = int.Parse(Plc.readFloatByAddress("D7712").ToString()), v = Plc.readFloatByAddress("D7709").ToString(), min = Plc.readFloatByAddress("D7710").ToString(), max = Plc.readFloatByAddress("D7711").ToString(), }; D data3 = new D() { n = "转子压装位置3压力值", t = 0, ng = int.Parse(Plc.readFloatByAddress("D7716").ToString()), v = Plc.readFloatByAddress("D7713").ToString(), min = Plc.readFloatByAddress("D7714").ToString(), max = Plc.readFloatByAddress("D7715").ToString(), }; D data4 = new D() { n = "转子压装位置4位移值", t = 0, ng = 1, v = Plc.readFloatByAddress("D7717").ToString(), min = Plc.readFloatByAddress("D7718").ToString(), max = Plc.readFloatByAddress("D7719").ToString(), }; D data5 = new D() { n = "转子压装位置4压力值", t = 0, ng = int.Parse(Plc.readFloatByAddress("D7724").ToString()), v = Plc.readFloatByAddress("D7721").ToString(), min = Plc.readFloatByAddress("D7722").ToString(), max = Plc.readFloatByAddress("D7723").ToString(), }; Root root = new Root(); root.d.Add(data1); root.d.Add(data2); root.d.Add(data3); root.d.Add(data4); root.d.Add(data5); string datastring = StringChange.ModeToJson(root); //查询是否已经存在数据,存在则更新不存在则保存 Datastation datastation = IsExistData(barcode); if (datastation != null) { //更新 datastation.Stime = DateTime.Now; datastation.Stationid = StationCode; datastation.Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1; datastation.Partsns = jsonString; datastation.Paratemp = datastring; int LockFlag = SqlSugarClient.Updateable(datastation).ExecuteCommand(); Console.WriteLine(StringChange.ModeToJson(datastation)); _logger.Info(StringChange.ModeToJson(datastation)); } else { datastation = new Datastation() { Stime = DateTime.Now, Stationid = StationCode, Productid = "", Partid = "", Modelid = "", Ng = Plc.readFloatByAddress("D7708").ToString() == "1" ? 0 : 1, Proc = 0, Sublinenum = 0, Sublinesnnum = 0, Partsnnum = 1, Sublineids = "", Partsns = jsonString, Sublinesns = StringChange.ModeToJson(new partsns()), Paratemp = datastring, Stringtemp = "", GroupStationId = "", Renum = "0", }; //存盘 int id = SqlSugarClient.Insertable(datastation).ExecuteReturnIdentity(); Plc.writeInt16ByAddress("D7704", 1); Console.WriteLine(StringChange.ModeToJson(datastation)); _logger.Info(StringChange.ModeToJson(datastation)); } } catch (Exception ex) { _logger.Error($"存盘异常{ex.Message}"); } } /// /// 查询上工位是否有数据,无数据或NG则下发PLC报警提示 /// /// private async void SelectStationQuality(PlcAbsractFactory Plc) { try { byte[] SemBarCode = Plc.readValueByAddress("D7701", 20); string ZZBarCode = ByteTransform.TransString(SemBarCode, 0, 20, Encoding.ASCII); Datastation datastation = IsExistData(ZZBarCode); if (datastation != null) { if (datastation.Ng != 0) { //下发PLC上工位不合格 Plc.writeInt16ByAddress("", 1); } } //上工位无数据 else { //下发PLC上工位不合格 Plc.writeInt16ByAddress("", 1); } } catch (Exception ex) { _logger.Error($"上工位查询异常{ex.Message}"); } } /// /// PLC心跳检测,重连机制 /// private void StartCheckStatus() { Task.Run(async () => { while (true) { try { foreach (var plc in plcList) { PlcConfig? plcConfig = host.Services.GetService().plcConfig.FirstOrDefault(x => x.plcKey == plc.ConfigKey); if (plc != null && plc.IsConnected) { plc.IsConnected = plc.readHeartByAddress(_plcHeartBeatAddress); //DB100.DBX0.0 if (!plc.IsConnected) { plc.IsConnected = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort); } } else { if (plcConfig != null) { bool result = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort); plc.IsConnected = result; } } } } catch (Exception ex) { _logger.Error($"监听PLC设备状态异常:{ex.Message}"); } await Task.Delay(1000 * 10); } }); } #region 中际产线弃用逻辑 private bool TryObject(object value, out object[] arry) { arry = null; try { arry = (object[])value; return true; } catch (Exception ex) { return false; } } public stationPara ParaFormart(object[] obj, int paraCount) { byte[] bytes = obj.Select(o => Convert.ToByte(o)).ToArray(); string str = Convert.ToString(Convert.ToInt32(bytes[2]), 2).PadLeft(8, '0'); string[] items = new string[8]; for (int i = 0; i < items.Length; i++) { items[i] = str[i].ToString(); } Array.Reverse(items); //byte[] bools = ByteTransform.TransByte(bytes, 2,1); isConnect = Convert.ToInt32(items[0]) == 1; State = Convert.ToInt32(items[1]).ToString(); stationPara sinfo = new stationPara(); int index = 0; //是否重投 if (sinfo.Restart) { //ICSharpCode.Core.LoggingService.Info(StationInfo.StationCode + ",开始重投"); } //是否有主线二维码 sinfo.BarcodeUpdate = Convert.ToInt32(items[3]) == 1; //是否有支线二维码 sinfo.MaterialBarcodeUpdate = Convert.ToInt32(items[4]) == 1; index++; //自动模式 //重构,收到作业或放行请求才进行解析 //PLC工作请求信号 sinfo.AskWork = ByteTransform.TransInt16(bytes, 5) > 0; index++; //放行请求 sinfo.MaskID = ByteTransform.TransInt16(bytes, 7); sinfo.NewFlag = sinfo.MaskID > 0 ? true : false; index += 3; //当前机种号 sinfo.machineID = ByteTransform.TransByte(bytes, 13); string NewMachineID = sinfo.machineID.ToString(); index++; //托盘号 int intNum = ByteTransform.TransByte(bytes, 15); //支线条码状态 index++; bool[] bools2 = ByteTransform.TransBool(bytes, 16, 1); //ArrayList array2 = ConvertToList(bools2); //数据保存区 index++; sinfo.ProductOkNg = ByteTransform.TransByte(bytes, 19); index++; //线体代号ABC' int gongxu = ByteTransform.TransByte(bytes, 21); sinfo.RFIDNo = string.Format("{0:X}", gongxu) + intNum.ToString().PadLeft(2, '0'); index += 1; //sinfo.productDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");//这里不用日期了 if (sinfo.BarcodeUpdate || sinfo.MaterialBarcodeUpdate) { GetBarcodeList(bytes, index, ref sinfo); } index = 180; for (int i = 0; i < paraCount; i++) { dataUnite du = new dataUnite(); du.actValue = ByteTransform.TransSingle(bytes, index).ToString(); du.MaxValue = ByteTransform.TransSingle(bytes, index + 4).ToString(); du.MinValue = ByteTransform.TransSingle(bytes, index + 8).ToString(); du.result = ByteTransform.TransInt32(bytes, index + 12); du.Remark = ByteTransform.TransInt32(bytes, index + 16).ToString(); index += 20; sinfo.SavedataList.Add(du); } if (sinfo.MaskID == 1) { foreach (var row in sinfo.SavedataList) { Console.WriteLine("------------------------"); Console.WriteLine("|生产值:" + row.actValue + "|"); Console.WriteLine("------------------------"); } } return sinfo; } private void GetBarcodeList(byte[] buffer, int index, ref stationPara sinfo) { try { //获取条码支线信息 //for (int i = 1; i <= 5; i++) //{ // subLine sl = new subLine(); // sl.lineID = buffer[index + i].ToString(); // sl.barcode = ""; // sinfo.subLineList.Add(sl); //} //int barcodeLegth = 10;//设置单个条码长度 //获取主条码 byte[] bytes = new byte[20]; Array.Copy(buffer, 22, bytes, 0, 20); //ByteTransform.DataFormat = HslCommunication.Core.DataFormat.DCBA; //ByteTransform.IsStringReverseByteWord = true; //if (BitConverter.IsLittleEndian) //{ // Array.Reverse(bytes, 0, 4); // Array.Reverse(bytes, 4, 4); // Array.Reverse(bytes, 8, 4); // Array.Reverse(bytes, 12, 4); // Array.Reverse(bytes, 16, 4); //} sinfo.ProductBarcode = ByteTransform.TransString(bytes, 0, 20, Encoding.ASCII); } catch (Exception ex) { _logger.Error("条码信息获取失败:" + ex.ToString()); } } public object MCValue { get { return _mcValue; } set { if (value == null) { return; } //数据没有变化,直接返回 object[] objectarray; if (!TryObject(value, out objectarray)) { return; } if (value == _mcValue) { return; } _mcValue = value; _stationInfo.Data = ParaFormart(objectarray, 0); if (_stationInfo.Data.AskWork) { //这里需要判断上工位结果是否OK _logger.Info("工位:" + _stationInfo.StationCode + " 收到作业请求信号"); //PreWorkThread(); } ////有新数据 if (isConnect && _stationInfo.Data.NewFlag) { _logger.Info("工位:" + _stationInfo.StationCode + " 收到作业完成信号,开始上传数据。托盘号:" + _stationInfo.Data.RFIDNo); //OnRerefreshData(); } } } #endregion } }