PlcControl.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. using HslCommunication;
  2. using Newtonsoft.Json.Linq;
  3. using ProjectManagementSystem.Common.Config;
  4. using ProjectManagementSystem.Common.Extenions;
  5. using ProjectManagementSystem.Common.Logger;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. namespace ProjectManagementSystem.Common.Core
  13. {
  14. public class PlcControl
  15. {
  16. private static PlcControl m_instance;
  17. private Dictionary<string, HslCommunication.Core.IReadWriteNet> m_plcDict = new Dictionary<string, HslCommunication.Core.IReadWriteNet>();
  18. public List<JObject> JDataList { get; set; } = new List<JObject>();
  19. private string[] columnNameArray = new string[]
  20. {
  21. "PLC允许进入" ,
  22. "PLC放行" ,
  23. "PLC返修" ,
  24. "AGV请求进入",
  25. "AGV正在进入",
  26. "AGV到位",
  27. "AGV正在离开"
  28. };
  29. public static PlcControl Instance
  30. {
  31. get
  32. {
  33. if (m_instance == null)
  34. {
  35. m_instance = new PlcControl();
  36. if (!m_instance.Initialize())
  37. {
  38. m_instance = null;
  39. }
  40. }
  41. return m_instance;
  42. }
  43. }
  44. private PlcControl()
  45. {
  46. }
  47. private bool Initialize()
  48. {
  49. var dataList = ExcelConfig.Instance.RouteConfigList;
  50. for (int i = 0; i < dataList.Count; i++)
  51. {
  52. var data = dataList[i];
  53. string plcIpAddr = data.PlcIpAddr;
  54. if (!string.IsNullOrEmpty(plcIpAddr))
  55. {
  56. bool selfPlcReadWrite = data.LocationCode.GetLocationMember("独立通讯(PLC)").ToValue<bool>();
  57. if (selfPlcReadWrite)
  58. {
  59. //每个库位独立的PLC通讯对象
  60. var plc = GetReadWriteNet(data);
  61. data.PlcReadWrite = plc;
  62. }
  63. else
  64. {
  65. //库位相同IP共用PLC通讯对象
  66. if (!m_plcDict.ContainsKey(plcIpAddr))
  67. {
  68. var plc = GetReadWriteNet(data);
  69. m_plcDict.Add(plcIpAddr, plc);
  70. }
  71. if (m_plcDict.TryGetValue(plcIpAddr, out var plcObj))
  72. {
  73. data.PlcReadWrite = plcObj;
  74. }
  75. }
  76. }
  77. }
  78. columnNameArray = Function.AppSetting.TryGetValue<string>("PlcSignalColumnName").ToValueArray<string>();
  79. var dataList2 = ExcelConfig.Instance.InfoPlcList;
  80. for (int i = 0; i < dataList2.Count; i++)
  81. {
  82. var data = dataList2[i];
  83. data.routeConfig = ExcelConfig.Instance.GetRouteConfig(data.库位号);
  84. data.JData = new JObject();
  85. string defaultAddr = data.routeConfig.PlcHeartbearAddr;
  86. data.PlcSignalAddrArray = new string[columnNameArray.Length];
  87. data.PlcSignalAddrLengthArray = new ushort[columnNameArray.Length];
  88. for (int infoIndex = 0; infoIndex < columnNameArray.Length; infoIndex++)
  89. {
  90. string info = columnNameArray[infoIndex];
  91. string plcRealAddr = data.routeConfig.LocationCode.GetLocationMember(info);
  92. data.PlcSignalAddrArray[infoIndex] = string.IsNullOrEmpty(plcRealAddr) ? defaultAddr : plcRealAddr;
  93. //读取长度2,要求PLC有多出来一个byte地址
  94. data.PlcSignalAddrLengthArray[infoIndex] = 2;
  95. }
  96. var jData = new JObject();
  97. jData["库位号"] = data.routeConfig.LocationCode;
  98. jData["IP地址"] = data.routeConfig.PlcIpAddr;
  99. JDataList.Add(jData);
  100. }
  101. Task.Factory.StartNew(UserThread, TaskCreationOptions.LongRunning);
  102. return true;
  103. }
  104. /// <summary>
  105. /// 获取创建的PLC通讯对象
  106. /// </summary>
  107. /// <param name="data"></param>
  108. /// <returns></returns>
  109. private HslCommunication.Core.IReadWriteNet GetReadWriteNet(RouteConfig data)
  110. {
  111. string plcIpAddr = data.PlcIpAddr;
  112. var plcProtocol = data.LocationCode.GetLocationMember("通讯协议(PLC)");
  113. switch (plcProtocol)
  114. {
  115. case "SiemensS7Net":
  116. {
  117. var plc = new HslCommunication.Profinet.Siemens.SiemensS7Net(HslCommunication.Profinet.Siemens.SiemensPLCS.S1500, plcIpAddr);
  118. plc.ConnectTimeOut = 1000;
  119. plc.ReceiveTimeOut = 1000;
  120. plc.SetPersistentConnection();
  121. return plc;
  122. }
  123. case "SiemensS7Net_S200Smart":
  124. {
  125. var plc = new HslCommunication.Profinet.Siemens.SiemensS7Net(HslCommunication.Profinet.Siemens.SiemensPLCS.S200Smart, plcIpAddr);
  126. plc.ConnectTimeOut = 1000;
  127. plc.ReceiveTimeOut = 1000;
  128. plc.SetPersistentConnection();
  129. return plc;
  130. }
  131. case "MelsecMcNet":
  132. {
  133. var plc = new HslCommunication.Profinet.Melsec.MelsecMcNet(plcIpAddr, 5000);
  134. plc.ConnectTimeOut = 1000;
  135. plc.ReceiveTimeOut = 1000;
  136. plc.SetPersistentConnection();
  137. return plc;
  138. }
  139. case "OmronFinsNet":
  140. {
  141. var plc = new HslCommunication.Profinet.Omron.OmronFinsNet(plcIpAddr, 9600);
  142. plc.ConnectTimeOut = 1000;
  143. plc.ReceiveTimeOut = 1000;
  144. plc.ByteTransform.DataFormat = HslCommunication.Core.DataFormat.BADC;
  145. plc.SetPersistentConnection();
  146. return plc;
  147. }
  148. case "OmronFinsUdp":
  149. {
  150. var plc = new HslCommunication.Profinet.Omron.OmronFinsUdp(plcIpAddr, 9600);
  151. plc.ReceiveTimeout = 1000;
  152. plc.ByteTransform.DataFormat = HslCommunication.Core.DataFormat.BADC;
  153. return plc;
  154. }
  155. case "AllenBradleyNet":
  156. {
  157. var plc = new HslCommunication.Profinet.AllenBradley.AllenBradleyNet(plcIpAddr);
  158. plc.ConnectTimeOut = 1000;
  159. plc.ReceiveTimeOut = 1000;
  160. plc.SetPersistentConnection();
  161. return plc;
  162. }
  163. case "ModbusTcpNet":
  164. {
  165. var plc = new HslCommunication.ModBus.ModbusTcpNet(plcIpAddr);
  166. plc.ConnectTimeOut = 1000;
  167. plc.ReceiveTimeOut = 1000;
  168. plc.ByteTransform.DataFormat = HslCommunication.Core.DataFormat.BADC;
  169. plc.SetPersistentConnection();
  170. return plc;
  171. }
  172. case "IOBoxNet":
  173. {
  174. var plc = new Profinet.IOBoxNet(plcIpAddr, 8898);
  175. return plc;
  176. }
  177. default:
  178. {
  179. var plc = new HslCommunication.Profinet.AllenBradley.AllenBradleyNet(plcIpAddr);
  180. plc.ConnectTimeOut = 1000;
  181. plc.ReceiveTimeOut = 1000;
  182. plc.SetPersistentConnection();
  183. return plc;
  184. }
  185. }
  186. }
  187. private void PlcTaskProc()
  188. {
  189. var configList = ExcelConfig.Instance.RouteConfigList;
  190. var plcGroupList = configList
  191. .Where(d => d.PlcReadWrite != null)
  192. .GroupBy(d => d.PlcIpAddr);
  193. foreach (var item in plcGroupList)
  194. {
  195. var first = item.FirstOrDefault(d => !string.IsNullOrEmpty(d.PlcHeartbearAddr));
  196. if (first == null)
  197. {
  198. continue;
  199. }
  200. //读取PLC心跳信号
  201. var tempResult = first.PlcReadWrite.ReadBool(first.PlcHeartbearAddr);
  202. if (first.PlcConnected != tempResult.IsSuccess)
  203. {
  204. CLog.Instance.SystemLog.WriteInfo($"{first.LocationCode} {first.PlcIpAddr} PLC连接:{tempResult.IsSuccess.ToChineseString()} Code:{tempResult.ErrorCode} Message:{tempResult.Message}");
  205. }
  206. foreach (var config in item)
  207. {
  208. config.PlcConnected = tempResult.IsSuccess;
  209. }
  210. }
  211. //for (int i = 0; i < configList.Count; i++)
  212. //{
  213. // var routeConfig = configList[i];
  214. // if (!string.IsNullOrEmpty(routeConfig.PlcHeartbearAddr)
  215. // && routeConfig.PlcReadWrite != null)
  216. // {
  217. // //读取PLC心跳信号
  218. // var tempResult = routeConfig.PlcReadWrite.ReadBool(routeConfig.PlcHeartbearAddr);
  219. // if (routeConfig.PlcConnected != tempResult.IsSuccess)
  220. // {
  221. // CLog.Instance.SystemLog.WriteInfo($"{routeConfig.LocationCode} {routeConfig.PlcIpAddr} PLC连接:{tempResult.IsSuccess.ToChineseString()}");
  222. // }
  223. // routeConfig.PlcConnected = tempResult.IsSuccess;
  224. // ////回写PLC心跳信号
  225. // //if (tempResult.IsSuccess
  226. // // && !string.IsNullOrEmpty(routeConfig.PlcHeartbearAddr_AGV))
  227. // //{
  228. // // routeConfig.PlcReadWrite.Write(routeConfig.PlcHeartbearAddr_AGV, tempResult.Content);
  229. // //}
  230. // }
  231. //}
  232. }
  233. public List<JObject> ReadPlcInfo()
  234. {
  235. //用于显示
  236. var infoPlcList = ExcelConfig.Instance.InfoPlcList;
  237. //var RouteConfigList = ExcelConfig.Instance.RouteConfigList;
  238. Parallel.ForEach(infoPlcList, delegate (InfoPlc info, ParallelLoopState loopState)
  239. {
  240. try
  241. {
  242. DateTime start = DateTime.Now;
  243. ////单个读取信号
  244. //for (int i = 0; i < columnNameArray.Length; i++)
  245. //{
  246. // string colName = columnNameArray[i];
  247. // string addr = info.routeConfig.LocationCode.GetLocationMember(colName);
  248. // if (!string.IsNullOrEmpty(addr))
  249. // {
  250. // var result = info.routeConfig.PlcReadWrite.ReadBool(addr);
  251. // if (result.IsSuccess)
  252. // {
  253. // info.JData[colName] = result.Content;
  254. // }
  255. // else
  256. // {
  257. // info.JData[colName] = null;
  258. // }
  259. // }
  260. // else
  261. // {
  262. // info.JData[colName] = null;
  263. // }
  264. //}
  265. //info.LastUpdateTime = DateTime.Now;
  266. //////离散地址批量读取,部分plc支持
  267. OperateResult<byte[]> result = null;
  268. switch (info.routeConfig.PlcReadWrite)
  269. {
  270. case HslCommunication.Profinet.AllenBradley.AllenBradleyNet plc:
  271. result = plc.Read(info.PlcSignalAddrArray);
  272. break;
  273. case HslCommunication.Profinet.Siemens.SiemensS7Net plc:
  274. result = plc.Read(info.PlcSignalAddrArray, info.PlcSignalAddrLengthArray);
  275. break;
  276. default:
  277. CLog.Instance.SystemLog.WriteInfo("PlcReadWrite转换失败");
  278. return;
  279. }
  280. //批量读取
  281. if (result.IsSuccess)
  282. {
  283. for (int i = 0; i < columnNameArray.Length; i++)
  284. {
  285. string colName = columnNameArray[i];
  286. string addr = info.routeConfig.LocationCode.GetLocationMember(colName);
  287. if (string.IsNullOrEmpty(addr))
  288. {
  289. info.JData[colName] = null;
  290. }
  291. else
  292. {
  293. switch (info.routeConfig.PlcReadWrite)
  294. {
  295. case HslCommunication.Profinet.AllenBradley.AllenBradleyNet plc:
  296. info.JData[colName] = plc.ByteTransform.TransBool(result.Content, i) ? "1" : "0";
  297. break;
  298. case HslCommunication.Profinet.Siemens.SiemensS7Net plc:
  299. if (addr.Contains("DBW") || addr.Count(d => d == '.') == 1)
  300. {
  301. info.JData[colName] = plc.ByteTransform.TransInt16(result.Content, i * 2);
  302. }
  303. else
  304. {
  305. int bitIndex = int.Parse(addr.Last().ToString());
  306. info.JData[colName] = result.Content[i * 2].GetBitVaule(bitIndex) ? "1" : "0";
  307. }
  308. break;
  309. default:
  310. break;
  311. }
  312. }
  313. }
  314. info.LastUpdateTime = DateTime.Now;
  315. }
  316. info.JData["耗时"] = Math.Round((DateTime.Now - start).TotalMilliseconds);
  317. info.JData["消息"] = result.Message;
  318. }
  319. catch (Exception ex)
  320. {
  321. info.JData["消息"] = ex.Message;
  322. }
  323. });
  324. for (int index = 0; index < infoPlcList.Count; index++)
  325. {
  326. var info = infoPlcList[index];
  327. var jData = JDataList[index];
  328. jData["更新时间"] = info.LastUpdateTime.ToString("G");
  329. jData["消息"] = info.JData["消息"];
  330. for (int i = 0; i < columnNameArray.Length; i++)
  331. {
  332. string colName = columnNameArray[i];
  333. jData[colName] = info.JData[colName];
  334. }
  335. jData["耗时(ms)"] = info.JData["耗时"];
  336. //jData["有效"] = info.有效;
  337. }
  338. return JDataList.ToList();
  339. }
  340. private void UserThread()
  341. {
  342. CLog.Instance.SystemLog.WriteDebug($"PlcControl已启动");
  343. Thread.Sleep(2000);
  344. while (true)
  345. {
  346. try
  347. {
  348. PlcTaskProc();
  349. }
  350. catch (Exception ex)
  351. {
  352. CLog.Instance.SystemLog.WriteException("PlcControl", ex);
  353. Thread.Sleep(5000);
  354. }
  355. Thread.Sleep(1000);
  356. }
  357. }
  358. }
  359. }