1 #include <boost/array.hpp> 19 namespace ba = boost::asio;
20 namespace bs = boost::system;
21 namespace dummy = ba::placeholders;
47 void HandleRead(
const boost::system::error_code& err,
size_t bytes_received)
50 if (bytes_received==0 || err)
52 if (err==ba::error::eof)
53 Warn(
"Connection closed by remote host.");
57 if (err && err!=ba::error::eof &&
58 err!=ba::error::basic_errors::not_connected &&
59 err!=ba::error::basic_errors::operation_aborted)
62 str <<
"Reading from " << URL() <<
": " << err.message() <<
" (" << err <<
")";
65 PostClose(err!=ba::error::basic_errors::operation_aborted);
69 fLastReception =
Time();
71 const string str(fArray.data(), bytes_received);
72 memset(fArray.data(), 0, fArray.size());
81 int hh=0, mm=0, ss=0, y=0, m=0, d=0;
83 bool keepalive =
false;
88 while (getline(is, line))
90 if (line.size()==1 && line[0]==13)
98 const size_t p = line.find_first_of(
": ");
102 std::transform(line.begin(), line.end(), line.begin(), (int(&)(int))std::tolower);
104 const string key = line.substr(0, p);
105 const string val = line.substr(p+2);
107 if (key==
"connection" && val==
"keep-alive")
114 if (line.substr(0, 2)==
"ZD")
115 data.
fZd = stoi(line.substr(2));
116 if (line.substr(0, 2)==
"AZ")
117 data.
fAz = stof(line.substr(2));
126 if (line.substr(0, 2)==
"T3")
127 data.
fT3 = stof(line.substr(2));
128 if (line.substr(0, 2)==
"T6")
129 data.
fT6 = stof(line.substr(2));
130 if (line.substr(0, 2)==
"T9")
131 data.
fT9 = stof(line.substr(2));
132 if (line.substr(0, 3)==
"T12")
133 data.
fT12 = stof(line.substr(3));
135 if (line.substr(0, 3)==
"CLB")
138 if (line.substr(0, 4)==
"HOUR")
139 hh = stoi(line.substr(4));
140 if (line.substr(0, 6)==
"MINUTS")
141 mm = stoi(line.substr(6));
142 if (line.substr(0, 7)==
"SECONDS")
143 ss = stoi(line.substr(7));
145 if (line.substr(0, 4)==
"YEAR")
146 y = stoi(line.substr(4));
147 if (line.substr(0, 5)==
"MONTH")
148 m = stoi(line.substr(5));
149 if (line.substr(0, 3)==
"DAY")
150 d = stoi(line.substr(3));
152 catch (
const exception &e)
154 Warn(
"Conversion of received data failed");
169 const Time tm =
Time(y>999 ? y : 2000+y, m, d, hh, mm, ss);
175 if (data.
fT3==0 && data.
fT6==0 && data.
fT9==0 && data.
fT12==0)
179 msg << tm.
GetAsStr(
"%H:%M:%S") <<
":" 183 <<
" T3-12=" << data.
fT3 188 <<
" Zd=" << data.
fZd <<
"°" 189 <<
" Az=" << data.
fAz <<
"°";
192 UpdateLidar(tm, data);
194 catch (
const exception &e)
196 Warn(
"Corrupted time received.");
205 dummy::error, dummy::bytes_transferred));
213 "GET "+fSite+
" HTTP/1.1\r\n" 215 "Content-Type: application/octet-stream\r\n" 216 "User-Agent: FACT\r\n" 217 "Host: www.fact-project.org\r\n" 218 "Pragma: no-cache\r\n" 219 "Cache-Control: no-cache\r\n" 221 "Connection: Keep-Alive\r\n" 222 "Cache-Control: max-age=0\r\n" 232 fKeepAlive.expires_from_now(boost::posix_time::seconds(fInterval/2));
234 this, dummy::error));
240 if (error && error!=ba::error::basic_errors::operation_aborted)
243 str <<
"Write timeout of " << URL() <<
": " << error.message() <<
" (" << error <<
")";
262 if (fKeepAlive.expires_at() > ba::deadline_timer::traits_type::now())
283 fIsVerbose(true), fLastReport(
Time::none), fLastReception(
Time::none), fKeepAlive(ioservice)
306 if (fLastReport.
IsValid() && fLastReport+boost::posix_time::seconds(fInterval*2)>
Time())
309 if (fLastReception.
IsValid() && fLastReception+boost::posix_time::seconds(fInterval*2)>
Time())
338 fDimLidar(
"MAGIC_LIDAR/DATA",
"F:1;F:1;F:1;F:1;F:1;F:1;F:1",
339 "|Zd[deg]:Pointing direction zenith distance" 340 "|Az[deg]:Pointing direction azimuth" 341 "|T3[1]:Transmission below 3km normalized to 1" 342 "|T6[1]:Transmission below 6km normalized to 1" 343 "|T9[1]:Transmission below 9km normalized to 1" 344 "|T12[1]:Transmission below 12km normalized to 1" 345 "|CLB[m]:Cloud base height")
352 template <
class T,
class S>
364 msg << name <<
" - Received event has " << has <<
" bytes, but expected " << size <<
".";
371 if (!CheckEventSize(evt.
GetSize(),
"SetVerbosity", 1))
372 return T::kSM_FatalError;
374 fLidar.SetVerbose(evt.
GetBool());
376 return T::GetCurrentState();
407 return fLidar.GetState();
417 "No connection to web-server could be established recently");
420 "Connection to webserver can be established, but received data is not recent or invalid");
423 "Connection to webserver can be established, receint data received");
426 T::AddEvent(
"SET_VERBOSE",
"B")
428 (
"set verbosity state" 429 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
445 fLidar.SetVerbose(!conf.
Get<
bool>(
"quiet"));
446 fLidar.SetInterval(conf.
Get<uint16_t>(
"interval"));
447 fLidar.SetDebugTx(conf.
Get<
bool>(
"debug-tx"));
448 fLidar.SetSite(conf.
Get<
string>(
"url"));
449 fLidar.SetEndpoint(conf.
Get<
string>(
"addr"));
450 fLidar.StartConnect();
461 template<
class T,
class S,
class R>
464 return Main::execute<T, StateMachineLidar<S, R>>(conf);
469 po::options_description control(
"MAGIC lidar control options");
470 control.add_options()
471 (
"no-dim,d",
po_switch(),
"Disable dim services")
472 (
"addr,a", var<string>(
"www.magic.iac.es:80"),
"Network address of Cosy")
473 (
"url,u", var<string>(
"/site/weather/lidar_data.txt"),
"File name and path to load")
474 (
"quiet,q",
po_bool(
true),
"Disable printing contents of all received messages (except dynamic data) in clear text.")
475 (
"interval,i", var<uint16_t>(30),
"Interval between two updates on the server in seconds")
476 (
"debug-tx",
po_bool(),
"Enable debugging of ethernet transmission.")
494 "The magiclidar is an interface to the MAGIC lidar data.\n" 496 "The default is that the program is started without user intercation. " 497 "All actions are supposed to arrive as DimCommands. Using the -c " 498 "option, a local shell can be initialized. With h or help a short " 499 "help message about the usuage can be brought to the screen.\n" 501 "Usage: magiclidar [-c type] [OPTIONS]\n" 502 " or: magiclidar [OPTIONS]\n";
528 int main(
int argc,
const char* argv[])
541 if (!conf.
Has(
"console"))
543 if (conf.
Get<
bool>(
"no-dim"))
544 return RunShell<LocalStream, StateMachine, ConnectionLidar>(conf);
546 return RunShell<LocalStream, StateMachineDim, ConnectionDimLidar>(conf);
549 if (conf.
Get<
bool>(
"no-dim"))
551 if (conf.
Get<
int>(
"console")==0)
552 return RunShell<LocalShell, StateMachine, ConnectionLidar>(conf);
554 return RunShell<LocalConsole, StateMachine, ConnectionLidar>(conf);
558 if (conf.
Get<
int>(
"console")==0)
559 return RunShell<LocalShell, StateMachineDim, ConnectionDimLidar>(conf);
561 return RunShell<LocalConsole, StateMachineDim, ConnectionDimLidar>(conf);
void HandleRequest(const bs::error_code &error)
ConnectionLidar(ba::io_service &ioservice, MessageImp &imp)
bool CheckEventSize(size_t has, const char *name, size_t size)
A general base-class describing events issues in a state machine.
int EvalOptions(Configuration &conf)
static const uint16_t kMaxAddr
void SetupConfiguration(Configuration &conf)
The base implementation of a distributed messaging system.
virtual void UpdateLidar(const Time &, const DimLidar &)
Adds some functionality to boost::posix_time::ptime for our needs.
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
po::typed_value< bool > * po_switch()
int main(int argc, const char *argv[])
boost::array< char, 4096 > fArray
void SetSite(const string &site)
bool Has(const std::string &var)
DimDescribedService fDimLidar
ConnectionDimLidar(ba::io_service &ioservice, MessageImp &imp)
void AddOptions(const po::options_description &opt, bool visible=true)
void setData(const void *ptr, size_t sz)
boost::asio::deadline_timer fKeepAlive
int RunShell(Configuration &conf)
void SetupConfiguration(Configuration &conf)
void ConnectionEstablished()
void SetVerbose(bool b=true)
Commandline parsing, resource file parsing and database access.
virtual void UpdateLidar(const Time &t, const DimLidar &data)
int SetVerbosity(const EventImp &evt)
void SetInterval(uint16_t i)
po::typed_value< bool > * po_bool(bool def=false)
std::string GetAsStr(const char *fmt="%Y-%m-%d %H:%M:%S") const
StateMachineLidar(ostream &out=cout)
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
virtual size_t GetSize() const
void HandleRead(const boost::system::error_code &err, size_t bytes_received)