目录
2.opc客户端程序:uaexpert 提取码:0kpmuaexpert 提取码:
3.使用KEPServerv6进行OPC_UA的服务器搭建:服务器搭建
4. 使用KEPServerv6添加仿真:此链接第五步或者此链接前两步
前言:
本文章介绍如何使用Qt搭建客户端并并和服务端完成简单的读写操作
(1)先给KEPServerv6添加仿真
(2)让uaexpert访问kepservere
点击OK即可连接成功,然后按下面步骤找到对应节点的信息
双击s1得到下面方框中的信息,这里面包含节点的信息,其中NodeId用于后面Qt访问
1.打开Qt,并在.pro文件和.h文件中分别加入:
QT += opcua
#include <QOpcUaClient>
#include <QOpcUaNode>
#include <QtOpcUa>
#include <QDebug>
2.在.ui文件里面加入三个按钮,并如下命名
三个按钮的槽函数分别如下:
void MainWindow::on_btn_requestEndpoints_clicked()
{
client->requestEndpoints(QUrl("opc.tcp://127.0.0.1:49320"));
}
void MainWindow::on_btn_readnode_clicked()
{
node->readAttributes(QOpcUa::NodeAttribute::Value);
qDebug()<<"readnode"<<node->nodeId();
}
void MainWindow::on_btn_writeAttribute_clicked()
{
QOpcUa::NodeAttribute attribute ;
attribute = QOpcUa::NodeAttribute::Value;
QVariant var=12;
//node->writeAttribute(attribute,QString("ssss"),QOpcUa::Types::String);
node->writeAttribute(attribute,var);
}
3.创建QOpcUaClient对象,官方例子如下
QOpcUaProvider provider;
if (provider.availableBackends().isEmpty())
return;
QOpcUaClient *client = provider.createClient(provider.availableBackends()[0]);
if (!client)
return;
// Connect to the stateChanged signal. Compatible slots of QObjects can be used instead of a lambda.
QObject::connect(client, &QOpcUaClient::stateChanged, [client](QOpcUaClient::ClientState state) {
qDebug() << "Client state changed:" << state;
if (state == QOpcUaClient::ClientState::Connected) {
QOpcUaNode *node = client->node("ns=0;i=84");
if (node)
qDebug() << "A node object has been created";
}
});
QObject::connect(client, &QOpcUaClient::endpointsRequestFinished,
[client](QList<QOpcUaEndpointDescription> endpoints) {
qDebug() << "Endpoints returned:" << endpoints.count();
if (endpoints.size())
client->connectToEndpoint(endpoints.first()); // Connect to the first endpoint in the list
});
client->requestEndpoints(QUrl("opc.tcp://127.0.0.1:4840")); // Request a list of endpoints from the server
创建 QOpcUaClient 使用 QOpcUaProvider , request a list of endpoints from the server using requestEndpoints 和调用 connectToEndpoint () to connect to one of the available endpoints. After the connection is established, a QOpcUaNode object for the root node is requested.
接下来按官方例子创建QOpcUaClient对象,并连接到服务器
(1)在.h文件中输入下面代码
public slots:
void on_btn_requestEndpoints_clicked();
void on_btn_readnode_clicked();
void on_btn_writeAttribute_clicked();
void SLOT_endpointsRequestFinished (QVector<QOpcUa::QEndpointDescription> endpoints , QOpcUa::UaStatusCode statusCode);
void SLOT_attributeRead ( QOpcUa::NodeAttributes attributes );
void SLOT_stateChanged (QOpcUaClient::ClientState state );
private:
Ui::MainWindow *ui;
QOpcUaClient *client;
QOpcUaProvider* provider;
QOpcUaNode* node;
(2)创建QOpcUaClient对象,并像例子中一样连接槽
provider = new QOpcUaProvider(this);
client = provider->createClient(QString("open62541"));
connect(client,&QOpcUaClient::endpointsRequestFinished,this,&MainWindow::SLOT_endpointsRequestFinished);
connect(client,&QOpcUaClient::stateChanged,this,&MainWindow::SLOT_stateChanged);
(3)按下按钮requestEndpoints,如果请求成功会跳到槽函数SLOT_endpointsRequestFinished
void MainWindow::SLOT_endpointsRequestFinished(QVector<QOpcUa::QEndpointDescription> endpoints, QOpcUa::UaStatusCode statusCode)
{
qDebug()<<endpoints.at(0).endpointUrl();
qDebug()<<statusCode;
qDebug() << "Endpoints returned:" << endpoints.count();
qDebug()<<endpoints.size();
if (endpoints.size())
client->connectToEndpoint(endpoints.at(0).endpointUrl()); // Connect to the first endpoint in the list
}
(4)跳到该槽函数后,会让创建的客户端对象连接到服务器,如果连接成功,会跳到槽函数SLOT_stateChanged
void MainWindow::SLOT_stateChanged(QOpcUaClient::ClientState state)
{
qDebug() << "Client state changed:" << state;
if (state == QOpcUaClient::ClientState::Connected) {
//QOpcUaNode定义
node = client->node("ns=2;s=my.plc.s1");
if (node)
qDebug() << "A node object has been created";
}
connect(node,&QOpcUaNode::attributeRead,this,&MainWindow::SLOT_attributeRead);
}
当创建的客户端对象连接到服务端之后,会进入到这个槽函数中,在这里面定义一个节点,其中节点的名字为在uaexpert中得到的nodeid,然后连接槽,如果读到节点属性后,就转到槽,官方创建节点例子如下
QOpcUaNode *rootNode; // Created before, see QOpcUaClient documentation.
// Connect to the attributeRead signal. Compatible slots of QObjects can be used instead of a lambda.
QObject::connect(rootNode, &QOpcUaNode::attributeRead, [rootNode, client](QOpcUa::NodeAttributes attr) {
qDebug() << "Signal for attributes:" << attr;
if (rootNode->attributeError(QOpcUa::NodeAttribute::BrowseName) != QOpcUa::UaStatusCode::Good) {
qDebug() << "Failed to read attribute:" << rootNode->attributeError(QOpcUa::NodeAttribute::BrowseName);
client->disconnectFromEndpoint();
}
qDebug() << "Browse name:" << rootNode->attribute(QOpcUa::NodeAttribute::BrowseName).value<QOpcUaQualifiedName>().name();
});
rootNode->readAttributes(QOpcUa::NodeAttribute::BrowseName); // Start a read operation for the node's BrowseName attribute.
这里面定义的节点没有赋值,我在操作的时候提示错误,所以我上面提前定义的时候就赋值了
(5)按下按钮readnode,转到槽SLOT_attributeRead,开始读节点内容
void MainWindow::SLOT_attributeRead(QOpcUa::NodeAttributes attributes)
{
qDebug() << "Signal for attributes:" << attributes;
qDebug()<<"value:"<<node->attribute(QOpcUa::NodeAttribute::Value);
}
节点的属性很多,在按钮readnode中,读的是Value,因此这里输出的就是Value,如果读的是其他值,这里可以得到其他值。(初值可以在KEPServerv6的客户端中更改)
(6)按下按钮writeAttribute,就可以对节点写入所定义的属性,这里属性可以参考:属性
总结:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
provider = new QOpcUaProvider(this);
//if (provider.availableBackends().isEmpty())
client = provider->createClient(QString("open62541"));
connect(client,&QOpcUaClient::endpointsRequestFinished,this,&MainWindow::SLOT_endpointsRequestFinished);
connect(client,&QOpcUaClient::stateChanged,this,&MainWindow::SLOT_stateChanged);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btn_requestEndpoints_clicked()
{
client->requestEndpoints(QUrl("opc.tcp://127.0.0.1:49320"));
}
void MainWindow::on_btn_readnode_clicked()
{
node->readAttributes(QOpcUa::NodeAttribute::Value);
qDebug()<<"readnode"<<node->nodeId();
}
void MainWindow::on_btn_writeAttribute_clicked()
{
QOpcUa::NodeAttribute attribute ;
attribute = QOpcUa::NodeAttribute::Value;
QVariant var=12;
//node->writeAttribute(attribute,QString("ssss"),QOpcUa::Types::String);
node->writeAttribute(attribute,var);
}
void MainWindow::SLOT_endpointsRequestFinished(QVector<QOpcUa::QEndpointDescription> endpoints, QOpcUa::UaStatusCode statusCode)
{
qDebug()<<endpoints.at(0).endpointUrl();
//qDebug() <<endpoints.first().endpointUrl();
qDebug()<<statusCode;
qDebug() << "Endpoints returned:" << endpoints.count();
qDebug()<<endpoints.size();
if (endpoints.size())
client->connectToEndpoint(endpoints.at(0).endpointUrl()); // Connect to the first endpoint in the list
}
void MainWindow::SLOT_attributeRead(QOpcUa::NodeAttributes attributes)
{
qDebug() << "Signal for attributes:" << attributes;
// if (node->attributeError(QOpcUa::NodeAttribute::BrowseName) != QOpcUa::UaStatusCode::Good) {
// qDebug() << "Failed to read attribute:" << node->attributeError(QOpcUa::NodeAttribute::BrowseName);
// client->disconnectFromEndpoint();
// }
//qDebug() << "Browse name:" << node->attribute(QOpcUa::NodeAttribute::BrowseName).value<QOpcUa::QQualifiedName>().name();
qDebug()<<"value:"<<node->attribute(QOpcUa::NodeAttribute::Value);
}
void MainWindow::SLOT_stateChanged(QOpcUaClient::ClientState state)
{
qDebug() << "Client state changed:" << state;
if (state == QOpcUaClient::ClientState::Connected) {
//QOpcUaNode定义
node = client->node("ns=2;s=my.plc.s1");
if (node)
qDebug() << "A node object has been created";
}
connect(node,&QOpcUaNode::attributeRead,this,&MainWindow::SLOT_attributeRead);
}
摘要:相机成像原理涉及点在不同坐标系中的矩阵变换,包括世界、相机、像平面和像素平面坐标系。具体变换关系可用矩阵表达,可求得单位向量。
文章浏览阅读4.4k次,点赞4次,收藏12次。SE 也就是 Secure Element,译为 “安全元素”主要应用场景在 手机手表交通卡、门禁、虚拟钱包、虚拟SIM卡,以及其他身份认证的且对安全级别有一定要求的业务。_sim trasmit apdu
文章浏览阅读5.1k次。Flutter自带WebView不想说啥了,就这样吧。反正一番周折之后选择使用第三方的InAppWebView。看源码可以看出本质上是用了Platform调回原生平台的webview,但是xing nen_inappwebview
文章浏览阅读6.7k次,点赞2次,收藏10次。spring boot/mvc通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理在spring web项目开发中,我们经常会遇到各种exception,这些exception根据业务或者场景不同抛出不同的信息和返回类型,有的exception需要返回json数据格式的错误,有的exceptio..._handlemaxuploadsizeexceededexception
文章浏览阅读365次,点赞3次,收藏5次。推荐开源项目:iOS-General-Tools - iOS 开发者的全能工具箱项目地址:https://gitcode.com/YouXianMing/iOS-General-ToolsiOS-General-Tools 是一个强大的、开源的 iOS 开发工具集合,由开发者 YouXianMing 维护。它旨在简化 iOS 应用开发过程中的各种任务,提高效率,并提供了一站式的解决方案。下面我...
文章浏览阅读220次。access_token用户执行微信公众号操作的凭证将appid和APPSECRET拼接到指定的url发送给微信服务器private static final String URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRE..._获取accesstoken json
文章浏览阅读1.5k次,点赞2次,收藏8次。思路:从一个用户(本例为“张佳玮”)出发,来爬取其粉丝,进而爬取其粉丝的粉丝…先来观察网页结构:审查元素:可以看到用户“关注的人”等信息在网页中用json格式保存在data中。当把鼠标移到列表中的某个名字上时,可以看到浏览器产生了一个Ajax请求:请求的url后面加上了很长的一串查询字符串。并且json中也请求了许多详细的信息。这与该用户的主页基本是对应的:实战我们..._运用分布式框架抓取知乎网站用户的信息,包括用户的姓名(昵称)、一句话介绍、部分
文章浏览阅读3.9k次,点赞8次,收藏35次。文章目录23种设计模式——装饰者模式1、装饰者模式概述2、装饰者模式的结构3、装饰者模式的实现4、装饰者模式的应用场景23种设计模式——装饰者模式1、装饰者模式概述背景有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。装饰者模式的定义装饰者(Decorator)模式的定义:指在不改_装饰者模式
文章浏览阅读6.2k次。【100个】关于网页制作论文参考文献大全汇总,作为大学生的毕业生应该明白了网页制作参考文献有哪些,收集好参考文献后的网页制作论文写作起来会更轻松!一、网页制作论文参考文献范文[1]开展电脑社团活动培养学生信息素养——中学生网页制作社团活动报告.童宇阳,2009第九届中国教育信息化创新与发展论坛[2]项目教学法在《网页制作基础》课程中的应用.胡永刚,20072007无锡职教教师论坛[3]基于SVG的..._计算机网页制作相关参考文献
文章浏览阅读1.7k次。前言:记录在自学生信过程中所遇到的一些问题,如何去解决的。希望我的经验可以对他人有帮助。 注意:不要复制代码,因软件版本更新等问题,命令会变化的。重点学习怎么去解决问题。 一:执行zcat cz2_1.fq.gz,屏幕出现了群魔乱舞,想要恢复到正常的命令行模式下。 1、直接终止正在运行的程序,使用ctrl+c。 2、让程序进入后台运行,使用ctrl+z,进..._couldn't build a bowtie2.index from hg38.fa
文章浏览阅读84次。在Angularjs开发一些经验总结随笔中提到我们需要按照业务却分angular controller,避免过大无所不能的上帝controller,我们把controller分离开了,但是有时候我们需要在controller中通信,一般为比较简单的通信机制,告诉同伴controller我的某个你所关心的东西改变了,怎么办?如果你是一个javascript程序员你会很自然的想到异步回调响应...
文章浏览阅读9.5k次。C++重要语言基础1.语言基础1.1空间的配置与释放--std:alloc(SGI实现)1.2内存池1.语言基础1.1空间的配置与释放–std:alloc(SGI实现)SGI标准模版库:设计时需要考虑的问题:从堆区申请内存空间;考虑多线程;考虑内存不足时的应对措施;考虑大量小区块可能造成的内存碎片问题;SGI的alloc类是使用了双层配置器:分别处理大内存请求和小内存请..._c++ 申请内存池用于接管内存分配