use CAEN_FElib_Stop for stop ReadData, added influxDB

This commit is contained in:
Ryan Tang 2023-01-18 18:10:31 -05:00
parent 2c0dc7d625
commit 27120a5c9a
8 changed files with 315 additions and 47 deletions

12
.vscode/settings.json vendored
View File

@ -45,6 +45,16 @@
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"script.C": "cpp"
"script.C": "cpp",
"ctime": "cpp",
"chrono": "cpp",
"condition_variable": "cpp",
"ratio": "cpp",
"iostream": "cpp",
"istream": "cpp",
"mutex": "cpp",
"semaphore": "cpp",
"stop_token": "cpp",
"thread": "cpp"
}
}

View File

@ -38,6 +38,8 @@ void Digitizer2Gen::Initialization(){
evt = NULL;
acqON = false;
}
//########################################### Handles functions
@ -179,12 +181,15 @@ void Digitizer2Gen::StartACQ(){
SendCommand("/cmd/armacquisition"); // this will also clear data
SendCommand("/cmd/swstartacquisition");
acqON = true;
}
void Digitizer2Gen::StopACQ(){
SendCommand("/cmd/disarmacquisition");
SendCommand("/cmd/SwStopAcquisition");
//SendCommand("/cmd/disarmacquisition");
acqON = false;
}
void Digitizer2Gen::SetPHADataFormat(unsigned short dataFormat){
@ -314,9 +319,9 @@ void Digitizer2Gen::SetPHADataFormat(unsigned short dataFormat){
ret = CAEN_FELib_GetHandle(handle, "/endpoint/dpppha/stats", &stat_handle);
ret |= CAEN_FELib_SetReadDataFormat(stat_handle,
" [ \
{ \"name\": \"REAL_TIME\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"DEAD_TIME\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"LIVE_TIME\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"REAL_TIME_NS\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"DEAD_TIME_NS\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"LIVE_TIME_NS\", \"type\": \"U64\", \"dim\": 1 }, \
{ \"name\": \"TRIGGER_CNT\", \"type\": \"U32\", \"dim\": 1 }, \
{ \"name\": \"SAVED_EVENT_CNT\", \"type\": \"U32\", \"dim\": 1 } \
]"
@ -345,10 +350,11 @@ int Digitizer2Gen::ReadStat(){
}
void Digitizer2Gen::PrintStat(){
printf("ch | Real Time | Dead Time | Live Time | Trigger | Saved \n");
printf("ch | Real Time[ns] | Dead Time[ns] | Live Time[ns] | Trigger | Saved | Rate[Hz] \n");
for( int i = 0; i < MaxNumberOfChannel; i++){
printf("%02d | %9lu | %9lu | %9lu | %7u | %7u \n",
i, realTime[i], deadTime[i], liveTime[i], triggerCount[i], savedEventCount[i]);
if( triggerCount[i] == 0 ) continue;
printf("%02d | %13lu | %13lu | %13lu | %7u | %7u | %.3f\n",
i, realTime[i], deadTime[i], liveTime[i], triggerCount[i], savedEventCount[i], triggerCount[i]*1e9*1.0/realTime[i]);
}
}
@ -530,7 +536,7 @@ void Digitizer2Gen::ProgramPHA(bool testPulse){
WriteValue("/par/SyncOutMode", "Disabled");
WriteValue("/par/RunDelay", "0"); // ns, that is for sync time with multi board
WriteValue("/par/IOlevel", "NIM");
WriteValue("/par/EnStatEvents", "1");
WriteValue("/par/EnStatEvents", "true");
// Channel setting
//WriteValue("/ch/0..63/par/EventTriggerSource", "GlobalTriggerSource");

View File

@ -54,6 +54,8 @@ class Digitizer2Gen {
char outFileName[100];
FILE * outFile;
unsigned int outFileSize;
bool acqON;
public:
Digitizer2Gen();
@ -74,6 +76,7 @@ class Digitizer2Gen {
void StartACQ();
void StopACQ();
bool IsAcqOn() {return acqON;}
void SetPHADataFormat(unsigned short dataFormat); // 0 = all data,
// 1 = analog trace-0 only + flags

View File

@ -2,14 +2,16 @@ CC = g++
COPTS = -fPIC -DLINUX -O2 -std=c++17 -lpthread
CAENLIBS = -lCAEN_FELib
all: test test_indep ClassDigitizer2Gen.o
all: test test_indep ClassDigitizer2Gen.o influxdb.o
test_indep : test_indep.cpp
$(CC) $(COPTS) -o test_indep test_indep.cpp $(CAENLIBS)
test : test.cpp ClassDigitizer2Gen.o
$(CC) $(COPTS) -o test test.cpp ClassDigitizer2Gen.o $(CAENLIBS)
test : test.cpp ClassDigitizer2Gen.o influxdb.o
$(CC) $(COPTS) ClassDigitizer2Gen.o influxdb.o -o test test.cpp $(CAENLIBS) -lcurl
ClassDigitizer2Gen.o : ClassDigitizer2Gen.cpp ClassDigitizer2Gen.h Event.h
$(CC) $(COPTS) -c ClassDigitizer2Gen.cpp $(CAENLIBS)
influxdb.o : influxdb.cpp influxdb.h
$(CC) $(COPTS) -c influxdb.cpp -lcurl

138
influxdb.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "influxdb.h"
InfluxDB::InfluxDB(std::string url, bool verbose){
curl = curl_easy_init();
if( verbose) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
this->databaseIP = url;
respondCode = 0;
dataPoints = "";
}
InfluxDB::~InfluxDB(){
curl_easy_cleanup(curl);
}
void InfluxDB::SetURL(std::string url){
this->databaseIP = url;
}
std::string InfluxDB::ShowDatabases(){
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_URL, (databaseIP + "/query").c_str());
std::string postFields="q=Show databases";
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(postFields.length()));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallBack);
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
Execute();
printf("|%s|\n", readBuffer.c_str());
databaseList.clear();
size_t pos = readBuffer.find("values");
if( pos > 0 ){
std::string kaka = readBuffer.substr(pos+8);
pos = kaka.find("}");
kaka = kaka.substr(0, pos);
int len = kaka.length();
bool startFlag = false;
std::string lala;
char yaya = '"';
for( int i = 0; i < len; i++){
if( startFlag == false && kaka[i] == yaya ) {
startFlag = true;
lala = "";
continue;
}
if( startFlag && kaka[i] == yaya ){
startFlag = false;
databaseList.push_back(lala);
continue;
}
if( startFlag ) lala += kaka[i];
}
}
return readBuffer;
}
std::string InfluxDB::Query(std::string databaseName, std::string query){
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_URL, (databaseIP + "/query?db=" + databaseName).c_str());
std::string postFields = "q=" + query;
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(postFields.length()));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallBack);
std::string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
Execute();
printf("|%s|\n", readBuffer.c_str());
return readBuffer;
}
void InfluxDB::CreateDatabase(std::string databaseName){
curl_easy_setopt(curl, CURLOPT_URL, (databaseIP + "/query").c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1);
std::string postFields = "q=CREATE DATABASE " + databaseName;
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(postFields.length()));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
Execute();
}
void InfluxDB::AddDataPoint(std::string fullString){
dataPoints += fullString + "\n";
}
void InfluxDB::ClearDataPointsBuffer(){
dataPoints = "";
}
void InfluxDB::PrintDataPoints(){
printf("%s\n", dataPoints.c_str());
}
void InfluxDB::WriteData(std::string databaseName){
curl_easy_setopt(curl, CURLOPT_URL, (databaseIP + "write?db=" + databaseName).c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(dataPoints.length()));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, dataPoints.c_str());
Execute();
}
void InfluxDB::Execute(){
respond = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respondCode);
//printf("==== respond code %ld \n", respondCode);
if( respond != CURLE_OK) printf("############# fail\n");
}
size_t InfluxDB::WriteCallBack(char *contents, size_t size, size_t nmemb, void *userp){
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}

52
influxdb.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef INFLUXDB_H
#define INFLUXDB_H
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include <curl/curl.h>
class InfluxDB{
private:
CURL * curl;
CURLcode respond;
long respondCode;
std::string databaseIP;
std::string dataPoints;
std::vector<std::string> databaseList;
static size_t WriteCallBack(char *contents, size_t size, size_t nmemb, void *userp);
void Execute();
public:
/// url = https://fsunuc.physics.fsu.edu/InfluxDB/
InfluxDB(std::string url, bool verbose = false);
~InfluxDB();
void SetURL(std::string url);
/// Query
std::string ShowDatabases(); /// this save the list of database into databaseList
std::string Query(std::string databaseName, std::string query);
/// the ShowDatabases() function must be called before
std::vector<std::string> GetDatabaseList() {return databaseList;}
void CreateDatabase(std::string databaseName);
/// for single or batch write,
/// 1, addDataPoint first, you can add as many as you like
/// 2, writeData.
void AddDataPoint(std::string fullString);
void ClearDataPointsBuffer();
void PrintDataPoints();
void WriteData(std::string databaseName);
};
#endif

View File

@ -10,6 +10,7 @@ void script(){
reader->ScanNumBlock();
/*
for( int i = 0; i < reader->GetTotalNumBlock() ; i++){
printf("########################## nBlock : %u, %u/%u\n", reader->GetNumBlock(),
reader->GetFilePos(),

126
test.cpp
View File

@ -3,8 +3,81 @@
#include <vector>
#include <unistd.h>
#include <time.h> // time in nano-sec
#include <iostream>
#include <thread>
#include <mutex>
#include "ClassDigitizer2Gen.h"
#include "influxdb.h"
#define maxRead 400
std::mutex digiMTX;
Digitizer2Gen * digi = new Digitizer2Gen();
InfluxDB * influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/", false);
unsigned int readCount = 0;
timespec ta, tb;
static void ReadDataLoop(){
clock_gettime(CLOCK_REALTIME, &ta);
//while(digi->IsAcqOn() && readCount < maxRead){
while(true){
digiMTX.lock();
int ret = digi->ReadData();
digiMTX.unlock();
if( ret == CAEN_FELib_Success){
digi->SaveDataToFile();
}else if(ret == CAEN_FELib_Stop){
digi->ErrorMsg("No more data");
break;
}else{
digi->ErrorMsg("ReadData()");
//digiMTX.unlock();
//break;
}
if( readCount % 100 == 0 ) {
clock_gettime(CLOCK_REALTIME, &tb);
printf("%4d, duration : %.0f\n", readCount, tb.tv_nsec-ta.tv_nsec + tb.tv_sec*1e+9 - ta.tv_sec*1e+9);
ta = tb;
}
readCount++;
}
}
char cmdStr[100];
static void StatLoop(){
//while(digi->IsAcqOn() && readCount < maxRead){
while(digi->IsAcqOn()){
digiMTX.lock();
digi->ReadStat();
for(int i = 0; i < 64; i++){
sprintf(cmdStr, "/ch/%d/par/SelfTrgRate", i);
std::string haha = digi->ReadValue( cmdStr, false);
influx->AddDataPoint("Rate,Ch=" + std::to_string(i) + " value=" + haha);
}
//digi->ReadValue("/ch/4/par/ChRealtimeMonitor", true);
//digi->ReadValue("/ch/4/par/ChDeadtimeMonitor", true);
//digi->ReadValue("/ch/4/par/ChTriggerCnt", true);
//digi->ReadValue("/ch/4/par/ChSavedEventCnt", true);
//digi->ReadValue("/ch/4/par/ChWaveCnt", true);
digiMTX.unlock();
influx->WriteData("testing");
influx->ClearDataPointsBuffer();
digi->PrintStat();
usleep(500*1000); // every 500 msec
}
}
int main(int argc, char* argv[]){
@ -16,7 +89,6 @@ int main(int argc, char* argv[]){
const char * url = "dig2://192.168.0.100/";
Digitizer2Gen * digi = new Digitizer2Gen();
digi->OpenDigitizer(url);
digi->ProgramPHA(false);
@ -57,51 +129,35 @@ int main(int argc, char* argv[]){
digi->OpenOutFile("haha");
digi->StartACQ();
timespec t0, t1;
clock_gettime(CLOCK_REALTIME, &t0);
for( int i = 0; i < 30; i++){
//usleep(100000);
std::thread th1 (ReadDataLoop);
std::thread th2 (StatLoop);
int ret = digi->ReadData();
char c;
printf("Press q for stop.");
do{
c = getchar();
}while( c != 'q');
//digi->ReadValue("/ch/4/par/SelfTrgRate", true);
//if( i% 2 == 0 ) printf("0x%X \n", atoi(digi->ReadValue("/par/AcquisitionStatus").c_str()) & 0x3F );
if( ret == CAEN_FELib_Success){
digi->SaveDataToFile();
//if( digi->evt->channel == 63 ) {
//if( i % 63 == 0 ) {
clock_gettime(CLOCK_REALTIME, &t1);
printf("%5d | t1-t0 : %10ld\n", i, t1.tv_nsec-t0.tv_nsec);
t0 = t1;
// //digi->ReadStat();
// //digi->PrintStat();
//}
}else{
printf("something wrong when ReadData() | ret = %d \n", ret);
digi->ErrorMsg("ReadData()");
}
}
digiMTX.lock();
digi->StopACQ();
digi->ReadStat();
digi->PrintStat();
digi->CloseOutFile();
digiMTX.unlock();
th1.join();
th2.join();
clock_gettime(CLOCK_REALTIME, &t1);
printf("t1-t0 : %.0f\n", t1.tv_nsec-t0.tv_nsec + t1.tv_sec*1e+9 - t0.tv_sec*1e+9);
digi->CloseOutFile();
digi->CloseDigitizer();
delete digi;
delete influx;
}