You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1326 lines
58 KiB
1326 lines
58 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Opc;
|
|
using Opc.Da;
|
|
using OpcCom;
|
|
using System.Threading;
|
|
using System.Data;
|
|
using DBFactory;
|
|
using CommonLib;
|
|
namespace OPCClient
|
|
{
|
|
public static class CCommonOPCClient
|
|
{
|
|
public static object lockob = 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 = new DBOperator();
|
|
//20110726
|
|
private static Dictionary<string, int> _connectCount = new Dictionary<string, int>(); //private static int _connectCount = 0;
|
|
//20110726
|
|
public static Dictionary<string, int> ConnectCount
|
|
{
|
|
get { return CCommonOPCClient._connectCount; }
|
|
set { CCommonOPCClient._connectCount = value; }
|
|
}
|
|
//public static int ConnectCount
|
|
//{
|
|
// get { return CCommonOPCClient._connectCount; }
|
|
// set {
|
|
// if (value == 0)
|
|
// {
|
|
// _opcError = "";
|
|
// }
|
|
// CCommonOPCClient._connectCount = value;
|
|
// }
|
|
//}
|
|
|
|
private static int[] _plcStates=null ;
|
|
|
|
public static int[] PlcStates
|
|
{
|
|
get { return CCommonOPCClient._plcStates; }
|
|
//set { CCommonOPCClient._plcStates = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 20110309订阅的组内标签数据变化事件
|
|
/// </summary>
|
|
/// <param name="subscriptionHandle">客户端句柄</param>
|
|
/// <param name="requestHandle">请求句柄</param>
|
|
/// <param name="values">标签值数组</param>
|
|
public static void OnDataChange(object subscriptionHandle, object requestHandle, ItemValueResult[] values)
|
|
{
|
|
lock (lockob)
|
|
{
|
|
//根据subscriptionHandle对应设备索引,依据设备种类(不同类型设备通讯数据帧不同)
|
|
//分别处理:完成,报警,光电开关,PLC发起的请求
|
|
int deviceindex = 0;
|
|
try
|
|
{
|
|
if (subscriptionHandle.ToString().IndexOf("split") >= 0)
|
|
{
|
|
deviceindex = System.Convert.ToInt32(subscriptionHandle.ToString().Substring(5));
|
|
if (values[0].Quality != Quality.Good) return;
|
|
Array arr = (Array)values[0].Value;
|
|
byte[] GDKG = null;
|
|
|
|
GDKG = new byte[arr.GetLength(0)];
|
|
Array.Copy(arr, GDKG, arr.GetLength(0));
|
|
//object lockthis = new object();
|
|
//lock (UpdateDB)
|
|
{
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, GDKG, null);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
deviceindex = System.Convert.ToInt32(subscriptionHandle);
|
|
Array arr = (Array)values[0].Value;
|
|
byte[] itemnamevalue = new byte[arr.GetLength(0)];
|
|
Array.Copy(arr, itemnamevalue, arr.GetLength(0));
|
|
int head = 0;
|
|
head = itemnamevalue[0];//读写标志
|
|
//if (head != 1) return;
|
|
//object lockthis = new object();
|
|
//lock (UpdateDB)
|
|
{
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, null, itemnamevalue);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
}
|
|
}
|
|
//电气PLC的有物字节单独建组(按照S7Connection),高端不需要
|
|
|
|
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{//20120420
|
|
_opcError = string.Format("OPC服务器订阅事件异常:{0},{1}", ex.Message, ex.StackTrace);
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, null, null);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//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);*/
|
|
}
|
|
|
|
static private 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; }
|
|
}
|
|
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; }
|
|
}
|
|
static private Opc.Da.Server m_server = null;//定义数据存取服务器
|
|
static private Opc.Server[] servers;
|
|
static private Opc.Da.Subscription subscription = null;//定义组对象(订阅者)
|
|
static private Opc.Da.SubscriptionState state = null;//定义组(订阅者)状态,相当于OPC规范中组的参数
|
|
static private Opc.Da.Subscription _readSubscription = null;//定义组对象(订阅者)
|
|
//static private Opc.Da.SubscriptionState _readstate = null;//定义组(订阅者)状态,相当于OPC规范中组的参数
|
|
static private Opc.Da.Subscription _writeSubscription = null;//定义组对象(订阅者)
|
|
static private Opc.Da.SubscriptionState _writestate = null;//定义组(订阅者)状态,相当于OPC规范中组的参数
|
|
static private Opc.Da.Subscription _tempSubscription = null;//定义组对象(订阅者)
|
|
static private Opc.Da.SubscriptionState _tempstate = null;//定义组(订阅者)状态,相当于OPC规范中组的参数
|
|
static private Opc.IDiscovery m_discovery = new OpcCom.ServerEnumerator();//定义枚举基于COM服务器的接口,用来搜索所有的此类服务器。
|
|
/// <summary>
|
|
/// 《设备索引,对应设备订阅》
|
|
/// </summary>
|
|
public static SubscriptionCollection SubscriptionGroup = new SubscriptionCollection();//定义组对象集合(订阅者集合)//20110309
|
|
//public static System.Collections.Hashtable SubscriptionG = new System.Collections.Hashtable();
|
|
//static Model.MDevice devinfo;//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 ;
|
|
}
|
|
//SELECT F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection,F_SplitByte FROM T_Base_Device where f_devicekindindex<>28 and F_DBW2Address >=0 and F_DBWGetLength>0 order by F_DeviceIndex asc
|
|
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;
|
|
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)
|
|
{
|
|
|
|
//设定设备订阅状态
|
|
_tempstate = new Opc.Da.SubscriptionState();//组(订阅者)状态,相当于OPC规范中组的参数
|
|
_tempstate.Name = dv[i]["F_ReadSubscription"].ToString();//组名
|
|
|
|
_tempstate.ServerHandle = null;//服务器给该组分配的句柄。
|
|
_tempstate.ClientHandle = dv[i]["F_ReadSubscription"].ToString();//客户端给该组分配的句柄。
|
|
_tempstate.Active = true;//激活该组。
|
|
_tempstate.UpdateRate = 500;//刷新频率为500毫秒。
|
|
_tempstate.Deadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。
|
|
_tempstate.Locale = null;//不设置地区值。
|
|
//添加设备订阅
|
|
_tempSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_tempstate);//创建设备订阅
|
|
//添加事件
|
|
|
|
|
|
//添加标签
|
|
////定义读item列表
|
|
Item[] items = new Item[1];//定义数据项,即item//20111110
|
|
|
|
int ii = 0;//20111110数据区
|
|
items[ii] = new Item();//创建一个项Item对象。
|
|
items[ii].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
|
|
items[ii].ItemPath = null; //该数据项在服务器中的路径。
|
|
items[ii].ItemName = dv[i]["F_S7Connection"].ToString() +
|
|
Model.CGeneralFunction.DBGet + ",byte" +
|
|
dv[i]["F_DBW2Address"].ToString() + "," +
|
|
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(); //该数据项在服务器中的名字。
|
|
|
|
//添加读Item
|
|
ItemResult[] irs = _tempSubscription.AddItems(items);
|
|
_tempSubscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);
|
|
if (SubscriptionGroup.Contains(_tempSubscription) == false)
|
|
{
|
|
SubscriptionGroup.Add(_tempSubscription);
|
|
}
|
|
|
|
}
|
|
}
|
|
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++)
|
|
{
|
|
//设定设备订阅状态
|
|
_tempstate = new Opc.Da.SubscriptionState();//组(订阅者)状态,相当于OPC规范中组的参数
|
|
_tempstate.Name = "split" + dv[i]["F_ReadSubscription"].ToString();//组名
|
|
_tempstate.ServerHandle = null;//服务器给该组分配的句柄。
|
|
_tempstate.ClientHandle ="split"+ dv[i]["F_ReadSubscription"].ToString();//客户端给该组分配的句柄。
|
|
_tempstate.Active = true;//激活该组。
|
|
_tempstate.UpdateRate = 500;//刷新频率为500毫秒。
|
|
_tempstate.Deadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。
|
|
_tempstate.Locale = null;//不设置地区值。
|
|
//添加设备订阅
|
|
_tempSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_tempstate);//创建设备订阅
|
|
//添加标签
|
|
////定义读item列表
|
|
Item[] items = new Item[1];//定义数据项,即item//20111110
|
|
|
|
int ii = 0;//20111110数据区
|
|
items[ii] = new Item();//创建一个项Item对象。
|
|
items[ii].ClientHandle = Guid.NewGuid().ToString();//客户端给该数据项分配的句柄。
|
|
items[ii].ItemPath = null; //该数据项在服务器中的路径。
|
|
items[ii].ItemName = dv[i]["F_S7Connection"].ToString() +
|
|
Model.CGeneralFunction.DBGet + ",byte" +
|
|
dv[i]["F_DBW2Address"].ToString() + "," +
|
|
(System.Convert.ToInt32(dv[i]["F_DBWGetLength"])).ToString(); //该数据项在服务器中的名字。
|
|
|
|
//添加读Item
|
|
ItemResult[] irs = _tempSubscription.AddItems(items);
|
|
//添加事件
|
|
_tempSubscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);
|
|
if (SubscriptionGroup.Contains(_tempSubscription) == false)
|
|
{
|
|
SubscriptionGroup.Add(_tempSubscription);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 获取主机的所有OPC服务器的标识名称数组
|
|
/// </summary>
|
|
/// <param name="hostname">主机名称</param>
|
|
/// <returns></returns>
|
|
public static List<string> GetOpcServers(string hostname)
|
|
{
|
|
try
|
|
{
|
|
ConnectData cd = new ConnectData(new System.Net.NetworkCredential(CommonClassLib.AppSettings.GetValue("OPCUsername"),
|
|
CommonClassLib.AppSettings.GetValue("OPCPassword")));//20120510
|
|
|
|
servers = m_discovery.GetAvailableServers(Specification.COM_DA_20, hostname, cd);//20120510
|
|
//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 && hostname!="127.0.0.1")//20120510
|
|
{
|
|
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 = 50;//刷新频率为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 = 50;//刷新频率为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 建立读全部标签组
|
|
//20110216
|
|
|
|
////设定读取组状态
|
|
//_readstate = new Opc.Da.SubscriptionState();//组(订阅者)状态,相当于OPC规范中组的参数
|
|
//_readstate.Name = "readopc";//组名
|
|
//_readstate.ServerHandle = null;//服务器给该组分配的句柄。
|
|
//_readstate.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
|
|
//_readstate.Active = true;//激活该组。
|
|
//_readstate.UpdateRate = 50;//刷新频率为100毫秒。
|
|
//_readstate.Deadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。
|
|
//_readstate.Locale = null;//不设置地区值。
|
|
////添加读组
|
|
//_readSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_readstate);//创建读取组
|
|
//20110216
|
|
//string[] itemName;
|
|
//DataView dv = dbo.ExceSQL("SELECT F_S7Connection,F_DBW2Address,F_DBWGetLength FROM T_Base_Device WHERE (F_DeviceKindIndex = 28)").Tables[0].DefaultView;
|
|
//if (dv.Count > 0)
|
|
//{
|
|
// itemName=new string[dv.Count];
|
|
// for(int i=0;i<dv.Count;i++)
|
|
// {
|
|
// itemName[i] = dv[i]["F_S7Connection"] + Model.CGeneralFunction.DBGet + ",byte"
|
|
// + dv[i]["F_DBW2Address"].ToString() + "," + ((int)dv[i]["F_DBWGetLength"]).ToString();
|
|
// }
|
|
// //{ "S7:[S7 connection_1]DB1,INT1", "S7:[@LOCALSERVER]DB1,INT20", "S7:[@LOCALSERVER]DB1,INT30", "S7:[@LOCALSERVER]DB1,INT50" };
|
|
//}
|
|
//else
|
|
//{
|
|
// return ;
|
|
//}
|
|
////定义读item列表
|
|
//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
|
|
//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 = 50;//刷新频率为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 = 50;//刷新频率为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 = 50;//刷新频率为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>
|
|
/// 读取指定S7Connection所有DB1对应标签数组的数据,返回值:“标签值”组成的数组
|
|
/// </summary>
|
|
/// <param name="S7Connection">OPC连接</param>
|
|
/// <returns></returns>
|
|
public static byte[] SyncReadAllItems(string S7Connection)
|
|
{//20110216
|
|
ItemValueResult[] values;
|
|
byte[] itemnamevalue;
|
|
try
|
|
{
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return null;
|
|
}
|
|
if (_readSubscription.Items != null)
|
|
{
|
|
_readSubscription.RemoveItems(_readSubscription.Items);
|
|
}
|
|
string[] itemName= new string[1];
|
|
DataView dv = dbo.ExceSQL("SELECT F_DBW2Address,F_DBWGetLength FROM T_Base_Device WHERE (F_DeviceKindIndex = 28 and F_S7Connection='"+S7Connection+"')").Tables[0].DefaultView;
|
|
if (dv.Count > 0)
|
|
{
|
|
|
|
itemName[0] = S7Connection + Model.CGeneralFunction.DBGet + ",byte"+ dv[0]["F_DBW2Address"].ToString() + "," + (System.Convert.ToInt32( dv[0]["F_DBWGetLength"])).ToString();
|
|
//20110726
|
|
}
|
|
else
|
|
{
|
|
return null ;
|
|
}
|
|
|
|
//定义读item列表
|
|
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
|
|
|
|
ItemResult[] irs = _readSubscription.AddItems(items);
|
|
//_plcStates = new int[System.Convert.ToInt32(devinfo28.Dbw2Getlength)];
|
|
//_readSubscription.DataChanged += new Opc.Da.DataChangedEventHandler(OnDataChange);
|
|
if (ConnectCount.ContainsKey(S7Connection) == false)//20110726
|
|
{
|
|
ConnectCount.Add(S7Connection, 0);
|
|
}
|
|
if (ConnectCount[S7Connection] > 1)//20110726
|
|
{
|
|
|
|
_opcError = "同步数据时:OPC Server没连接到PLC,并且超过重复连接次数!请先关闭命令开关,检查通讯线路,确认后重新打开命令开关!";
|
|
return null;
|
|
}
|
|
values = _readSubscription.Read(_readSubscription.Items);
|
|
if (values.Length <= 0)
|
|
{
|
|
ConnectCount[S7Connection]++;//20110726
|
|
_opcError = "同步读数据时:OPC Server没连接到PLC!";
|
|
return null;
|
|
}
|
|
if (values[0].Quality == Quality.Bad)
|
|
{
|
|
ConnectCount[S7Connection]++;//20110726
|
|
_opcError = "同步读数据时:OPC Server没连接到PLC!";
|
|
return null;
|
|
}
|
|
|
|
Array arr = (Array)values[0].Value;
|
|
itemnamevalue = new byte[arr.GetLength(0)];
|
|
Array.Copy(arr, itemnamevalue, arr.GetLength(0));
|
|
_readSubscription.RemoveItems(_readSubscription.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>
|
|
/// 读取指定标签名称的数据
|
|
/// </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 > 1)
|
|
// {
|
|
// _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;
|
|
// }
|
|
// Array arr = (Array)values[0].Value;
|
|
// itemnamevalue = new byte[arr.GetLength(0)];
|
|
// Array.Copy(arr, itemnamevalue, arr.GetLength(0));
|
|
// //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.ContainsKey(_PLCconnectionID) == false)//20110726
|
|
{
|
|
ConnectCount.Add(_PLCconnectionID, 0);
|
|
}
|
|
if (ConnectCount[_PLCconnectionID] > 1)//20110726
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20110726
|
|
_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);
|
|
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;
|
|
}
|
|
}
|
|
|
|
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.ContainsKey(_PLCconnectionID) == false)//20110726
|
|
{
|
|
ConnectCount.Add(_PLCconnectionID, 0);
|
|
}
|
|
if (ConnectCount[_PLCconnectionID] > 1)//20110726
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20110726
|
|
//_opcError = "同步数据时:OPC Server没连接到PLC:"+_PLCconnectionID.ToString()+",人工确认后进行【设备初始化】";
|
|
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].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].ToString();
|
|
}
|
|
|
|
ir = _writeSubscription.Write(itemvalues);
|
|
|
|
_writeSubscription.RemoveItems(_writeSubscription.Items);
|
|
if (ir.Length == 0)
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20120405
|
|
_opcError = "同步写数据时:OPC Server没连接到PLC:"+_PLCconnectionID.ToString();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (ir[0].ResultID !=ResultID.S_OK)
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20120405
|
|
_opcError = "同步写数据时:OPC Server没连接到PLC:"+_PLCconnectionID.ToString();
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
//_writeSubscription.Dispose();
|
|
//GC.Collect();
|
|
|
|
}
|
|
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
|
|
|
|
|
|
//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>
|
|
/// 获得设备类型索引
|
|
/// </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()
|
|
{
|
|
if (m_server== null) return;
|
|
if (m_server.IsConnected == false ) return;
|
|
|
|
|
|
foreach (Subscription sub in SubscriptionGroup)
|
|
{
|
|
try
|
|
{
|
|
m_server.CancelSubscription(sub);//m_server前文已说明,通知服务器要求删除组。
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
sub.Dispose();//强制.NET资源回收站回收该subscription的所有资源。
|
|
}
|
|
if (_readSubscription != null)
|
|
{
|
|
m_server.CancelSubscription(_readSubscription);//m_server前文已说明,通知服务器要求删除组。
|
|
_readSubscription.Dispose();//强制.NET资源回收站回收该subscription的所有资源。
|
|
}
|
|
|
|
if (_writeSubscription != null)
|
|
{
|
|
m_server.CancelSubscription(_writeSubscription);//m_server前文已说明,通知服务器要求删除组。
|
|
_writeSubscription.Dispose();//强制.NET资源回收站回收该subscription的所有资源。
|
|
}
|
|
m_server.Disconnect();//
|
|
}
|
|
public static void CreateReadSubscription()
|
|
{
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return;
|
|
}
|
|
#region 建立读全部标签组
|
|
Opc.Da.SubscriptionState _readstate = null;//定义组(订阅者)状态,相当于OPC规范中组的参数
|
|
//设定读取组状态
|
|
_readstate = new Opc.Da.SubscriptionState();//组(订阅者)状态,相当于OPC规范中组的参数
|
|
_readstate.Name = "readopc";//组名
|
|
_readstate.ServerHandle = null;//服务器给该组分配的句柄。
|
|
_readstate.ClientHandle = Guid.NewGuid().ToString();//客户端给该组分配的句柄。
|
|
_readstate.Active = true;//激活该组。
|
|
_readstate.UpdateRate = 50;//刷新频率为100毫秒。
|
|
_readstate.Deadband = 0;// 死区值,设为0时,服务器端该组内任何数据变化都通知组。
|
|
_readstate.Locale = null;//不设置地区值。
|
|
//添加读组
|
|
_readSubscription = (Opc.Da.Subscription)m_server.CreateSubscription(_readstate);//创建读取组
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
}
|