using System; using System.Collections.Generic; using S7.Net; using Newtonsoft.Json.Linq; using ProjectBase.Data.Logs; using ProjectBase.Data.Redis; using ProjectBase.Data.BaseDAL; using SIMDP.BLL; using SIMDP.Model; using ProjectBase.Util; using System.Timers; using System.Reflection; namespace SIMDP.Device { public class PlcS7Net : AbstractBaseDevice { #region 数据定义 /// /// PLC对象 /// protected Plc S7Plc; /// /// 数据节点字典 key-变量名称, value-节点信息 /// protected Dictionary allPoints = new Dictionary(); /// /// 监控节点列表 /// protected List monitorPoints = new List(); #endregion #region TYPE定义 public class S7NetPlcConfig { public S7NetPlcConfig(string json) { JObject jObject = JObject.Parse(json); CPU = getCpuTypeByName((string)jObject["CPU"]); JToken token = jObject["IP"]; if (token != null) IP = (string)token; token = jObject["Rack"]; if (token != null) RACK = (short)token; token = jObject["Slot"]; if (token != null) SLOT = (short)token; token = jObject["Timer"]; if (token != null) TIMER = Convert.ToDouble(token.ToString()); } public CpuType CPU { get; set; } public string IP { get; set; } = "192.168.0.1"; public short RACK { get; set; } = 0; public short SLOT { get; set; } = 1; public double TIMER { get; set; } = 1000; CpuType getCpuTypeByName(string cpuName) { if (cpuName.Contains("1200")) return CpuType.S71200; else if (cpuName.Contains("1500")) return CpuType.S71500; else if (cpuName.Contains("200")) return CpuType.S7200; else if (cpuName.Contains("300")) return CpuType.S7300; else if (cpuName.Contains("400")) return CpuType.S7400; else return CpuType.S71500; // 默认为1500 } } public class S7NetDataPointInfo { // 节点配置信息 public MoDataPoint mo; // 节点属性 public short DB { get; set; } public short ADDR { get; set; } public VarType TYPE { get; set; } public byte BIT { get; set; } = 0; // 节点值及动作定义 public object value = null; public MethodInfo proc = null; public S7NetDataPointInfo(MoDataPoint _mo) { mo = _mo; JObject jObject = JObject.Parse(mo.DataPointSource); DB = Convert.ToInt16((string)jObject["DB"]); ADDR = Convert.ToInt16((string)jObject["ADDR"]); TYPE = getVarTypeByDataPointType(mo.DataPointType); JToken token = jObject["BIT"]; if (token != null) BIT = Convert.ToByte(token.ToString()); } VarType getVarTypeByDataPointType(long type) { if (type == 1) return VarType.Bit; else if (type == 2) return VarType.Byte; else if (type == 3) return VarType.Int; else if (type == 4) return VarType.Word; else if (type == 5) return VarType.DInt; else if (type == 6) return VarType.DWord; else if (type == 7) return VarType.Real; else if (type == 9) return VarType.String; else return VarType.Bit; } } #endregion #region 接口实现 public override void Start(MoPlcInfo _plcInfo, List _dataPoints) { plcInfo = _plcInfo; S7NetPlcConfig plcConfig = new S7NetPlcConfig(plcInfo.LinkConfig); S7Plc = new Plc(plcConfig.CPU, plcConfig.IP, plcConfig.RACK, plcConfig.SLOT); timer.Interval = plcConfig.TIMER; timer.Elapsed += timer_Elapsed; timer.AutoReset = false; // PLC未连接状态 SetRedisPlcDisConnect(); // 创建PLC数据点表 CreateDataPointList(_dataPoints); // 初始化自定义函数 actionStart(); // 启动时尝试连接一次设备 Connect(); // 启动定时器 timerStopped = false; timer.Start(); } public override bool isConnected() { return S7Plc.IsConnected; } protected override bool Connect() { S7Plc.Open(); SetRedisPlcConnected(); LogHelper.log.Info("已连接到PLC:" + S7Plc.IP); return isConnected(); } protected override void Disconnect() { if (S7Plc != null) S7Plc.Close(); SetRedisPlcDisConnect(); } void CreateDataPointList(List dataPoints) { if (redis == null) redis = new RedisHelper(); Type t = this.GetType(); foreach (MoDataPoint dataPoint in dataPoints) { S7NetDataPointInfo dataPointInfo = new S7NetDataPointInfo(dataPoint); allPoints.Add(dataPoint.DataPointName, dataPointInfo); redis.SetString(dataPoint.DataPointId.ToString() + dataPoint.DataPointName, ""); //if (BLLFactory.Instance.IsSignalGroupById(dataPoint.DataPointGroupId)) // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑 if (dataPoint.DataProc.Trim() != "") { dataPointInfo.proc = t.GetMethod(dataPoint.DataProc); monitorPoints.Add(dataPointInfo); } } } #endregion #region 读写操作 /// /// 读取节点数据 /// public bool Read(string dataPointName, out object value) { value = null; if (!allPoints.ContainsKey(dataPointName)) { return false; } S7NetDataPointInfo p = allPoints[dataPointName]; return Read(p, out value); } public bool Read(S7NetDataPointInfo p, out object value) { switch (p.TYPE) { case VarType.Bit: value = Convert.ToBoolean(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1, p.BIT)); break; case VarType.Byte: value = Convert.ToByte(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.Int: value = Convert.ToInt16(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.Word: value = Convert.ToUInt16(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.DInt: value = Convert.ToInt32(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.DWord: value = Convert.ToUInt32(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.Real: value = Convert.ToDouble(S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR, p.TYPE, 1)); break; case VarType.String: byte length = (byte)S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR + 1, VarType.Byte, 1); value = S7Plc.Read(DataType.DataBlock, p.DB, p.ADDR + 2, p.TYPE, length).ToString(); break; default: value = null; return false; } UpdataRedisDataPoint(p.mo, value.ToString()); return true; } /// /// 写入节点数据 /// public bool Write(string dataPointName, object value) { if (!allPoints.ContainsKey(dataPointName)) { return false; } S7NetDataPointInfo p = allPoints[dataPointName]; switch (p.TYPE) { case VarType.Bit: S7Plc.WriteBit(DataType.DataBlock, p.DB, p.ADDR, p.BIT, Convert.ToBoolean(value)); break; case VarType.Byte: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToByte(value)); break; case VarType.Int: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToInt16(value)); break; case VarType.Word: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToUInt16(value)); break; case VarType.DInt: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToInt32(value)); break; case VarType.DWord: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToUInt32(value)); break; case VarType.Real: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR, Convert.ToDouble(value)); break; case VarType.String: S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR + 1, Convert.ToByte(value.ToString().Length)); S7Plc.Write(DataType.DataBlock, p.DB, p.ADDR + 2, value.ToString()); break; default: return false; } UpdataRedisDataPoint(p.mo, value.ToString()); return true; } #endregion } }