123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- using Newtonsoft.Json.Linq;
- using ProjectManagementSystem.Common.Config;
- using ProjectManagementSystem.Common.Extenions;
- using ProjectManagementSystem.Common.Logger;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace ProjectManagementSystem.Common.Core
- {
- public class PlcControl
- {
- private static PlcControl m_instance;
- private Dictionary<string, HslCommunication.Core.IReadWriteNet> m_plcDict = new Dictionary<string, HslCommunication.Core.IReadWriteNet>();
- public List<JObject> JDataList { get; set; } = new List<JObject>();
- private string[] columnNameArray = new string[]
- {
- "PLC允许进入" ,
- "PLC放行" ,
- "PLC返修" ,
- "AGV请求进入",
- "AGV正在进入",
- "AGV到位",
- "AGV正在离开"
- };
- private string[] signalMonitorColumnNameArray = new string[]
- {
- "PLC呼叫满盘",
- "PLC转运空盘"
- };
- public static PlcControl Instance
- {
- get
- {
- if (m_instance == null)
- {
- m_instance = new PlcControl();
- if (!m_instance.Initialize())
- {
- m_instance = null;
- }
- }
- return m_instance;
- }
- }
- private PlcControl()
- {
- }
- private bool Initialize()
- {
- var dataList = ExcelConfig.Instance.RouteConfigList;
- for (int i = 0; i < dataList.Count; i++)
- {
- var data = dataList[i];
- string plcIpAddr = data.PlcIpAddr;
- if (!string.IsNullOrEmpty(plcIpAddr))
- {
- bool selfPlcReadWrite = data.LocationCode.GetLocationMember("独立通讯(PLC)").ToValue<bool>();
- if (selfPlcReadWrite)
- {
- //每个库位独立的PLC通讯对象
- var plc = GetReadWriteNet(data);
- data.PlcReadWrite = plc;
- }
- else
- {
- //库位相同IP共用PLC通讯对象
- if (!m_plcDict.ContainsKey(plcIpAddr))
- {
- var plc = GetReadWriteNet(data);
- m_plcDict.Add(plcIpAddr, plc);
- }
- if (m_plcDict.ContainsKey(plcIpAddr))
- {
- data.PlcReadWrite = m_plcDict[plcIpAddr];
- }
- }
- }
- }
- columnNameArray = Function.AppSetting.TryGetValue<string>("PlcSignalColumnName").ToValueArray<string>();
- var dataList2 = ExcelConfig.Instance.InfoPlcList;
- for (int i = 0; i < dataList2.Count; i++)
- {
- var data = dataList2[i];
- data.routeConfig = ExcelConfig.Instance.RouteConfigList.FirstOrDefault(d => d.LocationCode == data.库位号);
- data.JData = new JObject();
- string defaultAddr = data.routeConfig.PlcHeartbearAddr;
- data.PlcSignalAddrArray = new string[columnNameArray.Length];
- data.PlcSignalAddrLengthArray = new ushort[columnNameArray.Length];
- for (int infoIndex = 0; infoIndex < columnNameArray.Length; infoIndex++)
- {
- string info = columnNameArray[infoIndex];
- string plcRealAddr = data.routeConfig.LocationCode.GetLocationMember(info);
- data.PlcSignalAddrArray[infoIndex] = string.IsNullOrEmpty(plcRealAddr) ? defaultAddr : plcRealAddr;
- data.PlcSignalAddrLengthArray[infoIndex] = 1;
- }
- var jData = new JObject();
- jData["库位号"] = data.routeConfig.LocationCode;
- jData["IP地址"] = data.routeConfig.PlcIpAddr;
- JDataList.Add(jData);
- }
- Task.Factory.StartNew(UserThread);
- return true;
- }
- /// <summary>
- /// 获取创建的PLC通讯对象
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- private HslCommunication.Core.IReadWriteNet GetReadWriteNet(RouteConfig data)
- {
- string plcIpAddr = data.PlcIpAddr;
- var plcProtocol = data.LocationCode.GetLocationMember("通讯协议(PLC)");
- switch (plcProtocol)
- {
- case "SiemensS7Net":
- {
- var plc = new HslCommunication.Profinet.Siemens.SiemensS7Net(HslCommunication.Profinet.Siemens.SiemensPLCS.S1500, plcIpAddr);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- case "MelsecMcNet":
- {
- var plc = new HslCommunication.Profinet.Melsec.MelsecMcNet(plcIpAddr, 5000);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- case "OmronFinsNet":
- {
- var plc = new HslCommunication.Profinet.Omron.OmronFinsNet(plcIpAddr, 5000);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- case "AllenBradleyNet":
- {
- var plc = new HslCommunication.Profinet.AllenBradley.AllenBradleyNet(plcIpAddr);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- case "ModbusRtuOverTcp":
- {
- var plc = new HslCommunication.ModBus.ModbusRtuOverTcp(plcIpAddr);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- default:
- {
- var plc = new HslCommunication.Profinet.AllenBradley.AllenBradleyNet(plcIpAddr);
- plc.ConnectTimeOut = 1000;
- plc.ReceiveTimeOut = 1000;
- plc.SetPersistentConnection();
- return plc;
- }
- }
- }
- private void Clear(RouteConfig routeConfig)
- {
- var plcBehaviorList = ExcelConfig.Instance.PlcBehaviorList
- .Where(d => !string.IsNullOrEmpty(d.Remark) && d.Remark.Contains("初始化"));
- if (plcBehaviorList == null
- || plcBehaviorList.Count() == 0)
- {
- //string strLog = $"{routeConfig.LocationCode} IP地址:{routeConfig.PlcIpAddr},无需清零地址";
- //CLog.Instance.SystemLog.WriteInfo(strLog);
- return;
- }
- foreach (var item in plcBehaviorList)
- {
- foreach (string addrDesc in item.DbAddressWrite)
- {
- string addr = routeConfig.LocationCode.GetPlcTaskAddr(addrDesc);
- if (string.IsNullOrEmpty(addr)) continue;
- int id = routeConfig.IOTransID;
- if(id > 0)
- {
- var readResult2 = DeviceControl.Instance.GetOutputIO(id, addr);
- if (readResult2.Item1
- && readResult2.Item2)
- {
- DeviceControl.Instance.SetOutputIO(id, addr, false);
- string strLog = $"{routeConfig.LocationCode},IO对接盒ID{id},清零:{addr} ({addrDesc})";
- CLog.Instance.SystemLog.WriteInfo(strLog);
- Thread.Sleep(50);
- }
- }
- var plc = routeConfig.PlcReadWrite;
- if (plc != null && routeConfig.PlcConnected)
- {
- var readResult = plc.ReadBool(addr);
- if (!readResult.IsSuccess
- || (readResult.IsSuccess && readResult.Content != false))
- {
- var result = plc.Write(addr, false);
- string strLog = $"{routeConfig.LocationCode},{routeConfig.PlcIpAddr},清零:{addr} ({addrDesc}),写入{result.IsSuccess.ToChineseString()}";
- CLog.Instance.SystemLog.WriteInfo(strLog);
- }
- }
- }
- }
- }
- private void PlcTaskProc()
- {
- var RouteConfigList = ExcelConfig.Instance.RouteConfigList;
- for (int i = 0; i < RouteConfigList.Count; i++)
- {
- var routeConfig = RouteConfigList[i];
- if (!string.IsNullOrEmpty(routeConfig.PlcHeartbearAddr)
- && routeConfig.PlcReadWrite != null)
- {
- //读取PLC心跳信号
- var tempResult = routeConfig.PlcReadWrite.ReadBool(routeConfig.PlcHeartbearAddr);
- if (routeConfig.PlcConnected != tempResult.IsSuccess)
- {
- CLog.Instance.SystemLog.WriteInfo($"{routeConfig.LocationCode} {routeConfig.PlcIpAddr} PLC连接:{tempResult.IsSuccess.ToChineseString()}");
- }
- routeConfig.PlcConnected = tempResult.IsSuccess;
- //回写PLC心跳信号
- if (tempResult.IsSuccess
- && !string.IsNullOrEmpty(routeConfig.PlcHeartbearAddr_AGV))
- {
- routeConfig.PlcReadWrite.Write(routeConfig.PlcHeartbearAddr_AGV, tempResult.Content);
- }
- }
- }
- }
- private void PlcMonitorProc()
- {
- var RouteConfigList = ExcelConfig.Instance.RouteConfigList;
- for (int i = 0; i < RouteConfigList.Count; i++)
- {
- var routeConfig = RouteConfigList[i];
- if (routeConfig.PlcConnected)
- {
- //监控PLC信号
- for (int idx = 0; idx < signalMonitorColumnNameArray.Length; idx++)
- {
- string colName = signalMonitorColumnNameArray[idx];
- var signalAddr = routeConfig.LocationCode.GetLocationMember(colName);
- if (!string.IsNullOrEmpty(signalAddr))
- {
- var readResult = routeConfig.PlcReadWrite.ReadBool(signalAddr);
- var signalValue = readResult.IsSuccess ? readResult.Content.ToString() : "读取失败";
- if (signalValue != routeConfig.JData[colName]?.ToString())
- {
- CLog.Instance.SystemLog.WriteInfo($"{routeConfig.LocationCode} {routeConfig.PlcIpAddr} {colName}信号:{signalAddr}={signalValue}");
- }
- routeConfig.JData[colName] = signalValue;
- }
- }
- }
- }
- }
- private void PlcClearProc()
- {
- var RouteConfigList = ExcelConfig.Instance.RouteConfigList;
- for (int i = 0; i < RouteConfigList.Count; i++)
- {
- var routeConfig = RouteConfigList[i];
- if (routeConfig.PlcIsNeedClear)
- {
- Clear(routeConfig);
- }
- }
- }
- public List<JObject> ReadPlcInfo()
- {
- //用于显示
- var infoPlcList = ExcelConfig.Instance.InfoPlcList;
- //var RouteConfigList = ExcelConfig.Instance.RouteConfigList;
- Parallel.ForEach(infoPlcList, delegate (InfoPlc info, ParallelLoopState loopState)
- {
- try
- {
- if (info.routeConfig.PlcConnected)
- {
- DateTime start = DateTime.Now;
- //单个读取信号
- for (int i = 0; i < columnNameArray.Length; i++)
- {
- string colName = columnNameArray[i];
- string addr = info.routeConfig.LocationCode.GetLocationMember(colName);
- if (!string.IsNullOrEmpty(addr))
- {
- var result = info.routeConfig.PlcReadWrite.ReadBool(addr);
- if (result.IsSuccess)
- {
- info.JData[colName] = result.Content;
- }
- else
- {
- info.JData[colName] = null;
- }
- }
- else
- {
- info.JData[colName] = null;
- }
- }
- info.LastUpdateTime = DateTime.Now;
- //////离散地址批量读取,部分plc支持
- ////var plc = info.routeConfig.PlcReadWrite as HslCommunication.Profinet.AllenBradley.AllenBradleyNet;
- //var plc = info.routeConfig.PlcReadWrite as HslCommunication.Profinet.Siemens.SiemensS7Net;
- //if (plc == null)
- //{
- // CLog.Instance.SystemLog.WriteInfo("PlcReadWrite转换失败");
- // return;
- //}
- ////批量读取
- //var result = plc.Read(info.PlcSignalAddrArray, info.PlcSignalAddrLengthArray);
- //if (result.IsSuccess)
- //{
- // for (int i = 0; i < columnNameArray.Length; i++)
- // {
- // string colName = columnNameArray[i];
- // string addr = info.routeConfig.LocationCode.GetLocationMember(colName);
- // if (string.IsNullOrEmpty(addr))
- // {
- // info.JData[colName] = null;
- // }
- // else
- // {
- // //info.JData[colName] = plc.ByteTransform.TransBool(result.Content, i);
- // int bitIndex = int.Parse(addr.Last().ToString());
- // info.JData[colName] = result.Content[i].GetBitVaule(bitIndex);
- // }
- // }
- // info.LastUpdateTime = DateTime.Now;
- //}
- info.JData["耗时"] = Math.Round((DateTime.Now - start).TotalMilliseconds);
- }
- }
- catch
- {
- }
- });
-
- for (int index = 0; index < infoPlcList.Count; index++)
- {
- var info = infoPlcList[index];
- var jData = JDataList[index];
- for (int i = 0; i < columnNameArray.Length; i++)
- {
- string colName = columnNameArray[i];
- jData[colName] = info.JData[colName];
- }
- jData["耗时(ms)"] = info.JData["耗时"];
- jData["LastUpdateTime"] = info.LastUpdateTime;
- jData["有效"] = info.有效;
- }
- return JDataList.ToList();
- }
- private void UserThread()
- {
- CLog.Instance.SystemLog.WriteDebug($"PlcControl已启动");
- Thread.Sleep(2000);
- uint counter = 0;
- while (true)
- {
- try
- {
- PlcTaskProc();
- PlcMonitorProc();
- if (counter % 10 == 0)
- {
- PlcClearProc();
- }
- }
- catch (Exception ex)
- {
- CLog.Instance.SystemLog.WriteException("PlcControl", ex);
- Thread.Sleep(5000);
- }
- counter++;
- Thread.Sleep(1000);
- }
- }
- }
- }
|