欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 如何对open62541.h/open62541.c的UA_Client进行状态(在线/掉线)监控

如何对open62541.h/open62541.c的UA_Client进行状态(在线/掉线)监控

2024/10/24 15:23:41 来源:https://blog.csdn.net/joyopirate/article/details/141123737  浏览:    关键词:如何对open62541.h/open62541.c的UA_Client进行状态(在线/掉线)监控

文章目录

  • 1.背景
  • 2.解决方案
  • 3.异步连接
  • 4.注意事项
    • 4.1.线程问题
    • 4.2.UA_Client_run_iterate

1.背景

目前在利用open62541.h/open62541.c编写了一个与PLC进行OPCUA通讯的上位机程序。
上位机这边会定时对PLC的某个opcua变量进行写操作。但是假如PLC离线或者说拔掉网线,上位机就会直接崩溃死机,并且报如下的错误:

[2024-08-12 10:07:25.528 (UTC+0800)] warn/channel	Connection 2516 | SecureChannel 28 | Receiving the response failed with StatusCode BadConnectionClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/client	Received Publish Response with code BadSecureChannelClosed
[2024-08-12 10:07:25.528 (UTC+0800)] warn/channel	Connection 0 | SecureChannel 0 | Could not receive with StatusCode BadConnectionClosed
[2024-08-12 10:07:25.528 (UTC+0800)] info/client	Client Status: ChannelState: Closed, SessionState: Created, ConnectStatus: Good

有没有什么办法可以监控client的状态,了解其是什么时候掉线,掉线了我就不写就行了。

2.解决方案

幸亏,是有这么一个回调函数的,参考官方的例子【open62541/examples/client_async.c】可以发现,我们可以对UA_ClientConfig中的stateCallback进行赋值,也就是注册一个状态回调函数,从而获取客户端的状态变化。

static void
onConnect(UA_Client *client, UA_SecureChannelState channelState,UA_SessionState sessionState, UA_StatusCode connectStatus) {printf("Async connect returned with status code %s\n",UA_StatusCode_name(connectStatus));
}---UA_ClientConfig *cc = UA_Client_getConfig(client);cc->stateCallback = onConnect;

一般检测channelState就行

// 状态变化回调函数,可以通过这个监测客户端是否断开连接
// 此回调函数的线程,貌似就是UA_Client_run_iterate所在的线程?起始应该不是,恐怕是在哪个线程调用了UA_Client相关的函数,就在那个线程;
static void
onStateChanged(UA_Client *client,UA_SecureChannelState channelState,UA_SessionState sessionState,UA_StatusCode connectStatus)
{if(channelState == UA_SECURECHANNELSTATE_CLOSED) // 连接已断开{qDebug() << "callback thread:" << QThread::currentThread();qDebug() << "连接已断开--------" << QDateTime::currentDateTime();---}
}

3.异步连接

在实际使用中,假如opcua服务端是离线的话,执行UA_Client_connect会导致线程卡住很长一段时间。假如不希望卡住的话,得使用异步连接:UA_Client_connectAsync
使用UA_Client_connectAsync后,需要在stateCallback函数中判断是否连接上。完全连接上的话,
UA_SessionState sessionState会等于UA_SESSIONSTATE_ACTIVATED;

static void
onStateChanged(UA_Client *client,UA_SecureChannelState channelState,UA_SessionState sessionState,UA_StatusCode connectStatus)
{
}

假如你在onStateChanged中将channelState、sessionState打印出来的话,会发现channelState先从上往下满足下面的顺序:
在这里插入图片描述
然后是sessionState从上往下满足下面的顺序:
在这里插入图片描述
此外,一定要记得在某个地方周期地调用UA_Client_run_iterate,否则,不会进入回调函数。

4.注意事项

4.1.线程问题

这个opcua库对多线程的处理比较差,很容易造成冲突。一定要自己加个互斥锁,否则程序很容易就崩掉。

4.2.UA_Client_run_iterate

一定要在某个地方周期调用。但是最好不是在子线程中调用,除非你有把握控制好线程冲突(比如加互斥锁之类)。


参考:
【open62541/examples/client_async.c】

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com