228 lines
7.9 KiB
C++
228 lines
7.9 KiB
C++
//
|
||
// Created by test on 2022/11/3.
|
||
//
|
||
|
||
#include "DBPclient.h"
|
||
|
||
#include <fstream>
|
||
#include <windows.h>
|
||
|
||
DBPclient::DBPclient(std::string endpoint, std::string username, std::string password) :
|
||
dbp_endpoint(std::move(endpoint)), dbp_username(std::move(username)), dbp_password(std::move(password)) {
|
||
m_dwHandle = 0;
|
||
|
||
}
|
||
|
||
DBPclient::~DBPclient() {
|
||
|
||
}
|
||
|
||
bool DBPclient::connect() {
|
||
// 设置连接参数
|
||
WORD wport = 12084;
|
||
|
||
m_dwHandle = DBPCreate2(dbp_endpoint.data(), dbp_username.data(), dbp_password.data(), wport, false); //创建对象
|
||
|
||
std::chrono::steady_clock::time_point t_begin = std::chrono::steady_clock::now();
|
||
//创建对象 启动连接
|
||
DWORD ret;
|
||
if (m_dwHandle) {
|
||
ret = DBPConnect(m_dwHandle);
|
||
if (ret == 0) {
|
||
//取连接信息
|
||
char sip[16];
|
||
int pnNum;
|
||
DBPGetSvrConInfo(m_dwHandle, sip, &pnNum);
|
||
|
||
std::chrono::steady_clock::time_point t_end = std::chrono::steady_clock::now();
|
||
std::chrono::duration<double> time_used = std::chrono::duration_cast < std::chrono::duration < double >> (
|
||
t_end - t_begin);
|
||
std::cout << "connect use:" << time_used << std::endl;
|
||
return true;
|
||
} else {
|
||
std::cout << "connect failed";
|
||
// std::chrono::steady_clock::time_point t_end = std::chrono::steady_clock::now();
|
||
// std::chrono::duration<double> time_used = std::chrono::duration_cast<std::chrono::duration<double>>(
|
||
// t_end - t_begin);
|
||
// std::cout << "connect failed use:" << time_used << std::endl;
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void DBPclient::disconnect() {
|
||
int pnCon;
|
||
DWORD ret;
|
||
ret = DBPIsConnect(m_dwHandle, &pnCon);
|
||
if (ret == 0 && pnCon != 0) //连接
|
||
{
|
||
DBPDisConnect(m_dwHandle);//关闭连接
|
||
DBPDestroy(m_dwHandle);//删除对象
|
||
std::cout << "disconnected";
|
||
}
|
||
}
|
||
|
||
struct DataInfo {
|
||
std::array<char, 80> szSName = {0};
|
||
std::array<char, 16> szSDBName = {0};
|
||
std::array<char, 80> szSDBTagName = {0};
|
||
std::array<char, 80> szSDes = {0};
|
||
std::array<char, 16> szSUnit = {0};
|
||
DWORD szDWid;
|
||
WORD szWType;
|
||
};
|
||
|
||
|
||
void DBPclient::readValue(const std::vector <std::string> &node_ids) {
|
||
std::vector <DataInfo> vData;
|
||
std::vector<char *> vTags;
|
||
|
||
// 读全部标签
|
||
if (m_dwHandle) {
|
||
// 查询标签,获取标签个数
|
||
DWORD ret;
|
||
long ltagnum, count = 0, nIndex = 0;
|
||
|
||
ret = DBPQueryTagFromDbp(//查询标签,查询后结果保存在对象中,下次用EnumTagAttr逐个取属性
|
||
m_dwHandle,
|
||
NULL, //标签名过滤传,NULL或空串表示全部
|
||
NULL, //描述过滤传,NULL或空串表示全部
|
||
-1, //类型,-1表示全部
|
||
<agnum //查询到的标签数
|
||
);//返回错误码
|
||
if (ret != 0) {
|
||
std::cout << "query tag error";
|
||
return;
|
||
}
|
||
|
||
std::cout << "tag num:" << ltagnum << std::endl;
|
||
|
||
vData.resize(ltagnum);
|
||
|
||
// 读标签属性
|
||
short errcode0; //错误代码
|
||
long ltagflag0; //标签标志,
|
||
|
||
std::chrono::steady_clock::time_point t_begin = std::chrono::steady_clock::now();
|
||
|
||
std::cout << "read tag" << std::endl;
|
||
for (long i = 0; i < vData.size(); i++) {
|
||
ret = DBPEnumTagAttr( //枚举查询后标签属性
|
||
m_dwHandle,
|
||
vData[i].szSName.data(), //标签名 80
|
||
vData[i].szSDBName.data(), //数据库实例名 16
|
||
vData[i].szSDBTagName.data(), //数据库标签名 80
|
||
vData[i].szSDes.data(), //描述 80
|
||
vData[i].szSUnit.data(), //单位 16
|
||
&vData[i].szDWid, //标签ID
|
||
&vData[i].szWType, //数据类型
|
||
&errcode0, //错误代码
|
||
<agflag0, //标签标志,
|
||
i //位置 0到查询的标签数-1
|
||
); //返回 DBP_OK表示成功,否则错误或没有了}
|
||
if (ret == 0) {
|
||
// for (auto const &t: vData[i].szSName) {
|
||
// std::cout << t;
|
||
// }
|
||
// std::cout << std::endl;
|
||
} else {
|
||
std::cout << i << "error code:" << errcode0 << std::endl;
|
||
return;
|
||
}
|
||
}
|
||
|
||
std::chrono::steady_clock::time_point t_end = std::chrono::steady_clock::now();
|
||
std::chrono::duration<double> time_used = std::chrono::duration_cast < std::chrono::duration < double >> (
|
||
t_end - t_begin);
|
||
std::cout << "read tag use:" << time_used << std::endl;
|
||
|
||
for (auto &d: vData) {
|
||
vTags.emplace_back(d.szSName.data());
|
||
}
|
||
|
||
std::vector<long> ltimes;
|
||
std::vector<short> snqas;
|
||
std::vector<double> dblals;
|
||
std::vector<long> lvals;
|
||
std::vector<int> ntypes;
|
||
std::vector<short> errs;
|
||
|
||
ltimes.resize(ltagnum);
|
||
snqas.resize(ltagnum);
|
||
dblals.resize(ltagnum);
|
||
lvals.resize(ltagnum);
|
||
ntypes.resize(ltagnum);
|
||
errs.resize(ltagnum);
|
||
|
||
|
||
std::cout << "read value" << std::endl;
|
||
std::chrono::steady_clock::time_point v_begin = std::chrono::steady_clock::now();
|
||
ret = DBPGetSnapshot( //读快照
|
||
m_dwHandle,
|
||
vTags.data(), //标签名数组
|
||
ltimes.data(), //in/out, 时标
|
||
snqas.data(), //in/out, 质量
|
||
dblals.data(), //in/out, 存放double值,DT_FLOAT32,DT_FLOAT64存放区
|
||
lvals.data(), //in/out, 存放Long值,DT_DIGITAL,DT_INT32,DT_INT64存放区
|
||
ntypes.data(), //in/out, 数据类型,DT_INT32,DT_FLOAT32等。
|
||
errs.data(), //in/out, 错误码
|
||
ltagnum //in, 个数
|
||
);//返回错误码
|
||
if (ret != 0) {
|
||
return;
|
||
}
|
||
|
||
std::chrono::steady_clock::time_point v_end = std::chrono::steady_clock::now();
|
||
std::chrono::duration<double> read_value_time_used =
|
||
std::chrono::duration_cast < std::chrono::duration < double >> (
|
||
v_end - v_begin);
|
||
std::cout << "read value use:" << read_value_time_used << std::endl;
|
||
for (int j = 0; j < ltagnum; j++) {
|
||
//std::cout << j << ":" << ntypes[j] << std::endl;
|
||
switch (ntypes[j]) {
|
||
case DT_DIGITAL:
|
||
dbp_read_value[vTags[j]] = lvals[j];
|
||
case DT_INT32:
|
||
dbp_read_value[vTags[j]] = lvals[j];
|
||
case DT_INT64:
|
||
//std::cout << lvals[j] << std::endl;
|
||
dbp_read_value[vTags[j]] = lvals[j];
|
||
break;
|
||
case DT_FLOAT32:
|
||
dbp_read_value[vTags[j]] = lvals[j];
|
||
case DT_FLOAT64:
|
||
//std::cout << dblals[j] << std::endl;
|
||
dbp_read_value[vTags[j]] = dblals[j];
|
||
break;
|
||
default:
|
||
dbp_read_value[vTags[j]] = 0;
|
||
}
|
||
}
|
||
}
|
||
std::fstream fs;
|
||
fs.open("value.txt", std::ios::ate | std::ios::out);
|
||
for (auto iter: dbp_read_value) {
|
||
fs << iter.first << ":" << iter.second << std::endl;
|
||
}
|
||
fs.close();
|
||
}
|
||
|
||
void DBPclient::stop() {
|
||
running = false;
|
||
disconnect();
|
||
}
|
||
|
||
void DBPclient::run() {
|
||
while (running) {
|
||
if (!connect()) {
|
||
//disconnect();
|
||
// spdlog::error("OPC-UA Server({}) not connected({}). Retrying to connect in 1 second.", ua_endpoint,
|
||
// retval);
|
||
std::cout << "Retrying to connect in 1 second." << std::endl;
|
||
Sleep(1000);
|
||
continue;
|
||
}
|
||
}
|
||
}
|