//注意在 .pro工程文件中添加 对网络访问的支持模块 QT+= network
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QtCore>
#include <iostream>
using namespace std ;
//用于插入和查询输出的数据结构与measurement结构对应
class InfluxPoint
{
public:
QString attr_oid;
QString attr_time;
qreal attr_value;
};
class TestInfluxdb : public QObject
{
public:
//构造函数1 入参形如"127.0.0.1:8086"
TestInfluxdb(const QString&host)
{
m_manager = new QNetworkAccessManager();
m_host = host;
}
//构造函数2,提供host和数据库名称db
TestInfluxdb(const QString&host, const QString& db)
{
m_manager = new QNetworkAccessManager();
m_db = db;
m_host = host;
}
//构造函数3,提供host 数据库名称db,用户,密码
TestInfluxdb(const QString&host, const QString& db, const QString& usr, const QString& pwd)
{
m_manager = new QNetworkAccessManager();
m_db = db;
m_usr = usr;
m_pwd = pwd;
m_host = host;
}
//析构函数
~TestInfluxdb()
{
delete m_manager;
}
//执行非查询语句
QString execNonSelect(const QString & url)
{
QByteArray ba;
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
QNetworkReply *reply = m_manager->post(req,ba);
QByteArray responseData;
QEventLoop eventLoop;
connect(m_manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec(); //block until finish
responseData = reply->readAll();
return responseData;
}
//执行查询语句
QString execSelect(const QString & url)
{
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply *reply = m_manager->get(req);
QByteArray responseData;
QEventLoop eventLoop;
connect(m_manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec(); //block until finish
responseData = reply->readAll();
return responseData;
}
//带post参数的非查询语句
QString execNonSelect(const QString & url, const QByteArray &ba)
{
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply *reply = m_manager->post(req, ba);
QByteArray responseData;
QEventLoop eventLoop;
connect(m_manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec();//block until finish
responseData = reply->readAll();
return responseData;
}
//建库
QString createDB(const QString& db)
{
QString urlCreate;
urlCreate = QString("http://%1/query?q=CREATE DATABASE %2").arg(m_host).arg(db);
return execNonSelect(urlCreate);
}
//删库
QString dropDB(const QString& db)
{
QString urlCreate;
urlCreate = QString("http://%1/query?q=DROP DATABASE %2").arg(m_host).arg(db);
return execNonSelect(urlCreate);
}
//显示包含库的名称
QString showDB()
{
QString urlCreate;
urlCreate = QString("http://%1/query?q=SHOW DATABASES").arg(m_host);
return execNonSelect(urlCreate);
}
//插入数据
QString insertData(const QString& db,const QString& table,QList<InfluxPoint>& datPoints)
{
if (datPoints.count() == 1)
{
const InfluxPoint& pt = datPoints[0];
QString urlCreate;
urlCreate = QString("http://%1/write?db=%2").arg(m_host).arg(db);
QString dat;
dat.append(table);
dat.append(QString(",%1=%2").arg("attr_oid").arg(pt.attr_oid)); //tag
dat.append(QString(",%1=%2 ").arg("attr_time").arg(pt.attr_time)); //value1
dat.append(QString("%1=%2 ").arg("attr_value").arg(pt.attr_value)); //value2
return execNonSelect(urlCreate,dat.toLocal8Bit());
}else if(datPoints.count() > 1)
{
QString urlCreate;
urlCreate = QString("http://%1/write?db=%2").arg(m_host).arg(db);
QString dat;
//注意拼装数据格式满足influxdb的接口
// ”,“用来分隔tag和field ,空格分隔value, 换行分隔 point。
for (auto& pt : datPoints)
{
//const InfluxPoint& pt = datPoints[0];
if (!dat.isEmpty())dat.append("\n");
dat.append(table);
//注意前后空格只能一个
dat.append(QString(",%1=%2").arg("attr_oid").arg(pt.attr_oid)); //tag
dat.append(QString(",%1=%2 ").arg("attr_time").arg(pt.attr_time)); //value1
dat.append(QString("%1=%2").arg("attr_value").arg(pt.attr_value)); //value2
}
return execNonSelect(urlCreate, dat.toLocal8Bit());
}
}
//数据查询
QString queryData(const QString& db, const QString& sql, QList<InfluxPoint>& datPoints)
{
QString urlCreate;
urlCreate = QString("http://%1/query?pretty=true&db=%2&q=%3").arg(m_host).arg(db).arg(sql);
return execSelect(urlCreate);
}
//数据查询带条件
QString queryData(const QString& db,
const QString& attr_oid,
QDateTime &begin,
QDateTime &end,
QList<InfluxPoint>& datPoints)
{
QString urlCreate;
QString sql;
begin = begin.addSecs(-8 * 3600);
end = end.addSecs(-8 * 3600);
sql.append(" select time,attr_oid,attr_value from Analog ");
sql.append(" where time>= '");
sql.append(begin.toString("yyyy-MM-ddTHH:mm:ssZ"));
sql.append("' and time<='");
sql.append(end.toString("yyyy-MM-ddTHH:mm:ssZ"));
sql.append("' tz('Asia/Shanghai')");
//sql.append("group by xxx ");
//sql.append("order by yyy ");
urlCreate = QString("http://%1/query?pretty=true&db=%2&q=%3").arg(m_host).arg(db).arg(sql);
return execSelect(urlCreate);
}
//json转字符串
static QString JsonToString(const QJsonObject& json,bool readable=false)
{
return QString(QJsonDocument(json).toJson(readable?QJsonDocument::Indented:QJsonDocument::Compact));
}
//字符串转json
static QJsonObject StringToJson(const QString& str)
{
QJsonObject l_ret;
QJsonParseError l_err;
QJsonDocument l_doc = QJsonDocument::fromJson(str.toUtf8(), &l_err);
if (l_err.error == QJsonParseError::NoError)
{
if (l_doc.isObject())
{
l_ret = l_doc.object();
}
}
return l_ret;
}
//json返回解析
static QString parseJsonRet(const QString& str)
{
//根对象的成员
QJsonObject root = TestInfluxdb::StringToJson(str);
if (root.isEmpty())
{
return "root is invalid";
}
//只有一个成员数组
QJsonArray results = root["results"].toArray();
if (results.count()==0)
{
return "results is invalid";
}
for (auto o : results)
{
if (o.isObject())
{
//qDebug() << TestInfluxdb::JsonToString(o.toObject(), true);
}
}
//数组的第一个对象
QJsonObject retObject = results[0].toObject();
//返回错误码
int statement_id = retObject["statement_id"].toInt();
if (statement_id != 0)
{
return "statement_id fail";
}
QJsonArray series = retObject["series"].toArray();
if (series.count() == 0)
{
return "series=0";
}
QJsonObject series1 = series[0].toObject();
QJsonArray columns = series1["columns"].toArray();//对应列数
QJsonArray values = series1["values"].toArray(); //对应行数
cout << JsonToString(root, true).toStdString() << endl;
return "success";
}
//静态方法,get方式访问 influxdb
static QString getHtml(QString url)
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url)));
QByteArray responseData;
QEventLoop eventLoop;
connect(manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec(); //block until finish
responseData = reply->readAll();
return QString(responseData);
}
//静态方法,post方式访问 influxdb
static QString postUrl(const QString& url,const QByteArray& ba)
{
QNetworkAccessManager *manager = new QNetworkAccessManager();
QByteArray baNew = ba;
baNew.append("q = CREATE DATABASE mydb;");
QUrl qurl(url+"?q=CREATE DATABASE mydb");
QNetworkReply *reply = manager->post(QNetworkRequest(qurl),baNew);
QByteArray responseData;
QEventLoop eventLoop;
connect(manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec(); //block until finish
responseData = reply->readAll();
return QString(responseData);
}
private:
QString m_host; //influxdb 服务地址
QString m_db; //数据库名称
QString m_usr; //用户名
QString m_pwd; //密码
QNetworkAccessManager *m_manager; //网络管理
};
int main(int argc, char *argv[])
{
TestInfluxdb influxdb("127.0.0.1:8086");
QCoreApplication a(argc, argv);
//QString data = TestInfluxdb::getHtml(QString("http://www.baidu.com") );
QList<InfluxPoint> lstDat;
QString data;
//测试建库
data = influxdb.createDB("epacsdb1");
//测试删库
data = influxdb.dropDB("epacsdb2");
//测试查表
data = influxdb.showDB();
//测试批量插入
#if 0
InfluxPoint pt1;
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
for (int i = 0; i < 200; i++)
{
pt1.attr_oid = QString("85001%1").arg(i);
pt1.attr_time ="152208";
pt1.attr_value = qrand();
lstDat.append(pt1);
}
data = influxdb.insertData("epacsdb1","Analog",lstDat);
#endif
//测试查询注意区分大小写
data = influxdb.queryData("epacsdb1", "select * from Analog limit 10;",lstDat);
//测试按时间条件查询
QDateTime dtBegin(QDate(2021,8,28),QTime(21,28,0));
QDateTime dtEnd(QDate(2021, 8, 28), QTime(22,0,0));
QString oidString;
data = influxdb.queryData("epacsdb1",oidString,dtBegin,dtEnd,lstDat);
TestInfluxdb::parseJsonRet(data);
cout<<data.toStdString()<<endl;
return a.exec();
}