using System;
using System.Collections.Generic;
using System.Text;
using Opc.Ua;
using Opc.Ua.Client;
using System.Threading;
using System.Data;
using DBFactory;
using CommonLib;
using Siemens.OpcUA;
namespace OPCClient
{
    public static class CCommonOPCClient
    {
        private static ushort S7NameSpace = 2;//20151120,默认值是32位系统的值2,64位系统的值是3
        private static Model.MDevice devinfo;
        private static Object thisLock = new Object();
        public static event CUpdateDBEventHandler UpdateDB;
        public static void OnUpdateDB(object sender,CUpdateDBChangeEventArgs e)
        {
            if (UpdateDB != null)
            {
                UpdateDB(sender, e);
            }
        }
        public static DBOperator dbo = CommonClassLib.AppSettings.dbo; //20130510
        
        //20110726
        private static Dictionary<string, int> _connectCount = new Dictionary<string, int>(); 
        //20110726
        public static Dictionary<string, int> ConnectCount
        {
            get { return CCommonOPCClient._connectCount; }
            set { CCommonOPCClient._connectCount = value; }
        }
       
        private static int[] _plcStates=null ;

        public static int[] PlcStates
        {
            get { return CCommonOPCClient._plcStates; }
            //set { CCommonOPCClient._plcStates = value; }
        }
        private static Server m_Server = null;
        private static Siemens.OpcUA.Subscription m_Subscription;
        
        /// <summary>
        /// 20110309订阅的组内标签数据变化事件
        /// </summary>
        /// <param name="subscriptionHandle">客户端句柄</param>
        /// <param name="requestHandle">请求句柄</param>
        /// <param name="values">标签值数组</param>
        public static void OnDataChange(object clientHandle, DataValue value)
        {
            lock (thisLock)
            {
                //根据subscriptionHandle对应设备索引,依据设备种类(不同类型设备通讯数据帧不同)
                //分别处理:完成,报警,光电开关,PLC发起的请求
                int deviceindex = 0;
                try
                {
                    if (clientHandle.ToString().IndexOf("split") >= 0)
                    {
                        deviceindex = System.Convert.ToInt32(clientHandle.ToString().Substring(5));
                    }
                    else
                    {
                        deviceindex = System.Convert.ToInt32(clientHandle);
                    }
                    devinfo = Model.CGetInfo.GetDeviceInfo(deviceindex);
                    if (StatusCode.IsNotGood(value.StatusCode))
                    {
                        if (devinfo == null)
                        {
                            OpcError = string.Format("设备索引{0}在数据库不存在!", clientHandle);

                            return;
                        }
                        //if (value.StatusCode.ToString() == "BadNoCommunication")
                        //{
                        //    CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                        //    CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                        //    CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                        //    StringBuilder[] itemnames = new StringBuilder[1] { new StringBuilder("") };
                        //    itemnames[0].Append(Model.CGeneralFunction.DBGet).Append(".").Append(Convert.ToString(devinfo.Dbw2Address)).Append(",b");
                        //    DataValueCollection dvc= SyncReadAllItemValue(itemnames);
                        //    if (dvc.Count > 0)
                        //    {
                        //        value = dvc[0];
                        //    }
                        //    OpcError = string.Format("{0}所在的PLC已经离线,自动重新读取数据!订阅标签状态:" + value.StatusCode.ToString(), clientHandle);
                        //    //return;
                        //}
                        //触发一个特殊事件提示PLC断开连接
                        if (ConnectCount.ContainsKey(devinfo.S7Connection) == false)//20110726
                        {
                            ConnectCount.Add(devinfo.S7Connection, 0);
                        }
                        
                        OpcError = string.Format("{0}所在的PLC已经离线!订阅标签状态:" + value.StatusCode.ToString(), clientHandle);
                        if (ConnectCount[devinfo.S7Connection] > 3)//20150204
                        {
                            _opcError = "订阅返回数据时:OPC Server没连接到PLC:" + devinfo.S7Connection.ToString() + ",人工确认后进行【PLC初始化】";//20150204
                            return;
                        }
                        ConnectCount[devinfo.S7Connection]++;//20150204
                        return;

                    }

                     ConnectCount[devinfo.S7Connection] = 0;
                    if (clientHandle.ToString().IndexOf("split") >= 0)
                    {
                        Array arr = (Array)value.Value;
                        byte[] GDKG = null;

                        GDKG = new byte[arr.GetLength(0)];
                        Array.Copy(arr, GDKG, arr.GetLength(0));
                        CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, GDKG, null);
                        OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
                    }
                    else
                    {
                        Array arr = (Array)value.Value;
                        byte[] itemnamevalue = new byte[arr.GetLength(0)];
                        Array.Copy(arr, itemnamevalue, arr.GetLength(0));
                        int head = 0;
                        head = itemnamevalue[0];//读写标志
                        CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, null, itemnamevalue);
                        OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);

                    }
                    
                }
                catch (Exception ex)
                {//20120420
                    OpcError = string.Format("OPC服务器订阅事件异常:{0},{1}", ex.Message, ex.StackTrace);
                    
                }
            }
        }

        static private string _PLCconnectionID = "S7 connection_1";//OPC.UA的新写法"ns=2,S7 connection_1.db2.0,b,5"表示:"S7:[S7 connection_1]的db2.DBB0开始5个字节"
        /// <summary>
        /// 建立PLC连接的ID,例如:"S7:[S7 connection_1]"
        /// 或者"S7:[@LOCALSERVER]"
        /// </summary>
        public static string PlcConnectionID
        {
            get { return CCommonOPCClient._PLCconnectionID; }
            set { CCommonOPCClient._PLCconnectionID = value; }
        }
        static private string _opcError;
        static private bool _IfConnectOPCServer=false ;
        static private string _hostname;
        /// <summary>
        /// OPC Server的机器名称或者IP地址
        /// </summary>
        public static string Hostname
        {
            get { return CCommonOPCClient._hostname; }
            set { CCommonOPCClient._hostname = value; }
        }
        static private string _progID;
        /// <summary>
        /// OPC Server的程序标识,例如:OPC.SimaticNET
        /// </summary>
        public static string ProgID
        {
            get { return CCommonOPCClient._progID; }
            set { CCommonOPCClient._progID = value; }
        }
        public static string OpcError
        {
            get { return CCommonOPCClient._opcError; }
            set { 
                CCommonOPCClient._opcError = value; 
                CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(0, null, null);
                OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
                }
        }
        
        /// <summary>
        /// 《设备索引,对应设备订阅》
        /// </summary>
        public static SubscriptionCollection  SubscriptionGroup = new SubscriptionCollection();//定义组对象集合(订阅者集合)//20110309
       
        /// <summary>
        /// 20110309每个设备创建一个订阅和DataChange事件
        /// </summary>
        public static void CreateSubscriptionGroup()
        {
            if (_IfConnectOPCServer == false)
            {
                _hostname = CommonClassLib.AppSettings.GetValue("HostName");
                _progID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                if (ConnectOPCServer(_hostname, _progID) == false) return ;
            }
            DataView dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_ReadSubscription =F_DeviceIndex) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                if (dv.Count < SubscriptionGroup.Count) return;
            }
            DataView dvx;
            #region//20220526注释
            //for (int i = 0; i < dv.Count; i++)
            //{
            //    string dt = DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
            //    dvx = dbo.ExceSQL(string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0})  AND (F_DeviceKindIndex <> 33) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"])).Tables[0].DefaultView;
            //    if (dvx.Count > 0)
            //    {
            //        NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() +"."+
            //            Model.CGeneralFunction.DBGet  +"."+
            //            dv[i]["F_DBW2Address"].ToString() + ",b," +
            //            (System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
                    
            //        // Add the attribute name/value to the list view.
            //        object serverHandle = null;


            //        try
            //        {
            //            // Add the item and apply any changes to it. 
            //            m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);

            //        }
            //        catch (ServiceResultException monitoredItemResult)
            //        {
            //            OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
                        
            //        }

            //    }
            //}
            #endregion

            #region//20220526在创建OPC订阅时候先创建条码扫描器的订阅,之后再创建其余设备类型的订阅
            for (int i = 0; i < dv.Count; i++)
            {
                string dt = string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0})  AND (F_DeviceKindIndex = 7 ) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"]);//DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
                dvx = dbo.ExceSQL(dt).Tables[0].DefaultView;//20220526先创建条码扫描器
                if (dvx.Count > 0)
                {
                    NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
                    Model.CGeneralFunction.DBGet + "." +
                    dv[i]["F_DBW2Address"].ToString() + ",b," +
                    (System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
                    // Add the attribute name/value to the list view.
                    object serverHandle = null;
                    try
                    {
                        // Add the item and apply any changes to it.
                        m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
                    }
                    catch (ServiceResultException monitoredItemResult)
                    {
                        OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
                    }
                }
               
                dvx = dbo.ExceSQL(string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0})  AND (F_DeviceKindIndex <>7 and F_DeviceKindIndex <>33 ) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"])).Tables[0].DefaultView;//20220526后创建非条码扫描器
                if (dvx.Count > 0)
                {
                    NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
                    Model.CGeneralFunction.DBGet + "." +
                    dv[i]["F_DBW2Address"].ToString() + ",b," +
                    (System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
                    // Add the attribute name/value to the list view.
                    object serverHandle = null;
                    try
                    {
                        // Add the item and apply any changes to it.
                        m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
                    }
                    catch (ServiceResultException monitoredItemResult)
                    {
                        OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
                    }
                }
            }

            #endregion
            dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_DeviceKindIndex=33)  ORDER BY F_ReadSubscription").Tables[0].DefaultView;
            
            for (int i = 0; i < dv.Count; i++)
            {
                NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
                       Model.CGeneralFunction.DBGet + "." +
                       dv[i]["F_DBW2Address"].ToString() + ",b," + System.Convert.ToInt32(dv[i]["F_DBWGetLength"]).ToString(), S7NameSpace);//20151120

                // Add the attribute name/value to the list view.
                object serverHandle = null;


                try
                {
                    // Add the item and apply any changes to it. 
                    m_Subscription.AddDataMonitoredItem(nodeId, "split" + dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
                    
                }
                catch (ServiceResultException monitoredItemResult)
                {
                    OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
                }

                
            }
        }
        /// <summary>
        /// 通过设置订阅的监控模式,刷新订阅
        /// </summary>
        /// <returns></returns>
        public static bool RefreshMonitoringMode()
        {//20150103增加断网恢复
            if (m_Subscription != null)
            {
                m_Subscription.RefreshMonitoringMode();
            }
            return true;
        }
        /// <summary>
        /// 连接指定主机的OPC服务器
        /// </summary>
        /// <param name="hostname">主机名称</param>
        /// <param name="ProgID">OPC服务器程序标识例如:"OPC.SimaticNET"</param>
        /// <returns></returns>
        public static bool ConnectOPCServer(string hostname, string ProgID)
        {
            try
            {
                //Uri discoveryUrl = new Uri("opc.tcp://" + hostname + ":4845");
                Uri discoveryUrl = new Uri("opc.tcp://" + hostname);
                Discovery discovery = new Discovery();
                EndpointDescriptionCollection endpoints = null;
                string rr = discovery.GetEndpoints(discoveryUrl, ref endpoints);
                
                for (int i = 0; i < endpoints.Count; i++)
                {
                    if ((endpoints[i].Server.ApplicationName.Text.IndexOf( ProgID)>-1)
                        && (endpoints[i].SecurityMode == MessageSecurityMode.None))//20151120
                    {
                        m_Server = new Server();
                        m_Server.CertificateEvent += new certificateValidation(m_Server_CertificateEvent);
                        m_Server.Connect(endpoints[i]);
                        _IfConnectOPCServer = true;
                        if (m_Subscription == null)
                        {
                            m_Subscription = m_Server.AddSubscription(100);
                        }
                        #region 自动读取“S7:”的命名空间索引//20151120
                        
                        DataValueCollection m_currentValues;
                        NodeId nodeId=new NodeId(2255);
                        NodeIdCollection nodesToRead = new NodeIdCollection(1);
                        nodesToRead.Add(nodeId);
                        m_Server.ReadValues(nodesToRead, out m_currentValues);
                        if (m_currentValues.Count > 0)
                        {
                            string[] arr;
                            arr =(string[]) m_currentValues[0].Value;
                            S7NameSpace =(ushort) Array.IndexOf(arr, "S7:");

                        }
                        #endregion

                        return true;
                        
                    }
                   
                }
                OpcError = "连接OPC数据存取服务器时:配置项OPCProgID和HostName不准确!";
                _IfConnectOPCServer = false;
                return false;
                
                
            }
            catch (Exception ex)
            {
                OpcError = "连接OPC数据存取服务器时:" + ex.Message;
                _IfConnectOPCServer = false;
                return false;
            }
            
        }
        public static DataValueCollection SyncReadAllItemValue(StringBuilder[] itemnames)
        {
            DataValueCollection m_currentValues;
            if (_IfConnectOPCServer == false)
            {
                if (ConnectOPCServer(_hostname, _progID) == false) return null;
            }
            if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
            {
                ConnectCount.Add(_PLCconnectionID, 0);
            }
            if (ConnectCount[_PLCconnectionID] > 3)//20150204
            {
                _opcError = "读数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
                return null;
            }
            NodeIdCollection nodesToRead = new NodeIdCollection(itemnames.GetLength(0));

            foreach (StringBuilder item in itemnames)
            {
                // NodeIds.
                String sNodeId = _PLCconnectionID + "." + item.ToString();
                NodeId nodeId = new NodeId(sNodeId,S7NameSpace);//20151120
                nodesToRead.Add(nodeId);
            }

            // Call to ClientAPI.
            m_Server.ReadValues(
                nodesToRead,
                out m_currentValues);
            return m_currentValues;
        }
        public static bool SyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalues)
        {
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return false;
                }
                if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
                {
                    ConnectCount.Add(_PLCconnectionID, 0);
                }
                if (ConnectCount[_PLCconnectionID] > 3)//20150204
                {
                    _opcError = "写数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
                    return false;
                }
                NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
                DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
                StatusCodeCollection results = null;
                int i = 0;

                foreach (StringBuilder  item in itemnames)
                {
                    // Values to write.
                    String sValue = itemvalues[i].ToString();

                    // Leave current value if write value is empty.
                    if (sValue.Length == 0)
                    {
                        i++;
                        continue;
                    }
                    #region win7等64位操作系统需要指定确切的数据类型//20151120

                    Type gt = typeof(byte);
                    if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
                    {
                        gt = typeof(byte);
                    }
                    else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
                    {
                        gt = typeof(short);
                    }
                    else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
                    {
                        gt = typeof(ushort);
                    }
                    else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
                    {
                        gt = typeof(int);
                    }
                    else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
                    {
                        gt = typeof(uint);
                    }
                    else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
                    {
                        gt = typeof(DateTime);
                    }
                    
                    Variant variant = new Variant(Convert.ChangeType(sValue, gt));
                    #endregion

                    DataValue value = new DataValue(variant);
                    values.Add(value);

                    // NodeIds.
                    String sNodeId =_PLCconnectionID+"."+ item.ToString();
                    NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
                    nodesToWrite.Add(nodeId);

                    i++;
                }

                // Call to ClientAPI.
                m_Server.WriteValues(
                    nodesToWrite,
                    values,
                    out results);
                int ia = 0;//richard.liu20141110
                foreach (StatusCode sc in results)
                {//richard.liu20141110
                    if (sc.Code != StatusCodes.Good)
                    {
                        ConnectCount[_PLCconnectionID]++;//20150204
                        OpcError = "向OPC数据存取服务器写数据时:WriteValues:" + nodesToWrite[ia].ToString() + "的返回值有错误!"+sc.ToString();
                        return false;
                    }
                    ia++;
                }
                ConnectCount[_PLCconnectionID] = 0;//20150204
                return true;    
            }
            catch (Exception ex)
            {
                ConnectCount[_PLCconnectionID]++;//20150204
                OpcError = "向OPC数据存取服务器写数据时:" + ex.Message;
                _IfConnectOPCServer = false;
                return false;
            }
        }

        #region 20220518 zb 异步写入数据
        public static bool ASyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalues)
        {
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return false;
                }
                if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
                {
                    ConnectCount.Add(_PLCconnectionID, 0);
                }
                if (ConnectCount[_PLCconnectionID] > 3)//20150204
                {
                    _opcError = "写数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
                    return false;
                }
                NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
                DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
                StatusCodeCollection results = null;
                int i = 0;

                foreach (StringBuilder item in itemnames)
                {
                    // Values to write.
                    String sValue = itemvalues[i].ToString();

                    // Leave current value if write value is empty.
                    if (sValue.Length == 0)
                    {
                        i++;
                        continue;
                    }
                    #region win7等64位操作系统需要指定确切的数据类型//20151120

                    Type gt = typeof(byte);
                    if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
                    {
                        gt = typeof(byte);
                    }
                    else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
                    {
                        gt = typeof(short);
                    }
                    else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
                    {
                        gt = typeof(ushort);
                    }
                    else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
                    {
                        gt = typeof(int);
                    }
                    else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
                    {
                        gt = typeof(uint);
                    }
                    else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
                    {
                        gt = typeof(DateTime);
                    }

                    Variant variant = new Variant(Convert.ChangeType(sValue, gt));
                    #endregion

                    DataValue value = new DataValue(variant);
                    values.Add(value);

                    // NodeIds.
                    String sNodeId = _PLCconnectionID + "." + item.ToString();
                    NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
                    nodesToWrite.Add(nodeId);

                    i++;
                }

                // 20220518 Call to ClientAPI.
                m_Server.AsyWriteValues(
                    nodesToWrite,
                    values,
                    out results);
                // 异步调用不需要判断返回值
                //int ia = 0;//richard.liu20141110
                //foreach (StatusCode sc in results)
                //{//richard.liu20141110
                //    if (sc.Code != StatusCodes.Good)
                //    {
                //        ConnectCount[_PLCconnectionID]++;//20150204
                //        OpcError = "向OPC数据存取服务器写数据时:WriteValues:" + nodesToWrite[ia].ToString() + "的返回值有错误!" + sc.ToString();
                //        return false;
                //    }
                //    ia++;
                //}
                ConnectCount[_PLCconnectionID] = 0;//20150204
                return true;
            }
            catch (Exception ex)
            {
                ConnectCount[_PLCconnectionID]++;//20150204
                OpcError = "向OPC数据存取服务器写数据时:" + ex.Message;
                _IfConnectOPCServer = false;
                return false;
            }
        }
        #endregion

        /// <summary>
        /// 获得设备类型索引
        /// </summary>
        /// <param name="devIdx">设备索引</param>
        /// <returns>设备类型索引</returns>
        static int GetDeviceKindIdx(int devIdx)
        {
            System.Object lockThis = new System.Object();
            lock (lockThis)
            {
                try
                {

                    DataView dv= dbo.ExceSQL(string.Format("SELECT F_DeviceKindIndex FROM T_Base_Device WHERE F_DeviceIndex={0}", devIdx)).Tables[0].DefaultView;
                    if (dv.Count > 0)
                    {
                        return System.Convert.ToInt32(dv[0]["F_DeviceKindIndex"]);
                    }
                    else
                        return 0;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
        public static void DisConnectOPCServer()
        {
            try
            {
                int result;
                if (m_Server == null) return;


                result = m_Server.Disconnect();

                // Disconnect succeeded.
                if (result == 0)
                {
                    m_Subscription.RemoveAllMonitoredItems();//20150103增加断网恢复
                    m_Server.RemoveSubscription(m_Subscription);
                    m_Subscription = null;
                }
                _IfConnectOPCServer = false;//20140514张博在山东电力发现此问题
            }
            catch (Exception ex)
            {
                OpcError = "关闭OPC数据存取服务器时:" + ex.Message;
            }
        }
        static void m_Server_CertificateEvent(CertificateValidator validator, CertificateValidationEventArgs e)
        {
            e.Accept = true;
            
        }
    }
}