using System; using System.Collections.Generic; using System.Reflection; using ProjectBase.Data.Logs; using ProjectBase.Data.Redis; using SIMDP.Model; using Opc.Ua; using OpcUaHelper; using Opc.Ua.Client.Controls; using Newtonsoft.Json.Linq; namespace SIMDP.Device { public class PlcOpcUA : AbstractBaseDevice { #region 数据定义 protected OpcUaClient m_OpcUaClient; protected string Address = ""; protected Dictionary allPoints = new Dictionary(); protected List monitorPoints = new List(); #endregion #region TYPE定义 public enum VarType { Bit = 1, Byte = 2, Int = 3, Word = 4, DInt = 5, DWord = 6, Real = 7, LReal = 8, String = 9 } public class OpcUaConfig { public OpcUaConfig(string json) {//"opc.tcp://DESKTOP-PA2AC31:53530/OPCUA/SimulationServer" JObject jObject = JObject.Parse(json); JToken token = jObject["Address"]; if (token != null) Address = (string)token; token = jObject["Timer"]; if (token != null) TIMER = Convert.ToDouble(token.ToString()); } public string Address { get; set; } public double TIMER { get; set; } = 1000; } public class OpcDataPointInfo { // 节点配置信息 public MoDataPoint mo; public string Tag { get; set; }//标签 例子:"ns=3;i=1008" public VarType TYPE { get; set; } public object value = null; public MethodInfo proc = null; public OpcDataPointInfo(MoDataPoint _mo) { mo = _mo; Tag = mo.DataPointSource; TYPE = getVarTypeByDataPointType(mo.DataPointType); } VarType getVarTypeByDataPointType(long type) {//常用的1、5、9 1bool 5double 9string 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 == 8) return VarType.LReal; else if (type == 9) return VarType.String; else return VarType.Bit; } } #endregion #region 接口实现 public override void Start(MoPlcInfo _plcInfo, List _dataPoints) { plcInfo = _plcInfo; OpcUaConfig plcConfig = new OpcUaConfig(plcInfo.LinkConfig); m_OpcUaClient = new OpcUaClient(); m_OpcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken()); Address = plcConfig.Address; timer.Interval = plcConfig.TIMER; timer.Elapsed += timer_Elapsed; timer.AutoReset = false; // PLC未连接状态 SetRedisPlcDisConnect(); // 创建PLC数据点表 CreateDataPointList(_dataPoints); // 初始化自定义函数 actionStart(); // 启动时尝试连接一次设备 Connect(); // 启动定时器 timerStopped = false; timer.Start(); } public override void Stop() { actionStop(); timerStopped = true; } public override bool isConnected() { return m_OpcUaClient.Connected; } protected override bool Connect() { try { m_OpcUaClient.ConnectServer(Address); } catch (Exception ex) { ClientUtils.HandleException("Connected Failed", ex); } if (m_OpcUaClient.Connected) { LogHelper.log.Info("已连接到OPC:" + m_OpcUaClient.OpcUaName); SetRedisPlcConnected(); actionConnected(); return true; } else { LogHelper.log.Warn("未能连接到OPC,状态:" + m_OpcUaClient.Connected.ToString()); SetRedisPlcDisConnect(); return false; } } protected override void Disconnect() { if (m_OpcUaClient != null) m_OpcUaClient.Disconnect(); SetRedisPlcDisConnect(); } void CreateDataPointList(List dataPoints) { if (redis == null) redis = new RedisHelper(); Type t = this.GetType(); foreach (MoDataPoint dataPoint in dataPoints) { OpcDataPointInfo dataPointInfo = new OpcDataPointInfo(dataPoint); allPoints.Add(dataPoint.DataPointName, dataPointInfo); redis.SetString(dataPoint.DataPointId.ToString() + dataPoint.DataPointName, ""); // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑 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; } OpcDataPointInfo p = allPoints[dataPointName]; return Read(p, out value); } public bool Read(OpcDataPointInfo p, out object value) { switch (p.TYPE) { case VarType.Bit: value = Convert.ToBoolean(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.Byte: value = Convert.ToByte(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.Int: value = Convert.ToInt16(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.Word: value = Convert.ToUInt16(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.DInt: value = Convert.ToInt32(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.DWord: value = Convert.ToUInt32(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.Real: value = Convert.ToSingle(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.LReal: value = Convert.ToDouble(m_OpcUaClient.ReadNode(p.Tag)); break; case VarType.String: value = m_OpcUaClient.ReadNode(p.Tag).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; } OpcDataPointInfo p = allPoints[dataPointName]; switch (p.TYPE) { case VarType.Bit: m_OpcUaClient.WriteNode(p.Tag, Convert.ToBoolean(value)); break; case VarType.Byte: m_OpcUaClient.WriteNode(p.Tag, Convert.ToByte(value)); break; case VarType.Int: m_OpcUaClient.WriteNode(p.Tag, Convert.ToInt16(value)); break; case VarType.Word: m_OpcUaClient.WriteNode(p.Tag, Convert.ToUInt16(value)); break; case VarType.DInt: m_OpcUaClient.WriteNode(p.Tag, Convert.ToInt32(value)); break; case VarType.DWord: m_OpcUaClient.WriteNode(p.Tag, Convert.ToUInt32(value)); break; case VarType.Real: m_OpcUaClient.WriteNode(p.Tag, Convert.ToSingle(value)); break; case VarType.LReal: m_OpcUaClient.WriteNode(p.Tag, Convert.ToDouble(value)); break; case VarType.String: m_OpcUaClient.WriteNode(p.Tag, value.ToString()); break; default: return false; } //LogHelper.log.Debug($"PLC信号({dataPointName})写入值:{value.ToString()}"); UpdataRedisDataPoint(p.mo, value.ToString()); return true; } #endregion } }