1 #include <boost/array.hpp> 23 namespace ba = boost::asio;
24 namespace bs = boost::system;
25 namespace dummy = ba::placeholders;
51 void HandleRead(
const boost::system::error_code& err,
size_t bytes_received)
54 if (bytes_received==0 || err)
56 if (err==ba::error::eof)
57 Warn(
"Connection closed by remote host.");
61 if (err && err!=ba::error::eof &&
62 err!=ba::error::basic_errors::not_connected &&
63 err!=ba::error::basic_errors::operation_aborted)
66 str <<
"Reading from " << URL() <<
": " << err.message() <<
" (" << err <<
")";
69 PostClose(err!=ba::error::basic_errors::operation_aborted);
73 fLastReception =
Time();
75 const string str(fArray.data(), bytes_received);
76 memset(fArray.data(), 0, fArray.size());
85 int hh=0, mm=0, ss=0, y=0, m=0, d=0;
87 bool keepalive =
false;
91 while (getline(is, line))
93 if (line.size()==1 && line[0]==13)
101 const size_t p = line.find_first_of(
": ");
105 std::transform(line.begin(), line.end(), line.begin(), (int(&)(int))std::tolower);
107 const string key = line.substr(0, p);
108 const string val = line.substr(p+2);
110 if (key==
"connection" && val==
"keep-alive")
115 if (line.substr(0, 2)==
"ST")
116 data.
fStatus = stoi(line.substr(2));
118 if (line.substr(0, 2)==
"TE")
119 data.
fTemp = stof(line.substr(2));
121 if (line.substr(0, 2)==
"DP")
122 data.
fDew = stof(line.substr(2));
124 if (line.substr(0, 3)==
"HUM")
125 data.
fHum = stof(line.substr(3));
127 if (line.substr(0, 2)==
"WS")
128 data.
fWind = stof(line.substr(2));
130 if (line.substr(0, 3)==
"MWD")
131 data.
fDir = stof(line.substr(3));
133 if (line.substr(0, 2)==
"WP")
134 data.
fGusts = stof(line.substr(2));
136 if (line.substr(0, 5)==
"PRESS")
137 data.
fPress = stof(line.substr(5));
139 if (line.substr(0, 4)==
"HOUR")
140 hh = stoi(line.substr(4));
142 if (line.substr(0, 6)==
"MINUTS")
143 mm = stoi(line.substr(6));
145 if (line.substr(0, 7)==
"SECONDS")
146 ss = stoi(line.substr(7));
148 if (line.substr(0, 4)==
"YEAR")
149 y = stoi(line.substr(4));
151 if (line.substr(0, 5)==
"MONTH")
152 m = stoi(line.substr(5));
154 if (line.substr(0, 3)==
"DAY")
155 d = stoi(line.substr(3));
164 const Time tm =
Time(2000+y, m, d, hh, mm, ss);
170 <<
" T=" << data.
fTemp <<
"°C" 171 <<
" H=" << data.
fHum <<
"%" 172 <<
" P=" << data.
fPress <<
"hPa" 173 <<
" Td=" << data.
fDew <<
"°C" 174 <<
" V=" << data.
fWind <<
"km/h" 175 <<
" Vmax=" << data.
fGusts <<
"km/h" 176 <<
" dir=" << data.
fDir <<
"°";
179 UpdateWeather(tm, data);
183 catch (
const exception &e)
185 Warn(
"Corrupted time received.");
194 dummy::error, dummy::bytes_transferred));
202 "GET "+fSite+
" HTTP/1.1\r\n" 204 "Content-Type: application/octet-stream\r\n" 205 "User-Agent: FACT\r\n" 206 "Host: www.fact-project.org\r\n" 207 "Pragma: no-cache\r\n" 208 "Cache-Control: no-cache\r\n" 210 "Connection: Keep-Alive\r\n" 211 "Cache-Control: max-age=0\r\n" 221 fKeepAlive.expires_from_now(boost::posix_time::seconds(fInterval/2));
223 this, dummy::error));
229 if (error && error!=ba::error::basic_errors::operation_aborted)
232 str <<
"Write timeout of " << URL() <<
": " << error.message() <<
" (" << error <<
")";
251 if (fKeepAlive.expires_at() > ba::deadline_timer::traits_type::now())
272 fIsVerbose(true), fLastReport(
Time::none), fLastReception(
Time::none), fKeepAlive(ioservice)
295 if (fLastReport.
IsValid() && fLastReport+boost::posix_time::seconds(fInterval*2)>
Time())
298 if (fLastReception.
IsValid() && fLastReception+boost::posix_time::seconds(fInterval*2)>
Time())
327 fDimWeather(
"MAGIC_WEATHER/DATA",
"S:1;F:1;F:1;F:1;F:1;F:1;F:1;F:1",
329 "|T[deg C]:Temperature" 330 "|T_dew[deg C]:Dew point" 332 "|P[hPa]:Air pressure" 333 "|v[km/h]:Wind speed" 334 "|v_max[km/h]:Wind gusts" 335 "|d[deg]:Wind direction (N-E)")
342 template <
class T,
class S>
354 msg << name <<
" - Received event has " << has <<
" bytes, but expected " << size <<
".";
361 if (!CheckEventSize(evt.
GetSize(),
"SetVerbosity", 1))
362 return T::kSM_FatalError;
364 fWeather.SetVerbose(evt.
GetBool());
366 return T::GetCurrentState();
397 return fWeather.GetState();
406 "No connection to web-server could be established recently");
409 "Connection to webserver can be established, but received data is not recent or invalid");
412 "Connection to webserver can be established, receint data received");
415 T::AddEvent(
"SET_VERBOSE",
"B")
417 (
"set verbosity state" 418 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
434 fWeather.SetVerbose(!conf.
Get<
bool>(
"quiet"));
435 fWeather.SetInterval(conf.
Get<uint16_t>(
"interval"));
436 fWeather.SetDebugTx(conf.
Get<
bool>(
"debug-tx"));
437 fWeather.SetSite(conf.
Get<
string>(
"url"));
438 fWeather.SetEndpoint(conf.
Get<
string>(
"addr"));
439 fWeather.StartConnect();
452 template<
class T,
class S,
class R>
455 return Main::execute<T, StateMachineWeather<S, R>>(conf);
460 po::options_description control(
"MAGIC weather control options");
461 control.add_options()
462 (
"no-dim,d",
po_switch(),
"Disable dim services")
463 (
"addr,a", var<string>(
"www.magic.iac.es:80"),
"Network address of Cosy")
464 (
"url,u", var<string>(
"/site/weather/weather_data.txt"),
"File name and path to load")
465 (
"quiet,q",
po_bool(
true),
"Disable printing contents of all received messages (except dynamic data) in clear text.")
466 (
"interval,i", var<uint16_t>(30),
"Interval between two updates on the server in seconds")
467 (
"debug-tx",
po_bool(),
"Enable debugging of ethernet transmission.")
485 "The magicweather is an interface to the MAGIC weather data.\n" 487 "The default is that the program is started without user intercation. " 488 "All actions are supposed to arrive as DimCommands. Using the -c " 489 "option, a local shell can be initialized. With h or help a short " 490 "help message about the usuage can be brought to the screen.\n" 492 "Usage: magicweather [-c type] [OPTIONS]\n" 493 " or: magicweather [OPTIONS]\n";
519 int main(
int argc,
const char* argv[])
532 if (!conf.
Has(
"console"))
534 if (conf.
Get<
bool>(
"no-dim"))
535 return RunShell<LocalStream, StateMachine, ConnectionWeather>(conf);
537 return RunShell<LocalStream, StateMachineDim, ConnectionDimWeather>(conf);
540 if (conf.
Get<
bool>(
"no-dim"))
542 if (conf.
Get<
int>(
"console")==0)
543 return RunShell<LocalShell, StateMachine, ConnectionWeather>(conf);
545 return RunShell<LocalConsole, StateMachine, ConnectionWeather>(conf);
549 if (conf.
Get<
int>(
"console")==0)
550 return RunShell<LocalShell, StateMachineDim, ConnectionDimWeather>(conf);
552 return RunShell<LocalConsole, StateMachineDim, ConnectionDimWeather>(conf);
A general base-class describing events issues in a state machine.
void SetupConfiguration(Configuration &conf)
The base implementation of a distributed messaging system.
Adds some functionality to boost::posix_time::ptime for our needs.
ConnectionWeather(ba::io_service &ioservice, MessageImp &imp)
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
po::typed_value< bool > * po_switch()
void ConnectionEstablished()
static const uint16_t kMaxAddr
void HandleRead(const boost::system::error_code &err, size_t bytes_received)
virtual void UpdateWeather(const Time &, const DimWeather &)
bool Has(const std::string &var)
void AddOptions(const po::options_description &opt, bool visible=true)
void setData(const void *ptr, size_t sz)
int main(int argc, const char *argv[])
bool CheckEventSize(size_t has, const char *name, size_t size)
void HandleRequest(const bs::error_code &error)
void SetInterval(uint16_t i)
virtual void UpdateWeather(const Time &t, const DimWeather &data)
void SetVerbose(bool b=true)
DimDescribedService fDimWeather
ba::deadline_timer fKeepAlive
Commandline parsing, resource file parsing and database access.
void SetSite(const string &site)
int RunShell(Configuration &conf)
boost::array< char, 4096 > fArray
StateMachineWeather(ostream &out=cout)
int SetVerbosity(const EventImp &evt)
po::typed_value< bool > * po_bool(bool def=false)
int EvalOptions(Configuration &conf)
std::string GetAsStr(const char *fmt="%Y-%m-%d %H:%M:%S") const
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
ConnectionDimWeather(ba::io_service &ioservice, MessageImp &imp)
void SetupConfiguration(Configuration &conf)
virtual size_t GetSize() const