Index: /trunk/FACT++/src/HeadersGCN.h
===================================================================
--- /trunk/FACT++/src/HeadersGCN.h	(revision 16980)
+++ /trunk/FACT++/src/HeadersGCN.h	(revision 16981)
@@ -10,6 +10,139 @@
             kDisconnected = 1,
             kConnected    = 2,
+            kValid        = 3,
         };
+
     }
+
+    struct PaketType_t
+    {
+        int16_t type;
+        string  name;
+        string  description;
+    };
+
+    static const PaketType_t kTypes[] =
+    {   // inactive, ACTIVE[1], T-Only[-], in-work[+]
+        { 1,   /*   */ "GRB_COORDS",	           "BATSE Trigger coords (the first GCN Notice Type)" },
+        { 2,   /* 1 */ "TEST_COORDS",	           "Test coords" },
+        { 3,   /* 1 */ "IM_ALIVE",	           "I'm alive socket packet every 60 sec" },
+        { 4,   /* 1 */ "KILL_SOCKET",	           "Kill a socket connection" },
+        { 11,  /*   */ "MAXBC",	                   "MAXC1/BC" },
+        { 21,  /*   */ "BRAD_COORDS",	           "Special Test coords packet for BRADFORD" },
+        { 22,  /*   */ "GRB_FINAL",	           "Final BATSE coords" },
+        { 24,  /*   */ "HUNTS_SRC",	 	   "Huntsville LOCBURST GRB coords (HitL)" },
+        { 25,  /*   */ "ALEXIS_SRC",	           "ALEXIS Transient coords" },
+        { 26,  /*   */ "XTE_PCA_ALERT",	           "XTE-PCA ToO Observation Scheduled" },
+        { 27,  /*   */ "XTE_PCA_SRC",	           "XTE-PCA GRB coords" },
+        { 28,  /*   */ "XTE_ASM_ALERT",	           "XTE-ASM Alert" },
+        { 29,  /*   */ "XTE_ASM_SRC",	           "XTE-ASM GRB coords" },
+        { 30,  /*   */ "COMPTEL_SRC",	           "COMPTEL GRB coords" },
+        { 31,  /*   */ "IPN_RAW",	           "IPN_RAW GRB annulus coords (position is center of Annulus)" },
+        { 32,  /*   */ "IPN_SEG",	           "IPN+POS GRB annulus seg (kind of a cheat to allow error filter)" },
+        { 33,  /*   */ "SAX_WFC_ALERT",	           "SAX-WFC Alert" },
+        { 34,  /*   */ "SAX_WFC_SRC",	 	   "SAX-WFC GRB coords" },
+        { 35,  /*   */ "SAX_NFI_ALERT",	           "SAX-NFI Alert" },
+        { 36,  /*   */ "SAX_NFI_SRC",	           "SAX-NFI GRB coords" },
+        { 37,  /*   */ "XTE_ASM_TRANS",	 	   "XTE-ASM TRANSIENT coords" },
+        { 38,  /* 1 */ "spare38",	           "(spare; used for s/w development testing)" },
+        { 39,  /* 1 */ "IPN_POS",	           "IPN Position coords" },
+        { 40,  /*   */ "HETE_ALERT_SRC",	   "HETE Trigger Alert" },
+        { 41,  /*   */ "HETE_UPDATE_SRC",	   "HETE Update position (multiples)" },
+        { 42,  /*   */ "HETE_FINAL_SRC",	   "HETE Last/Final position" },
+        { 43,  /*   */ "HETE_GNDANA_SRC",	   "HETE position from Ground Analysis (HitL)" },
+        { 44,  /* 1 */ "HETE_TEST",	           "HETE TEST" },
+        { 45,  /* 1 */ "GRB_CNTRPART",	           "GRB Counterpart coordinates" },
+        { 46,  /* 1 */ "SWIFT_TOO_FOM",	           "SWIFT TOO-form of the FOM" },
+        { 47,  /* 1 */ "SWIFT_TOO_SC_SLEW",	   "SWIFT TOO-form of the SC_SLEW" },
+        { 48,  /* - */ "DOW_TOD",	           "Day-of-Week Time-of-Day end2end testing" },
+        { 50,  /* 1 */ "spare50",	           "(spare; not yet assigned)" },
+        { 51,  /* 1 */ "INTEGRAL_POINTDIR",	   "INTEGRAL Pointing Direction" },
+        { 52,  /* 1 */ "INTEGRAL_SPIACS",	   "INTEGRAL SPIACS" },
+        { 53,  /* 1 */ "INTEGRAL_WAKEUP",	   "INTEGRAL Wakeup" },
+        { 54,  /* 1 */ "INTEGRAL_REFINED",	   "INTEGRAL Refined" },
+        { 55,  /* 1 */ "INTEGRAL_OFFLINE",	   "INTEGRAL Offline (HitL)" },
+        { 56,  /* 1 */ "INTEGRAL_WEAK",	           "INTEGRAL Weak" },
+        { 57,  /* + */ "AAVSO",	                   "AAVSO" },
+        { 58,  /*   */ "MILAGRO_POS",	           "MILAGRO Position" },
+        { 59,  /* 1 */ "KONUS_LC",	           "KONUS Lightcurve" },
+        { 60,  /* 1 */ "SWIFT_BAT_GRB_ALERT",	   "BAT ALERT. Never transmitted by the s/c." },
+        { 61,  /* 1 */ "SWIFT_BAT_GRB_POS_ACK",	   "BAT GRB Position Acknowledge" },
+        { 62,  /* 1 */ "SWIFT_BAT_GRB_POS_NACK",   "BAT GRB Position NOT_Ack (pos not found)." },
+        { 63,  /* 1 */ "SWIFT_BAT_GRB_LC",	   "BAT GRB Lightcurve" },
+        { 64,  /* - */ "SWIFT_BAT_SCALEDMAP",	   "BAT Scaled Map" },
+        { 65,  /* 1 */ "SWIFT_FOM_OBS",	           "BAT FOM to Observe (FOM_2OBSAT)" },
+        { 66,  /* 1 */ "SWIFT_SC_SLEW",	           "BAT S/C to Slew (FOSC_2OBSAT)" },
+        { 67,  /* 1 */ "SWIFT_XRT_POSITION",	   "XRT Position" },
+        { 68,  /* - */ "SWIFT_XRT_SPECTRUM",	   "XRT Spectrum" },
+        { 69,  /* 1 */ "SWIFT_XRT_IMAGE",	   "XRT Image (aka postage stamp)" },
+        { 70,  /* - */ "SWIFT_XRT_LC",	           "XRT Lightcurve (aka Prompt)" },
+        { 71,  /* 1 */ "SWIFT_XRT_CENTROID",	   "XRT Centroid Error (Pos Nack)" },
+        { 72,  /* 1 */ "SWIFT_UVOT_DBURST",	   "UVOT DarkBurst (aka Neighbor, aka GeNie)" },
+        { 73,  /* 1 */ "SWIFT_UVOT_FCHART",	   "UVOT Finding Chart" },
+        { 76,  /* + */ "SWIFT_BAT_GRB_LC_PROC",	   "BAT GRB Lightcurve processed" },
+        { 77,  /* - */ "SWIFT_XRT_SPECTRUM_PROC",  "XRT Spectrum processed" },
+        { 78,  /* 1 */ "SWIFT_XRT_IMAGE_PROC",	   "XRT Image processed" },
+        { 79,  /* 1 */ "SWIFT_UVOT_DBURST_PROC",   "UVOT DarkBurst proc mesg (aka Neighbor)" },
+        { 80,  /* 1 */ "SWIFT_UVOT_FCHART_PROC",   "UVOT Finding Chart processed" },
+        { 81,  /* 1 */ "SWIFT_UVOT_POS",	   "UVOT Position" },
+        { 82,  /* 1 */ "SWIFT_BAT_GRB_POS_TEST",   "BAT GRB Position Test" },
+        { 83,  /* 1 */ "SWIFT_POINTDIR",	   "Pointing Direction" },
+        { 84,  /* 1 */ "SWIFT_BAT_TRANS",	   "BAT Hard X-ray Transient coords" },
+        { 85,  /* - */ "SWIFT_XRT_THRESHPIX",	   "XRT Thresholded-Pixel-list" },
+        { 86,  /* - */ "SWIFT_XRT_THRESHPIX_PROC", "XRT Thresholded-Pixel-list processed" },
+        { 87,  /* - */ "SWIFT_XRT_SPER",	   "XRT Single-Pixel-Event-Report" },
+        { 88,  /* - */ "SWIFT_XRT_SPER_PROC",	   "XRT Single-Pixel-Event-Report processed" },
+        { 89,  /* 1 */ "SWIFT_UVOT_POS_NACK",	   "UVOT Position Nack (contains BATs/XRTs position)" },
+        { 90,  /* - */ "SWIFT_BAT_ALARM_SHORT",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 91,  /* - */ "SWIFT_BAT_ALARM_LONG",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 92,  /* - */ "SWIFT_UVOT_EMERGENCY",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 93,  /* - */ "SWIFT_XRT_EMERGENCY",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 94,  /* - */ "SWIFT_FOM_PPT_ARG_ERR",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 95,  /* - */ "SWIFT_FOM_SAFE_POINT",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 96,  /* - */ "SWIFT_FOM_SLEW_ABORT",	   "SWIFT Appendix_C non-public (Team Ops)" },
+        { 97,  /* 1 */ "SWIFT_BAT_QL_POS",	   "BAT Quick Look Position (1-6 sec sooner)" },
+        { 98,  /* 1 */ "SWIFT_BAT_SUB_THRESHOLD",  "BAT Sub-Threshold Position" },
+        { 99,  /* 1 */ "SWIFT_BAT_SLEW_POS",	   "BAT Burst/Trans Pos during slewing" },
+        { 100, /* 1 */ "AGILE_GRB_WAKEUP",	   "AGILE GRB Wake-Up Position" },
+        { 101, /* 1 */ "AGILE_GRB_GROUND",	   "AGILE GRB Prompt Position" },
+        { 102, /* 1 */ "AGILE_GRB_REFINED",	   "AGILE GRB Refined Position" },
+        { 107, /* 1 */ "AGILE_POINTDIR",	   "AGILE Pointing Direction" },
+        { 108, /* + */ "AGILE_TRANS",	           "AGILE Transient Position" },
+        { 109, /* 1 */ "AGILE_GRB_POS_TEST",	   "AGILE GRB Position Test" },
+        { 110, /* 1 */ "FERMI_GBM_ALERT",	   "GBM Alert" },
+        { 111, /* 1 */ "FERMI_GBM_FLT_POS",	   "GBM Flightt-calculated Position" },
+        { 112, /* 1 */ "FERMI_GBM_GND_POS",	   "GBM Ground-calculated Position" },
+        { 113, /* + */ "FERMI_GBM_LC",	           "GBM Lightcurve" },
+        { 114, /* - */ "FERMI_GBM_GND_INTERNAL",   "GBM Gnd-calc Internal (beyond 112)" },
+        { 115, /* 1 */ "FERMI_GBM_FIN_POS",	   "GBM Final Position HitL or Offline" },
+        { 118, /* + */ "FERMI_GBM_TRANS",	   "GBM Transient Position" },
+        { 119, /* 1 */ "FERMI_GBM_POS_TEST",	   "GBM Position Test" },
+        { 120, /* - */ "FERMI_LAT_POS_INI",	   "LAT Position Initial" },
+        { 121, /* 1 */ "FERMI_LAT_POS_UPD",	   "LAT Position Update" },
+        { 122, /* - */ "FERMI_LAT_POS_DIAG",	   "LAT Position Diagnostic" },
+        { 123, /* + */ "FERMI_LAT_TRANS",	   "LAT Transient Position (previously unknown source)" },
+        { 124, /* 1 */ "FERMI_LAT_POS_TEST",	   "LAT Position Test (like UPD only)" },
+        { 125, /* + */ "FERMI_LAT_MONITOR",	   "LAT Monitor (eg Blazar, AGN, etc)" },
+        { 126, /* 1 */ "FERMI_SC_SLEW",	           "Spcecraft Slew" },
+        { 127, /* 1 */ "FERMI_LAT_GND",	           "LAT Ground-analysis refined Pos" },
+        { 128, /* + */ "FERMI_LAT_OFFLINE",	   "LAT Ground-analysis Trigger Pos, Offline" },
+        { 129, /* 1 */ "FERMI_POINTDIR",	   "Pointing Direction" },
+        { 130, /* 1 */ "SIMBADNED",	           "SIMBAD/NED Search Results" },
+        { 131, /* + */ "PIOTS_OT_POS",	           "Pi-Of-The-Sky Optical Transient Pos" },
+        { 132, /* + */ "KAIT_SN",	           "KAIT SuperNova" },
+        { 133, /* 1 */ "SWIFT_BAT_MONITOR",	   "Swift BAT Transient Monitor LC page event" },
+        { 134, /* 1 */ "MAXI_UNKNOWN",	           "MAXI previously Unknown source transient (GRBs or other x-ray trans)" },
+        { 135, /* 1 */ "MAXI_KNOWN",	           "MAXI previously Known source transient (already in some catalog)" },
+        { 136, /* 1 */ "MAXI_TEST",	           "MAXI Test notice (for the Unknown type)" },
+        { 137, /* + */ "OGLE",	                   "OGLE lensing event (Inten, yes; but not Signif)" },
+        { 138, /* + */ "CBAT",	                   "CBAT" },
+        { 139, /* + */ "MOA",	                   "MOA lensing event (turn off inten for now!!!)" },
+        { 140, /* 1 */ "SWIFT_BAT_SUBSUB",	   "BAT SubSubThreshold trigger" },
+        { 141, /* 1 */ "SWIFT_BAT_KNOWN_SRC",	   "Known source detected in ach BAT image" },
+        { 142, /* 1 */ "VOE_1.1_IM_ALIVE",	   "I'm alive socket packet sent every 60 sec" },
+        { 143, /* 1 */ "VOE_2.0_IM_ALIVE",	   "I'm alive socket packet sent every 60 sec" },
+        { 148, /* 1 */ "SUZAKU_LC",	           "SUZAKU-WAM Lightcurve" },
+        { -1,          "",                         "" },
+    };
 }
 
Index: /trunk/FACT++/src/gcn.cc
===================================================================
--- /trunk/FACT++/src/gcn.cc	(revision 16980)
+++ /trunk/FACT++/src/gcn.cc	(revision 16981)
@@ -31,4 +31,6 @@
 {
 private:
+    map<uint16_t, GCN::PaketType_t> fTypes;
+
     vector<string> fEndPoints;
     int fEndPoint;
@@ -42,4 +44,25 @@
     Time fLastKeepAlive;
 
+    GCN::PaketType_t GetType(const QDomElement &what)
+    {
+        const QDomNodeList param = what.elementsByTagName("Param");
+        for (int i=0; i<param.count(); i++)
+        {
+            const QDomElement elem = param.at(i).toElement();
+            if (elem.attribute("name").toStdString()!="Packet_Type")
+                continue;
+
+            const uint16_t val = elem.attribute("value").toUInt();
+            const auto it = fTypes.find(val);
+            if (it!=fTypes.end())
+                return it->second;
+
+            Warn("Unknown paket type "+to_string(val)+".");
+        }
+
+        return { -1, "", "" };
+    }
+
+
     int ProcessXml(const QDomElement &root)
     {
@@ -49,6 +72,4 @@
         const string role = root.attribute("role", "").toStdString();
         const string name = root.tagName().toStdString();
-
-        Out() << Time().GetAsStr() << " ----- " << name << " [" << role << "] -----" << endl;
 
         // A full description can be found at http://voevent.dc3.com/schema/default.html
@@ -65,7 +86,11 @@
                 fLastKeepAlive = Time(time.text().toStdString());
 
-                Out() << " " << time.tagName().toStdString() << " = " << fLastKeepAlive.GetAsStr() << '\n';
-                Out() << " " << orig.tagName().toStdString() << " = " << orig.text().toStdString() << '\n';
-                Out() << endl;
+                if (fIsVerbose)
+                {
+                    Out() << Time().GetAsStr() << " ----- " << name << " [" << role << "] -----" << endl;
+                    Out() << " " << time.tagName().toStdString() << " = " << fLastKeepAlive.GetAsStr() << '\n';
+                    Out() << " " << orig.tagName().toStdString() << " = " << orig.text().toStdString() << '\n';
+                    Out() << endl;
+                }
 
                 return true;
@@ -80,4 +105,5 @@
         if (name=="voe:VOEvent")
         {
+            // WHAT: http://gcn.gsfc.nasa.gov/tech_describe.html
             const QDomElement who  = root.firstChildElement("Who");
             const QDomElement what = root.firstChildElement("What");
@@ -115,5 +141,57 @@
                 return -1;
 
-            const string unit = pos2d.attribute("unit", "").toStdString();
+            const GCN::PaketType_t ptype = GetType(what);
+
+            //  59/31: Konus LC / IPN raw         [observation]
+            //   110:  Fermi GBM (ART)            [observation]  (Initial)       // Stop data taking
+            //   111:  Fermi GBM (FLT)            [observation]  (after ~2s)     // Start pointing/run
+            //   112:  Fermi GBM (GND)            [observation]  (after 2-20s)   // Refine pointing
+            //   115:  Fermi GBM position         [observation]  (final ~hours)
+            //
+            //    51:  Intergal pointdir              [utility]
+            //    83:  Swift pointdir                 [utility]
+            //   129:  Fermi pointdir                 [utility]
+            //
+            //     2:  Test coord             (      1)  [test]
+            //    44:  HETE test              ( 41- 43)  [test]
+            //    52:  Integral SPIACS                   [test]
+            //    53:  Integral Wakeup                   [test]
+            //    54:  Integral refined                  [test]
+            //    55:  Integral Offline                  [test]
+            //    56:  Integral Weak                     [test]
+            //    82:  BAT   GRB pos test     (     61)  [test]
+            //   109:  AGILE GRB pos test     (100-103)  [test]
+            //   119:  Fermi GRB pos test     (111-113)  [test]
+            //   124:  Fermi LAT pos upd test (120-122)  [test]
+            //   136:  MAXI coord test        (    134)  [test]
+            //
+            // Integral: RA=1.2343, Dec=2.3456
+            //
+
+            /*
+             54
+             ==
+             <Group name="Test_mpos" >
+               <Param name="Test_Notice"              value="true" />
+             </Group>
+
+
+             82
+             ==
+             <Group name="Solution_Status" >
+               <Param name="Test_Submission"          value="false" />
+             </Group>
+
+
+             115
+             ===
+             2013-07-20 19:04:13: TIME = 2013-07-20 02:46:40
+
+             <Group name="Trigger_ID" >
+               <Param name="Test_Submission"       value="false" />
+             </Group>
+             */
+
+            const string unit = pos2d.attribute("unit").toStdString();
 
             const double ra  = c1.text().toDouble();
@@ -124,6 +202,7 @@
             const string n2 = name2.text().toStdString();
 
-            Out() << Time(date.text().toStdString()).GetAsStr() << " ----- " << sname.text().toStdString() << '\n';
+            Out() << Time(date.text().toStdString()).GetAsStr() << " ----- " << sname.text().toStdString() << " [" << role << "]\n";
             Out() << "[" << desc.text().toStdString()  << "]\n";
+            Out() << ptype.name << "[" << ptype.type << "]: " << ptype.description << endl;
             Out() << left;
             Out() << "  " << setw(5) << "TIME" << "= " << Time(time.text().toStdString()).GetAsStr() << '\n';
@@ -138,19 +217,5 @@
                 Nova::EquPosn equ;
                 equ.ra  = ra;
-                equ.dec = dec;
-
-                /*
-                 <Group name="Obs_Support_Info" >
-                 <Description>The Sun and Moon values are valid at the time the VOEvent XML message was created.</Description>
-                 <Param name="Sun_RA"        value="117.44" unit="deg" ucd="pos.eq.ra" />
-                 <Param name="Sun_Dec"       value="21.04" unit="deg" ucd="pos.eq.dec" />
-                 <Param name="Sun_Distance"  value="105.22" unit="deg" ucd="pos.angDistance" />
-                 <Param name="Sun_Hr_Angle"  value="-3.70" unit="hr" />
-                 <Param name="Moon_RA"       value="225.90" unit="deg" ucd="pos.eq.ra" />
-                 <Param name="Moon_Dec"      value="-16.75" unit="deg" ucd="pos.eq.dec" />
-                 <Param name="MOON_Distance" value="67.47" unit="deg" ucd="pos.angDistance" />
-                 <Param name="Moon_Illum"    value="69.44" unit="%" ucd="arith.ratio" />
-                 </Group>
-                 */
+                equ.dec = dec; 
 
                 const Nova::ZdAzPosn pos = Nova::GetHrzFromEqu(equ, jd);
@@ -205,4 +270,6 @@
         }
 
+        Out() << Time().GetAsStr() << " ----- " << name << " [" << role << "] -----" << endl;
+
         return false;
     }
@@ -279,6 +346,6 @@
     {
         ba::async_read(*this, ba::buffer(&fRxSize, 4),
-                             boost::bind(&ConnectionGCN::HandleReceivedData, this,
-                                         dummy::error, dummy::bytes_transferred, 0));
+                       boost::bind(&ConnectionGCN::HandleReceivedData, this,
+                                   dummy::error, dummy::bytes_transferred, 0));
     }
 
@@ -291,7 +358,10 @@
 public:
     ConnectionGCN(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
-        fIsVerbose(false), fDebugRx(false)
+        fIsVerbose(false), fDebugRx(false), fLastKeepAlive(Time::none)
     {
         SetLogStream(&imp);
+
+        for (auto it=GCN::kTypes; it->type>0; it++)
+            fTypes[it->type] = *it;
     }
 
@@ -319,4 +389,9 @@
         Connection::StartConnect();
     }
+
+    bool IsValid()
+    {
+        return fLastKeepAlive.IsValid() ? Time()-fLastKeepAlive<boost::posix_time::minutes(2) : false;
+    }
 };
 
@@ -371,5 +446,8 @@
     int Execute()
     {
-        return fGCN.IsConnected() ? State::kConnected : State::kDisconnected;
+        if (!fGCN.IsConnected())
+            return State::kDisconnected;
+
+        return fGCN.IsValid() ? State::kValid : State::kConnected;
     }
 
@@ -412,7 +490,8 @@
         T::AddStateName(State::kDisconnected, "Disconnected",
                      "No connection to GCN.");
-
         T::AddStateName(State::kConnected, "Connected",
                      "Connection to GCN established.");
+        T::AddStateName(State::kValid, "Valid",
+                     "Connection valid (keep alive received within past 2min)");
 
         // Verbosity commands
@@ -421,5 +500,4 @@
             ("set verbosity state"
              "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
-
         T::AddEvent("SET_DEBUG_RX", "B:1")
             (bind(&StateMachineGCN::SetDebugRx, this, placeholders::_1))
@@ -432,5 +510,4 @@
             (bind(&StateMachineGCN::Disconnect, this))
             ("disconnect from ethernet");
-
         T::AddEvent("RECONNECT", "O", State::kDisconnected, State::kConnected)
             (bind(&StateMachineGCN::Reconnect, this, placeholders::_1))
