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.
717 lines
32 KiB
717 lines
32 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 ushort S7NameSpace = 2;//20151120,默认值是32位系统的值2,64位系统的值是3
|
|
private static Model.MDevice devinfo;
|
|
private static Object thisLock = new Object();
|
|
public static event CUpdateDBEventHandler UpdateDB;
|
|
public static void OnUpdateDB(object sender,CUpdateDBChangeEventArgs e)
|
|
{
|
|
if (UpdateDB != null)
|
|
{
|
|
UpdateDB(sender, e);
|
|
}
|
|
}
|
|
public static DBOperator dbo = CommonClassLib.AppSettings.dbo; //20130510
|
|
|
|
//20110726
|
|
private static Dictionary<string, int> _connectCount = new Dictionary<string, int>();
|
|
//20110726
|
|
public static Dictionary<string, int> ConnectCount
|
|
{
|
|
get { return CCommonOPCClient._connectCount; }
|
|
set { CCommonOPCClient._connectCount = value; }
|
|
}
|
|
|
|
private static int[] _plcStates=null ;
|
|
|
|
public static int[] PlcStates
|
|
{
|
|
get { return CCommonOPCClient._plcStates; }
|
|
//set { CCommonOPCClient._plcStates = value; }
|
|
}
|
|
private static Server m_Server = null;
|
|
private static Siemens.OpcUA.Subscription m_Subscription;
|
|
|
|
/// <summary>
|
|
/// 20110309订阅的组内标签数据变化事件
|
|
/// </summary>
|
|
/// <param name="subscriptionHandle">客户端句柄</param>
|
|
/// <param name="requestHandle">请求句柄</param>
|
|
/// <param name="values">标签值数组</param>
|
|
public static void OnDataChange(object clientHandle, DataValue value)
|
|
{
|
|
lock (thisLock)
|
|
{
|
|
//根据subscriptionHandle对应设备索引,依据设备种类(不同类型设备通讯数据帧不同)
|
|
//分别处理:完成,报警,光电开关,PLC发起的请求
|
|
int deviceindex = 0;
|
|
try
|
|
{
|
|
if (clientHandle.ToString().IndexOf("split") >= 0)
|
|
{
|
|
deviceindex = System.Convert.ToInt32(clientHandle.ToString().Substring(5));
|
|
}
|
|
else
|
|
{
|
|
deviceindex = System.Convert.ToInt32(clientHandle);
|
|
}
|
|
devinfo = Model.CGetInfo.GetDeviceInfo(deviceindex);
|
|
if (StatusCode.IsNotGood(value.StatusCode))
|
|
{
|
|
if (devinfo == null)
|
|
{
|
|
OpcError = string.Format("设备索引{0}在数据库不存在!", clientHandle);
|
|
|
|
return;
|
|
}
|
|
//if (value.StatusCode.ToString() == "BadNoCommunication")
|
|
//{
|
|
// CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
|
|
// CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
|
|
// CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
|
|
// StringBuilder[] itemnames = new StringBuilder[1] { new StringBuilder("") };
|
|
// itemnames[0].Append(Model.CGeneralFunction.DBGet).Append(".").Append(Convert.ToString(devinfo.Dbw2Address)).Append(",b");
|
|
// DataValueCollection dvc= SyncReadAllItemValue(itemnames);
|
|
// if (dvc.Count > 0)
|
|
// {
|
|
// value = dvc[0];
|
|
// }
|
|
// OpcError = string.Format("{0}所在的PLC已经离线,自动重新读取数据!订阅标签状态:" + value.StatusCode.ToString(), clientHandle);
|
|
// //return;
|
|
//}
|
|
//触发一个特殊事件提示PLC断开连接
|
|
if (ConnectCount.ContainsKey(devinfo.S7Connection) == false)//20110726
|
|
{
|
|
ConnectCount.Add(devinfo.S7Connection, 0);
|
|
}
|
|
|
|
OpcError = string.Format("{0}所在的PLC已经离线!订阅标签状态:" + value.StatusCode.ToString(), clientHandle);
|
|
if (ConnectCount[devinfo.S7Connection] > 3)//20150204
|
|
{
|
|
_opcError = "订阅返回数据时:OPC Server没连接到PLC:" + devinfo.S7Connection.ToString() + ",人工确认后进行【PLC初始化】";//20150204
|
|
return;
|
|
}
|
|
ConnectCount[devinfo.S7Connection]++;//20150204
|
|
return;
|
|
|
|
}
|
|
|
|
ConnectCount[devinfo.S7Connection] = 0;
|
|
if (clientHandle.ToString().IndexOf("split") >= 0)
|
|
{
|
|
Array arr = (Array)value.Value;
|
|
byte[] GDKG = null;
|
|
|
|
GDKG = new byte[arr.GetLength(0)];
|
|
Array.Copy(arr, GDKG, arr.GetLength(0));
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, GDKG, null);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
}
|
|
else
|
|
{
|
|
Array arr = (Array)value.Value;
|
|
byte[] itemnamevalue = new byte[arr.GetLength(0)];
|
|
Array.Copy(arr, itemnamevalue, arr.GetLength(0));
|
|
int head = 0;
|
|
head = itemnamevalue[0];//读写标志
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, null, itemnamevalue);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{//20120420
|
|
OpcError = string.Format("OPC服务器订阅事件异常:{0},{1}", ex.Message, ex.StackTrace);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
static private string _PLCconnectionID = "S7 connection_1";//OPC.UA的新写法"ns=2,S7 connection_1.db2.0,b,5"表示:"S7:[S7 connection_1]的db2.DBB0开始5个字节"
|
|
/// <summary>
|
|
/// 建立PLC连接的ID,例如:"S7:[S7 connection_1]"
|
|
/// 或者"S7:[@LOCALSERVER]"
|
|
/// </summary>
|
|
public static string PlcConnectionID
|
|
{
|
|
get { return CCommonOPCClient._PLCconnectionID; }
|
|
set { CCommonOPCClient._PLCconnectionID = value; }
|
|
}
|
|
static private string _opcError;
|
|
static private bool _IfConnectOPCServer=false ;
|
|
static private string _hostname;
|
|
/// <summary>
|
|
/// OPC Server的机器名称或者IP地址
|
|
/// </summary>
|
|
public static string Hostname
|
|
{
|
|
get { return CCommonOPCClient._hostname; }
|
|
set { CCommonOPCClient._hostname = value; }
|
|
}
|
|
static private string _progID;
|
|
/// <summary>
|
|
/// OPC Server的程序标识,例如:OPC.SimaticNET
|
|
/// </summary>
|
|
public static string ProgID
|
|
{
|
|
get { return CCommonOPCClient._progID; }
|
|
set { CCommonOPCClient._progID = value; }
|
|
}
|
|
public static string OpcError
|
|
{
|
|
get { return CCommonOPCClient._opcError; }
|
|
set {
|
|
CCommonOPCClient._opcError = value;
|
|
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(0, null, null);
|
|
OnUpdateDB("OPCClient.CCommonOPCClient.OnDataChange", udbe);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 《设备索引,对应设备订阅》
|
|
/// </summary>
|
|
public static SubscriptionCollection SubscriptionGroup = new SubscriptionCollection();//定义组对象集合(订阅者集合)//20110309
|
|
|
|
/// <summary>
|
|
/// 20110309每个设备创建一个订阅和DataChange事件
|
|
/// </summary>
|
|
public static void CreateSubscriptionGroup()
|
|
{
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
_hostname = CommonClassLib.AppSettings.GetValue("HostName");
|
|
_progID = CommonClassLib.AppSettings.GetValue("OPCProgID");
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return ;
|
|
}
|
|
DataView dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_S7Connection='S7 connection_1' ) AND (F_ReadSubscription =F_DeviceIndex) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
|
|
if (dv.Count > 0)
|
|
{
|
|
if (dv.Count < SubscriptionGroup.Count) return;
|
|
}
|
|
DataView dvx;
|
|
#region//20220526注释
|
|
//for (int i = 0; i < dv.Count; i++)
|
|
//{
|
|
// string dt = DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
|
|
// dvx = dbo.ExceSQL(string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0}) AND (F_DeviceKindIndex <> 33) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"])).Tables[0].DefaultView;
|
|
// if (dvx.Count > 0)
|
|
// {
|
|
// NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() +"."+
|
|
// Model.CGeneralFunction.DBGet +"."+
|
|
// dv[i]["F_DBW2Address"].ToString() + ",b," +
|
|
// (System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
|
|
|
|
// // Add the attribute name/value to the list view.
|
|
// object serverHandle = null;
|
|
|
|
|
|
// try
|
|
// {
|
|
// // Add the item and apply any changes to it.
|
|
// m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
|
|
|
|
// }
|
|
// catch (ServiceResultException monitoredItemResult)
|
|
// {
|
|
// OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
|
|
|
|
// }
|
|
|
|
// }
|
|
//}
|
|
#endregion
|
|
|
|
#region//20220526在创建OPC订阅时候先创建条码扫描器的订阅,之后再创建其余设备类型的订阅
|
|
for (int i = 0; i < dv.Count; i++)
|
|
{
|
|
string dt = string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0}) AND (F_DeviceKindIndex = 7 ) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"]);//DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
|
|
dvx = dbo.ExceSQL(dt).Tables[0].DefaultView;//20220526先创建条码扫描器
|
|
if (dvx.Count > 0)
|
|
{
|
|
NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
|
|
Model.CGeneralFunction.DBGet + "." +
|
|
dv[i]["F_DBW2Address"].ToString() + ",b," +
|
|
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
|
|
// Add the attribute name/value to the list view.
|
|
object serverHandle = null;
|
|
try
|
|
{
|
|
// Add the item and apply any changes to it.
|
|
m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
|
|
}
|
|
catch (ServiceResultException monitoredItemResult)
|
|
{
|
|
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
|
|
}
|
|
}
|
|
|
|
dvx = dbo.ExceSQL(string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0}) AND (F_DeviceKindIndex <>7 and F_DeviceKindIndex <>33 ) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"])).Tables[0].DefaultView;//20220526后创建非条码扫描器
|
|
if (dvx.Count > 0)
|
|
{
|
|
NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
|
|
Model.CGeneralFunction.DBGet + "." +
|
|
dv[i]["F_DBW2Address"].ToString() + ",b," +
|
|
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
|
|
// Add the attribute name/value to the list view.
|
|
object serverHandle = null;
|
|
try
|
|
{
|
|
// Add the item and apply any changes to it.
|
|
m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
|
|
}
|
|
catch (ServiceResultException monitoredItemResult)
|
|
{
|
|
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_DeviceKindIndex=33) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
|
|
|
|
for (int i = 0; i < dv.Count; i++)
|
|
{
|
|
NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
|
|
Model.CGeneralFunction.DBGet + "." +
|
|
dv[i]["F_DBW2Address"].ToString() + ",b," + System.Convert.ToInt32(dv[i]["F_DBWGetLength"]).ToString(), S7NameSpace);//20151120
|
|
|
|
// Add the attribute name/value to the list view.
|
|
object serverHandle = null;
|
|
|
|
|
|
try
|
|
{
|
|
// Add the item and apply any changes to it.
|
|
m_Subscription.AddDataMonitoredItem(nodeId, "split" + dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
|
|
|
|
}
|
|
catch (ServiceResultException monitoredItemResult)
|
|
{
|
|
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
|
|
}
|
|
|
|
|
|
}
|
|
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_S7Connection='S7 connection_2' ) AND (F_ReadSubscription =F_DeviceIndex) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
|
|
if (dv.Count > 0)
|
|
{
|
|
if (dv.Count < SubscriptionGroup.Count) return;
|
|
}
|
|
|
|
|
|
#region//LHDF 码垛系统订阅
|
|
for (int i = 0; i < dv.Count; i++)
|
|
{
|
|
|
|
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;//20220526后创建非条码扫描器
|
|
if (dvx.Count > 0)
|
|
{
|
|
NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
|
|
Model.CGeneralFunction.DBGet_Stack + "." +
|
|
dv[i]["F_DBW2Address"].ToString() + ",b," +
|
|
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
|
|
// Add the attribute name/value to the list view.
|
|
object serverHandle = null;
|
|
try
|
|
{
|
|
// Add the item and apply any changes to it.
|
|
m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
|
|
}
|
|
catch (ServiceResultException monitoredItemResult)
|
|
{
|
|
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
/// <summary>
|
|
/// 通过设置订阅的监控模式,刷新订阅
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static bool RefreshMonitoringMode()
|
|
{//20150103增加断网恢复
|
|
if (m_Subscription != null)
|
|
{
|
|
m_Subscription.RefreshMonitoringMode();
|
|
}
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// 连接指定主机的OPC服务器
|
|
/// </summary>
|
|
/// <param name="hostname">主机名称</param>
|
|
/// <param name="ProgID">OPC服务器程序标识例如:"OPC.SimaticNET"</param>
|
|
/// <returns></returns>
|
|
public static bool ConnectOPCServer(string hostname, string ProgID)
|
|
{
|
|
try
|
|
{
|
|
//Uri discoveryUrl = new Uri("opc.tcp://" + hostname + ":4845");
|
|
Uri discoveryUrl = new Uri("opc.tcp://" + hostname);
|
|
Discovery discovery = new Discovery();
|
|
EndpointDescriptionCollection endpoints = null;
|
|
string rr = discovery.GetEndpoints(discoveryUrl, ref endpoints);
|
|
|
|
for (int i = 0; i < endpoints.Count; i++)
|
|
{
|
|
if ((endpoints[i].Server.ApplicationName.Text.IndexOf( ProgID)>-1)
|
|
&& (endpoints[i].SecurityMode == MessageSecurityMode.None))//20151120
|
|
{
|
|
m_Server = new Server();
|
|
m_Server.CertificateEvent += new certificateValidation(m_Server_CertificateEvent);
|
|
m_Server.Connect(endpoints[i]);
|
|
_IfConnectOPCServer = true;
|
|
if (m_Subscription == null)
|
|
{
|
|
m_Subscription = m_Server.AddSubscription(100);
|
|
}
|
|
#region 自动读取“S7:”的命名空间索引//20151120
|
|
|
|
DataValueCollection m_currentValues;
|
|
NodeId nodeId=new NodeId(2255);
|
|
NodeIdCollection nodesToRead = new NodeIdCollection(1);
|
|
nodesToRead.Add(nodeId);
|
|
m_Server.ReadValues(nodesToRead, out m_currentValues);
|
|
if (m_currentValues.Count > 0)
|
|
{
|
|
string[] arr;
|
|
arr =(string[]) m_currentValues[0].Value;
|
|
S7NameSpace =(ushort) Array.IndexOf(arr, "S7:");
|
|
|
|
}
|
|
#endregion
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
OpcError = "连接OPC数据存取服务器时:配置项OPCProgID和HostName不准确!";
|
|
_IfConnectOPCServer = false;
|
|
return false;
|
|
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
OpcError = "连接OPC数据存取服务器时:" + ex.Message;
|
|
_IfConnectOPCServer = false;
|
|
return false;
|
|
}
|
|
|
|
}
|
|
public static DataValueCollection SyncReadAllItemValue(StringBuilder[] itemnames)
|
|
{
|
|
DataValueCollection m_currentValues;
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return null;
|
|
}
|
|
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
|
|
{
|
|
ConnectCount.Add(_PLCconnectionID, 0);
|
|
}
|
|
if (ConnectCount[_PLCconnectionID] > 3)//20150204
|
|
{
|
|
_opcError = "读数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
|
|
return null;
|
|
}
|
|
NodeIdCollection nodesToRead = new NodeIdCollection(itemnames.GetLength(0));
|
|
|
|
foreach (StringBuilder item in itemnames)
|
|
{
|
|
// NodeIds.
|
|
String sNodeId = _PLCconnectionID + "." + item.ToString();
|
|
NodeId nodeId = new NodeId(sNodeId,S7NameSpace);//20151120
|
|
nodesToRead.Add(nodeId);
|
|
}
|
|
|
|
// Call to ClientAPI.
|
|
m_Server.ReadValues(
|
|
nodesToRead,
|
|
out m_currentValues);
|
|
return m_currentValues;
|
|
}
|
|
public static bool SyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalues)
|
|
{
|
|
try
|
|
{
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return false;
|
|
}
|
|
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
|
|
{
|
|
ConnectCount.Add(_PLCconnectionID, 0);
|
|
}
|
|
if (ConnectCount[_PLCconnectionID] > 3)//20150204
|
|
{
|
|
_opcError = "写数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
|
|
return false;
|
|
}
|
|
NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
|
|
DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
|
|
StatusCodeCollection results = null;
|
|
int i = 0;
|
|
|
|
foreach (StringBuilder item in itemnames)
|
|
{
|
|
// Values to write.
|
|
String sValue = itemvalues[i].ToString();
|
|
|
|
// Leave current value if write value is empty.
|
|
if (sValue.Length == 0)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
#region win7等64位操作系统需要指定确切的数据类型//20151120
|
|
|
|
Type gt = typeof(byte);
|
|
if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
|
|
{
|
|
gt = typeof(byte);
|
|
}
|
|
else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
|
|
{
|
|
gt = typeof(short);
|
|
}
|
|
else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
|
|
{
|
|
gt = typeof(ushort);
|
|
}
|
|
else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
|
|
{
|
|
gt = typeof(int);
|
|
}
|
|
else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
|
|
{
|
|
gt = typeof(uint);
|
|
}
|
|
else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
|
|
{
|
|
gt = typeof(DateTime);
|
|
}
|
|
|
|
Variant variant = new Variant(Convert.ChangeType(sValue, gt));
|
|
#endregion
|
|
|
|
DataValue value = new DataValue(variant);
|
|
values.Add(value);
|
|
|
|
// NodeIds.
|
|
String sNodeId =_PLCconnectionID+"."+ item.ToString();
|
|
NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
|
|
nodesToWrite.Add(nodeId);
|
|
|
|
i++;
|
|
}
|
|
|
|
// Call to ClientAPI.
|
|
m_Server.WriteValues(
|
|
nodesToWrite,
|
|
values,
|
|
out results);
|
|
int ia = 0;//richard.liu20141110
|
|
foreach (StatusCode sc in results)
|
|
{//richard.liu20141110
|
|
if (sc.Code != StatusCodes.Good)
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20150204
|
|
OpcError = "向OPC数据存取服务器写数据时:WriteValues:" + nodesToWrite[ia].ToString() + "的返回值有错误!"+sc.ToString();
|
|
return false;
|
|
}
|
|
ia++;
|
|
}
|
|
ConnectCount[_PLCconnectionID] = 0;//20150204
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20150204
|
|
OpcError = "向OPC数据存取服务器写数据时:" + ex.Message;
|
|
_IfConnectOPCServer = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#region 20220518 异步写入数据
|
|
public static bool ASyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalues)
|
|
{
|
|
try
|
|
{
|
|
if (_IfConnectOPCServer == false)
|
|
{
|
|
if (ConnectOPCServer(_hostname, _progID) == false) return false;
|
|
}
|
|
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
|
|
{
|
|
ConnectCount.Add(_PLCconnectionID, 0);
|
|
}
|
|
if (ConnectCount[_PLCconnectionID] > 3)//20150204
|
|
{
|
|
_opcError = "写数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
|
|
return false;
|
|
}
|
|
NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
|
|
DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
|
|
StatusCodeCollection results = null;
|
|
int i = 0;
|
|
|
|
foreach (StringBuilder item in itemnames)
|
|
{
|
|
// Values to write.
|
|
String sValue = itemvalues[i].ToString();
|
|
|
|
// Leave current value if write value is empty.
|
|
if (sValue.Length == 0)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
#region win7等64位操作系统需要指定确切的数据类型//20151120
|
|
|
|
Type gt = typeof(byte);
|
|
if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
|
|
{
|
|
gt = typeof(byte);
|
|
}
|
|
else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
|
|
{
|
|
gt = typeof(short);
|
|
}
|
|
else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
|
|
{
|
|
gt = typeof(ushort);
|
|
}
|
|
else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
|
|
{
|
|
gt = typeof(int);
|
|
}
|
|
else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
|
|
{
|
|
gt = typeof(uint);
|
|
}
|
|
else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
|
|
{
|
|
gt = typeof(DateTime);
|
|
}
|
|
|
|
Variant variant = new Variant(Convert.ChangeType(sValue, gt));
|
|
#endregion
|
|
|
|
DataValue value = new DataValue(variant);
|
|
values.Add(value);
|
|
|
|
// NodeIds.
|
|
String sNodeId = _PLCconnectionID + "." + item.ToString();
|
|
NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
|
|
nodesToWrite.Add(nodeId);
|
|
|
|
i++;
|
|
}
|
|
|
|
// 20220518 Call to ClientAPI.
|
|
m_Server.AsyWriteValues(
|
|
nodesToWrite,
|
|
values,
|
|
out results);
|
|
// 异步调用不需要判断返回值
|
|
//int ia = 0;//richard.liu20141110
|
|
//foreach (StatusCode sc in results)
|
|
//{//richard.liu20141110
|
|
// if (sc.Code != StatusCodes.Good)
|
|
// {
|
|
// ConnectCount[_PLCconnectionID]++;//20150204
|
|
// OpcError = "向OPC数据存取服务器写数据时:WriteValues:" + nodesToWrite[ia].ToString() + "的返回值有错误!" + sc.ToString();
|
|
// return false;
|
|
// }
|
|
// ia++;
|
|
//}
|
|
ConnectCount[_PLCconnectionID] = 0;//20150204
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ConnectCount[_PLCconnectionID]++;//20150204
|
|
OpcError = "向OPC数据存取服务器写数据时:" + ex.Message;
|
|
_IfConnectOPCServer = false;
|
|
return false;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 获得设备类型索引
|
|
/// </summary>
|
|
/// <param name="devIdx">设备索引</param>
|
|
/// <returns>设备类型索引</returns>
|
|
static int GetDeviceKindIdx(int devIdx)
|
|
{
|
|
System.Object lockThis = new System.Object();
|
|
lock (lockThis)
|
|
{
|
|
try
|
|
{
|
|
|
|
DataView dv= dbo.ExceSQL(string.Format("SELECT F_DeviceKindIndex FROM T_Base_Device WHERE F_DeviceIndex={0}", devIdx)).Tables[0].DefaultView;
|
|
if (dv.Count > 0)
|
|
{
|
|
return System.Convert.ToInt32(dv[0]["F_DeviceKindIndex"]);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
public static void DisConnectOPCServer()
|
|
{
|
|
try
|
|
{
|
|
int result;
|
|
if (m_Server == null) return;
|
|
|
|
|
|
result = m_Server.Disconnect();
|
|
|
|
// Disconnect succeeded.
|
|
if (result == 0)
|
|
{
|
|
m_Subscription.RemoveAllMonitoredItems();//20150103增加断网恢复
|
|
m_Server.RemoveSubscription(m_Subscription);
|
|
m_Subscription = null;
|
|
}
|
|
_IfConnectOPCServer = false;//20140514张博在山东电力发现此问题
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
OpcError = "关闭OPC数据存取服务器时:" + ex.Message;
|
|
}
|
|
}
|
|
static void m_Server_CertificateEvent(CertificateValidator validator, CertificateValidationEventArgs e)
|
|
{
|
|
e.Accept = true;
|
|
|
|
}
|
|
}
|
|
}
|