123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- using System;
- using System.Timers;
- using System.IO.Ports;
- using System.Collections.Generic;
- using Newtonsoft.Json.Linq;
- using ProjectBase.Data.Logs;
- using ProjectBase.Data.Redis;
- using Modbus.Device;
- using SIMDP.Model;
- using ProjectBase.Util;
- using System.Linq;
- using System.Reflection;
- namespace SIMDP.Device
- {
- public class ModbusRtu : AbstractBaseDevice
- {
- #region 数据定义
- /// <summary>
- /// Modbus对象
- /// </summary>
- protected IModbusMaster master;
- /// <summary>
- /// 串口对象
- /// </summary>
- protected SerialPort port;
- /// <summary>
- /// 数据节点字典 key-变量名称, value-节点信息
- /// </summary>
- protected Dictionary<string, ModbusDataPointInfo> allPoints = new Dictionary<string, ModbusDataPointInfo>();
- /// <summary>
- /// 监控节点列表
- /// </summary>
- protected List<ModbusDataPointInfo> monitorPoints = new List<ModbusDataPointInfo>();
- /// <summary>
- /// 连接状态
- /// </summary>
- protected bool isConnect = false;
- #endregion
- #region TYPE定义
- public class ModbusRtuConfig
- {
- public ModbusRtuConfig(string json)
- {
- JObject jObject = JObject.Parse(json);
- JToken token;
- if ((token = jObject["PORT"]) != null)
- PORT = (string)token;
- if ((token = jObject["baudRate"]) != null)
- baudRate = (int)token;
- if ((token = jObject["parity"]) != null)
- parity = (Parity)(int)token;
- if ((token = jObject["dataBits"]) != null)
- dataBits = (int)token;
- if ((token = jObject["stopBits"]) != null)
- stopBits = (StopBits)(int)token;
- if ((token = jObject["TIMER"]) != null)
- TIMER = (double)token;
- }
- // 串口属性
- public string PORT { get; set; } = "COM1";
- public int baudRate { get; set; } = 9600;
- public Parity parity { get; set; } = Parity.None;
- public int dataBits { get; set; } = 8;
- public StopBits stopBits { get; set; } = StopBits.One;
- // 轮询时间
- public double TIMER { get; set; } = 500;
- }
- 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<MoDataPoint> _dataPoints)
- {
- plcInfo = _plcInfo;
- ModbusRtuConfig config = new ModbusRtuConfig(plcInfo.LinkConfig);
- port = new SerialPort(config.PORT, config.baudRate, config.parity, config.dataBits, config.stopBits);
- port.ReadTimeout = 1000;
- timer.Interval = config.TIMER;
- timer.Elapsed += timer_Elapsed;
- timer.AutoReset = false;
- // PLC未连接状态
- SetRedisPlcDisConnect();
- // 创建PLC数据点表
- CreateDataPointList(_dataPoints);
- // 初始化自定义函数
- actionStart();
- // 启动时尝试连接一次设备
- Connect();
- // 启动定时器
- timerStopped = false;
- timer.Start();
- }
- public override bool isConnected()
- {
- return isConnect;
- }
- protected override bool Connect()
- {
- master = ModbusSerialMaster.CreateRtu(port);
- port.Open();
- port.Close();
- SetRedisPlcConnected();
- LogHelper.log.Info("已连接到Modbus RTU: " + port.PortName);
- isConnect = true;
- return isConnected();
- }
- protected override void Disconnect()
- {
- if (port.IsOpen)
- port.Close();
- isConnect = false;
- if (master != null)
- master.Dispose();
- SetRedisPlcDisConnect();
- }
- protected void CreateDataPointList(List<MoDataPoint> 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<BlDataGroup>.Instance.IsSignalGroupById(dataPoint.DataPointGroupId))
- // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑
- if (dataPoint.DataProc.Trim() != "")
- {
- dataPointInfo.proc = t.GetMethod(dataPoint.DataProc);
- monitorPoints.Add(dataPointInfo);
- }
- }
- }
- #endregion
- #region 读写操作
- /// <summary>
- /// 读取寄存器数据
- /// </summary>
- 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;
- 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);
- }
- }
- 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(" + port.PortName + ")信号(" + pointInfo.mo.DataPointName + ")发生异常:" + ex.Message);
- Disconnect();
- return false;
- }
- }
- #endregion
- }
- }
|