using System; using System.Collections.Generic; using ProjectBase.Data.Logs; using SIMDP.Model; using System.Timers; using OPCAutomation; using System.Reflection; namespace SIMDP.Device { public class PlcOpcDA : AbstractBaseDevice { #region 数据定义 /// /// OPCServer Object /// OPCServer KepServer; /// /// OPCGroup Object /// OPCGroup KepGroupAll; /// /// OPCGroup Object /// OPCGroup KepGroupSubscribe; /// /// OPCItems Object /// 客户端句柄 /// int itmHandleClient = 1234; /// /// OPC点表 /// List opcPointList; /// /// 数据节点字典 key-变量名称, value-节点信息 /// protected Dictionary allPoints = new Dictionary(); /// /// 监控节点列表 /// protected Dictionary monitorPoints = new Dictionary(); #endregion #region TYPE定义 public class OpcDataPointInfo { // 节点配置信息 public MoDataPoint mo; public OPCItem item; public object value = null; public MethodInfo proc = null; public OpcDataPointInfo(MoDataPoint _mo, OPCItem _item) { mo = _mo; item = _item; } } #endregion #region 接口实现 public override void Start(MoPlcInfo _plcInfo, List _dataPoints) { KepServer = new OPCServer(); plcInfo = _plcInfo; opcPointList = _dataPoints; // PLC未连接状态 SetRedisPlcDisConnect(); // 初始化自定义函数 actionStart(); // 启动时尝试连接一次设备 Connect(); // 启动定时器 timer.Interval = 1000; timerStopped = false; timer.Start(); } public override bool isConnected() { return (KepServer.ServerState == (int)OPCServerState.OPCRunning); } protected override bool Connect() { KepServer.Connect(plcInfo.LinkConfig); if (KepServer.ServerState == (int)OPCServerState.OPCRunning) { LogHelper.log.Info("已连接到OPC:" + KepServer.ServerName); if (CreateGroup()) SetRedisPlcConnected(); else KepServer.Disconnect(); } else //这里你可以根据返回的状态来自定义显示信息,请查看自动化接口API文档 { LogHelper.log.Warn("未能连接到OPC,状态:" + KepServer.ServerState.ToString()); } return isConnected(); } protected override void Disconnect() { if (KepServer != null) KepServer.Disconnect(); SetRedisPlcDisConnect(); } /// /// 创建组 /// public bool CreateGroup() { try { OPCGroups KepGroups = ((IOPCAutoServer)KepServer).OPCGroups; KepGroups.DefaultGroupDeadband = 0; KepGroups.DefaultGroupIsActive = true; KepGroups.DefaultGroupUpdateRate = 500; KepGroupAll = KepGroups.Add("SIMDPOPCGROUP"); // 所有节点组(可读写) KepGroupAll.IsSubscribed = false; KepGroupSubscribe = KepGroups.Add("SIMDPSUBSCRIBE"); // 监控节点组(变更订阅) KepGroupSubscribe.IsSubscribed = true; // 添加节点到OPCGROUP allPoints.Clear(); monitorPoints.Clear(); Type t = this.GetType(); OPCItems KepItems = KepGroupAll.OPCItems; OPCItems KepItemsSubscribe = KepGroupSubscribe.OPCItems; foreach (var mo in opcPointList) { OPCItem KepItem = KepItems.AddItem(mo.DataPointSource, itmHandleClient); OpcDataPointInfo point = new OpcDataPointInfo(mo, KepItem); allPoints.Add(mo.DataPointName, point); //if (BLLFactory.Instance.IsSignalGroupById(mo.DataPointGroupId)) // 不再按照信号组类型区分是否为监控节点,只按照是否有执行逻辑 if (mo.DataProc.Trim() != "") { OPCItem monitorItem = KepItemsSubscribe.AddItem(mo.DataPointSource, itmHandleClient); OpcDataPointInfo monitorPoint = new OpcDataPointInfo(mo, monitorItem); monitorPoint.proc = t.GetMethod(mo.DataProc); monitorPoints.Add(itmHandleClient, monitorPoint); } itmHandleClient++; } KepGroupSubscribe.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange); } catch (Exception err) { LogHelper.log.Error("创建组出现错误:" + err.Message); return false; } return true; } #endregion #region 读写操作 /// /// 每当项数据有变化时执行的事件 /// /// 处理ID /// 项个数 /// 项客户端句柄 /// TAG值 /// 品质 /// 时间戳 void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps) { for (int i = 1; i <= NumItems; i++) { object value = ItemValues.GetValue(i); if (value == null) continue; int iHandle = (int)ClientHandles.GetValue(i); OpcDataPointInfo point; if (!monitorPoints.TryGetValue(iHandle, out point)) continue; // 处理信号 UpdataRedisDataPoint(point.mo, value.ToString(), true); if (point.proc != null) point.proc.Invoke(this, new object[] { value }); } } /// /// 写入OPC变量 /// public bool Write(string dataPointName, object value) { OpcDataPointInfo pointInfo; if (allPoints.TryGetValue(dataPointName, out pointInfo)) { pointInfo.item.Write(value); UpdataRedisDataPoint(pointInfo.mo, value.ToString(), true); return true; } else { LogHelper.log.Error("写入OPC变量错误,未定义变量名:" + dataPointName); return false; } } /// /// 读取OPC变量 /// public bool Read(string dataPointName, out object value) { OpcDataPointInfo pointInfo; if (allPoints.TryGetValue(dataPointName, out pointInfo)) { object quality; object timestamp; pointInfo.item.Read((short)OPCDataSource.OPCDevice, out value, out quality, out timestamp); UpdataRedisDataPoint(pointInfo.mo, value.ToString(), true); return true; } else { LogHelper.log.Error("读取OPC变量错误,未定义变量名:" + dataPointName); value = null; return false; } } #endregion } }