00001
00002
00003
00004
00005
00007
00008 #include "art/Framework/Core/EDAnalyzer.h"
00009 #include "art/Framework/Core/ModuleMacros.h"
00010 #include "art/Framework/Principal/Run.h"
00011 #include "art/Framework/Principal/Event.h"
00012 #include "art/Framework/Principal/Handle.h"
00013 #include "canvas/Utilities/Exception.h"
00014
00015 #include "artdaq-ots/Overlays/UDPFragment.hh"
00016 #include "artdaq-core/Data/Fragment.hh"
00017 #include "otsdaq-core/Macros/CoutMacros.h"
00018
00019
00020 #include <boost/asio.hpp>
00021 using boost::asio::ip::udp;
00022
00023 #include <algorithm>
00024 #include <cassert>
00025 #include <cmath>
00026 #include <fstream>
00027 #include <iomanip>
00028 #include <vector>
00029 #include <iostream>
00030 #include <arpa/inet.h>
00031
00032
00033 namespace ots {
00034
00035 class JSONDispatcher : public art::EDAnalyzer {
00036 public:
00037 explicit JSONDispatcher(fhicl::ParameterSet const & pset);
00038 virtual ~JSONDispatcher();
00039
00040 virtual void analyze(art::Event const & evt) override;
00041 virtual void beginRun(art::Run const & run) override;
00042
00043 private:
00044 int prescale_;
00045 std::string raw_data_label_;
00046 std::string frag_type_;
00047 boost::asio::io_service io_service_;
00048 udp::socket socket_;
00049 udp::endpoint remote_endpoint_;
00050 };
00051
00052 }
00053
00054 ots::JSONDispatcher::JSONDispatcher(fhicl::ParameterSet const & pset)
00055 : art::EDAnalyzer(pset)
00056 , prescale_(pset.get<int>("prescale",1))
00057 , raw_data_label_(pset.get<std::string>("raw_data_label", "daq"))
00058 , frag_type_(pset.get<std::string>("frag_type", "UDP"))
00059 , io_service_()
00060 , socket_(io_service_, udp::v4())
00061 {
00062 std::cout << __COUT_HDR_FL__ << "JSONDispatcher Constructor Start" << std::endl;
00063 int port = pset.get<int>("port",35555);
00064
00065
00066 boost::system::error_code ec;
00067 socket_.set_option(boost::asio::socket_base::reuse_address(true),ec);
00068 if(ec) {
00069 mf::LogError("JSONDispatcher") << "An error occurred setting reuse_address: " << ec.message() << std::endl;
00070 }
00071
00072 socket_.set_option(boost::asio::socket_base::broadcast(true),ec);
00073 if(ec) {
00074 mf::LogError("JSONDispatcher") << "An error occurred setting broadcast: " << ec.message() << std::endl;
00075 }
00076
00077
00078 remote_endpoint_ = udp::endpoint(boost::asio::ip::address_v4::broadcast(), port);
00079 std::cout << __COUT_HDR_FL__ << "JSONDispatcher Constructor End" << std::endl;
00080 }
00081
00082 ots::JSONDispatcher::~JSONDispatcher()
00083 {
00084 }
00085
00086 void ots::JSONDispatcher::beginRun(art::Run const & run)
00087 {
00088 std::cout << __COUT_HDR_FL__ << "JSONDispatcher beginning run " << run.run() << std::endl;
00089 }
00090
00091
00092 void ots::JSONDispatcher::analyze(art::Event const & evt)
00093 {
00094
00095 art::EventNumber_t eventNumber = evt.event();
00096 mf::LogInfo("JSONDispatcher") << "Received event with sequence ID " << eventNumber;
00097 if((int)eventNumber % prescale_ == 0) {
00098
00099 std::ostringstream outputJSON;
00100 outputJSON << "{\"run\":" << std::to_string(evt.run()) << ",\"subrun\":"<<std::to_string(evt.subRun()) << ",\"event\":"<<std::to_string(eventNumber);
00101
00102
00103
00104
00105
00106
00107
00108
00109 art::Handle<artdaq::Fragments> raw;
00110 evt.getByLabel(raw_data_label_, frag_type_, raw);
00111 outputJSON <<",\"fragments\":[";
00112
00113 if (raw.isValid())
00114 {
00115
00116 for (size_t idx = 0; idx < raw->size(); ++idx)
00117 {
00118 if(idx > 0) { outputJSON << ","; }
00119 outputJSON << "{";
00120 const auto& frag((*raw)[idx]);
00121
00122 ots::UDPFragment bb(frag);
00123 int type = 0;
00124
00125 if (frag.hasMetadata())
00126 {
00127 outputJSON << "\"metadata\":{";
00128
00129 auto md = frag.metadata<ots::UDPFragment::Metadata>();
00130 outputJSON << "\"port\":"<<std::to_string(md->port)<<",";
00131 char buf[sizeof(in_addr)];
00132 struct sockaddr_in addr;
00133 addr.sin_addr.s_addr = md->address;
00134 inet_ntop(AF_INET, &(addr.sin_addr), buf, INET_ADDRSTRLEN);
00135 outputJSON << "\"address\":\""<<std::string(buf) << "\"";
00136 outputJSON << "},";
00137 }
00138 outputJSON << "\"header\":{";
00139 outputJSON << "\"event_size\":"<<std::to_string(bb.hdr_event_size())<<",";
00140 outputJSON << "\"data_type\":"<<std::to_string(bb.hdr_data_type());
00141 type = bb.hdr_data_type();
00142 outputJSON << "},";
00143 outputJSON << "\"data\":";
00144 if(type == 0 || type > 2)
00145 {
00146 outputJSON << "[";
00147 auto it = bb.dataBegin();
00148 outputJSON << std::hex << "\"0x" << (int)*it << "\"" << std::dec;
00149 ++it;
00150
00151 for(; it !=bb.dataEnd(); ++it)
00152 {
00153 outputJSON << "," << std::hex << "\"0x" << (int)*it << "\"" << std::dec;
00154 }
00155 outputJSON << "]";
00156 }
00157 else
00158 {
00159 if(type == 2) { outputJSON << "\""; }
00160 std::string output = std::string((const char *)bb.dataBegin());
00161 if(type == 2)
00162 {
00163 std::string find = "\"";
00164 std::string replace = "\\\"";
00165 for(std::string::size_type i = 0; (i = output.find(find, i)) != std::string::npos;)
00166 {
00167 output.replace(i, find.length(), replace);
00168 i += replace.length();
00169 }
00170 }
00171 outputJSON << output;
00172 if(type == 2) { outputJSON << "\""; }
00173 }
00174 outputJSON << "}";
00175 }
00176 }
00177 else
00178 {
00179 return;
00180 }
00181
00182 outputJSON << "]}";
00183
00184 std::string s = outputJSON.str() + "\0";
00185
00186 auto message = boost::asio::buffer(s);
00187
00188 socket_.send_to(message, remote_endpoint_);
00189
00190
00191 }
00192 }
00193
00194 DEFINE_ART_MODULE(ots::JSONDispatcher)