@[Kepware与C#]
Kepware与C#
概述
本章描述的是,如何使用C#读写Kepware软件上的标记值。
这是我网上下载的示例代码☞提取码:jv4x
运行的程序如图所示:
个人测试代码
前提是安装了Kepware软件
①添加引用
下载DLL
②工具类代码
OpcUaClient工具类
using Common.Log;
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace namespace1
{
/// <summary>
/// 一个二次封装了的OPC UA库
/// </summary>
public class OpcUaClient
{
#region Private Fields
private static Logger logger = Logger.getLogger();
private Dictionary<string, Subscription> dic_subscriptions;//系统所有的节点信息
private ApplicationInstance application;
private ApplicationConfiguration m_configuration;
private Session m_session;
private bool m_IsConnected; //是否已经连接过
private SessionReconnectHandler m_reconnectHandler;
private bool m_useSecurity;
private EventHandler m_ConnectComplete;
private EventHandler<OpcUaStatusEventArgs> m_OpcStatusChange;
private int m_reconnectPeriod = 10; // 重连状态
private EventHandler m_ReconnectStarting;
private EventHandler m_KeepAliveComplete;
private EventHandler m_ReconnectComplete;
#endregion
#region Public Members
public string OpcUaName = "Opc Ua Helper";
/// <summary>
/// Whether to use security when connecting.
/// </summary>
public bool UseSecurity
{
get { return m_useSecurity; }
set { m_useSecurity = value; }
}
/// <summary>
/// The user identity to use when creating the session.
/// </summary>
public IUserIdentity UserIdentity { get; set; }
/// <summary>
/// The currently active session.
/// </summary>
public Session Session
{
get { return m_session; }
}
/// <summary>
/// Indicate the connect status
/// </summary>
public bool Connected
{
get { return m_IsConnected; }
}
/// <summary>
/// The number of seconds between reconnect attempts (0 means reconnect is disabled).
/// </summary>
public int ReconnectPeriod
{
get { return m_reconnectPeriod; }
set { m_reconnectPeriod = value; }
}
/// <summary>
/// Raised when a good keep alive from the server arrives.
/// </summary>
public event EventHandler KeepAliveComplete
{
add { m_KeepAliveComplete += value; }
remove { m_KeepAliveComplete -= value; }
}
/// <summary>
/// Raised when a reconnect operation starts.
/// </summary>
public event EventHandler ReconnectStarting
{
add { m_ReconnectStarting += value; }
remove { m_ReconnectStarting -= value; }
}
/// <summary>
/// Raised when a reconnect operation completes.
/// </summary>
public event EventHandler ReconnectComplete
{
add { m_ReconnectComplete += value; }
remove { m_ReconnectComplete -= value; }
}
/// <summary>
/// Raised after successfully connecting to or disconnecing from a server.
/// </summary>
public event EventHandler ConnectComplete
{
add { m_ConnectComplete += value; }
remove { m_ConnectComplete -= value; }
}
/// <summary>
/// Raised after the client status change
/// </summary>
public event EventHandler<OpcUaStatusEventArgs> OpcStatusChange
{
add { m_OpcStatusChange += value; }
remove { m_OpcStatusChange -= value; }
}
/// <summary>
/// 配置信息
/// </summary>
public ApplicationConfiguration AppConfig
{
get
{
return m_configuration;
}
}
#endregion
#region OpcUaClient 默认的构造函数,实例化一个新的OPC UA类,初始化配置
/// <summary>
/// 默认的构造函数,实例化一个新的OPC UA类,初始化配置
/// </summary>
public OpcUaClient()
{
dic_subscriptions = new Dictionary<string, Subscription>();//初始化变量 ‘系统所有的节点信息’
var certificateValidator = new CertificateValidator();
certificateValidator.CertificateValidation += (sender, eventArgs) =>
{
if (ServiceResult.IsGood(eventArgs.Error))
eventArgs.Accept = true;
else if (eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted)
eventArgs.Accept = true;
else
throw new Exception(string.Format("Failed to validate certificate with error code {0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo));
};
SecurityConfiguration securityConfigurationcv = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true,
RejectSHA1SignedCertificates = false,
MinimumCertificateKeySize = 1024,
};
certificateValidator.Update(securityConfigurationcv);
// Build the application configuration
application = new ApplicationInstance
{
ApplicationType = ApplicationType.Client,
ConfigSectionName = OpcUaName,
ApplicationConfiguration = new ApplicationConfiguration
{
ApplicationName = OpcUaName,
ApplicationType = ApplicationType.Client,
CertificateValidator = certificateValidator,
ServerConfiguration = new ServerConfiguration
{
MaxSubscriptionCount = 100000,
MaxMessageQueueSize = 1000000,
MaxNotificationQueueSize = 1000000,
MaxPublishRequestCount = 10000000,
},
SecurityConfiguration = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true,
RejectSHA1SignedCertificates = false,
MinimumCertificateKeySize = 1024,
},
TransportQuotas = new TransportQuotas
{
OperationTimeout = 6000000,
MaxStringLength = int.MaxValue,
MaxByteStringLength = int.MaxValue,
MaxArrayLength = 65535,
MaxMessageSize = 419430400,
MaxBufferSize = 65535,
ChannelLifetime = -1,
SecurityTokenLifetime = -1
},
ClientConfiguration = new ClientConfiguration
{
DefaultSessionTimeout = -1,
MinSubscriptionLifetime = -1,
},
DisableHiResClock = true
}
};
m_configuration = application.ApplicationConfiguration;
}
#endregion
#region Connect 连接 POC
/// <summary>
/// connect to server
/// </summary>
/// <param name="serverUrl">remote url</param>
public async Task ConnectServer(string serverUrl)
{
m_session = await Connect(serverUrl);
}
/// <summary>
/// Creates a new session.
/// </summary>
/// <returns>The new session object.</returns>
private async Task<Session> Connect(string serverUrl)
{
logger.DebugStart("OpcUaClient.Connect -> serverUrl="+ serverUrl);
// disconnect from existing session.
//Disconnect();
if (serverUrl==String.Empty|| serverUrl==null)
{
throw new ArgumentNullException("serverUrl");
}
if (m_configuration == null)
{
throw new ArgumentNullException("m_configuration");
}
// select the best endpoint.
EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(serverUrl, UseSecurity,3000);//超时设置 为3s
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration);
ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration);
m_session = await Session.Create(
m_configuration,
endpoint,
false,
false,
(string.IsNullOrEmpty(OpcUaName)) ? m_configuration.ApplicationName : OpcUaName,
60000,
UserIdentity,
new string[] { });
// set up keep alive callback.
m_session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive);
// update the client status
m_IsConnected = true;
// raise an event.
DoConnectComplete(null);
// return the new session.
logger.DebugEnd("OpcUaClient.Connect");
return m_session;
}
#endregion
#region Disconnect 断开连接 POC
/// <summary>
/// Disconnects from the server.
/// </summary>
public void Disconnect()
{
//修改状态
UpdateStatus(false, DateTime.UtcNow, "Disconnected");
// stop any reconnect operation.
if (m_reconnectHandler != null)
{
m_reconnectHandler.Dispose();
m_reconnectHandler = null;
}
// disconnect any existing session.
if (m_session != null)
{
m_session.Close(10000);
m_session = null;
}
// update the client status
m_IsConnected = false;
// raise an event.
DoConnectComplete(null);
}
#endregion
#region 设置OPC客户端的日志输出
/// <summary>
/// 设置OPC客户端的日志输出
/// </summary>
/// <param name="filePath">完整的文件路径</param>
/// <param name="deleteExisting">是否删除原文件</param>
public void SetLogPathName(string filePath, bool deleteExisting)
{
Utils.SetTraceLog(filePath, deleteExisting);
Utils.SetTraceMask(515);
}
#endregion
#region Event Handlers 异常处理
/// <summary>
/// Handles a keep alive event from a session.
/// </summary>
private void Session_KeepAlive(Session session, KeepAliveEventArgs e)
{
try
{
// check for events from discarded sessions.
if (!Object.ReferenceEquals( session, m_session ))
{
return;
}
// start reconnect sequence on communication error.
if (ServiceResult.IsBad( e.Status ))
{
if (m_reconnectPeriod <= 0)
{
// 上报连接状态
UpdateStatus( true, e.CurrentTime, "Communication Error ({0})", e.Status );
return;
}
// 上报连接状态
UpdateStatus( true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod );
if (m_reconnectHandler == null)
{
if(m_ReconnectStarting!=null){
m_ReconnectStarting.Invoke( this, e );
}
m_reconnectHandler = new SessionReconnectHandler( );
m_reconnectHandler.BeginReconnect( m_session, m_reconnectPeriod * 1000, Server_ReconnectComplete );
}
return;
}
// 上报连接状态
UpdateStatus( false, e.CurrentTime, "Connected [{0}]", session.Endpoint.EndpointUrl );
// raise any additional notifications.
if (m_KeepAliveComplete != null)
{
m_KeepAliveComplete.Invoke(this, e);
}
}
catch (Exception exception)
{
Console.Write(exception);
throw;
}
}
/// <summary>
/// Report the client status
/// </summary>
/// <param name="error">Whether the status represents an error.</param>
/// <param name="time">The time associated with the status.</param>
/// <param name="status">The status message.</param>
/// <param name="args">Arguments used to format the status message.</param>
private void UpdateStatus(bool error, DateTime time, string status, params object[] args)
{
m_OpcStatusChange?.Invoke(this, new OpcUaStatusEventArgs()
{
Error = error,
Time = time.ToLocalTime(),
Text = String.Format(status, args),
});
}
/// <summary>
/// Handles a reconnect event complete from the reconnect handler.
/// </summary>
private void Server_ReconnectComplete(object sender, EventArgs e)
{
try
{
// ignore callbacks from discarded objects.
if (!Object.ReferenceEquals( sender, m_reconnectHandler ))
{
return;
}
m_session = m_reconnectHandler.Session;
m_reconnectHandler.Dispose( );
m_reconnectHandler = null;
// raise any additional notifications.
if (m_ReconnectComplete != null)
{
m_ReconnectComplete.Invoke(this, e);
}
}
catch (Exception exception)
{
Console.Write(exception);
throw;
}
}
#endregion
#region Node Write/Read Support
/// <summary>
/// Read a value node from server
/// </summary>
/// <param name="nodeId">node id</param>
/// <returns>DataValue</returns>
public DataValue ReadNode(NodeId nodeId)
{
ReadValueIdCollection nodesToRead = new ReadValueIdCollection
{
new ReadValueId( )
{
NodeId = nodeId,
AttributeId = Attributes.Value
}
};
// read the current value
m_session.Read(
null,
0,
TimestampsToReturn.Neither,
nodesToRead,
out DataValueCollection results,
out DiagnosticInfoCollection diagnosticInfos);
ClientBase.ValidateResponse(results, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
return results[0];
}
/// <summary>
/// write a note to server(you should use try catch)
/// </summary>
/// <typeparam name="T">The type of tag to write on</typeparam>
/// <param name="tag">节点名称</param>
/// <param name="value">值</param>
/// <returns>if success True,otherwise False</returns>
public bool WriteNode<T>(string tag, T value)
{
WriteValue valueToWrite = new WriteValue()
{
NodeId = new NodeId(tag),
AttributeId = Attributes.Value
};
valueToWrite.Value.Value = value;
valueToWrite.Value.StatusCode = StatusCodes.Good;
valueToWrite.Value.ServerTimestamp = DateTime.MinValue;
valueToWrite.Value.SourceTimestamp = DateTime.MinValue;
WriteValueCollection valuesToWrite = new WriteValueCollection
{
valueToWrite
};
// 写入当前的值
m_session.Write(
null,
valuesToWrite,
out StatusCodeCollection results,
out DiagnosticInfoCollection diagnosticInfos);
ClientBase.ValidateResponse(results, valuesToWrite);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite);
if (StatusCode.IsBad(results[0]))
{
throw new ServiceResultException(results[0]);
}
return !StatusCode.IsBad(results[0]);
}
#endregion
/// <summary>
/// Raises the connect complete event on the main GUI thread.
/// </summary>
private void DoConnectComplete(object state)
{
//m_ConnectComplete?.Invoke( this, null );
if(m_ConnectComplete!=null){
m_ConnectComplete.Invoke(this, null);
}
}
}
}
OpcUaClient工具类
using System;
using Opc.Ua;
using Common.Log;
using Common.Response;
namespace namespace1
{
public class OpcUaHelper
{
private static Logger logger = Logger.getLogger();
private OpcUaClient m_OpcUaClient = null;
private string curStatusStr=String.Empty;
private bool curStatus = false;
# region 单例模式
/// <summary>
/// 获取一个单例对象
/// </summary>
/// <returns></returns>
private static OpcUaHelper instance;
private static readonly object locks = new object();//确保线程同步
private OpcUaHelper() {
m_OpcUaClient = new OpcUaClient();
}
/// <summary>
///获取唯一可用的对象
/// </summary>
/// <returns></returns>
public static OpcUaHelper getInstance()
{
if (instance == null)
{
lock (locks)
{
if (instance == null)
{
instance = new OpcUaHelper();
}
}
}
return instance;
}
#endregion
/// <summary>
/// 连接OPC软件,返回m_OpcUaClient0
/// </summary>
/// <param name="url"></param>
/// <param name="user"></param>
/// <param name="password"></param>
/// <param name="m_OpcUaClient0"></param>
/// <returns></returns>
public bool connectGet(string url, string user, string password,out OpcUaClient m_OpcUaClient0)
{
bool result = false;
m_OpcUaClient0 = null;
try
{
//连接OPC软件
connectServer(url, user, password);
result = connectFlag;
m_OpcUaClient0 = m_OpcUaClient;
}
catch (Exception ex)
{
logger.Error("Common.OpcUaHelper.connectGet -> url=" + url + ",user=" + user + ",password=" + password + "—>" + ex.ToString());
}
return result;
}
/// <summary>
/// 连接OPC软件
/// </summary>
/// <param name="url"></param>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool connect(string url, string user, string password)
{
bool result = false;
try
{
//连接OPC软件
connectServer(url,user,password);
result = connectFlag;
}
catch (Exception ex)
{
logger.Error("OpcUaHelper.connect -> url=" + url + ",user=" + user + ",password=" + password + "—>" + ex.ToString());
}
return result;
}
/// <summary>
/// OPC 客户端的状态变化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void M_OpcUaClient_OpcStatusChange(object sender, OpcUaStatusEventArgs e)
{
//logger.Debug("Current session:" + m_OpcUaClient.Session.Connected);
if (curStatusStr != e.Text|| e.Error||!m_OpcUaClient.Session.Connected)
{
curStatusStr = e.Text;
logger.Debug("OpcStatus:" + e.ToString());
}
//修改当前会话状态
if (e.Error || !m_OpcUaClient.Session.Connected)
{
curStatus = false;
}
else
{
curStatus = true;
}
}
/// <summary>
/// 获取当前会话的状态
/// </summary>
/// <returns></returns>
public Boolean getCurrentStatue()
{
return curStatus;
}
/// <summary>
/// 连接服务器结束后事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void M_OpcUaClient_ConnectComplete(object sender, EventArgs e)
{
try
{
//logger.Info("Connect Success.");
}
catch (Exception exception)
{
logger.Error("OpcUaHelper.M_OpcUaClient_ConnectComplete ->" + exception.ToString());
}
}
private bool connectFlag = false;
/// <summary>
/// 连接OPC软件
/// </summary>
/// <param name="url"></param>
/// <param name="user"></param>
/// <param name="password"></param>
private async void connectServer(string url, string user, string password)
{
connectFlag = false;
try
{
m_OpcUaClient.SetLogPathName((new BasePathHelper().GetRootPath()) + "\\Log\\opc.ua.client.txt", true);//输出日志
m_OpcUaClient.OpcStatusChange += M_OpcUaClient_OpcStatusChange;//监控状态
m_OpcUaClient.ConnectComplete += M_OpcUaClient_ConnectComplete;//完成事件
m_OpcUaClient.UserIdentity = new UserIdentity(user, password);
await m_OpcUaClient.ConnectServer(url);
connectFlag = true;
}
catch (Exception ex)
{
logger.Error("OpcUaHelper.connectServer url=" + url+ ",user="+ user+ ",password="+ password+"——"+ ex.ToString());
}
}
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
m_OpcUaClient.Disconnect();
}
catch (Exception ex)
{
logger.Error("Common.OpcUaHelper.connect Disconnect unsuccessfully. ——"+ex.ToString());
throw;
}
}
/// <summary>
/// 读取指定地址的值
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public ReturnVO<String> readNode(string tag)
{
ReturnVO<String> result = null;
if (tag != string.Empty)
{
try
{
NodeId nodeId = new NodeId(tag);
DataValue value = m_OpcUaClient.ReadNode(nodeId);
if (value != null)
{
if (!(value.ToString()).Contains("null"))
{
result = new ReturnVO<String>(true, null, value.ToString());
}
else
{
//读取指定地址失败,请查看OPC软件与PLC通讯是否正常或OPC软件中该地址是否存在
ErrorCode.Opc error = ErrorCode.Opc.ox100002;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.readNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag);
}
}
else
{
//读取指定地址失败,编码错误
ErrorCode.Common error = ErrorCode.Common.cx100001;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.readNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag);
}
}
catch (Exception ex)
{
//读取指定地址失败,编码错误
ErrorCode.Common error = ErrorCode.Common.cx100001;
result = new ReturnVO<String>(false, error.GetDescription(), null);
Global.IsConnected = false;
logger.Error("Common.OpcUaHelper.readNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag);
logger.Error("Common.OpcUaHelper.readNode " + ex.ToString());
throw;
}
}
else
{
//参数传递错误
ErrorCode.Common error = ErrorCode.Common.cx100002;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.readNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag);
}
return result;
}
/// <summary>
/// 写入指定地址指定数据类型的值
/// </summary>
/// <param name="tag"></param>
/// <param name="value"></param>
/// <returns></returns>
public ReturnVO<String> writeNode(string tag, string value)
{
ReturnVO<String> result = null;
if (tag != string.Empty && value != string.Empty)
{
try
{
//获取节点的数据类型
NodeId nodeId = new NodeId(tag);
DataValue node = m_OpcUaClient.ReadNode(nodeId);
if (node != null)
{
if (!(node.ToString()).Contains("null"))
{
BuiltInType builtInType = node.WrappedValue.TypeInfo.BuiltInType;
//写入数据
dynamic inputValue = GetValueFromString(value, builtInType);
bool b = m_OpcUaClient.WriteNode(tag, inputValue);
result = new ReturnVO<String>(b,b?"": ErrorCode.Opc.ox100004.GetDescription(), null);//可能出现写入失败 ox100004
}
else
{
//读取指定地址失败,请查看OPC软件与PLC通讯是否正常或OPC软件中该地址是否存在
ErrorCode.Opc error = ErrorCode.Opc.ox100002;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.writeNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag + ",value=" + value);
}
}
else
{
//编码错误
ErrorCode.Common error = ErrorCode.Common.cx100001;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.writeNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag + ",value=" + value);
}
}
catch (Exception ex)
{
//编码错误
ErrorCode.Common error = ErrorCode.Common.cx100001;
result = new ReturnVO<String>(false, error.GetDescription(), null);
Global.IsConnected = false;
logger.Error("Common.OpcUaHelper.writeNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag + ",value=" + value);
logger.Error("Common.OpcUaHelper.writeNode " + ex.ToString());
throw;
}
}
else
{
//参数传递错误
ErrorCode.Common error = ErrorCode.Common.cx100002;
result = new ReturnVO<String>(false, error.GetDescription(), null);
logger.Error("Common.OpcUaHelper.writeNode " + error + "->" + error.GetDescription() + "-> Param:tag=" + tag + ",value=" + value);
}
return result;
}
/// <summary>
/// 将字符串转换为指定数据类型
/// </summary>
/// <param name="value"></param>
/// <param name="builtInType"></param>
/// <returns></returns>
private dynamic GetValueFromString(string value, BuiltInType builtInType)
{
switch (builtInType)
{
case BuiltInType.Boolean:
{
return bool.Parse(value);
}
case BuiltInType.Byte:
{
return byte.Parse(value);
}
case BuiltInType.DateTime:
{
return DateTime.Parse(value);
}
case BuiltInType.Double:
{
return double.Parse(value);
}
case BuiltInType.Float:
{
return float.Parse(value);
}
case BuiltInType.Guid:
{
return Guid.Parse(value);
}
case BuiltInType.Int16:
{
return short.Parse(value);
}
case BuiltInType.Int32:
{
return int.Parse(value);
}
case BuiltInType.Int64:
{
return long.Parse(value);
}
case BuiltInType.Integer:
{
return int.Parse(value);
}
case BuiltInType.LocalizedText:
{
return value;
}
case BuiltInType.SByte:
{
return sbyte.Parse(value);
}
case BuiltInType.String:
{
return value;
}
case BuiltInType.UInt16:
{
return ushort.Parse(value);
}
case BuiltInType.UInt32:
{
return uint.Parse(value);
}
case BuiltInType.UInt64:
{
return ulong.Parse(value);
}
case BuiltInType.UInteger:
{
return uint.Parse(value);
}
default: throw new Exception("Not supported data type");
}
}
}
}
OpcUaClient工具类
using Opc.Ua;
using System;
namespace namespace1
{
/// <summary>
/// OPC UA的状态更新消息
/// </summary>
public class OpcUaStatusEventArgs
{
/// <summary>
/// 是否异常
/// </summary>
public bool Error { get; set; }
/// <summary>
/// 时间
/// </summary>
public DateTime Time { get; set; }
/// <summary>
/// 文本
/// </summary>
public string Text { get; set; }
/// <summary>
/// 转化为字符串
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Error ? "[异常]" : "[正常]" + Time.ToString(" yyyy-MM-dd HH:mm:ss ") + Text;
}
}
/// <summary>
/// 读取属性过程中用于描述的
/// </summary>
public class OpcNodeAttribute
{
/// <summary>
/// 属性的名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 属性的类型描述
/// </summary>
public string Type { get; set; }
/// <summary>
/// 操作结果状态描述
/// </summary>
public StatusCode StatusCode { get; set; }
/// <summary>
/// 属性的值,如果读取错误,返回文本描述
/// </summary>
public object Value { get; set; }
}
}
Server工具类
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace namespace1
{
[DataContract]
public class Server
{
[DataMember]
public String IP { set; get; }
[DataMember]
public String User { set; get; }
[DataMember]
public String PassWord { set; get; }
[DataMember]
public String Code { set; get; }
[DataMember]
public String Name { set; get; }
[DataMember]
public String Description { set; get; }
[DataMember]
public List<Sign> Signs{ set; get; }
public String toString()
{
return "Server[Code="+Code+ ",Name="+Name+",Description="+Description+",IP="+IP +",User="+User+",PassWord="+PassWord+ ",Signs.Length="+(Signs==null?"0":(Signs.Count+""))+"]";
}
}
[DataContract]
public class Sign
{
[DataMember]
public String Code { set; get; }
[DataMember]
public String Name { set; get; }
[DataMember]
public String Description { set; get; }
[DataMember]
public String DataType { set; get; }
[DataMember]
public String ReadPeriod { set; get; }
[DataMember]
public String NodeID { set; get; }
[DataMember]
public String Value { set; get; }
}
}
ReturnVO 工具类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace namespace1
{
[DataContract]
public class ReturnVO<T>
{
[DataMember]
private Boolean ret = true;
[DataMember]
private String msg = "";
[DataMember]
private T model;
public ReturnVO(Boolean ret, String msg, T model)
{
this.ret = ret;
this.msg = msg;
this.model = model;
}
public Boolean isRet()
{
return ret;
}
public void setRet(Boolean ret)
{
this.ret = ret;
}
public String getMsg()
{
return msg;
}
public void setMsg(String msg)
{
this.msg = msg;
}
public T getModel()
{
return model;
}
public void setModel(T model)
{
this.model = model;
}
public String toString()
{
String str = "";
if (model != null)
{
str = model.ToString();
}
return "ReturnVO [ret=" + ret + ", msg=" + msg + ", model=" + str + "]";
}
}
}
调用代码:
连接Kepware
OpcUaHelper opcUaHelper = OpcUaHelper.getInstance();
string url="";//Kepware上设置的URL
string user="";//Kepware上设置的账号
string password="";//Kepware上设置的密码
bool b = opcUaHelper.connect(url, user, password);
if (b) {
//连接成功
}else{
//连接失败
}
读标记
ReturnVO<string> obj=opcUaHelper.readNode(NodeID);
if (obj.isRet())
{
string v = obj.getModel();//正确的时候放入读取的信息
}else{
string v = obj.getMsg();//错误的时候放入错误信息
}
写标记
ReturnVO<string> obj=opcUaHelper.writeNode(NodeID,Value);
if (obj.isRet())
{
string v = obj.getModel();//正确的时候放入读取的信息
}else{
string v = obj.getMsg();//错误的时候放入错误信息
}
NodeID和Value都是string类型,
NodeID是标记的地址ID,例如‘ns=2;s=Ethernet.Equip1.B0221’
Value 是 数字
断开连接
opcUaHelper.Disconnect();
关于如何设置Kepware的URL、账号与密码
点开右下角的托盘,找到Kepware的小图标,选中右击
①设置URL
点击[OPC UA 配置],显示如下
注意:需要使用的URL必须处于[已启用]状态
可以新删改URL,并可编辑URL的安全策略
②设置账号、密码
打开[设置]→[用户管理器]
可以新删改账户与密码。
注意:最后改完后,一定要点击[重新初始化®]