Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
*.d
*.a
*~
*ClassDict.cpp
*.pcm
*.rootmap
lib
Dependencies
*/a.out
Expand All @@ -12,3 +15,4 @@ RemoteControl
Example/Example
Example/Example_root
Win_Mac_translation
core
24 changes: 12 additions & 12 deletions Example/Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,19 +265,13 @@ int main(){
// Each submitted plot with the same name is stored in the database as a different version.
/////////////////////////////////////////////////////////////////
std::vector<float> plot_x(5);
for (size_t i = 0; i < plot_x.size(); ++i) plot_x[i] = i;
std::vector<float> plot_y(plot_x.size());
for (auto& y : plot_y) y = rand();

std::string plot_layout = "{"
"\"title\":\"A random plot\","
"\"xaxis\":{\"title\":\"x\"},"
"\"yaxis\":{\"title\":\"y\"}"
"}";
for (size_t i = 0; i < plot_x.size(); ++i) plot_x[i] = i;

Store store; // for conversion to JSON
std::vector<std::string> traces(2);

Store store;
for (auto& y : plot_y) y = rand();
store.Set("x", plot_x);
store.Set("y", plot_y);
store >> traces[0];
Expand All @@ -287,19 +281,25 @@ int main(){
store.Set("y", plot_y);
store >> traces[1];

std::string plot_layout = "{"
"\"title\":\"A random plot\","
"\"xaxis\":{\"title\":\"x\"},"
"\"yaxis\":{\"title\":\"y\"}"
"}";

DAQ_inter.SendPlotlyPlot("test_plot", traces, plot_layout);

/////////////////////////// generic SQL query example //////////////////////

std::string resp;
std::cout<<"Testing submitting generic SQL queries"<<std::endl;
// single-record query
bool qryok = DAQ_inter.SQLQuery("daq","SELECT config_id, name, version, data FROM configurations",resp);
bool qryok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 1",resp);
std::cout<<"single-record query success: "<<qryok<<", response: '"<<resp<<"'"<<std::endl;

// for multi-record queries
std::vector<std::string> resps;
qryok = DAQ_inter.SQLQuery("daq","SELECT version, data FROM device_config WHERE device='"+device_name+"'",resps);
qryok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 5",resps);
std::cout<<"multi-record query success: "<<qryok<<", got "<<resps.size()<<" records:"<<std::endl;
for(int i=0; i<std::min(resps.size(),size_t(5)); ++i) std::cout<<i<<": '"<<resps.at(i)<<"'"<<std::endl;
if(resps.size()>5) std::cout<<"...\n"<<std::endl;
Expand Down Expand Up @@ -373,7 +373,7 @@ int main(){
monitoring_data>>monitoring_json; /// prducing monitoring json

// send to the database
bool ok = DAQ_inter.SendMonitoringData("general", monitoring_json);
bool ok = DAQ_inter.SendMonitoringData(monitoring_json, "general");
if(!ok){
std::cerr<<"sendmonitoringdata failed"<<std::endl;
}
Expand Down
6 changes: 3 additions & 3 deletions Example/Example.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,12 @@ def change_voltage(self, control_name: str) -> str:
print("testing generic sql queries")
# single-record query
resp = std.string()
qryok = DAQ_inter.SQLQuery("daq","SELECT config_id, name, version, data FROM configurations",resp)
qryok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 1",resp)
print("single-record query success: ",qryok,", response: '",resp,"'")

# for multi-record queries
resps = std.vector['std::string']()
qryok = DAQ_inter.SQLQuery("daq","SELECT device, version, data FROM device_config",resps)
qryok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 5",resps)
print("multi-record query success: ",qryok,", responses:")
for i in range(min(5,resps.size())):
print(i,": '",resps[i],"'")
Expand Down Expand Up @@ -336,7 +336,7 @@ def change_voltage(self, control_name: str) -> str:
monitoring_data.__rshift__['std::string'](monitoring_json)

# send to the Database for plotting on the webpage
DAQ_inter.SendMonitoringData("general", monitoring_json)
DAQ_inter.SendMonitoringData(monitoring_json, "general")

# retrieve and respond to control changes
###########################################
Expand Down
40 changes: 22 additions & 18 deletions Example/Example_root.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,13 @@ int main(int argc, const char** argv){
std::string graph_name = "TotallyCoolSine";
std::string graph_draw_options = "ALP";

// each time the same unique name is inserted, a new version of the plot is stored.
// when saving a new version over TCP we may optionally pass a pointer to an integer,
// which will be populated with the version number of the created entry.
int graph_db_ver=0;

// store it in the database
bool persistent=true; // TODO
// For now this setting only affects whether the request is sent over multicast (false, default) or tcp (true)
// At a later date we may add the option for plots to only be stored in a temporary table.
std::cout<<"Sending to database via TCP"<<std::endl;
bool ok = DAQ_inter.SendROOTplot(graph_name, graph_draw_options, graph_json, persistent, &graph_db_ver);
std::cout<<"Sending to database"<<std::endl;
bool ok = DAQ_inter.SendROOTplot(graph_name, graph_draw_options, graph_json);
if(!ok){
std::cerr<<"Error sending plot '"<<graph_name<<"' to database!"<<std::endl;
} else {
std::cout<<"Created plot '"<<graph_name<<"' version "<<graph_db_ver<<std::endl;
std::cout<<"Sent OK"<<std::endl;
}

// Another example, this time storing a TH2.
Expand All @@ -101,13 +93,26 @@ int main(int argc, const char** argv){
// and specify the draw options
std::string hist_draw_options = "colz";

// send to the database. We omit the optional arguments this time.
// Each time a plot with the same name as an existing plot is inserted, it makes a new version of that plot.
// The 'lifetime' parameter (default=5) defines how long it plots are to be retained in the database.
// When a new version of a given plot is created, any existing plots of the same name
// that have a (version+lifetime) less than the version number of the new plot will be pruned.
// This behaviour may be subject to change: feedback to the DAQ group is welcome!
// N.B. pruning is presently not functional as it is likely to be a separate background task.
int lifetime=3;

// ROOT plots may be sent either via ZMQ or multicast (the 'acknowledged' argument in SendROOTplot).
// If SendROOTplotZmq is used explicitly (acknowledged=1) you may pass a version number argument
// that will be set to the version number of the newly created entry.
int db_ver=0;

// send to the database
std::cout<<"Sending to database via multicast"<<std::endl;
ok = DAQ_inter.SendROOTplot(histo_name, hist_draw_options, hist_json);
ok = DAQ_inter.SendROOTplotZmq(histo_name, hist_draw_options, hist_json, db_ver, 0, lifetime);
if(!ok){
std::cerr<<"Error sending plot '"<<histo_name<<"' to database!"<<std::endl;
} else {
std::cout<<"Sent OK"<<std::endl;
std::cout<<"Created plot version "<<db_ver<<std::endl;
}

// ============================================================= //
Expand Down Expand Up @@ -148,10 +153,9 @@ int main(int argc, const char** argv){
// repeat for the histogram
std::string ret_hist_draw_options;
std::string ret_hist_json;
int ret_hist_version=-1;
std::cout<<"Getting latest version of plot "<<histo_name<<std::endl;
ok = DAQ_inter.GetROOTplot(histo_name, ret_hist_version, ret_hist_draw_options, ret_hist_json);
if(!ok) std::cerr<<"Failed to get ROOT plot '"<<histo_name<<"' from database!"<<std::endl;
std::cout<<"Getting version "<<db_ver<<" of plot "<<histo_name<<std::endl;
ok = DAQ_inter.GetROOTplot(histo_name, db_ver, ret_hist_draw_options, ret_hist_json);
if(!ok) std::cerr<<"Failed to get ROOT plot '"<<histo_name<<"' version "<<db_ver<<" from database!"<<std::endl;
else std::cout<<"Converting to TH2"<<std::endl;

// This time we use an alternative FromJSON signature using raw pointers instead of unique_ptr:
Expand Down
103 changes: 103 additions & 0 deletions Example/Test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <iostream>
#include <DAQInterface.h>
#include <functional>

using namespace ToolFramework;

std::string Check(int ok){
return ok ? "\033[32mPASS" : "\033[31mFAIL";
}

const std::string Reset = "\033[39m";

int main(){

int verbose=1;

std::string Interface_configfile = "./InterfaceConfig";

DAQInterface DAQ_inter(Interface_configfile);
//std::this_thread::sleep_for(std::chrono::seconds(2)); // sleep for a little longer, connecting is slow
std::string device_name = DAQ_inter.GetDeviceName();
std::string tmp;
bool ok;

if(verbose) std::cout<<"Testing logging..."<<std::flush;
ok = DAQ_inter.SendLog("test log message");
if(!ok || verbose) std::cout<<"Logs sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"Testing monitoring..."<<std::flush;
ok = DAQ_inter.SendMonitoringData("{\"message\":\"test mon message\"}","general");
if(!ok || verbose) std::cout<<"monitoring sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"Sending test alarm..."<<std::flush;
ok = DAQ_inter.SendAlarm("Test alarm");
if(!ok || verbose) std::cout<<"Test alarm sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"Sending test calibration data..."<<std::flush;
ok = DAQ_inter.SendCalibrationData("{\"data\":[1,2,3]}","test calib data");
if(!ok || verbose) std::cout<<"test calibration data sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"getting test calibration data..."<<std::flush;
ok = DAQ_inter.GetCalibrationData(tmp, -1, device_name);
if(!ok || verbose) std::cout<<"get calibration data: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Sending test device config..."<<std::flush;
ok = DAQ_inter.SendDeviceConfig("{\"device settings\":[3,2,1]}","test user","test dev config");
if(!ok || verbose) std::cout<<"test device config sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"Getting test device config..."<<std::flush;
ok = DAQ_inter.GetDeviceConfig(tmp, -1);
if(!ok || verbose) std::cout<<"get device config: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Sending test run config..."<<std::flush;
ok = DAQ_inter.SendRunConfig("{\""+device_name+"\":1}","test run","test user","test run config");
if(!ok || verbose) std::cout<<"test run config sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"Getting test run config by id..."<<std::flush;
ok = DAQ_inter.GetRunConfig(tmp, 1);
if(!ok || verbose) std::cout<<"get run config by id: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Getting test run config by name & version..."<<std::flush;
ok = DAQ_inter.GetRunConfig(tmp, "test run",1);
if(!ok || verbose) std::cout<<"get run config by name: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Getting test device config by run id..."<<std::flush;
ok = DAQ_inter.GetDeviceConfigFromRunConfig(tmp, 1);
if(!ok || verbose) std::cout<<"get device config by run config id: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Getting test device config by run name and version..."<<std::flush;
ok = DAQ_inter.GetDeviceConfigFromRunConfig(tmp, "test run",1);
if(!ok || verbose) std::cout<<"get device config by run config name & version: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Sending test PlotlyPlot..."<<std::flush;
std::string trace = "{\"x\":[1,2,3],\"y\":[3,2,1]}";
std::string layout = "{ \"title\":\"test plot\", \"xaxis\":{\"title\":\"x\"}, \"yaxis\":{\"title\":\"y\"} }";
ok = DAQ_inter.SendPlotlyPlot("test_plot", trace, layout);
if(!ok || verbose) std::cout<<"test plotly plot sent: "<<Check(ok)<<Reset<<std::endl;

if(verbose) std::cout<<"getting test plotlyplot..."<<std::flush;
trace=""; layout="";
ok = DAQ_inter.GetPlotlyPlot("test_plot", trace, layout);
if(!ok || verbose) std::cout<<"get plotly plot: "<<Check(ok)<<" = "<<trace<<", "<<layout<<Reset<<std::endl;

// TODO add testing Get/Send Rootplot
// requires either ROOT install, or hard-coded json that may not be small, or a test file

if(verbose) std::cout<<"Testing single-record SQL query"<<Reset<<std::endl;
ok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 1",tmp);
if(!ok || verbose) std::cout<<"single-record SQL sent: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

if(verbose) std::cout<<"Testing multi-record SQL query"<<Reset<<std::endl;
std::vector<std::string> resps;
ok = DAQ_inter.SQLQuery("SELECT time, message FROM logging ORDER BY time DESC LIMIT 5",resps);
if(!ok || verbose) std::cout<<"multi-record SQL sent: "<<Check(ok)<<", got "<<resps.size()<<" rows"<<Reset<<std::endl;
if(ok && verbose) for(int i=0; i<resps.size(); ++i) std::cout<<"\t"<<i<<": '"<<resps.at(i)<<"'"<<Reset<<std::endl;

if(verbose) std::cout<<"Sending bad SQL query ..."<<Reset<<std::endl;
ok = DAQ_inter.SQLQuery("SELECT potato, message FROM logging ORDER BY time DESC LIMIT 1",tmp);
if(!ok || verbose) std::cout<<"bad SQL returned: "<<Check(ok)<<" = "<<tmp<<Reset<<std::endl;

return 0;

}
35 changes: 17 additions & 18 deletions InterfaceConfig
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
UUID b16a0186-c5df-474c-b880-9fc6c0670d7d # unique identifier for client (must be valid uuid)
device_name Example # name of devices
verbosity 1 # Verbosity level of interface
db_name daq #
max_retries 3 #
advertise_endpoints 0 #
resend_period_ms 1000 #
print_stats_period_ms 1000 #
clt_pub_port 55556 #
clt_dlr_port 55555 #
clt_pub_socket_timeout 500 #
clt_dlr_socket_timeout 500 #
inpoll_timeout 50 # keep these short!
outpoll_timeout 50 # keep these short!
command_timeout 2000 #
log_port 55554 #
mon_port 55553 #
multicast_address 239.192.1.1 #
UUID b16a0186-c5df-474c-b880-9fc6c0670d7d # unique identifier for client (must be valid uuid)
device_name Example # name of devices
verbosity 1 # Verbosity level of interface
max_retries 3 #
resend_period_ms 1000 #
print_stats_period_ms 1000 #
clt_pub_port 55556 #
clt_dlr_port 55555 #
clt_pub_socket_timeout 500 #
clt_dlr_socket_timeout 500 #
inpoll_timeout 50 # keep these short!
outpoll_timeout 50 # keep these short!
command_timeout 2000 #
log_port 5000 #
mon_port 5000 #
log_address 239.192.1.2 #
mon_address 239.192.1.3 #
42 changes: 32 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Dependencies=./Dependencies

CXXFLAGS=-g -fmax-errors=3 -std=c++20 -Werror=array-bounds -Werror=return-type -Wpedantic

ifeq ($(MAKECMDGOALS),debug)
CXXFLAGS+= -O0 -lSegFault -rdynamic -DDEBUG
else
CXXFLAGS+= -O3
endif

ZMQLib= -L $(Dependencies)/zeromq-4.0.7/lib -lzmq
ZMQInclude= -I $(Dependencies)/zeromq-4.0.7/include/

Expand All @@ -16,37 +24,51 @@ RootInclude= -I`root-config --incdir`
RootFlags=`root-config --cflags`
RootLib= `root-config --libs`

sources= $(filter-out %DAQInterfaceClassDict.cpp, $(wildcard src/*.cpp))
sources= $(filter-out %DAQInterfaceClassDict.cpp, $(wildcard src/*.cpp) $(wildcard include/*.h))

.phony: python

all: lib/libDAQInterface.so Win_Mac_translation Example/Example RemoteControl
debug: all

all: lib/libDAQInterface.so Win_Mac_translation Example/Example Example/Test RemoteControl

lib/libDAQInterface.so: $(sources)
g++ -O3 -fPIC -Wpedantic -std=c++11 -shared src/DAQInterface.cpp -I include -o lib/libDAQInterface.so -lpthread $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(BoostLib)
g++ $(CXXFLAGS) -fPIC -shared src/DAQInterface.cpp -I include -o lib/libDAQInterface.so -lpthread $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(BoostLib)

Win_Mac_translation: Win_Mac_translation.cpp lib/libDAQInterface.so
g++ -O3 -Wpedantic -std=c++11 Win_Mac_translation.cpp -o Win_Mac_translation -I ./include/ -L lib/ -lDAQInterface -lpthread $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(BoostLib) $(ToolDAQLib) $(BoostLib)
g++ $(CXXFLAGS) Win_Mac_translation.cpp -o Win_Mac_translation -I ./include/ -L lib/ -lDAQInterface -lpthread $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(BoostLib) $(ToolDAQLib) $(BoostLib)

# this is the default example showing the majority of features
Example/Example: Example/Example.cpp lib/libDAQInterface.so
g++ -O3 -Wpedantic -std=c++11 $^ -o $@ -I ./include/ -L lib/ -lDAQInterface -lpthread $(ToolDAQInclude) $(ToolDAQLib) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(BoostLib) $(ToolDAQLib)
g++ $(CXXFLAGS) $^ -o $@ -I ./include/ -L lib/ -lDAQInterface -lpthread $(ToolDAQInclude) $(ToolDAQLib) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(BoostLib) $(ToolDAQLib)

# this is required ONLY to demonstrate the use of storing and retreiving ROOT plots in the database
Example/Example_root: Example/Example_root.cpp lib/libDAQInterface.so
g++ -O3 -Wpedantic -std=c++11 $(RootFlags) $^ -o $@ -I ./include/ -L lib/ -lDAQInterface -lpthread $(ToolDAQInclude) $(ToolDAQLib) $(RootLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolDAQLib) $(ToolFrameworkLib) $(BoostInclude) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(BoostLib) $(ToolDAQLib)
g++ $(CXXFLAGS) $(RootFlags) $^ -o $@ -I ./include/ -L lib/ -lDAQInterface -lpthread $(ToolDAQInclude) $(ToolFrameworkInclude) $(BoostInclude) $(ZMQInclude) $(ToolFrameworkLib) $(ToolDAQLib) $(ZMQLib) $(BoostLib) $(RootLib)

# this is required ONLY if you want to run the python example, or use the libDAQInterface in python
python: lib/libDAQInterfaceClassDict.so
python: lib/libDAQInterface.so lib/libDAQInterfaceClassDict.so

# functionality testing
Example/Test: Example/Test.cpp lib/libDAQInterface.so
g++ $(CXXFLAGS) $^ -o $@ -I ./include/ -L lib/ -lDAQInterface -lpthread $(ToolDAQInclude) $(ToolDAQLib) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(BoostInclude) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(BoostLib) $(ToolDAQLib)

lib/libDAQInterfaceClassDict.so: include/DAQInterface.h include/DAQInterfaceLinkdef.h
rootcling -f src/DAQInterfaceClassDict.cpp -c -p -rmf lib/libDAQInterfaceClassDict.rootmap $^ -I ./include/ $(ToolFrameworkInclude) $(ToolDAQInclude) $(BoostInclude) $(ZMQInclude)
g++ -shared -fPIC src/DAQInterfaceClassDict.cpp -o $@ -I ./ -I ./include/ $(ToolFrameworkInclude) $(ToolDAQInclude) $(BoostInclude) $(ZMQInclude) $(RootInclude) -L lib -lDAQInterface $(RootLib)
g++ -shared $(CXXFLAGS) -fPIC src/DAQInterfaceClassDict.cpp -o $@ -I ./ -I ./include/ $(ToolFrameworkInclude) $(ToolDAQInclude) $(BoostInclude) $(ZMQInclude) $(RootInclude) -L lib -lDAQInterface $(RootLib)
cp src/DAQInterfaceClassDict_rdict.pcm lib/
# end python requirements

RemoteControl: $(Dependencies)/ToolDAQFramework/src/RemoteControl/RemoteControl.cpp lib/libDAQInterface.so
g++ -O3 -Wpedantic -std=c++11 $(Dependencies)/ToolDAQFramework/src/RemoteControl/RemoteControl.cpp -o RemoteControl -I ./include/ -L lib/ -lDAQInterface -lpthread $(BoostInclude) $(BoostLib) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(ToolDAQLib) $(BoostLib)
g++ $(CXXFLAGS) $(Dependencies)/ToolDAQFramework/src/RemoteControl/RemoteControl.cpp -o RemoteControl -I ./include/ -L lib/ -lDAQInterface -lpthread $(BoostInclude) $(BoostLib) $(ZMQInclude) $(ZMQLib) $(ToolDAQLib) $(ToolDAQInclude) $(ToolFrameworkInclude) $(ToolFrameworkLib) $(ToolDAQLib) $(BoostLib)

clean:
rm -f lib/libDAQInterface.so RemoteControl Win_Mac_translation Example/Example Example/Example_root
rm -f lib/libDAQInterface.so \
RemoteControl \
Win_Mac_translation \
Example/Example \
Example/Example_root \
lib/DAQInterfaceClassDict_rdict.pcm \
lib/libDAQInterfaceClassDict.rootmap \
lib/libDAQInterfaceClassDict.so

Loading