Index: /trunk/FACT++/src/smartfact.cc
===================================================================
--- /trunk/FACT++/src/smartfact.cc	(revision 14035)
+++ /trunk/FACT++/src/smartfact.cc	(revision 14036)
@@ -3,4 +3,8 @@
 #include <libnova/lunar.h>
 #include <libnova/rise_set.h>
+#endif
+
+#ifdef HAVE_SQL
+#include <mysql++/mysql++.h>
 #endif
 
@@ -282,5 +286,5 @@
     }
 
-    double Angle(double r, double d)
+    double Angle(double r, double d) const
     {
         const double theta0 = M_PI/2-d*M_PI/180;
@@ -303,4 +307,13 @@
 
         return acos(arg) * 180/M_PI;
+    }
+
+    static string Color(double angle)
+    {
+        if (angle<10 || angle>150)
+            return HTML::kRed;
+        if (angle<20 || angle>140)
+            return HTML::kYellow;
+        return HTML::kGreen;
     }
 };
@@ -326,4 +339,5 @@
 
     Time fLastUpdate;
+    Time fLastAstroCalc;
 
     string fPath;
@@ -625,5 +639,5 @@
         if (!CheckDataSize(d, "Mcp:Configuration", 16, true))
         {
-            fMcpConfigurationState     = 0;
+            fMcpConfigurationState     = DimState::kOffline;
             fMcpConfigurationMaxTime   = 0;
             fMcpConfigurationMaxEvents = 0;
@@ -698,12 +712,9 @@
         //const uint16_t idx = uint16_t(floor(fmod(fMagicWeatherHist[kDir].back()/22.5+360+11.25, 360)/22.5))%16;
 
-        Sun  sun (-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
-        Moon moon(-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
-
         ostringstream out;
         out << d.GetJavaDate() << '\n';
-        out << sun.color << '\t' << sun.description << '\n';
+        out << fSun.color << '\t' << fSun.description << '\n';
         out << setprecision(2);
-        out << (sun.isday?HTML::kWhite:moon.color) << '\t' << moon.description << '\n';
+        out << (fSun.isday?HTML::kWhite:fMoon.color) << '\t' << fMoon.description << '\n';
         out << setprecision(3);
         for (int i=0; i<6; i++)
@@ -716,27 +727,5 @@
             out << "\t\n";
 
-        fSun  = sun;
-        fMoon = moon;
-
         ofstream(fPath+"/weather.data") << out.str();
-
-        out.str("");
-        out << sun.time.JavaDate() << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunRiseDarkTime.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunRiseAstronomical.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunRiseCivil.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunRiseDayTime.GetAsStr("%H:%M") << '\n';
-
-        out << HTML::kWhite << '\t' << sun.fSunSetDayTime.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunSetCivil.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunSetAstronomical.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << sun.fSunSetDarkTime.GetAsStr("%H:%M") << '\n';
-
-        out << HTML::kWhite << '\t' << moon.fMoonRise.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << moon.fMoonTransit.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t' << moon.fMoonSet.GetAsStr("%H:%M") << '\n';
-        out << HTML::kWhite << '\t';
-
-        ofstream(fPath+"/astro.data") << out.str();
 
         WriteWeather(d, "temp",  kTemp,   -5,   35);
@@ -852,11 +841,5 @@
         {
             const double angle = moon.Angle(Ra, Dec);
-
-            string col = HTML::kGreen;
-            if (angle<20 || angle>140)
-                col = HTML::kYellow;
-            if (angle<10 || angle>150)
-                col = HTML::kRed;
-            out << col << '\t' << setprecision(3) << angle << '\n';
+            out << Moon::Color(angle) << '\t' << setprecision(3) << angle << '\n';
 
             fDriveControlMoonDist = angle;
@@ -1661,4 +1644,99 @@
     }
 
+    void UpdateAstronomy()
+    {
+        Time now;
+
+        fSun  = Sun (-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
+        fMoon = Moon(-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
+
+        ostringstream out;
+        out << fSun.time.JavaDate() << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunRiseDarkTime.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunRiseAstronomical.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunRiseCivil.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunRiseDayTime.GetAsStr("%H:%M") << '\n';
+
+        out << HTML::kWhite << '\t' << fSun.fSunSetDayTime.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunSetCivil.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunSetAstronomical.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fSun.fSunSetDarkTime.GetAsStr("%H:%M") << '\n';
+
+        out << HTML::kWhite << '\t' << fMoon.fMoonRise.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fMoon.fMoonTransit.GetAsStr("%H:%M") << '\n';
+        out << HTML::kWhite << '\t' << fMoon.fMoonSet.GetAsStr("%H:%M") << '\n';
+
+        out << fMoon.color  << '\t' << fMoon.description << '\n';
+
+#ifdef HAVE_SQL
+        try
+        {
+            const string fDatabase = "readpo:readc0nf1g@10.0.100.21/scheduling";
+
+            //static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))?");
+            static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))");
+            // 2: user
+            // 4: pass
+            // 5: server
+            // 7: port
+            // 9: db
+
+            boost::smatch what;
+            if (!boost::regex_match(fDatabase, what, expr, boost::match_extra))
+                throw runtime_error("Couldn't parse '"+fDatabase+"'.");
+
+            if (what.size()!=10)
+                throw runtime_error("Error parsing '"+fDatabase+"'.");
+
+            const string user   = what[2];
+            const string passwd = what[4];
+            const string server = what[5];
+            const string db     = what[9];
+            const int port      = atoi(string(what[7]).c_str());
+            /*
+             ostringstream out;
+             out << "Connecting to '";
+             if (!user.empty())
+             out << user << "@";
+             out << server;
+             if (port)
+             out << ":" << port;
+             if (!db.empty())
+             out << "/" << db;
+
+             T::Message(out);
+             */
+            mysqlpp::Connection conn(db.c_str(), server.c_str(), user.c_str(), passwd.c_str(), port);
+
+            const mysqlpp::StoreQueryResult res =
+                conn.query("SELECT fSourceName, fRightAscension, fDeclination FROM source").store();
+
+            out << HTML::kWhite << '\t';
+
+            for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++)
+            {
+                const string name = (*v)[0].c_str();
+                const double ra   = (*v)[1];
+                const double dec  = (*v)[2];
+
+                const int32_t angle = fMoon.Angle(ra, dec);
+
+                out << "<tr bgcolor='" << Moon::Color(angle) << "'>";
+                out << "<td>" << name << "</td>";
+                out << "<td>" << round(angle) << "&deg;</td>";
+                out << "</tr>";
+            }
+            out << '\n';
+            out << HTML::kWhite << '\t' << Time()-now << '\n';
+        }
+        catch (const exception &e)
+        {
+            Warn("Source database access: "+string(e.what()));
+        }
+#endif
+
+        ofstream(fPath+"/astro.data") << out.str();
+    }
+
     int Execute()
     {
@@ -1673,5 +1751,4 @@
         if (now-fLastUpdate<boost::posix_time::seconds(1))
             return fDimDNS.online() ? kStateRunning : kStateDimNetworkNA;
-
         fLastUpdate=now;
 
@@ -2129,4 +2206,10 @@
         ofstream(fPath+"/status.data") << out.str();
 
+        if (now-fLastAstroCalc>boost::posix_time::seconds(15))
+        {
+            UpdateAstronomy();
+            fLastAstroCalc = now;
+        }
+
         return fDimDNS.online() ? kStateRunning : kStateDimNetworkNA;
     }
@@ -2135,4 +2218,5 @@
 public:
     StateMachineSmartFACT(ostream &out=cout) : StateMachineDim(out, "SMART_FACT"),
+        fLastAstroCalc(boost::date_time::neg_infin),
         fPath("www/smartfact/data"),
         fControlScriptDepth(0),
Index: /trunk/FACT++/www/smartfact/index.css
===================================================================
--- /trunk/FACT++/www/smartfact/index.css	(revision 14035)
+++ /trunk/FACT++/www/smartfact/index.css	(revision 14036)
@@ -194,6 +194,5 @@
 }
 
-.tfoot td
-{
+.tfoot td {
 	vertical-align:middle;
 }
@@ -204,6 +203,5 @@
 }*/
 
-.container
-{
+.container {
  	padding: 0;
         margin: 0;
@@ -214,14 +212,28 @@
 
 h1 {
- margin:0;
-}
+ 	margin:0;
+}
+
 h2 {
- margin:0;
-}
+ 	margin:0;
+}
+
 h3 {
- margin:0;
-}
+ 	margin:0;
+}
+
 h4 {
- margin:0;
- color:#206;
-}
+ 	margin:0;
+ 	color:#206;
+}
+
+.astro td:nth-child(1) {
+        padding:0px 0px 0px 5px;
+        margin:0;
+}
+
+.astro td:nth-child(2) {
+	text-align:right;
+        padding:0px 5px 0px 0px;
+        margin:0;
+}
