using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using HslCommunication; using HslCommunication.Profinet.Delta; using Newtonsoft.Json; namespace WIDESEA_WCS.WCSClient.Delta { public class DeltaPLCClient { public DeltaTcpNet DeltaDvpTcpNetClient { get; set; } public DeltaPLCClient() { DeltaDvpTcpNetClient = new DeltaTcpNet(); PLCDBItems = new List(); } /// /// PLC连接对应的地址 /// public List PLCDBItems { get; set; } /// /// 连接名称 /// public string PLCName { get; set; } /// /// IP地址 /// public string PLCIPAddress { get; set; } /// /// 连接说明 /// public string PLCDescroption { get; set; } /// /// 端口号(默认102) /// public int Port { get; set; } = 502; /// /// 是否已连接 /// public bool IsConnected { get; set; } = false; #region 连接PLC,将短连接切换成长连接模式 /// /// 连接PLC /// public string Connect() { DeltaDvpTcpNetClient.IpAddress = PLCIPAddress; DeltaDvpTcpNetClient.Port = Port; DeltaDvpTcpNetClient.ConnectTimeOut = 2000; DeltaDvpTcpNetClient.Series = DeltaSeries.AS; DeltaDvpTcpNetClient?.ConnectClose(); OperateResult result = DeltaDvpTcpNetClient.ConnectServer(); if (!result.IsSuccess) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{PLCName}连接失败{Environment.NewLine}错误信息:{result.Message}", PLCName); IsConnected = false; return $"连接失败,错误信息:{result.Message}"; } else { IsConnected = true; WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:{PLCName}连接成功!", PLCName); return $"连接成功"; } } #endregion #region 断开与PLC的连接,将长连接切换成短连接模式 /// /// 断开与PLC的连接 /// public void Disconnect() { DeltaDvpTcpNetClient?.ConnectClose(); WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:已断开与{PLCName}的连接!", PLCName); } #endregion #region 根据名称/描述读取PLC数据 /// /// 根据名称/描述读取PLC数据 /// /// 名称/描述(数据库中plcdetail_name列) /// public virtual object ReadValue(string itemName) { lock (DeltaDvpTcpNetClient) { object result = null; DBItemGroup item = this.PLCDBItems.Where(x => x.ItemName == itemName).FirstOrDefault(); if (item == null) return -1; string itemAddress = item.ItemAddress; string itemDatatype = item.ItemDataType; try { result = Read(itemAddress, itemDatatype); } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{item.ItemDataType},{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } } #endregion #region 根据PLCDBItem读取PLC数据 /// /// 根据PLCDBItem读取PLC数据 /// /// /// public virtual object ReadValue(DBItemGroup item) { lock (DeltaDvpTcpNetClient) { object result = null; if (item == null) return -1; string itemAddress = item.ItemAddress; string itemDatatype = item.ItemDataType; try { result = Read(itemAddress, itemDatatype); } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{item.ItemDataType},{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } } #endregion #region 根据设备编号读取PLC数据 /// /// 根据设备编号读取PLC数据 /// /// 设备编号 /// json字符串 public object ReadValues(string equipNum) { lock (DeltaDvpTcpNetClient) { object result = null; Dictionary keyValuePairs = new Dictionary(); List items = this.PLCDBItems.Where(x => x.EquipNum == equipNum).ToList(); for (int i = 0; i < items.Count(); i++) { keyValuePairs.Add(items[i].ItemName, ReadValue(items[i].ItemName)); } result = JsonConvert.SerializeObject(keyValuePairs); return result; } } #endregion #region 根据名称/描述读取PLC数据返回设备编号和值的JSON字符串 /// /// 根据名称/描述读取PLC数据返回设备编号和值的JSON字符串 /// /// 名称/描述(数据库中plcdetail_name列) /// json字符串 public string ReadValuesByItemName(string itemName) { lock (DeltaDvpTcpNetClient) { string result = null; Dictionary keyValuePairs = new Dictionary(); List items = this.PLCDBItems.Where(x => x.ItemName == itemName).ToList(); for (int i = 0; i < items.Count(); i++) { keyValuePairs.Add(items[i].EquipNum, ReadValue(items[i])); } result = JsonConvert.SerializeObject(keyValuePairs); return result; } } #endregion #region 根据名称/描述和设备编号读取PLC数据 /// /// 根据名称/描述和设备编号读取PLC数据 /// /// 名称/描述(数据库中plcdetail_name列) /// 设备编号 /// public virtual object ReadValue(string itemName, string equipNum) { lock (DeltaDvpTcpNetClient) { object result = null; DBItemGroup item = this.PLCDBItems.Where(x => x.ItemName == itemName && x.EquipNum == equipNum).FirstOrDefault(); if (item == null) { try { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:{Environment.NewLine}{PLCName}读取数据{Environment.NewLine}{Environment.NewLine}({equipNum}):未在协议找到编号{equipNum}的地址", PLCName); } catch { } return -1; } string itemAddress = item.ItemAddress; string itemDatatype = item.ItemDataType; try { result = Read(itemAddress, itemDatatype); } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{item.ItemDataType},{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { //WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:{Environment.NewLine}{PLCName}读取数据{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):" + result, PLCName); } catch { } return result; } } #endregion #region 将数据写入到PLC中 /// /// 将数据写入到PLC中 /// /// 名称/描述(数据库中plcdetail_name列) /// 写入的值 /// public virtual bool WriteValue(string itemName, object value) { lock (DeltaDvpTcpNetClient) { OperateResult operateResult = new OperateResult(); ; bool result = false; string writeResult = ""; DBItemGroup item = this.PLCDBItems.Where(x => x.ItemName == itemName).FirstOrDefault(); if (item == null) return false; string itemAddress = item.ItemAddress; string itemDatatype = item.ItemDataType; try { operateResult = Write(itemAddress, itemDatatype, value); result = operateResult.IsSuccess; writeResult = result ? "成功" : $"失败:{operateResult.Message}"; } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:{PLCName}写入数据{writeResult}{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):" + value, PLCName); } catch { } return result; } } #endregion #region 将数据写入到PLC中 /// /// 将数据写入到PLC中 /// /// 名称/描述(数据库中plcdetail_name列) /// 写入的值 /// public virtual bool WriteValue(string itemName, string equipNum, object value) { lock (DeltaDvpTcpNetClient) { OperateResult operateResult = new OperateResult(); ; bool result = false; string writeResult = ""; DBItemGroup item = this.PLCDBItems.Where(x => x.ItemName == itemName && x.EquipNum == equipNum).FirstOrDefault(); if (item == null) return false; string itemAddress = item.ItemAddress; string itemDatatype = item.ItemDataType; try { operateResult = Write(itemAddress, itemDatatype, value); result = operateResult.IsSuccess; writeResult = result ? "成功" : $"失败:{operateResult.Message}"; } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Info:{PLCName}写入数据{writeResult}{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):" + value, PLCName); } catch { } return result; } } #endregion #region 批量写入数据 /// /// 批量写入数据(数据类型必须一致) /// /// DB块起始地址 /// 数据类型 /// 写入的值 /// public OperateResult WriteArray(string adress, string type, object value) { OperateResult result = new OperateResult(); try { switch (type.ToLower()) { case "int": result = DeltaDvpTcpNetClient.Write(adress, value as ushort[]); break; case "dint": result = DeltaDvpTcpNetClient.Write(adress, value as int[]); break; case "char": string temp = value.ToString(); byte[] writeData = Encoding.Default.GetBytes(temp); result = DeltaDvpTcpNetClient.Write(adress, writeData); break; case "bool": result = DeltaDvpTcpNetClient.Write(adress, value as bool[]); break; } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{type}{Environment.NewLine}{adress}:{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } #endregion #region 批量读取数据 /// /// 批量读取数据(数据类型必须一致) /// /// DB块起始地址 /// 数据类型 /// 读取长度 /// public object ReadArray(string adress, string type, int length) { object result = -1; ; try { switch (type.ToLower()) { case "int": result = DeltaDvpTcpNetClient.ReadUInt16(adress, Convert.ToUInt16(length)).Content; break; case "dint": result = DeltaDvpTcpNetClient.ReadUInt32(adress, Convert.ToUInt16(length)).Content; break; case "char": byte[] temps = DeltaDvpTcpNetClient.Read(adress, Convert.ToUInt16(length)).Content; result = Encoding.Default.GetString(temps).ToCharArray(); break; case "bool": result = DeltaDvpTcpNetClient.ReadBool(adress, Convert.ToUInt16(length)).Content; break; case "byte": break; } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{type},{adress}:{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } #endregion #region 根据DB地址及类型读取数据,最根本读取方法 /// /// 根据DB地址及类型读取数据 /// /// DB地址(DB块+.+偏移量) /// 数据类型(int/dint/string/bool) /// public object Read(string adress, string type) { object result = -1; ; try { switch (type.ToLower()) { case "int": result = DeltaDvpTcpNetClient.ReadUInt16(adress).Content; break; case "dint": result = DeltaDvpTcpNetClient.ReadUInt32(adress).Content; break; case "string": OperateResult operateResult = DeltaDvpTcpNetClient.ReadString(adress, 20); operateResult.Content = operateResult.Content?.Replace("\\", "")?.Replace("\0", "")?.Replace("\u0014", ""); result = operateResult.Content == null ? "" : operateResult.Content.Trim(); break; case "bool": result = DeltaDvpTcpNetClient.ReadBool(adress).Content; break; default: throw new Exception($"未找到该数据类型:{type}"); //break; } } catch (Exception ex) { StackTrace stackTrace = new StackTrace(); StackFrame[] stackFrames = stackTrace.GetFrames(); string str = ""; foreach (var item in stackFrames) { str += "方法名:" + item.GetMethod().Name + ",行号:" + item.GetFileLineNumber() + ",文件名:" + item.GetFileName() + Environment.NewLine; } WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{type},{adress}:{Environment.NewLine}错误信息:{ex.Message},{ str}", PLCName); } return result; } #endregion #region 根据DB地址及类型写入数据,最根本写入方法 /// /// 根据DB地址及类型写入数据 /// /// DB地址(DB块+.+偏移量) /// 数据类型(int/dint/string/bool) /// 写入的值 /// 返回成功或失败 public OperateResult Write(string adress, string type, object value) { OperateResult result = new OperateResult(); try { switch (type.ToLower()) { case "int": result = DeltaDvpTcpNetClient.Write(adress, Convert.ToUInt16(value)); break; case "dint": result = DeltaDvpTcpNetClient.Write(adress, Convert.ToUInt32(value)); break; case "string": string[] adressTmp = adress.Split('.'); result = DeltaDvpTcpNetClient.Write(adressTmp[0] + "." + (Convert.ToInt32(adressTmp[1]) - 2), value.ToString()); break; case "bool": result = DeltaDvpTcpNetClient.Write(adress, Convert.ToBoolean(value)); break; default: throw new Exception($"未找到该数据类型:{type}"); } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog(PLCName).Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{type}{Environment.NewLine}{adress}:{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } #endregion } }