using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Office.Interop.Word; using NLog; using Sharp7; using thinger.DataConvertLib; namespace Commom.DotNetDevices { public class PlcIO { private Sharp7.S7Client S77; private object objLock = new object(); private object objLock1 = new object(); #region 构造函数 /// /// 构造函数 /// /// IP地址 /// 槽号300=2 1200;1500 = 1或2 其他型号不确定 public PlcIO(string IP, int Slot, ref string message) { S77 = new Sharp7.S7Client(); // 连接到plc 0=机架号 int Result = S77.ConnectTo(IP, 0, Slot); if (Result != 0) { //for (int i = 0; i < 8; i++) //{ // Thread.Sleep(500); // Result = S77.ConnectTo(IP, 0, Slot); // if (Result == 0) // { // break; // } //} message = "未通电或线路故障!"; } } #endregion #region DB点读写设备 /// /// 读取PLC值 /// /// DB区指定值 其他默认为0 V区只能为1 /// 字符类型 /// 偏移量/地址 /// public string GetPlcDBValue(int dBNumber, string type, string pos) { lock (objLock) { Logger logger = LogManager.GetCurrentClassLogger(); try { byte[] Buffer = new byte[2000]; string[] poss = pos.Split('.'); int size = Sharp7.S7.DataSizeByte(this.GetDataType(type)); if (type == "String") { size = 20; } int Result = S77.DBRead(dBNumber, int.Parse(poss[0]), size, Buffer); string returnStr = "读取" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "类型:" + type + "\t"; string valueStr = string.Empty; if (Result == 0) { switch (type) { case "Bit": valueStr = Sharp7.S7.GetBitAt(Buffer, int.Parse(poss[0]), int.Parse(poss[1])).ToString(); break; case "Byte": valueStr = Sharp7.S7.GetByteAt(Buffer, int.Parse(poss[1])).ToString(); break; case "Char": valueStr = Sharp7.S7.GetCharsAt(Buffer, int.Parse(poss[1]), size); break; case "Word": valueStr = Sharp7.S7.GetWordAt(Buffer, int.Parse(poss[1])).ToString(); break; case "Int": valueStr = Sharp7.S7.GetIntAt(Buffer, int.Parse(poss[1])).ToString(); break; case "DWord": valueStr = Sharp7.S7.GetDWordAt(Buffer, int.Parse(poss[1])).ToString(); break; case "DInt": valueStr = Sharp7.S7.GetDIntAt(Buffer, int.Parse(poss[1])).ToString(); break; case "Real": valueStr = Sharp7.S7.GetRealAt(Buffer, int.Parse(poss[1])).ToString(); break; case "LReal": valueStr = Sharp7.S7.GetLRealAt(Buffer, int.Parse(poss[1])).ToString(); break; case "String": valueStr = Sharp7.S7.GetStringAt(Buffer, int.Parse(poss[1])).ToString(); break; case "String1": valueStr = Sharp7.S7.GetCharsAt(Buffer, int.Parse(poss[1]), 12); break; } logger.Error(returnStr + "值:" + valueStr, "读取PLC值:"); return valueStr; } return S77.ErrorText(Result); } catch (Exception ex) { logger.Error(ex.Message, "读取PLC值错误:"); throw ex; } } } /// /// 读取PLC数组格式 /// /// 槽位 /// 起始位/偏移点 /// 数组长度 /// null:读取失败 byte[]:数组结果 public byte[] GetPlcArrayDBValues(int dBNumber, int start, int leng) { byte[] arrayValues = new byte[leng]; var result1 = S77.DBRead(dBNumber, start, leng, arrayValues); if (result1 == 0) { return arrayValues; } return null; } /// /// 写入PLC值 /// /// db点 /// 偏移量 /// 类型 /// 值 /// 是否是控制字 /// true:写入成功 false:写入失败 public bool SetPlcDBValue(int dBNumber, string type, string value, string pos, bool isPos = false) { lock (objLock1) { bool bl = false; try { // 写入值 int size = Sharp7.S7.DataSizeByte(this.GetDataType(type)); if (type == "String") { size = 18; } var Buffer = new byte[600]; int Result = S77.DBRead(dBNumber, 0, size, Buffer); string[] poss = pos.Split('.'); switch (type) { case "Bit": Sharp7.S7.SetBitAt(ref Buffer, int.Parse(poss[0]), int.Parse(poss[1]), bool.Parse(value)); break; case "Byte": Sharp7.S7.SetByteAt(Buffer, int.Parse(poss[1]), byte.Parse(value)); break; case "Char": Sharp7.S7.SetCharsAt(Buffer, int.Parse(poss[1]), value); break; case "Word": Sharp7.S7.SetWordAt(Buffer, int.Parse(poss[1]), ushort.Parse(value)); break; case "Int": Sharp7.S7.SetIntAt(Buffer, int.Parse(poss[1]), short.Parse(value)); break; case "DWord": Sharp7.S7.SetDWordAt(Buffer, int.Parse(poss[1]), uint.Parse(value)); break; case "DInt": Sharp7.S7.SetDIntAt(Buffer, int.Parse(poss[1]), int.Parse(value)); break; case "Real": Sharp7.S7.SetRealAt(Buffer, int.Parse(poss[1]), float.Parse(value)); break; case "LReal": Sharp7.S7.SetLRealAt(Buffer, int.Parse(poss[1]), float.Parse(value)); break; case "String": Sharp7.S7.SetStringAt(Buffer, int.Parse(poss[1]), size, value); break; } int Result2 = S77.DBWrite(dBNumber, int.Parse(poss[0]), size, Buffer); string value1 = this.GetPlcDBValue(dBNumber, type, pos); if (isPos) //写入的是控制字 { if (Result2 == 0) { bl = true; string returnStr = "写入" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "值:" + value + "\t"; Logger logger = LogManager.GetCurrentClassLogger(); logger.Error(returnStr, "写入PLC值:"); return bl; } else { string returnStr = $"写入{pos}---DB点:{dBNumber.ToString()}偏移量:{pos}值:{value},返回结果{Result2}" + "\t"; Logger logger = LogManager.GetCurrentClassLogger(); logger.Error(returnStr, "写入PLC值失败:"); bool bll = this.SetPlcDBValue(dBNumber, type, value, pos); if (bll) { bl = true; } } } else //写入托盘号、任务号等信息 { if (value1 == value && Result2 == 0) { string returnStr = "写入" + pos + "---DB点:" + dBNumber.ToString() + "偏移量:" + pos + "值:" + value + "\t"; Logger logger = LogManager.GetCurrentClassLogger(); logger.Error(returnStr, "写入PLC值:"); return true; } else { string returnStr = $"写入{pos}---DB点:{dBNumber.ToString()}偏移量:{pos}值:{value},返回结果{Result2}--读取{value1}" + "\t"; Logger logger = LogManager.GetCurrentClassLogger(); logger.Error(returnStr, "写入PLC值失败:"); } //else //{ // // 暂时停止重复写入 // //bool bll = this.SetPlcDBValue(dBNumber, type, value, pos); // //if (bll) // //{ // // bl = true; // //} //} } #endregion return bl; } catch (Exception ex) { throw ex; } } } /// /// 写入数组类型PLC值 未测试 /// /// DB点 /// 起始字节、偏移量 /// 数组长度+1 /// 写入的值 /// public bool SetPlcArrayDBValues(int dBNumber, int start, int leng, byte[] arrayValues) { try { bool bl = false; var result1 = S77.DBWrite(dBNumber, start, leng, arrayValues); if (result1 == 0) { bl = true; } return bl; } catch (Exception ex) { throw ex; } } public static bool GetBitAt(byte[] Buffer, int Pos, int Bit) { byte[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; if (Bit < 0) Bit = 0; if (Bit > 7) Bit = 7; return (Buffer[Pos] & Mask[Bit]) != 0; } #region MB点读写设备 /// /// 读取PLC值 /// /// 起始字节 /// 字符类型 /// 偏移量/地址 /// public string GetPlcMBValue(string type, string pos) { try { byte[] Buffer = new byte[5000]; string[] poss = pos.Split('.'); int size = Sharp7.S7.DataSizeByte(this.GetDataType(type)); int Result = S77.MBRead(int.Parse(poss[0]), Buffer.Length, Buffer); string valueStr = string.Empty; valueStr = Convert.ToString(Sharp7.S7.GetBitAt(Buffer, 0, int.Parse(poss[1]))); if (Result == 0) { return valueStr; } return S77.ErrorText(Result); } catch (Exception ex) { throw ex; } } /// /// 多点读取PLC值 /// /// 报警信息的第一个偏移量 /// 报警集合 public bool[] GetPlcMBValues(string pos) { try { string[] poss = pos.Split('.'); byte[] Buffer = new byte[400]; int Result = S77.MBRead(int.Parse(poss[0]), 300, Buffer); bool[] de = BitLib.GetBitArrayFromByteArray(Buffer, Buffer.Length); return de; } catch (Exception ex) { throw ex; } } /// /// 写入PLC值 /// /// 偏移量 /// 类型 /// 值 /// true:写入成功 false:写入失败 public bool SetPlcMBValue(string type, string value, string pos) { bool bl = false; try { // 写入值 int size = Sharp7.S7.DataSizeByte(this.GetDataType(type)); var Buffer = new byte[600]; int Result = S77.MBRead(0, size, Buffer); string[] poss = pos.Split('.'); switch (type) { case "Bit": Sharp7.S7.SetBitAt(ref Buffer, int.Parse(poss[0]), int.Parse(poss[1]), bool.Parse(value)); break; case "Byte": Sharp7.S7.SetByteAt(Buffer, int.Parse(poss[1]), byte.Parse(value)); break; case "Char": Sharp7.S7.SetCharsAt(Buffer, int.Parse(poss[1]), value); break; case "Word": Sharp7.S7.SetWordAt(Buffer, int.Parse(poss[1]), ushort.Parse(value)); break; case "Int": Sharp7.S7.SetIntAt(Buffer, int.Parse(poss[1]), short.Parse(value)); break; case "DWord": Sharp7.S7.SetDWordAt(Buffer, int.Parse(poss[1]), uint.Parse(value)); break; case "DInt": Sharp7.S7.SetDIntAt(Buffer, int.Parse(poss[1]), int.Parse(value)); break; case "Real": Sharp7.S7.SetRealAt(Buffer, int.Parse(poss[1]), float.Parse(value)); break; case "String": Sharp7.S7.SetStringAt(Buffer, int.Parse(poss[1]), size, value); break; } Result = S77.MBWrite(int.Parse(poss[0]), size, Buffer); // 验证是否写入成功,不成功再次写入。4秒内尝试写入8次。 for (int i = 0; i < 8; i++) { Thread.Sleep(100); string plcValue = this.GetPlcMBValue(type, pos); if (value == plcValue) { bl = true; break; } else { // 再次写入值 Result = S77.MBWrite(int.Parse(poss[0]), size, Buffer); } bl = false; } return bl; } catch (Exception ex) { throw ex; } } #endregion /// /// 关闭连接 /// public void ClosePlc() { try { S77.Disconnect(); } catch (Exception ex) { Logger logger = LogManager.GetCurrentClassLogger(); logger.Error(ex.Message, "关闭连接错误:"); } } #region 数据处理 /// /// 获取类型对应长度 /// /// 数据类型 /// 所需长度 private int GetDataType(string type) { switch (type) { case "Bit": return Sharp7.S7Consts.S7WLBit; case "Byte": return Sharp7.S7Consts.S7WLByte; case "Char": return Sharp7.S7Consts.S7WLChar; case "Word": return Sharp7.S7Consts.S7WLWord; case "Int": return Sharp7.S7Consts.S7WLInt; case "DWord": return Sharp7.S7Consts.S7WLDWord; case "DInt": return Sharp7.S7Consts.S7WLDInt; case "Real": return Sharp7.S7Consts.S7WLReal; case "Counter": return Sharp7.S7Consts.S7WLCounter; case "Timer": return Sharp7.S7Consts.S7WLTimer; case "String": return 255; default: return 0; } } #endregion } }