using HslCommunication; using HslCommunication.Profinet.Omron; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace WIDESEA_WCS.WCSClient.Omron { public class OmronPLCClient { /// /// 欧姆龙PLC连接 /// public OmronFinsNet OmronFinsNetClient { get; set; } /// /// 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; } = 9600; /// /// 是否已连接 /// public bool IsConnected { get; set; } = false; public OmronPLCClient() { PLCDBItems = new List(); } #region 连接PLC,将短连接切换成长连接模式 /// /// 连接PLC /// public string Connect() { OmronFinsNetClient = new OmronFinsNet(PLCIPAddress, Port); //链接plc var result = OmronFinsNetClient.ConnectServer(); if (!result.IsSuccess) { WIDESEA_Common.Tools.WriteLog.GetLog().Write($"Error:{PLCName}连接失败{Environment.NewLine}错误信息:{result.Message}", PLCName); IsConnected = false; return $"连接失败,错误信息:{result.Message}"; } else { IsConnected = true; WIDESEA_Common.Tools.WriteLog.GetLog().Write($"Info:{PLCName}连接成功!", PLCName); return $"连接成功"; } } #endregion #region 断开与PLC的连接,将长连接切换成短连接模式 /// /// 断开与PLC的连接 /// public void Disconnect() { this.OmronFinsNetClient?.ConnectClose(); WIDESEA_Common.Tools.WriteLog.GetLog().Write($"Info:已断开与{PLCName}的连接!", PLCName); } #endregion #region 根据名称/描述读取PLC数据 /// /// 根据名称/描述读取PLC数据 /// /// 名称/描述(数据库中plcdetail_name列) /// public virtual object ReadValue(string itemName) { lock (OmronFinsNetClient) { 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().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 (OmronFinsNetClient) { 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().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 (OmronFinsNetClient) { 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 (OmronFinsNetClient) { 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 (OmronFinsNetClient) { 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().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().Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{item.ItemDataType},{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { //WIDESEA_Common.Tools.WriteLog.GetLog().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 (OmronFinsNetClient) { 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().Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { WIDESEA_Common.Tools.WriteLog.GetLog().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 (OmronFinsNetClient) { 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().Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{item.ItemDataType}{Environment.NewLine}{item.Remark}({itemAddress}):{Environment.NewLine}错误信息:{ex.Message}", PLCName); } try { WIDESEA_Common.Tools.WriteLog.GetLog().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 = OmronFinsNetClient.Write(adress, value as ushort[]); break; case "dint": result = OmronFinsNetClient.Write(adress, value as int[]); break; case "char": string temp = value.ToString(); byte[] writeData = Encoding.Default.GetBytes(temp); result = OmronFinsNetClient.Write(adress, writeData); break; case "bool": result = OmronFinsNetClient.Write(adress, value as bool[]); break; } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog().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 = OmronFinsNetClient.ReadUInt16(adress, Convert.ToUInt16(length)).Content; break; case "dint": result = OmronFinsNetClient.ReadUInt32(adress, Convert.ToUInt16(length)).Content; break; case "char": byte[] temps = OmronFinsNetClient.Read(adress, Convert.ToUInt16(length)).Content; result = Encoding.Default.GetString(temps).ToCharArray(); break; case "bool": result = OmronFinsNetClient.ReadBool(adress, Convert.ToUInt16(length)).Content; break; case "byte": break; } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog().Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{type},{adress}:{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } #endregion #region 根据DB地址及类型读取数据,最根本读取方法 public T Read(string address, int len = 1) { var Type = typeof(T); if (Type == typeof(bool)) { return (T)GetContent(OmronFinsNetClient.ReadBool(address, (ushort)1)); } else if (Type == typeof(ushort)) { return (T)GetContent(OmronFinsNetClient.ReadUInt16(address)); } else if (Type == typeof(byte[])) { return (T)GetContent(OmronFinsNetClient.Read(address, (ushort)len)); } else if (Type == typeof(float)) { return (T)GetContent(OmronFinsNetClient.ReadFloat(address)); } else if (Type == typeof(string)) { return (T)GetContent(OmronFinsNetClient.ReadString(address, (ushort)len)); } else { throw new Exception($"类型{typeof(T)},未定义!"); } } private object GetContent(OperateResult operateResult) { if (operateResult.IsSuccess) { return operateResult.Content; } else { throw new Exception($"读取失败,{operateResult.Message}"); } } /// /// 根据DB地址及类型读取数据 /// /// DB地址(DB块+.+偏移量) /// 数据类型(int/dint/string/bool) /// public object Read(string adress, string type) { object result = -1; ; try { switch (type.ToLower()) { case "int": result = OmronFinsNetClient.ReadUInt16(adress).Content; break; case "dint": result = OmronFinsNetClient.ReadUInt32(adress).Content; break; case "string": OperateResult operateResult = OmronFinsNetClient.ReadString(adress, 20); operateResult.Content = operateResult.Content?.Replace("\\", "")?.Replace("\0", "")?.Replace("\u0014", ""); result = operateResult.Content == null ? "" : operateResult.Content.Trim(); break; case "bool": result = OmronFinsNetClient.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().Write($"Error:{Environment.NewLine}{PLCName}读取数据失败{Environment.NewLine}数据类型:{type},{adress}:{Environment.NewLine}错误信息:{ex.Message},{ str}", PLCName); } return result; } #endregion #region 根据DB地址及类型写入数据,最根本写入方法 public void Write(string address, object value) { OperateResult result = null; var type = value.GetType(); if (type == typeof(int)) { result = OmronFinsNetClient.Write(address, Convert.ToUInt16(value)); } else if (type == typeof(bool)) { result = OmronFinsNetClient.Write(address, (bool)value); } else if (type == typeof(string)) { result = OmronFinsNetClient.Write(address, (string)value); } else if (type == typeof(byte[])) { result = OmronFinsNetClient.Write(address, (byte[])value); } else { throw new Exception($"类型{type},未定义!"); } if (!result.IsSuccess) { throw new Exception($"地址:{address},写入失败!"); } } /// /// 根据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 = OmronFinsNetClient.Write(adress, Convert.ToUInt16(value)); break; case "dint": result = OmronFinsNetClient.Write(adress, Convert.ToUInt32(value)); break; case "string": string[] adressTmp = adress.Split('.'); result = OmronFinsNetClient.Write(adressTmp[0] + "." + (Convert.ToInt32(adressTmp[1]) - 2), value.ToString()); break; case "bool": result = OmronFinsNetClient.Write(adress, Convert.ToBoolean(value)); break; default: throw new Exception($"未找到该数据类型:{type}"); } } catch (Exception ex) { WIDESEA_Common.Tools.WriteLog.GetLog().Write($"Error:{PLCName}写入数据失败{Environment.NewLine}数据类型:{type}{Environment.NewLine}{adress}:{Environment.NewLine}错误信息:{ex.Message}", PLCName); } return result; } #endregion } }