using System; using System.Timers; using System.Collections.Generic; using Newtonsoft.Json.Linq; using ProjectBase.Data.Logs; using ProjectBase.Data.Redis; using ProjectBase.Data.BaseDAL; using Modbus.Device; using SIMDP.Model; using ProjectBase.Util; using SIMDP.BLL; using System.Linq; using System.Reflection; using System.Net.Sockets; namespace SIMDP.Device { public class ModbusTcp : AbstractBaseDevice { #region 数据定义 /// /// ModbusTcp配置信息 /// protected ModbusTcpConfig config; /// /// Modbus对象 /// protected IModbusMaster master; /// /// TCP连接对象 /// protected TcpClient tcpClient; /// /// 数据节点字典 key-变量名称, value-节点信息 /// protected Dictionary allPoints = new Dictionary(); /// /// 监控节点列表 /// protected List monitorPoints = new List(); /// /// 连接状态 /// protected bool isConnect = false; #endregion #region TYPE定义 public class ModbusTcpConfig { public ModbusTcpConfig(string json) { JObject jObject = JObject.Parse(json); JToken token; if ((token = jObject["IP"]) != null) IP = (string)token; if ((token = jObject["PORT"]) != null) PORT = (int)token; if ((token = jObject["TIMER"]) != null) TIMER = (double)token; } // 串口属性 public string IP { get; set; } = "127.0.0.1"; public int PORT { get; set; } = 502; // 轮询时间 public double TIMER { get; set; } = 200; } public class ModbusDataPointInfo { // 节点配置信息 public MoDataPoint mo; // 节点属性 public string 类型 { get; set; } public byte 站号 { get; set; } public ushort 地址 { get; set; } public ushort 长度 { get; set; } = 1; // 节点值及动作定义 public object value = null; public MethodInfo proc = null; public ModbusDataPointInfo(MoDataPoint _mo) { mo = _mo; 类型 = SysEnvironment.dirType.FirstOrDefault(p => p.Key == mo.DataPointType).Value; JObject jObject = JObject.Parse(mo.DataPointSource); 站号 = Convert.ToByte((string)jObject["站号"]); 地址 = Convert.ToUInt16((string)jObject["地址"]); if (jObject["长度"] != null) 长度 = Convert.ToUInt16((string)jObject["长度"]); } } #endregion #region 接口实现 public override void Start(MoPlcInfo _plcInfo, List _dataPoints) { plcInfo = _plcInfo; config = new ModbusTcpConfig(plcInfo.LinkConfig); timer.Interval = config.TIMER; timer.Elapsed += timer_Elapsed; timer.AutoReset = false; // PLC未连接状态 SetRedisPlcDisConnect(); // 创建PLC数据点表 CreateDataPointList(_dataPoints); // 初始化自定义函数 actionStart(); // 启动时尝试连接一次设备 Connect(); // 启动定时器 timerStopped = false; timer.Start(); } /// /// PLC连接状态 /// public override bool isConnected() { return isConnect; } protected override bool Connect() { tcpClient = new TcpClient { ReceiveTimeout = 1000 }; tcpClient.Connect(config.IP, config.PORT); master = ModbusIpMaster.CreateIp(tcpClient); SetRedisPlcConnected(); LogHelper.log.Info("已连接到Modbus TCP: " + config.IP); isConnect = true; actionConnected(); return isConnected(); } protected override void Disconnect() { if (tcpClient != null) tcpClient.Close(); isConnect = false; if (master != null) master.Dispose(); SetRedisPlcDisConnect(); } protected void CreateDataPointList(List dataPoints) { if (redis == null) redis = new RedisHelper(); Type t = this.GetType(); foreach (MoDataPoint dataPoint in dataPoints) { ModbusDataPointInfo dataPointInfo = new ModbusDataPointInfo(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; } ModbusDataPointInfo pointInfo = allPoints[dataPointName]; return Read(pointInfo, out value); } public bool Read(ModbusDataPointInfo pointInfo, out object value) { bool[] coilsBuffer; //线圈数组 ushort[] registerBuffer; // 寄存器数组 value = (Decimal)0; string binary = ""; try { if (pointInfo.类型 == "BOOL") { coilsBuffer = master.ReadCoils(pointInfo.站号, pointInfo.地址, pointInfo.长度); for (int i = 0; i < coilsBuffer.Length; i++) { value = (Decimal)value * 2 + (coilsBuffer[i] ? 1 : 0); binary += coilsBuffer[i] ? "1" : "0"; } UpdataRedisDataPoint(pointInfo.mo, binary); } else { registerBuffer = master.ReadHoldingRegisters(pointInfo.站号, pointInfo.地址, pointInfo.长度); for (int i = 0; i < registerBuffer.Length; i++) { value = (Decimal)value * 256 + registerBuffer[i]; } UpdataRedisDataPoint(pointInfo.mo, value.ToString()); } return true; } catch (Exception ex) { LogHelper.log.Error("读取Modbus(" + config.IP + ")信号(" + pointInfo.mo.DataPointName + ")发生异常:" + ex.Message); Disconnect(); return false; } } #endregion } }