123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using NX_CommonClassLibrary;
- using NX_LogClassLibrary;
- using NX_ModelClassLibrary.BaseModel;
- using NX_ModelClassLibrary.CustomEnum;
- using NX_ModelClassLibrary.CustomEvent;
- using NX_ModelClassLibrary.OpcModel;
- using NX_WcsDal.CommonBusiness;
- using Opc.Ua;
- using Opc.Ua.Client;
- using Opc.Ua.Configuration;
- using OpcUaHelper;
- namespace NX_OpcUaClientLibrary
- {
- /// <summary>
- /// OpcUa客户端帮助类
- /// 基于OPC基金会开源的.net版本OPCUA客户端项目的二次封装
- /// Copyright20210125 (C) sunyalong
- /// 允许修改、添加满足自己项目的需要。
- /// 添加、修改后请详细注释。违者会强制删除不予采用。
- /// </summary>
- public class LeadOpcUaClientHelper
- {
- #region 单例模式
- /// <summary>
- /// 单例模式对象
- /// </summary>
- private static LeadOpcUaClientHelper _instance = null;
- private static readonly object lockObj = new object();
- /// <summary>
- /// 单例模式方法
- /// </summary>
- public static LeadOpcUaClientHelper Instance
- {
- get
- {
- if (_instance == null)
- {
- lock (lockObj)
- {
- if (_instance == null)
- {
- _instance = new LeadOpcUaClientHelper();
- }
- }
- }
- return _instance;
- }
- }
- #endregion
- #region 全局变量
- /// <summary>
- /// 日志显示帮助类对象
- /// </summary>
- public ShowLogToFrmHelper showLogToFrm = new ShowLogToFrmHelper();
- /// <summary>
- /// 日志头部
- /// </summary>
- private readonly string LogHeadText = "OpcUa客户端帮助类 ==>> ";
- /// <summary>
- /// OPCUA客户端列表
- /// </summary>
- private ConcurrentDictionary<BasWcsPlcMd, OpcUaClient> opcUaClientLst = new ConcurrentDictionary<BasWcsPlcMd, OpcUaClient>();
- /// <summary>
- /// 所有设备OPCItem变量信息列表
- /// </summary>
- public List<WcsOpcItemMd> allOpcItemList;
- #region 2021 0602 孙亚龙注释掉旧版代码
- ///// <summary>
- ///// 堆垛机OpcUa客户端
- ///// </summary>
- //private OpcUaClient crn_OpcUaClient;
- ///// <summary>
- ///// 输送线OpcUa客户端
- ///// </summary>
- //private OpcUaClient tran_OpcUaClient;
- ///// <summary>
- ///// 堆垛机OPC UA服务器地址
- ///// </summary>
- //private readonly string CrnOpcUaServerIpAddress = AppConfigHelper.Get("CrnOpcUaServerIpAddress");
- ///// <summary>
- ///// 输送线OPC UA服务器地址
- ///// </summary>
- //private readonly string TranOpcUaServerIpAddress = AppConfigHelper.Get("TranOpcUaServerIpAddress");
- ///// <summary>
- ///// 堆垛机OPC UA服务器连接状态
- ///// </summary>
- //private bool CrnOpcUaServerConnStatus = false;
- ///// <summary>
- ///// 输送线OPC UA服务器连接状态
- ///// </summary>
- //private bool TranOpcUaServerConnStatus = false;
- #endregion 2021 0602 孙亚龙注释掉旧版代码
- #endregion
- /// <summary>
- /// 连接所有PLC的OPCUa服务器,并设置PLC的OPCItem变量为订阅模式。
- /// </summary>
- /// <param name="basWcsPlcMdList">WCS涉及的所有PLC信息列表</param>
- /// <returns></returns>
- public bool ConnAllOpcUaServer(List<BasWcsPlcMd> basWcsPlcMdList)
- {
- try
- {
- foreach (BasWcsPlcMd item in basWcsPlcMdList)
- {
- if (opcUaClientLst.TryAdd(item, new OpcUaClient { UserIdentity = new UserIdentity("Administrator", "123456") }))
- {
- opcUaClientLst[item].ConnectServer(item.IpAddr);
- ShowLogToForm($"OpcUa客户端连接OpcUa服务器成功!IP地址:【{item.IpAddr}】", true, LogTypeEnum.Run);
- }
- }
- foreach (var item in opcUaClientLst)
- {
- string[] MonitorNodeTagArr = allOpcItemList.FindAll(x => x.PlcCode == item.Key.PlcCode).Select(x => x.OpcItemPos).ToArray();
- item.Value.AddSubscription(item.Key.PlcCode, MonitorNodeTagArr, SubCallback);
- ShowLogToForm($"OpcUa客户端设置OpcItem订阅模式成功!IP地址:【{item.Key.IpAddr}】", true, LogTypeEnum.Run);
- }
- return true;
- }
- catch (Exception ex)
- {
- ShowLogToForm($"OpcUa客户端连接OpcUa服务器发生异常:【{ex.Message}】!", true, LogTypeEnum.Err);
- return false;
- }
- }
- #region 2021 0602 孙亚龙注释掉旧版代码
- //public async Task<bool> ConnCrnOpcUaServer()
- //{
- // try
- // {
- // crn_OpcUaClient = new OpcUaClient
- // {
- // UserIdentity = new UserIdentity("Administrator", "123456")
- // };
- // await crn_OpcUaClient.ConnectServer(CrnOpcUaServerIpAddress);
- // ShowLogToForm($"堆垛机OpcUa客户端连接Opc服务器成功!IP地址:【{CrnOpcUaServerIpAddress}】", true, LogTypeEnum.Run);
- // CrnOpcUaServerConnStatus = true;
- // return true;
- // }
- // catch (Exception ex)
- // {
- // ShowLogToForm($"堆垛机OpcUa客户端连接Opc服务器发生异常:【{ex.Message}】!IP地址:【{CrnOpcUaServerIpAddress}】", true, LogTypeEnum.Err);
- // CrnOpcUaServerConnStatus = false;
- // return false;
- // }
- //}
- //public async Task<bool> ConnTranOpcUaServer()
- //{
- // try
- // {
- // tran_OpcUaClient = new OpcUaClient
- // {
- // UserIdentity = new UserIdentity("Administrator", "123456")
- // };
- // await tran_OpcUaClient.ConnectServer(TranOpcUaServerIpAddress);
- // ShowLogToForm($"输送线OpcUa客户端连接Opc服务器成功!IP地址:【{TranOpcUaServerIpAddress}】", true, LogTypeEnum.Run);
- // TranOpcUaServerConnStatus = true;
- // return true;
- // }
- // catch (Exception ex)
- // {
- // ShowLogToForm($"输送线OpcUa客户端连接Opc服务器发生异常:【{ex.Message}】!IP地址:【{TranOpcUaServerIpAddress}】", true, LogTypeEnum.Err);
- // TranOpcUaServerConnStatus = false;
- // return false;
- // }
- //}
- //public bool SetOpcItemSubscription()
- //{
- // try
- // {
- // List<string> MonitorNodeTags_Crn = new List<string>();
- // List<string> MonitorNodeTags_Tran = new List<string>();
- // foreach (WcsOpcItemMd item in allOpcItemList)
- // {
- // if (item.PlcCode == "CrnPlc001")
- // {
- // MonitorNodeTags_Crn.Add(item.OpcItemPos);
- // }
- // if (item.PlcCode == "TranPlc001")
- // {
- // MonitorNodeTags_Tran.Add(item.OpcItemPos);
- // }
- // }
- // crn_OpcUaClient.AddSubscription("Crn", MonitorNodeTags_Crn.ToArray(), SubCallback);
- // ShowLogToForm($"堆垛机设置OpcItem订阅模式成功!", true, LogTypeEnum.Run);
- // tran_OpcUaClient.AddSubscription("Tran", MonitorNodeTags_Tran.ToArray(), SubCallback);
- // ShowLogToForm($"输送线设置OpcItem订阅模式成功!", true, LogTypeEnum.Run);
- // return true;
- // }
- // catch (Exception ex)
- // {
- // ShowLogToForm($"堆垛机设置OpcItem订阅模式发生异常:【{ex.Message}】!", true, LogTypeEnum.Err);
- // ShowLogToForm($"输送线设置OpcItem订阅模式发生异常:【{ex.Message}】!", true, LogTypeEnum.Err);
- // return false;
- // }
- //}
- #endregion 2021 0602 孙亚龙注释掉旧版代码
- private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args)
- {
- MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- WcsOpcItemMd tmpMonitoredOpcItem = allOpcItemList.FirstOrDefault(x => x.OpcItemPos == monitoredItem.StartNodeId.ToString() && x.PlcCode == key);
- if (tmpMonitoredOpcItem != null)
- {
- tmpMonitoredOpcItem.OpcItemValue = notification.Value.WrappedValue.Value.ToString();
- Task.Run(() => {
- BasCommon_Dal.Instance.UpdateOpcItemMonitorToDataBase(tmpMonitoredOpcItem);
- });
- }
- #region 2021 0602 孙亚龙注释掉旧版代码
- //if (key == "Crn")
- //{
- // MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- // WcsOpcItemMd tmpMonitoredOpcItem = allOpcItemList.FirstOrDefault(x => x.OpcItemPos == monitoredItem.StartNodeId.ToString() && x.PlcCode == "CrnPlc001");
- // if (tmpMonitoredOpcItem != null)
- // {
- // tmpMonitoredOpcItem.OpcItemValue = notification.Value.WrappedValue.Value.ToString();
- // Task.Run(() =>
- // {
- // BasCommon_Dal.Instance.UpdateOpcItemMonitorToDataBase(tmpMonitoredOpcItem);
- // });
- // }
- //}
- //else if (key == "Tran")
- //{
- // MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- // WcsOpcItemMd tmpMonitoredOpcItem = allOpcItemList.FirstOrDefault(x => x.OpcItemPos == monitoredItem.StartNodeId.ToString() && x.PlcCode == "TranPlc001");
- // if (tmpMonitoredOpcItem != null)
- // {
- // tmpMonitoredOpcItem.OpcItemValue = notification.Value.WrappedValue.Value.ToString();
- // Task.Run(() =>
- // {
- // BasCommon_Dal.Instance.UpdateOpcItemMonitorToDataBase(tmpMonitoredOpcItem);
- // });
- // }
- //}
- #endregion 2021 0602 孙亚龙注释掉旧版代码
- }
- /// <summary>
- /// 写入OPC变量值
- /// </summary>
- /// <param name="wcsOpcItemMd">opc变量对象</param>
- /// <param name="value">写入值</param>
- /// <returns></returns>
- public bool WriteOpcItemValue(WcsOpcItemMd wcsOpcItemMd, object value)
- {
- try
- {
- OpcUaClient tmpOpcUaClient = opcUaClientLst.Where(x => x.Key.PlcCode == wcsOpcItemMd.PlcCode).FirstOrDefault().Value;
- switch (wcsOpcItemMd.PlcItemDataType)
- {
- case 1:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt32(value));
- case 2:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value.ToString());
- case 3:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToBoolean(value));
- case 4:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToDouble(value));
- case 5:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt16(value));
- case 6:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToByte(value));
- default:
- return tmpOpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value);
- }
- #region 孙亚龙 20210602 注释旧版代码
- //if (wcsOpcItemMd.PlcCode == "CrnPlc001")
- //{
- // switch (wcsOpcItemMd.PlcItemDataType)
- // {
- // case 1:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt32(value));
- // case 2:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value.ToString());
- // case 3:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToBoolean(value));
- // case 4:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToDouble(value));
- // case 5:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt16(value));
- // case 6:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToByte(value));
- // default:
- // return crn_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value);
- // }
- //}
- //if (wcsOpcItemMd.PlcCode == "TranPlc001")
- //{
- // switch (wcsOpcItemMd.PlcItemDataType)
- // {
- // case 1:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt32(value));
- // case 2:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value.ToString());
- // case 3:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToBoolean(value));
- // case 4:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToDouble(value));
- // case 5:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToInt16(value));
- // case 6:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, Convert.ToByte(value));
- // default:
- // return tran_OpcUaClient.WriteNode(wcsOpcItemMd.OpcItemPos, value);
- // }
- //}
- #endregion
- }
- catch(Exception ex)
- {
- ShowLogToForm($"OpcItem变量写入发生异常:【{ex.Message}】!设备名称:【{wcsOpcItemMd.DevName}】PLC:【{wcsOpcItemMd.PlcName}】OPC变量:【{wcsOpcItemMd.OpcItemCode}】变量OPC地址:【{wcsOpcItemMd.OpcItemPos}】写入值:【{value}】", true, LogTypeEnum.Err);
- return false;
- }
- }
- public void CloseConnect()
- {
- foreach (var item in opcUaClientLst)
- {
- item.Value.Disconnect();
- }
- #region 孙亚龙 20210602 注释旧版代码
- //if (CrnOpcUaServerConnStatus)
- //{
- // crn_OpcUaClient.Disconnect();
- //}
- //if (TranOpcUaServerConnStatus)
- //{
- // tran_OpcUaClient.Disconnect();
- //}
- #endregion
- }
- #region 桌面显示Log、记录log到文本
- /// <summary>
- /// 桌面显示Log、记录log到文本
- /// </summary>
- /// <param name="msg">log内容</param>
- /// <param name="isShowFormFlag">是否输出到桌面日志端。true:输出桌面;false:只记录文本</param>
- /// <param name="logTypeEnum">日志类型枚举</param>
- private void ShowLogToForm(string msg, bool isShowFormFlag, LogTypeEnum logTypeEnum)
- {
- if (isShowFormFlag)
- {
- showLogToFrm.ShowLog(new ShowLogToFrmEventArgs(LogHeadText + msg));
- }
- LogHelper.WriteLog(LogHeadText + msg, logTypeEnum);
- }
- #endregion
- }
- }
|