在modular2 edge 中需要使用C++ 访问influxdb 数据库,之前使用influxdb.cxx https://github.com/awegrzyn/influxdb-cxx.来实现,最近要将他们添加到modular-2 edge 的microservice 中去,详细一看,这个库居然没有读数据的功能,而且封装的很深,改起来比较麻烦,干脆自己来写一个。网络上轻量级的http client 库并不多。最后决定使用libcurl 库。
在influxdb 的文档中,经常使用curl 命令,这是一个命令程序,而libcurl 是一个C++ 的库。它的依赖项是curl。
liburl库
安装
sudo apt-get update
sudo apt-get install curl
sudo apt-get install libcurl4-openssl-dev
ubuntu 中 一般安装在
头文件 :\usr\include\x86_64-linux-gnu\curl 中
库: \usr\lib\x86_64-linux-gnu\libcurl.so
在编译时只要添加 -lcurl 的选项,在程序中使用按下面的方式使用头文件
#include <curl/curl.h>
就可以使用libcurl 库了。编译应用程序时,编译命令中 添加 -lcurl 选项。
influxdb数据库
安装
在windows wsl 下安装
sudo apt-get update && sudo apt-get install influxdb
启动 influxdb
>influxd
访问influxdb 的代码,读influxdb 的响应(json格式)需要使用一个writecallback
size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
string InfluxdbQuery(string url,string body) {
CURL *curl;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
CURLcode res;
string readBuffer;
if(curl) {
struct curl_slist* header =NULL;
header = curl_slist_append(header , "Content-Type: application/x-www-form-urlencoded");
// string post_data="q=SELECT * FROM \"weather\" WHERE time > now() - 5h";
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header );
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return readBuffer;
}
return NULL;
}
访问influxdb
void influxdbWrite(float temperature,float humidity)
{
cout<<"write data to database"<<endl;
InfluxdbQuery(influxdb_url+"/write?db=modular2","weather,tag=0 temperature="+to_string(temperature)+"\n weather,tag=0 humidity="+to_string(humidity));
}
void influxdbCreate(string db_name)
{
cout<<"create db "<<influxdb_url+"/query?q=CREATE+DATABASE+"+db_name<<endl;
InfluxdbQuery(influxdb_url+"/query?","q=q=CREATE+DATABASE+"+db_name);
}
读数据
相对复杂一点,这里我使用了rapidjson 来解析json
string influxdbReadHours(int hours)
{
Document response;
Value result(kArrayType);
Value series(kArrayType);
Value values(kArrayType);
string res= InfluxdbQuery(influxdb_url+"/query?db=modular2","q=SELECT * FROM \"weather\" WHERE time > now() - "+to_string(hours)+"h");
cout<<"res:"<<res<<endl;
response.Parse(res.c_str());
if (response.HasMember("results"))
{
result=response["results"];
cout<<"result"<<endl;
if(result[0].HasMember("series"))
{
cout<<"series"<<endl;
series=result[0]["series"];
if(series[0].HasMember("values"))
{
cout<<"values"<<endl;
values= series[0]["values"];
Document message;
message.SetObject();
Document::AllocatorType& allocator = message.GetAllocator();
message.AddMember("result","readhours",allocator);
message.AddMember("value",values,allocator);
StringBuffer buffer;
buffer.Clear();
Writer<StringBuffer> writer(buffer);
message.Accept(writer);
string msg_payload=buffer.GetString();
return msg_payload;
}
}
}
return "{\"result\":\"ERROR\"}";
}
influxdb query 命令返回的是一个json 格式,它长成这个样子
{"results":
[{
"statement_id":0,
"series":[{
"name":"weather",
"columns":["time","humidity","temperature"],
"values":[
["2019-10-16T09:26:08.6381712Z",1.2,3.2],
["2019-10-16T09:26:09.8858292Z",2.4,6.4],
["2019-10-16T09:26:10.8968504Z",3.6,9.6],
["2019-10-16T09:26:11.9083915Z",4.8,12.8],
["2019-10-16T09:26:12.9187716Z",6,16],
["2019-10-16T09:26:13.9316999Z",7.2,19.2],
["2019-10-16T09:26:14.9459197Z",8.4,22.4],
["2019-10-16T09:26:15.9566043Z",9.6,25.6],
["2019-10-16T09:26:16.9726852Z",10.8,28.8],
["2019-10-16T09:26:17.98236Z",12,32],
]}
]}
]}
自己写程序,觉得更踏实!