123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- 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 数据定义
- /// <summary>
- /// OPCServer Object
- /// </summary>
- OPCServer KepServer;
- /// <summary>
- /// OPCGroup Object
- /// </summary>
- OPCGroup KepGroupAll;
- /// <summary>
- /// OPCGroup Object
- /// </summary>
- OPCGroup KepGroupSubscribe;
- /// <summary>
- /// OPCItems Object
- /// 客户端句柄
- /// </summary>
- int itmHandleClient = 1234;
- /// <summary>
- /// OPC点表
- /// </summary>
- List<MoDataPoint> opcPointList;
- /// <summary>
- /// 数据节点字典 key-变量名称, value-节点信息
- /// </summary>
- protected Dictionary<string, OpcDataPointInfo> allPoints = new Dictionary<string, OpcDataPointInfo>();
- /// <summary>
- /// 监控节点列表
- /// </summary>
- protected Dictionary<int, OpcDataPointInfo> monitorPoints = new Dictionary<int, OpcDataPointInfo>();
- #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<MoDataPoint> _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();
- }
- /// <summary>
- /// 创建组
- /// </summary>
- 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<BlDataGroup>.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 读写操作
- /// <summary>
- /// 每当项数据有变化时执行的事件
- /// </summary>
- /// <param name="TransactionID">处理ID</param>
- /// <param name="NumItems">项个数</param>
- /// <param name="ClientHandles">项客户端句柄</param>
- /// <param name="ItemValues">TAG值</param>
- /// <param name="Qualities">品质</param>
- /// <param name="TimeStamps">时间戳</param>
- 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 });
- }
- }
- /// <summary>
- /// 写入OPC变量
- /// </summary>
- 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;
- }
- }
- /// <summary>
- /// 读取OPC变量
- /// </summary>
- 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
- }
- }
|