15 #include "../externals/nova.h" 19 #include <QtXml/QDomDocument> 21 namespace ba = boost::asio;
22 namespace bs = boost::system;
23 namespace dummy = ba::placeholders;
33 map<uint16_t, GCN::PaketType_t>
fTypes;
48 const QDomNodeList param = what.elementsByTagName(
"Param");
49 for (
int i=0;
i<param.count();
i++)
51 const QDomElement elem = param.at(
i).toElement();
52 if (elem.attribute(
"name").toStdString()!=
"Packet_Type")
55 const uint16_t val = elem.attribute(
"value").toUInt();
56 const auto it = fTypes.find(val);
60 Warn(
"Unknown paket type "+to_string(val)+
".");
63 return { -1,
"",
"" };
72 const string role = root.attribute(
"role",
"").toStdString();
73 const string name = root.tagName().toStdString();
77 if (name==
"trn:Transport")
81 const QDomElement orig = root.firstChildElement(
"Origin");
82 const QDomElement
time = root.firstChildElement(
"TimeStamp");
83 if (orig.isNull() || time.isNull())
86 fLastKeepAlive =
Time(time.text().toStdString());
90 Out() <<
Time().
GetAsStr() <<
" ----- " << name <<
" [" << role <<
"] -----" << endl;
91 Out() <<
" " << time.tagName().toStdString() <<
" = " << fLastKeepAlive.
GetAsStr() <<
'\n';
92 Out() <<
" " << orig.tagName().toStdString() <<
" = " << orig.text().toStdString() <<
'\n';
102 ofstream fout(
"gcn.stream", ios::app);
103 fout <<
"------------------------------------------------------------------------------\n" << fRxData.data() << endl;
105 if (name==
"voe:VOEvent")
108 const QDomElement who = root.firstChildElement(
"Who");
109 const QDomElement what = root.firstChildElement(
"What");
110 const QDomElement when = root.firstChildElement(
"WhereWhen");
116 if (who.isNull() || what.isNull() || when.isNull())
119 const QDomElement date = who.firstChildElement(
"Date");
120 const QDomElement author = who.firstChildElement(
"Author");
121 const QDomElement sname = author.firstChildElement(
"shortName");
122 const QDomElement desc = what.firstChildElement(
"Description");
124 const QDomElement obsdat = when.firstChildElement(
"ObsDataLocation");
125 const QDomElement obsloc = obsdat.firstChildElement(
"ObservationLocation");
126 const QDomElement coord = obsloc.firstChildElement(
"AstroCoords");
128 const QDomElement
time = coord.firstChildElement(
"Time").firstChildElement(
"TimeInstant").firstChildElement(
"ISOTime");
129 const QDomElement pos2d = coord.firstChildElement(
"Position2D");
130 const QDomElement name1 = pos2d.firstChildElement(
"Name1");
131 const QDomElement name2 = pos2d.firstChildElement(
"Name2");
132 const QDomElement val2 = pos2d.firstChildElement(
"Value2");
133 const QDomElement c1 = val2.firstChildElement(
"C1");
134 const QDomElement c2 = val2.firstChildElement(
"C2");
135 const QDomElement errad = pos2d.firstChildElement(
"Error2Radius");
137 if (date.isNull() || author.isNull() || sname.isNull() || desc.isNull() ||
138 obsdat.isNull() || obsloc.isNull() || coord.isNull() || time.isNull() ||
139 pos2d.isNull() || name1.isNull() || name2.isNull() || val2.isNull() ||
140 c1.isNull() || c2.isNull() || errad.isNull())
195 const string unit = pos2d.attribute(
"unit").toStdString();
197 const double ra = c1.text().toDouble();
198 const double dec = c2.text().toDouble();
199 const double err = errad.text().toDouble();
201 const string n1 = name1.text().toStdString();
202 const string n2 = name2.text().toStdString();
204 Out() <<
Time(date.text().toStdString()).GetAsStr() <<
" ----- " << sname.text().toStdString() <<
" [" << role <<
"]\n";
205 Out() <<
"[" << desc.text().toStdString() <<
"]\n";
208 Out() <<
" " << setw(5) <<
"TIME" <<
"= " <<
Time(time.text().toStdString()).GetAsStr() <<
'\n';
209 Out() <<
" " << setw(5) << n1 <<
"= " << ra << unit <<
'\n';
210 Out() <<
" " << setw(5) << n2 <<
"= " << dec << unit <<
'\n';
211 Out() <<
" " << setw(5) <<
"ERR" <<
"= " << err << unit <<
'\n';
213 if (n1==
"RA" && n2==
"Dec" && unit==
"deg")
215 const double jd =
Time().
JD();
228 Out() <<
" " << setw(5) <<
"ZD" <<
"= " << pos.
zd <<
"deg\n";
229 Out() <<
" " << setw(5) <<
"Az" <<
"= " << pos.
az <<
"deg\n";
231 Out() <<
" " << setw(5) <<
"MOON" <<
"= " << int(disk*100) <<
"%\n";
232 Out() <<
" " << setw(5) <<
"DIST" <<
"= " << dist <<
"deg\n";
234 if (dist>10 && dist<170 && pos.
zd<80 && sun.
zd>108)
236 Out() <<
" visible ";
249 if (role==
"observation")
259 if (role==
"retraction")
272 Out() <<
Time().
GetAsStr() <<
" ----- " << name <<
" [" << role <<
"] -----" << endl;
280 if (bytes_received==0 || err)
282 if (err==ba::error::eof)
283 Warn(
"Connection closed by remote host (GCN).");
287 if (err && err!=ba::error::eof &&
288 err!=ba::error::basic_errors::not_connected &&
289 err!=ba::error::basic_errors::operation_aborted)
292 str <<
"Reading from " << URL() <<
": " << err.message() <<
" (" << err <<
")";
295 PostClose(err!=ba::error::basic_errors::operation_aborted);
301 fRxSize = ntohl(fRxSize);
302 fRxData.assign(fRxSize+1, 0);
303 ba::async_read(*
this,
ba::buffer(fRxData, fRxSize),
305 dummy::error, dummy::bytes_transferred, 1));
311 Out() <<
"------------------------------------------------------\n";
312 Out() << fRxData.data() <<
'\n';
313 Out() <<
"------------------------------------------------------" << endl;
317 if (!doc.setContent(QString(fRxData.data()),
false))
319 Warn(
"Parsing of xml failed [0].");
325 Out() <<
"Parsed:\n-------\n" << doc.toString().toStdString() << endl;
327 const int rc = ProcessXml(doc.documentElement());
330 Warn(
"Parsing of xml failed [1].");
337 Out() <<
"------------------------------------------------------\n";
338 Out() << doc.toString().toStdString() <<
'\n';
339 Out() <<
"------------------------------------------------------" << endl;
347 ba::async_read(*
this,
ba::buffer(&fRxSize, 4),
349 dummy::error, dummy::bytes_transferred, 0));
360 fIsVerbose(false), fDebugRx(false), fLastKeepAlive(
Time::none)
365 fTypes[it->type] = *it;
387 if (fEndPoints.size()>0)
388 SetEndpoint(fEndPoints[fEndPoint++%fEndPoints.size()]);
394 return fLastKeepAlive.
IsValid() ?
Time()-fLastKeepAlive<boost::posix_time::minutes(2) :
false;
414 template <
class T,
class S>
423 fGCN.PostClose(
false);
425 return T::GetCurrentState();
431 fGCN.PostClose(
false);
435 ba::io_service::poll();
441 fGCN.PostClose(
true);
443 return T::GetCurrentState();
448 if (!fGCN.IsConnected())
460 msg << name <<
" - Received event has " << has <<
" bytes, but expected " << size <<
".";
467 if (!CheckEventSize(evt.
GetSize(),
"SetVerbosity", 1))
468 return T::kSM_FatalError;
470 fGCN.SetVerbose(evt.
GetBool());
472 return T::GetCurrentState();
477 if (!CheckEventSize(evt.
GetSize(),
"SetDebugRx", 1))
478 return T::kSM_FatalError;
480 fGCN.SetDebugRx(evt.
GetBool());
482 return T::GetCurrentState();
491 "No connection to GCN.");
493 "Connection to GCN established.");
495 "Connection valid (keep alive received within past 2min)");
498 T::AddEvent(
"SET_VERBOSE",
"B:1")
500 (
"set verbosity state" 501 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
502 T::AddEvent(
"SET_DEBUG_RX",
"B:1")
504 (
"Set debux-rx state" 505 "|debug[bool]:dump received text and parsed text to console (yes/no)");
511 (
"disconnect from ethernet");
514 (
"(Re)connect ethernet connection to FTM, a new address can be given" 515 "|[host][string]:new ethernet address in the form <host:port>");
524 fGCN.SetEndPoints(v);
531 fGCN.SetVerbose(!conf.
Get<
bool>(
"quiet"));
532 fGCN.SetEndPoints(conf.
Vec<
string>(
"addr"));
542 template<
class T,
class S,
class R>
545 return Main::execute<T, StateMachineGCN<S, R>>(conf);
550 po::options_description control(
"FTM control options");
551 control.add_options()
552 (
"no-dim",
po_bool(),
"Disable dim services")
553 (
"addr,a", vars<string>(),
"Network addresses of GCN server")
554 (
"quiet,q",
po_bool(
true),
"Disable printing contents of all received messages (except dynamic data) in clear text.")
572 "The gcn reads and evaluates alerts from the GCN network.\n" 574 "The default is that the program is started without user intercation. " 575 "All actions are supposed to arrive as DimCommands. Using the -c " 576 "option, a local shell can be initialized. With h or help a short " 577 "help message about the usuage can be brought to the screen.\n" 579 "Usage: gcn [-c type] [OPTIONS]\n" 580 " or: gcn [OPTIONS]\n";
586 Main::PrintHelp<StateMachineGCN<StateMachine, ConnectionGCN>>();
606 int main(
int argc,
const char* argv[])
619 if (!conf.
Has(
"console"))
621 if (conf.
Get<
bool>(
"no-dim"))
622 return RunShell<LocalStream, StateMachine, ConnectionGCN>(conf);
624 return RunShell<LocalStream, StateMachineDim, ConnectionDimGCN>(conf);
627 if (conf.
Get<
bool>(
"no-dim"))
629 if (conf.
Get<
int>(
"console")==0)
630 return RunShell<LocalShell, StateMachine, ConnectionGCN>(conf);
632 return RunShell<LocalConsole, StateMachine, ConnectionGCN>(conf);
636 if (conf.
Get<
int>(
"console")==0)
637 return RunShell<LocalShell, StateMachineDim, ConnectionDimGCN>(conf);
639 return RunShell<LocalConsole, StateMachineDim, ConnectionDimGCN>(conf);
map< uint16_t, GCN::PaketType_t > fTypes
A general base-class describing events issues in a state machine.
EquPosn GetLunarEquCoords(double jd, double precision=0)
void SetupConfiguration(Configuration &conf)
The base implementation of a distributed messaging system.
int SetDebugRx(const EventImp &evt)
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)
void SetEndPoints(const vector< string > &v)
void ConnectionEstablished()
int Reconnect(const EventImp &evt)
std::vector< T > Vec(const std::string &var)
int main(int argc, const char *argv[])
std::string GetString() const
double GetLunarDisk(double jd)
GCN::PaketType_t GetType(const QDomElement &what)
static const PaketType_t kTypes[]
virtual void StartConnect()
bool Has(const std::string &var)
void HandleReceivedData(const bs::error_code &err, size_t bytes_received, int type)
int ProcessXml(const QDomElement &root)
void AddOptions(const po::options_description &opt, bool visible=true)
void SetVerbose(bool b=true)
Warning because the service this data corrsponds to might have been last updated longer ago than Local time
StateMachineGCN(ostream &out=cout)
vector< string > fEndPoints
Commandline parsing, resource file parsing and database access.
void SetupConfiguration(Configuration &conf)
HrzPosn GetHrzFromEqu(const EquPosn &equ, const LnLatPosn &obs, double jd)
int EvalOptions(Configuration &conf)
vector< string > fEndPoints
int RunShell(Configuration &conf)
bool CheckEventSize(size_t has, const char *name, size_t size)
po::typed_value< bool > * po_bool(bool def=false)
ConnectionDimGCN(ba::io_service &ioservice, MessageImp &imp)
double GetAngularSeparation(const EquPosn &p1, const EquPosn &p2)
void SetEndpoint(const string &url)
std::string GetAsStr(const char *fmt="%Y-%m-%d %H:%M:%S") const
int SetVerbosity(const EventImp &evt)
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
EquPosn GetSolarEquCoords(double jd)
ConnectionGCN(ba::io_service &ioservice, MessageImp &imp)
virtual size_t GetSize() const