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.
512 lines
22 KiB
512 lines
22 KiB
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 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.IsGood(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);
|
|
}
|
|
ConnectCount[devinfo.S7Connection]++;
|
|
OpcError = string.Format("{0}���ڵ�PLC�Ѿ����ߣ����ı�ǩ״̬��" + value.StatusCode.ToString(), clientHandle);
|
|
|
|
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�ij�����ʶ�����磺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;
|
|
for (int i = 0; i < dv.Count; i++)
|
|
{
|
|
if (dv[i]["F_S7Connection"].ToString() != "S7 connection_1" && dv[i]["F_S7Connection"].ToString() != "S7 connection_2")//ר���豸���ɼ�
|
|
{
|
|
continue;
|
|
}
|
|
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(), 3);//richard.liu20140824 xp:����NameSpaceIndex=2��win7:����NameSpaceIndex=3
|
|
|
|
// 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, 300, out serverHandle);
|
|
|
|
}
|
|
catch (ServiceResultException monitoredItemResult)
|
|
{
|
|
OpcError = "����OPC������ʱ��" + monitoredItemResult.Message;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
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++)
|
|
{
|
|
if (dv[i]["F_S7Connection"].ToString() != "S7 connection_1" && dv[i]["F_S7Connection"].ToString() != "S7 connection_2")//ר���豸���ɼ�
|
|
{
|
|
continue;
|
|
}
|
|
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(), 3);//richard.liu20140824 xp:����NameSpaceIndex=2��win7:����NameSpaceIndex=3
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
public static void kkk()
|
|
{
|
|
DisConnectOPCServer();
|
|
_IfConnectOPCServer = false;
|
|
_hostname = CommonClassLib.AppSettings.GetValue("HostName");
|
|
_progID = CommonClassLib.AppSettings.GetValue("OPCProgID");
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return;
|
|
CreateSubscriptionGroup();
|
|
//for (int i = 0; i < 20; i++)
|
|
//{
|
|
// //object ooo = severhandel[i];
|
|
// m_Subscription.RemoveMonitoredItem(severhandel[i]);
|
|
//}
|
|
}
|
|
/// <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 + ":55101");
|
|
Discovery discovery = new Discovery();
|
|
EndpointDescriptionCollection endpoints = null;
|
|
string rr = discovery.GetEndpoints(discoveryUrl, ref endpoints);
|
|
|
|
for (int i = 0; i < endpoints.Count; i++)
|
|
{
|
|
endpoints[i].EndpointUrl = discoveryUrl.ToString();
|
|
//richard.liu20140824
|
|
//xp: if ((endpoints[i].Server.ApplicationName.Text == ProgID + "@" + hostname.ToUpper())
|
|
//win7: if ((endpoints[i].Server.ApplicationName.Text == ProgID )
|
|
if ((endpoints[i].Server.ApplicationName.Text == ProgID )
|
|
&& (endpoints[i].SecurityMode == MessageSecurityMode.None))//OPC.SimaticNET.S7@LIU-SHAOPENG
|
|
{
|
|
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);
|
|
}
|
|
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] > 1)//20110726
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20110726
|
|
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,3);//richard.liu20140824 xp:����NameSpaceIndex=2��win7:����NameSpaceIndex=3
|
|
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] > 1)//20110726
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20110726
|
|
//_opcError = "ͬ������ʱ��OPC Serverû���ӵ�PLC:"+_PLCconnectionID.ToString()+"���˹�ȷ�Ϻ����С��豸��ʼ����";
|
|
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λ����ϵͳ��Ҫָ��ȷ�е���������//richard.liu20141118��������sValue����item
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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, 3); //richard.liu20140824 xp:����NameSpaceIndex=2��win7:����NameSpaceIndex=3
|
|
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)
|
|
{
|
|
OpcError = "��OPC���ݴ�ȡ������д����ʱ��WriteValues:" + nodesToWrite[ia].ToString() + "�ķ���ֵ�д�����"+sc.ToString();
|
|
return false;
|
|
}
|
|
ia++;
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
OpcError = "��OPC���ݴ�ȡ������д����ʱ��" + ex.Message;
|
|
_IfConnectOPCServer = false;
|
|
return false;
|
|
}
|
|
}
|
|
/// <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_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;
|
|
|
|
}
|
|
}
|
|
}
|