using Opc;
using Opc.Da;
using RGD.Common;
using RGD.DataService;
using System;
using System.Collections.Generic;
using System.Text;

namespace RGD.OPCClient
{
    public static class CCommonOPCClient
    {
        //声明委托
        public delegate void WimFrmNotify(int[] _RRword);

        //定义一个委托变量
        public static WimFrmNotify _notifyer;

        //public static DBOperator dbo = new DBOperator();
        private static RGD.Model.MDevice devinfo28;

        private static int _connectCount = 0;

        public static int ConnectCount
        {
            get { return CCommonOPCClient._connectCount; }
            set
            {
                if (value == 0)
                {
                    _opcError = "";
                }
                CCommonOPCClient._connectCount = value;
            }
        }

        private static int[] _plcStates;

        public static int[] PlcStates
        {
            get { return CCommonOPCClient._plcStates; }
            //set { CCommonOPCClient._plcStates = value; }
        }

        //对于错误报警、状态信息应该在此建立通用组，并且注册事件，通过值变化检测所有组内的报警信息
        public static void OnDataChange(object subscriptionHandle, object requestHandle, ItemValueResult[] values)
        {
            try
            {
                foreach (ItemValueResult item in values)
                {//处理每一个ItemValueResult
                    if (item.ClientHandle == null)
                    {//服务器发过来的无用信息。
                        continue;
                    }
                    //
                    Array.Copy((Array)item.Value, _plcStates, _plcStates.GetLength(0));
                    StringBuilder sb = new StringBuilder();
                    foreach (int i in _plcStates)
                    {
                        sb.Append(i + ",");
                    }
                    LogUtil.WriteLog("", "OnDataChange回调:" + sb.ToString());
                }

                //kanbl 回调通知
                if (_notifyer != null)
                {
                    if (values.Length <= 0 || values[0].Quality == Quality.Bad)
                    {
                        //kanbl
                        System.Diagnostics.Trace.WriteLine(String.Format("OnDataChange values.Length <= 0 || values[0].Quality == Quality.Bad"));
                        return;
                    }

                    byte[] itemnamevalue = new byte[(int)devinfo28.Dbw2Getlength];

                    Array.Copy((Array)values[0].Value, itemnamevalue, (int)devinfo28.Dbw2Getlength);

                    int[] _RRword = new int[(int)devinfo28.Dbw2Getlength];
                    Array.Copy(itemnamevalue, _RRword, (int)devinfo28.Dbw2Getlength);
                    //调用
                    _notifyer(_RRword);
                }
            }
            catch (Exception ex)
            {
                _opcError = "获取OPC服务器时：" + ex.Message;
            }
        }

        //WriteComplete回调
        public static void OnWriteComplete(object requestHandle, Opc.IdentifiedResult[] values)
        {
            /*Console.WriteLine("发生异步写name:{0},value:{1}", values[0].ItemName, values[0].GetType());
            if ((int)requestHandle == 2)
                Console.WriteLine("事件信号句柄为{0}", requestHandle);*/
        }

        private static string _PLCconnectionID = "S7:[S7 connection_1]";

        /// <summary>
        /// 建立PLC连接的ID，例如："S7:[S7 connection_1]"
        /// 或者"S7:[@LOCALSERVER]"
        /// </summary>
        public static string PlcConnectionID
        {
            get { return CCommonOPCClient._PLCconnectionID; }
            set { CCommonOPCClient._PLCconnectionID = value; }
        }

        private static string _opcError;
        private static bool _IfConnectOPCServer = false;
        private static string _hostname;

        /// <summary>
        /// OPC Server的机器名称或者IP地址
        /// </summary>
        public static string Hostname
        {
            get { return CCommonOPCClient._hostname; }
            set { CCommonOPCClient._hostname = value; }
        }

        private static 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; }
        }

        private static Opc.Da.Server m_server = null;//定义数据存取服务器
        private static Opc.Server[] servers;
        private static Opc.Da.Subscription subscription = null;//定义组对象（订阅者）
        private static Opc.Da.SubscriptionState state = null;//定义组（订阅者）状态，相当于OPC规范中组的参数
        private static Opc.Da.Subscription _readSubscription = null;//定义组对象（订阅者）
        private static Opc.Da.SubscriptionState _readstate = null;//定义组（订阅者）状态，相当于OPC规范中组的参数
        private static Opc.Da.Subscription _writeSubscription = null;//定义组对象（订阅者）
        private static Opc.Da.SubscriptionState _writestate = null;//定义组（订阅者）状态，相当于OPC规范中组的参数
        private static Opc.Da.Subscription _tempSubscription = null;//定义组对象（订阅者）
        private static Opc.Da.SubscriptionState _tempstate = null;//定义组（订阅者）状态，相当于OPC规范中组的参数

        //  static private Opc.IDiscovery m_discovery = new OpcCom.ServerEnumerator();//定义枚举基于COM服务器的接口，用来搜索所有的此类服务器。
        private static Opc.IDiscovery m_discovery = new OpcCom.ServerEnumerator();//定义枚举基于COM服务器的接口，用来搜索所有的此类服务器。

        /// <summary>
        /// 获取主机的所有OPC服务器的标识名称数组
        /// </summary>
        /// <param name="hostname">主机名称</param>
        /// <returns></returns>
        public static List<string> GetOpcServers(string hostname)
        {
            try
            {
                servers = m_discovery.GetAvailableServers(Specification.COM_DA_20, hostname, null);
                //daver表示数据存取规范版本，Specification.COMDA_20等于2.0版本。
                //host为计算机名，null表示不需要任何网络安全认证。
                if (servers != null)
                {
                    List<string> ser = new List<string>(); ;
                    foreach (Opc.Da.Server server in servers)
                    {
                        ser.Add(server.Name);
                    }
                    return ser;
                }
                return null;
            }
            catch (Exception ex)
            {
                _opcError = "获取OPC服务器时：" + ex.Message;
                return null;
            }
        }

        /// <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
            {
                GetOpcServers(hostname);
                //if (ProgID.Contains(hostname) == false)
                //{
                //    ProgID = hostname + "." + ProgID;
                //}

                foreach (Opc.Da.Server server in servers)
                {
                    //server即为需要连接的OPC数据存取服务器。
                    if (String.Compare(server.Name, ProgID, true) == 0)//为true忽略大小写
                    {
                        m_server = server;//建立连接。
                        break;
                    }
                }
                //连接服务器
                if (m_server != null)//非空连接服务器
                {
                    m_server.Connect();
                    _IfConnectOPCServer = true;
                    CreateItemGroup();
                    return true;
                }
                else
                {
                    _IfConnectOPCServer = false;
                    return false;
                }
            }
            catch (Exception ex)
            {
                _opcError = "连接OPC数据存取服务器时：" + ex.Message;
                _IfConnectOPCServer = false;
                return false;
            }
        }

        /// <summary>
        /// 创建OPC组（订阅者），定义组内变量名称
        /// </summary>
        /// <param name="groupname">OPC组（订阅者）名称</param>
        /// <param name="itemnames">指定组内所有变量名称,数组的值举例"S7:[S7 connection_1]DB1,INT1"</param>
        /// <returns></returns>
        public static Opc.Da.Subscription CreateItemGroup(string groupname, string[] itemnames)
        {
            string[] itemName;
            //定义item列表
            Item[] items;
            ItemResult[] irs;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                //设定组状态
                state = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                state.Name = groupname;//组名
                state.ServerHandle = null;//服务器给该组分配的句柄。
                state.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                state.Active = true;//激活该组。
                state.UpdateRate = 100;//刷新频率为100毫秒。
                state.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                state.Locale = null;//不设置地区值。

                //添加组
                subscription = (Opc.Da.Subscription)m_server.CreateSubscription(state);//创建组

                //定义Item列表
                //对应类型为:{Byte,Byte,Char,Short,String,Word,Boolean}
                itemName = itemnames;//{ "S7:[S7 connection_1]DB1,INT1", "S7:[@LOCALSERVER]DB1,INT20", "S7:[@LOCALSERVER]DB1,INT30", "S7:[@LOCALSERVER]DB1,INT50" };

                //定义item列表
                items = new Item[itemName.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = itemName[i]; //该数据项在服务器中的名字。
                }

                //添加Item
                irs = subscription.AddItems(items);
                return subscription;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "创建OPC组时：" + ex.Message;
                return null;
            }
            finally
            {
                itemName = null;
                //定义item列表
                items = null;
                irs = null;
            }
        }

        /// <summary>
        /// 创建OPC组（订阅者），不定义组内变量名称
        /// </summary>
        /// <param name="groupname">OPC组（订阅者）名称</param>
        /// <returns></returns>
        public static Opc.Da.Subscription CreateItemGroup(string groupname)
        {
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                //设定组状态
                state = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                state.Name = groupname;//组名
                state.ServerHandle = null;//服务器给该组分配的句柄。
                state.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                state.Active = true;//激活该组。
                state.UpdateRate = 100;//刷新频率为100毫秒。
                state.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                state.Locale = null;//不设置地区值。

                //添加组
                subscription = (Opc.Da.Subscription)m_server.CreateSubscription(state);//创建组

                return subscription;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "创建OPC组时：" + ex.Message;
                return null;
            }
        }

        /// <summary>
        /// 创建几个默认组：read和write、临时读写组tempGroup
        /// </summary>
        /// <returns></returns>
        public static void CreateItemGroup()
        {
            try
            {
                //if (_IfConnectOPCServer == false)
                //{
                //    if (ConnectOPCServer(_hostname, _progID) == false) return ;
                //}

                #region 建立读全部标签组

                devinfo28 = BaseDeviceService.GetDeviceInfo(65534);

                //设定读取组状态
                _readstate = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                _readstate.Name = "readopc";//组名
                _readstate.ServerHandle = null;//服务器给该组分配的句柄。
                _readstate.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                _readstate.Active = true;//激活该组。
                _readstate.UpdateRate = 5000;//刷新频率为100毫秒。
                _readstate.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                _readstate.Locale = null;//不设置地区值。
                //添加读组
                _readSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_readstate);//创建读取组
                //20100221
                string[] itemName = new string[1] { _PLCconnectionID + "DB2,byte" + devinfo28.Dbw2Address.ToString() + "," + ((int)devinfo28.Dbw2Getlength).ToString() + "" };//{ "S7:[S7 connection_1]DB1,INT1", "S7:[@LOCALSERVER]DB1,INT20", "S7:[@LOCALSERVER]DB1,INT30", "S7:[@LOCALSERVER]DB1,INT50" };

                //定义读item列表
                Item[] items = new Item[itemName.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值v
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = itemName[i]; //该数据项在服务器中的名字。
                }

                //添加读Item
                ItemResult[] irs = _readSubscription.AddItems(items);
                _plcStates = new int[System.Convert.ToInt32(devinfo28.Dbw2Getlength)];
                _readSubscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);

                #endregion 建立读全部标签组

                //设定写组状态
                _writestate = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                _writestate.Name = "writeopc";//组名
                _writestate.ServerHandle = null;//服务器给该组分配的句柄。
                _writestate.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                _writestate.Active = true;//激活该组。
                _writestate.UpdateRate = 100;//刷新频率为100毫秒。
                _writestate.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                _writestate.Locale = null;//不设置地区值。
                //添加写入组
                _writeSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_writestate);//创建写入组

                //设定临时读组状态
                _tempstate = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                _tempstate.Name = "opctemp";//组名
                _tempstate.ServerHandle = null;//服务器给该组分配的句柄。
                _tempstate.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                _tempstate.Active = true;//激活该组。
                _tempstate.UpdateRate = 100;//刷新频率为100毫秒。
                _tempstate.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                _tempstate.Locale = null;//不设置地区值。
                //添加写入组
                _tempSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_tempstate);//创建写入组
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "创建OPC组时：" + ex.Message;
                return;
            }
        }

        /// <summary>
        /// 创建OPC组（订阅者），定义组内变量名称
        /// </summary>
        /// <param name="plcConnectionID">组态软件中定义的每个PLC连接的标识</param>
        /// <param name="groupname">OPC组（订阅者）名称</param>
        /// <param name="itemnames">指定组内所有变量名称,数组的值举例"DB1,INT1"</param>
        /// <returns></returns>
        public static Opc.Da.Subscription CreateItemGroup(string plcConnectionID, string groupname, string[] itemnames)
        {
            string[] itemName;
            //定义item列表
            Item[] items;
            ItemResult[] irs;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                //设定组状态
                state = new Opc.Da.SubscriptionState();//组（订阅者）状态，相当于OPC规范中组的参数
                state.Name = groupname;//组名
                state.ServerHandle = null;//服务器给该组分配的句柄。
                state.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
                state.Active = true;//激活该组。
                state.UpdateRate = 100;//刷新频率为100毫秒。
                state.Deadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                state.Locale = null;//不设置地区值。

                //添加组
                subscription = (Opc.Da.Subscription)m_server.CreateSubscription(state);//创建组

                //定义Item列表
                //对应类型为:{Byte,Byte,Char,Short,String,Word,Boolean}
                itemName = itemnames;//{ "S7:[S7 connection_1]DB1,INT1", "S7:[@LOCALSERVER]DB1,INT20", "S7:[@LOCALSERVER]DB1,INT30", "S7:[@LOCALSERVER]DB1,INT50" };

                //定义item列表
                items = new Item[itemName.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = plcConnectionID + itemName[i]; //该数据项在服务器中的名字。
                }

                //添加Item
                irs = subscription.AddItems(items);
                return subscription;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "创建OPC组时：" + ex.Message;
                return null;
            }
            finally
            {
                itemName = null;
                //定义item列表
                items = null;
                irs = null;
            }
        }

        /// <summary>
        /// 同步读取全部OPC组内变量的值，List《变量名+ ":" +变量值》
        /// </summary>
        /// <param name="subscription">OPC组名称</param>
        /// <returns></returns>
        public static List<string> SyncReadAllItems(Opc.Da.Subscription subscription)
        {
            ItemValueResult[] values;
            List<string> itemnamevalue;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                itemnamevalue = new List<string>();
                //注册回调事件
                //subscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);

                //以下测试同步读
                //以下读整个组
                values = subscription.Read(subscription.Items);
                foreach (ItemValueResult value in values)
                {
                    itemnamevalue.Add(value.ItemName + ":" + value.Value);
                }
                //subscription.RemoveItems(subscription.Items);
                //subscription.Dispose();
                return itemnamevalue;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步读数据时：" + ex.Message;
                return null;
            }
            finally
            {
                values = null;
                itemnamevalue = null;
            }
        }

        /// <summary>
        /// 读取指定标签数组的数据，返回值：“标签值”组成的数组
        /// </summary>
        /// <param name="itemnames">标签数组</param>
        /// <returns></returns>
        public static List<string> SyncReadAllItems(string[] itemnames)
        {
            Subscription subs;
            List<string> itemnamevalue;
            ItemValueResult[] values;

            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                subs = CreateItemGroup(_PLCconnectionID, Guid.NewGuid().ToString(), itemnames);
                itemnamevalue = new List<string>();

                values = subs.Read(subs.Items);
                foreach (ItemValueResult value in values)
                {
                    itemnamevalue.Add(System.Convert.ToString(value.Value));
                }
                subs.Dispose();
                return itemnamevalue;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步读数据时：" + ex.Message;
                return null;
            }
            finally
            {
                itemnamevalue = null;
                values = null;
            }
        }

        /// <summary>
        /// 读取指定标签名称的数据
        /// </summary>
        /// <param name="itemname">标签名称</param>
        /// <returns></returns>
        public static string SyncReadItemValue(string itemname)
        {
            string[] items = new string[1] { itemname };
            Subscription subs = CreateItemGroup(_PLCconnectionID, Guid.NewGuid().ToString(), items);
            string itemnamevalue = "";
            ItemValueResult[] values = subs.Read(subs.Items);
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }

                if (values.Length > 0)
                {
                    if (values[0].Value != null)
                    {
                        itemnamevalue = values[0].Value.ToString();
                    }
                }
                subs.RemoveItems(subs.Items);
                subs.Dispose();
                return itemnamevalue;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步读数据时：" + ex.Message;
                return null;
            }
            finally
            {
                items = null;
                subs = null;
                itemnamevalue = null;
                values = null;
            }
        }

        //20100221

        #region 同步读、写OPC

        /// <summary>
        /// 读取整个_readSubscription组的内容
        /// </summary>
        /// <returns></returns>
        public static byte[] SyncReadAllItems()
        {
            ItemValueResult[] values;
            byte[] itemnamevalue;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                //List<string> itemnamevalue = new List<string>();
                //注册回调事件
                //subscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);

                //以下测试同步读
                //以下读整个组
                if (ConnectCount > 3)
                {
                    _opcError = "同步数据时：OPC Server没连接到PLC，并且超过重复连接次数!请先关闭命令开关，检查通讯线路，确认后重新打开命令开关！";
                    return null;
                }
                values = _readSubscription.Read(_readSubscription.Items);
                if (values.Length <= 0)
                {
                    _opcError = "同步读数据时：OPC Server没连接到PLC!";
                    return null;
                }
                if (values[0].Quality == Quality.Bad)
                {
                    ConnectCount++;
                    _opcError = "同步读数据时：OPC Server没连接到PLC!";
                    return null;
                }
                itemnamevalue = new byte[(int)devinfo28.Dbw2Getlength];

                Array.Copy((Array)values[0].Value, itemnamevalue, (int)devinfo28.Dbw2Getlength);
                //subscription.RemoveItems(subscription.Items);
                //subscription.Dispose();
                return itemnamevalue;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步读数据时：" + ex.Message;
                return null;
            }
            finally
            {
                itemnamevalue = null;
                values = null;
            }
        }

        /// <summary>
        /// 延吉向指定OPC标签组写入数据（_writeSubscription组）多对多写入
        /// </summary>
        /// <param name="itemnames"></param>
        /// <param name="itemvalue"></param>
        /// <returns></returns>
        public static bool SyncWriteAllItemValue(string[] itemnames, string[] itemvalue)
        {
            Item[] items;
            ItemValue[] itemvalues;
            IdentifiedResult[] ir;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return false;
                }
                if (ConnectCount > 1)
                {
                    _opcError = "同步数据时：OPC Server没连接到PLC，并且超过重复连接次数!请先关闭命令开关，检查通讯线路，确认后重新打开命令开关！";
                    return false;
                }
                //定义item列表
                items = new Item[itemnames.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = _PLCconnectionID + itemnames[i]; //该数据项在服务器中的名字。
                }
                _writeSubscription.AddItems(items);
                if (_writeSubscription.Items.Length==8)
                {

                }
                itemvalues = new ItemValue[_writeSubscription.Items.Length];
                for (int ii = 0; ii < _writeSubscription.Items.Length; ii++)
                {
                    itemvalues[ii] = new ItemValue((ItemIdentifier)_writeSubscription.Items[ii]);
                    itemvalues[ii].Value = itemvalue[ii];
                }

                ir = _writeSubscription.Write(itemvalues);

                _writeSubscription.RemoveItems(_writeSubscription.Items);
                //_writeSubscription.Dispose();
                //GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步写数据时：" + ex.Message;
                return false;
            }
            finally
            {
                items = null;
                itemvalues = null;
                ir = null;
            }
        }

        /// <summary>
        /// 单个标签，按字节写入多个byte数据20110515  一对多写入
        /// </summary>
        /// <param name="itemnames">单个标签的名称,注意：只包含一个元素的数组</param>
        /// <param name="itemvalue">要写入的byte数组</param>
        /// <returns></returns>
        public static bool SyncWriteAllItemValue(string[] itemnames, byte[] itemvalue)
        {
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return false;
                }
                //定义item列表
                Item[] items = new Item[itemnames.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[0] = new Item();//创建一个项Item对象。
                    items[0].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[0].ItemPath = null; //该数据项在服务器中的路径。
                    items[0].ItemName = _PLCconnectionID + itemnames[0]; //该数据项在服务器中的名字。
                }
                _writeSubscription.AddItems(items);
                ItemValue[] itemvalues = new ItemValue[itemnames.Length];
                for (int ii = 0; ii < itemnames.Length; ii++)//ii恒等于0
                {
                    itemvalues[ii] = new ItemValue((ItemIdentifier)_writeSubscription.Items[ii]);
                    itemvalues[ii].Value = itemvalue;//传入object类型20110515
                }

                IdentifiedResult[] ir = _writeSubscription.Write(itemvalues);

                _writeSubscription.RemoveItems(_writeSubscription.Items);
                //_writeSubscription.Dispose();
                GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步写数据时：" + ex.Message;
                return false;
            }
        }

        public static bool SyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalue)
        {
            Item[] items;
            ItemValue[] itemvalues;
            IdentifiedResult[] ir;
            try
            {
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return false;
                }
                if (ConnectCount > 1)
                {
                    _opcError = "同步数据时：OPC Server没连接到PLC，并且超过重复连接次数!请先关闭命令开关，检查通讯线路，确认后重新打开命令开关！";
                    return false;
                }
                //定义item列表
                items = new Item[itemnames.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = itemnames[i].ToString(); //该数据项在服务器中的名字。
                }
                _writeSubscription.AddItems(items);
                itemvalues = new ItemValue[_writeSubscription.Items.Length];
                for (int ii = 0; ii < _writeSubscription.Items.Length; ii++)
                {
                    itemvalues[ii] = new ItemValue((ItemIdentifier)_writeSubscription.Items[ii]);
                    itemvalues[ii].Value = itemvalue[ii];
                }

                ir = _writeSubscription.Write(itemvalues);

                _writeSubscription.RemoveItems(_writeSubscription.Items);
                //_writeSubscription.Dispose();
                //GC.Collect();
                return true;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步写数据时：" + ex.Message;
                return false;
            }
            finally
            {
                items = null;
                itemvalues = null;
                ir = null;
            }
        }

        /// <summary>
        /// 延吉读取指定OPC标签组数据（_tempSubscription组）
        /// </summary>
        /// <param name="itemnames"></param>
        /// <returns></returns>
        public static object[] SyncReadItemValues(string[] itemnames)
        {
            Item[] items;
            ItemResult[] irs;
            ItemValueResult[] values;
            object[] itemnamevalue;
            try
            {
                //string ss; string ss1;
                //ss = DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
                if (_IfConnectOPCServer == false)
                {
                    if (ConnectOPCServer(_hostname, _progID) == false) return null;
                }
                //定义item列表
                items = new Item[itemnames.Length];//定义数据项，即item
                int i;
                for (i = 0; i < items.Length; i++)//item初始化赋值
                {
                    items[i] = new Item();//创建一个项Item对象。
                    items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
                    items[i].ItemPath = null; //该数据项在服务器中的路径。
                    items[i].ItemName = _PLCconnectionID + itemnames[i]; //该数据项在服务器中的名字。
                }
                irs = _tempSubscription.AddItems(items);

                values = _tempSubscription.Read(_tempSubscription.Items);
                if (values[0].Quality == Quality.Bad)
                {
                    _opcError = "同步读数据时：OPC Server没连接到PLC!";
                    return null;
                }
                itemnamevalue = new object[values.Length];
                int k = 0;
                foreach (ItemValueResult value in values)
                {
                    itemnamevalue[k] = value.Value;
                    k++;
                }
                //Array.Copy(values.[0].Value, itemnamevalue, values.Length);
                _tempSubscription.RemoveItems(_tempSubscription.Items);
                //_tempSubscription.Dispose();
                //GC.Collect();
                //ss1 = DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
                return itemnamevalue;
            }
            catch (Exception ex)
            {
                //if ((m_server == null) || (m_server.IsConnected == false))
                //{
                _IfConnectOPCServer = false;
                //}
                _opcError = "同步读数据时：" + ex.Message;
                return null;
            }
            finally
            {
                items = null;
                irs = null;
                values = null;
                itemnamevalue = null;
            }
        }

        #endregion 同步读、写OPC

        //20100221
        //#region 延吉同步写、异步读OPC
        //static byte[] AsyncReadAllItemNameValue= new byte[(int)devinfo28.Dbw2Getlength];
        //static bool AsyncReadOK=false ;
        ///// <summary>
        ///// 延吉异步读取整个_readSubscription组的内容
        ///// </summary>
        ///// <returns></returns>
        //public static void AsyncReadAllItems()
        //{
        //    try
        //    {
        //        if (_IfConnectOPCServer == false)
        //        {
        //            if (ConnectOPCServer(_hostname, _progID) == false) return ;
        //        }

        //        IRequest quest=null ;
        //        _readSubscription.Read(_readSubscription.Items, Guid.NewGuid().ToString(), OnReadComplete,out quest);

        //    }
        //    catch (Exception ex)
        //    {
        //        //if ((m_server == null) || (m_server.IsConnected == false))
        //        //{
        //        _IfConnectOPCServer = false;
        //        //}
        //        _opcError = "异步读数据时：" + ex.Message;
        //        AsyncReadOK = false;
        //        return ;
        //    }
        //    finally
        //    {
        //    }
        //}
        ///// <summary>
        ///// 延吉向指定OPC标签组同步写入数据（_writeSubscription组）
        ///// </summary>
        ///// <param name="itemnames"></param>
        ///// <param name="itemvalue"></param>
        ///// <returns></returns>
        //public static bool SyncWriteGroupItemValue(string[] itemnames, string[] itemvalue)
        //{
        //    Item[] items;
        //    ItemValue[] itemvalues;
        //    IdentifiedResult[] ir;
        //    try
        //    {
        //        if (AsyncReadOK == false) return false;
        //        if (_IfConnectOPCServer == false)
        //        {
        //            if (ConnectOPCServer(_hostname, _progID) == false) return false;
        //        }
        //        //定义item列表
        //        items = new Item[itemnames.Length];//定义数据项，即item
        //        int i;
        //        for (i = 0; i < items.Length; i++)//item初始化赋值
        //        {
        //            items[i] = new Item();//创建一个项Item对象。
        //            items[i].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
        //            items[i].ItemPath = null; //该数据项在服务器中的路径。
        //            items[i].ItemName = _PLCconnectionID + itemnames[i]; //该数据项在服务器中的名字。
        //        }
        //        _writeSubscription.AddItems(items);
        //        itemvalues = new ItemValue[_writeSubscription.Items.Length];
        //        for (int ii = 0; ii < _writeSubscription.Items.Length; ii++)
        //        {
        //            itemvalues[ii] = new ItemValue((ItemIdentifier)_writeSubscription.Items[ii]);
        //            itemvalues[ii].Value = itemvalue[ii];
        //        }

        //        ir = _writeSubscription.Write(itemvalues);

        //        _writeSubscription.RemoveItems(_writeSubscription.Items);
        //        //_writeSubscription.Dispose();
        //        GC.Collect();
        //        return true;
        //    }
        //    catch (Exception ex)
        //    {
        //        //if ((m_server == null) || (m_server.IsConnected == false))
        //        //{
        //        _IfConnectOPCServer = false;
        //        //}
        //        _opcError = "同步写数据时：" + ex.Message;
        //        return false;
        //    }
        //    finally
        //    {
        //        items = null;
        //        itemvalues = null;
        //        ir = null;
        //    }
        //}
        ////ReadComplete回调
        //public static void OnReadComplete(object requestHandle, Opc.Da.ItemValueResult[] values)
        //{
        //    /*Console.WriteLine("发生异步读name:{0},value:{1}", values[0].ItemName, values[0].Value);
        //    if ((int)requestHandle == 1)
        //        Console.WriteLine("事件信号句柄为{0}", requestHandle);*/
        //    //不区分请求句柄了，直接接收OPC数据
        //    try
        //    {
        //        if (values.Length <= 0)
        //        {
        //            _opcError = "异步读数据时：OPC Server没连接到PLC!";
        //            AsyncReadOK = false;
        //            return ;
        //        }
        //        if (values[0].Quality == Quality.Bad)
        //        {
        //            _opcError = "异步读数据时：OPC Server没连接到PLC!";
        //            AsyncReadOK = false;
        //            return ;
        //        }

        //        Array.Copy((Array)values[0].Value, AsyncReadAllItemNameValue, AsyncReadAllItemNameValue.GetLength(0));// (int)devinfo28.Dbw2Getlength
        //        AsyncReadOK = true;
        //    }
        //    catch (Exception ex)
        //    {
        //        _opcError = "异步读数据时："+ex.Message ;
        //        AsyncReadOK = false;
        //        return;
        //    }
        //    finally
        //    {
        //        values = null;
        //    }
        //}
        //#endregion

        /// <summary>
        /// 同步向OPC组名称内每个变量写入值
        /// </summary>
        /// <param name="subscription">OPC组名称</param>
        /// <param name="itemvalue">每个变量的值</param>
        /// <returns></returns>
    }
}