#ifdef HAVE_LIBNOVA #include #include #include #endif #include "Dim.h" #include "Event.h" #include "Shell.h" #include "StateMachineDim.h" #include "Connection.h" #include "Configuration.h" #include "Console.h" #include "Converter.h" #include "DimServiceInfoList.h" #include "PixelMap.h" #include "tools.h" #include "LocalControl.h" #include "HeadersFAD.h" #include "HeadersBIAS.h" #include "HeadersFTM.h" using namespace std; // ------------------------------------------------------------------------ #include "DimDescriptionService.h" #include "DimState.h" // ------------------------------------------------------------------------ const static string kHtmlWhite = "#ffffff"; const static string kHtmlYellow = "#fffff0"; const static string kHtmlRed = "#fff8f0"; const static string kHtmlGreen = "#f0fff0"; const static string kHtmlBlue = "#f0f0ff"; // ======================================================================== // ======================================================================== // ======================================================================== class Astro { public: Time time; Time fSunRiseDayTime; Time fSunRiseCivil; Time fSunRiseAstronomical; Time fSunRiseDarkTime; Time fSunSetDayTime; Time fSunSetCivil; Time fSunSetAstronomical; Time fSunSetDarkTime; int state; string description; string color; bool isday; public: Astro(double lon, double lat, const Time &t=Time()) : time(t) { #ifdef HAVE_LIBNOVA ln_lnlat_posn observer; observer.lng = lon; observer.lat = lat; // get Julian day from local time const double JD = time.JD(); ln_rst_time sun_day; ln_rst_time sun_civil; ln_rst_time sun_astronomical; ln_rst_time sun_dark; // Warning: return code of 1 means circumpolar and is not checked! //ln_get_lunar_rst (JD-0.5, &observer, &moon); ln_get_solar_rst (JD-0.5, &observer, &sun_day); ln_get_solar_rst_horizon(JD-0.5, &observer, - 6, &sun_civil); ln_get_solar_rst_horizon(JD-0.5, &observer, -12, &sun_astronomical); ln_get_solar_rst_horizon(JD-0.5, &observer, -18, &sun_dark); fSunSetDayTime = Time(sun_day.set); fSunSetCivil = Time(sun_civil.set); fSunSetAstronomical = Time(sun_astronomical.set); fSunSetDarkTime = Time(sun_dark.set); fSunRiseDayTime = Time(sun_day.rise); fSunRiseCivil = Time(sun_civil.rise); fSunRiseAstronomical = Time(sun_astronomical.rise); fSunRiseDarkTime = Time(sun_dark.rise); const bool is_day = JD>sun_day.rise; const bool is_night = JD>sun_dark.set; //ln_get_lunar_rst (JD+0.5, &observer, &moon); ln_get_solar_rst (JD+0.5, &observer, &sun_day); ln_get_solar_rst_horizon(JD+0.5, &observer, - 6, &sun_civil); ln_get_solar_rst_horizon(JD+0.5, &observer, -12, &sun_astronomical); ln_get_solar_rst_horizon(JD+0.5, &observer, -18, &sun_dark); if (is_day) { fSunRiseDayTime = Time(sun_day.rise); fSunRiseCivil = Time(sun_civil.rise); fSunRiseAstronomical = Time(sun_astronomical.rise); fSunRiseDarkTime = Time(sun_dark.rise); } if (is_night) { fSunSetDayTime = Time(sun_day.set); fSunSetCivil = Time(sun_civil.set); fSunSetAstronomical = Time(sun_astronomical.set); fSunSetDarkTime = Time(sun_dark.set); } // case 0: midnight to sun-rise | !is_day && !is_night | rise/set // case 1: sun-rise to sun-set | is_day && !is_night | set /rise // case 2: sun-set to midnight | is_day && is_night | rise/set /* if (is_day^is_night) { cout << "SunSet: " << fSunSetDayTime << endl; cout << "SunRise: " << fSunRiseDayTime << endl; } else { cout << "SunRise: " << fSunRiseDayTime << endl; cout << "SunSet: " << fSunSetDayTime << endl; }*/ isday = is_day^is_night; state = isday ? 4 : 0; if (time>fSunSetDayTime) state++; if (time>fSunSetCivil) state++; if (time>fSunSetAstronomical) state++; if (time>fSunSetDarkTime) state++; if (time>fSunRiseDarkTime) state++; if (time>fSunRiseAstronomical) state++; if (time>fSunRiseCivil) state++; if (time>fSunRiseDayTime) state++; string name[] = { "dark time", "astron. twilight", "civil twilight", "sunrise", "day time", "sunset", "civil twilight", "astron. twilight", "dark time" }; description = state[name]; string arr; ostringstream out; if (isday) { out << fSunSetDarkTime-time; arr = "↓"; } else { out << fSunRiseDayTime-time; arr = "↑"; } description += " ["+out.str().substr(0, 5)+arr+"]"; switch (state) { case 0: case 1: color = kHtmlGreen; break; case 2: case 3: color = kHtmlYellow; break; case 4: color = kHtmlRed; break; case 5: case 6: color = kHtmlYellow; break; case 7: case 8: color = kHtmlGreen; break; } #endif } }; class Moon { public: double ra; double dec; double disk; bool visible; Time fMoonRise; Time fMoonTransit; Time fMoonSet; string description; string color; Time time; Moon(double lon, double lat, const Time &t=Time()) : time(t) { #ifdef HAVE_LIBNOVA const double JD = time.JD(); ln_lnlat_posn observer; observer.lng = lon; observer.lat = lat; ln_rst_time moon; ln_get_lunar_rst(JD-0.5, &observer, &moon); fMoonRise = Time(moon.rise); fMoonTransit = Time(moon.transit); fMoonSet = Time(moon.set); visible = (JD>moon.rise && JDmoon.rise) && moon.rise>moon.set); const bool is_up = JD>moon.rise; const bool is_sinking = JD>moon.transit; const bool is_dn = JD>moon.set; ln_get_lunar_rst(JD+0.5, &observer, &moon); if (is_up) fMoonRise = Time(moon.rise); if (is_sinking) fMoonTransit = Time(moon.transit); if (is_dn) fMoonSet = Time(moon.set); ln_equ_posn pos; ln_get_lunar_equ_coords(JD, &pos); ra = pos.ra/15; dec = pos.dec; disk = ln_get_lunar_disk(JD)*100; if (!visible || disk<25) color = kHtmlGreen; else color = disk>75 ? kHtmlRed : kHtmlYellow; string arr; ostringstream dt; if (fMoonSet 1.0) arg = 1.0; if(arg < -1.0) arg = -1.0; return acos(arg) * 180/M_PI; } }; // ======================================================================== // ======================================================================== // ======================================================================== class StateMachineSmartFACT : public StateMachineDim//, public DimInfoHandler { private: enum states_t { kStateDimNetworkNA = 1, kStateRunning, }; // ------------------------- Internal variables ----------------------- PixelMap fPixelMap; Time fLastUpdate; string fPath; // ----------------------------- Data storage ------------------------- deque fControlMessageHist; uint32_t fMcpConfigurationState; // For consistency int64_t fMcpConfigurationMaxTime; int64_t fMcpConfigurationMaxEvents; string fMcpConfigurationName; Time fMcpConfigurationRunStart; enum weather_t { kWeatherBegin=0, kTemp = kWeatherBegin, kDew, kHum, kPress, kWind, kGusts, kDir, kWeatherEnd = kDir+1 }; deque fMagicWeatherHist[kWeatherEnd]; vector fFeedbackCalibration; float fFeedbackTempOffset; float fFeedbackUserOffset; vector fBiasControlVoltageVec; float fBiasControlVoltageMed; float fBiasControlCurrentMed; float fBiasControlCurrentMax; deque fBiasControlCurrentHist; deque fFscControlTemperatureHist; float fFscControlHumidityAvg; float fDriveControlPointingZd; string fDriveControlPointingAz; string fDriveControlSourceName; deque fDriveControlTrackingDevHist; int64_t fFadControlNumEvents; float fFtmControlTriggerRateCam; deque fFtmControlTriggerRateHist; vector fFtmPatchThresholds; bool fFtmControlFtuOk; uint64_t fRateScanDataId; uint8_t fRateScanBoard; deque fRateScanDataHist[41]; // ------------- Initialize variables before the Dim stuff ------------ DimVersion fDimDNS; DimControl fDimControl; DimDescribedState fDimMcp; DimDescribedState fDimDataLogger; DimDescribedState fDimDriveControl; DimDescribedState fDimMagicWeather; DimDescribedState fDimFeedback; DimDescribedState fDimBiasControl; DimDescribedState fDimFtmControl; DimDescribedState fDimFadControl; DimDescribedState fDimFscControl; DimDescribedState fDimRateControl; DimDescribedState fDimRateScan; DimDescribedState fDimChatServer; // ------------------------------------------------------------------- bool CheckDataSize(const EventImp &d, const char *name, size_t size, bool min=false) { if ((!min && d.GetSize()==size) || (min && d.GetSize()>size)) return true; ostringstream msg; msg << name << " - Received service has " << d.GetSize() << " bytes, but expected "; if (min) msg << "more than "; msg << size << "."; Warn(msg); return false; } // ------------------------------------------------------------------- template void WriteBinary(const EventImp &d, const string &fname, const T &t, double scale, double offset=0) { vector val(t.size(), 0); for (uint64_t i=0; i127) range=127; if (range<0) range=0; val[i] = (uint8_t)range; } const char *ptr = reinterpret_cast(val.data()); ostringstream out; out << d.GetJavaDate() << '\n'; out << offset << '\n'; out << offset+scale << '\n'; out.write(ptr, val.size()*sizeof(uint8_t)); ofstream(fPath+"/"+fname+".bin") << out.str(); } // ------------------------------------------------------------------- struct Statistics { float min; float max; float med; float avg; //float rms; template Statistics(const T &t, size_t offset_min=0, size_t offset_max=0) : min(0), max(0), med(0), avg(0) { if (t.size()==0) return; T copy(t); sort(copy.begin(), copy.end()); if (offset_min>t.size()) offset_min = 0; if (offset_max>t.size()) offset_max = 0; min = copy[offset_min]; max = copy[copy.size()-1-offset_max]; avg = accumulate (t.begin(), t.end(), 0.)/t.size(); const size_t p = t.size()/2; med = copy[p]; } }; void HandleControlMessageImp(const EventImp &d) { if (d.GetSize()==0) return; const string str = fControlMessageHist.size()>0 ? fControlMessageHist.back() : "
  :  :  
"; const string time = "
"+d.GetTimeAsStr("%H:%M:%S")+"
"; ostringstream tst; tst << d.GetQoS(); string msg; msg += str.substr(0, time.length())==time ? "
        
" : time; msg += d.Ptr(); fControlMessageHist.push_back(msg); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << "#ffffff\t"; for (auto it=fControlMessageHist.begin(); it!=fControlMessageHist.end(); it++) out << *it << "
"; out << '\n'; ofstream(fPath+"/test.txt") << out.str(); } int HandleDimControlMessage(const EventImp &d) { if (d.GetQoS()==90) HandleControlMessageImp(d); return GetCurrentState(); } void HandleControlStateChange(const EventImp &d) { if (d.GetQoS()==-2) fControlMessageHist.clear(); if (d.GetQoS()<0) HandleControlMessageImp(d); } int HandleMcpConfiguration(const EventImp &d) { if (!CheckDataSize(d, "Mcp:Configuration", 16, true)) { fMcpConfigurationState = -4; fMcpConfigurationMaxTime = 0; fMcpConfigurationMaxEvents = 0; fMcpConfigurationName = ""; fMcpConfigurationRunStart = Time(Time::none); return GetCurrentState(); } fMcpConfigurationState = d.GetQoS(); fMcpConfigurationMaxTime = d.Get(); fMcpConfigurationMaxEvents = d.Get(8); fMcpConfigurationName = d.Ptr(16); if (d.GetQoS()==12) fMcpConfigurationRunStart = Time(); return GetCurrentState(); } void WriteWeather(const EventImp &d, const string &name, int i, float min, float max) { const Statistics stat(fMagicWeatherHist[i]); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n'; out << "#ffffff\t" << stat.min << '\n'; out << "#ffffff\t" << stat.avg << '\n'; out << "#ffffff\t" << stat.max << '\n'; ofstream(fPath+"/"+name+".txt") << out.str(); WriteBinary(d, "magicweather-"+name+"-hist", fMagicWeatherHist[i], max-min, min); } int HandleMagicWeatherData(const EventImp &d) { if (!CheckDataSize(d, "MagicWeather:Data", 7*4+2)) return GetCurrentState(); // Store a history of the last 300 entries for (int i=kWeatherBegin; i(2)[i]); if (fMagicWeatherHist[i].size()>300) fMagicWeatherHist[i].pop_front(); } static const char *dir[] = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" }; const uint16_t idx = uint16_t(floor(fMagicWeatherHist[kDir].back()/22.5+16.5))%16; //const uint16_t idx = uint16_t(floor(fmod(fMagicWeatherHist[kDir].back()/22.5+360+11.25, 360)/22.5))%16; Astro astro(-(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 << astro.color << '\t' << astro.description << '\n'; out << setprecision(2); out << (astro.isday?kHtmlWhite:moon.color) << '\t' << moon.description << '\n'; out << setprecision(3); for (int i=0; i<6; i++) out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n'; out << "#ffffff\t" << dir[idx] << '\n'; ofstream(fPath+"/magicweather.txt") << out.str(); out.str(""); out << astro.time.JavaDate() << '\n'; out << kHtmlWhite << '\t' << astro.fSunRiseDarkTime.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunRiseAstronomical.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunRiseCivil.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunRiseDayTime.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunSetDayTime.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunSetCivil.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunSetAstronomical.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << astro.fSunSetDarkTime.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << moon.fMoonRise.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << moon.fMoonTransit.GetAsStr("%H:%M") << '\n'; out << kHtmlWhite << '\t' << moon.fMoonSet.GetAsStr("%H:%M") << '\n'; ofstream(fPath+"/astro.txt") << out.str(); WriteWeather(d, "temp", kTemp, -5, 35); WriteWeather(d, "dew", kDew, -5, 35); WriteWeather(d, "hum", kHum, 0, 100); WriteWeather(d, "wind", kWind, 0, 100); WriteWeather(d, "gusts", kGusts, 0, 100); WriteWeather(d, "press", kPress, 700, 1000); return GetCurrentState(); } int HandleDrivePointing(const EventImp &d) { if (!CheckDataSize(d, "DriveControl:Pointing", 16)) return GetCurrentState(); fDriveControlPointingZd = d.Get(); const double az = d.Get(8); static const char *dir[] = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" }; const uint16_t idx = uint16_t(floor(az/22.5+16.5))%16; fDriveControlPointingAz = dir[idx]; ostringstream out; out << d.GetJavaDate() << '\n'; out << setprecision(5); out << fDriveControlPointingZd << '\n'; out << az << '\n'; ofstream(fPath+"/drive-pointing.txt") << out.str(); return GetCurrentState(); } int HandleDriveTracking(const EventImp &d) { if (!CheckDataSize(d, "DriveControl:Tracking", 56)) return GetCurrentState(); const double Ra = d.Get(0*8); const double Dec = d.Get(1*8); const double Zd = d.Get(3*8); const double Az = d.Get(4*8); const double zd = Zd * M_PI / 180; const double dzd = d.Get(5*8) * M_PI / 180; const double daz = d.Get(6*8) * M_PI / 180; // Correct: // const double d = cos(del) - sin(zd+dzd)*sin(zd)*(1.-cos(daz)); // Simplified: double dev = cos(dzd) - sin(zd+dzd)*sin(zd)*(1.-cos(daz)); dev = acos(dev) * 180 / M_PI * 3600; fDriveControlTrackingDevHist.push_back(dev); if (fDriveControlTrackingDevHist.size()>300) fDriveControlTrackingDevHist.pop_front(); WriteBinary(d, "control-deviation-hist", fDriveControlTrackingDevHist, 120); ostringstream out; out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << fDriveControlSourceName << '\n'; out << setprecision(5); out << kHtmlWhite << '\t' << Ra << '\n'; out << kHtmlWhite << '\t' << Dec << '\n'; out << setprecision(3); out << kHtmlWhite << '\t' << Zd << '\n'; out << kHtmlWhite << '\t' << Az << '\n'; out << kHtmlWhite << '\t' << dev << '\n'; Moon moon(-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600); if (moon.visible) { const double angle = moon.Angle(Ra, Dec); string col = kHtmlGreen; if (angle<35 || angle>145) col = kHtmlYellow; if (angle<25 || angle>155) col = kHtmlRed; out << col << '\t' << setprecision(3) << angle << '\n'; } else out << kHtmlWhite << "\t— \n"; ofstream(fPath+"/tracking.txt") << out.str(); return GetCurrentState(); } int HandleDriveSource(const EventImp &d) { if (!CheckDataSize(d, "DriveControl:Source", 7*4+2, true)) return GetCurrentState(); const double *ptr = d.Ptr(); const double ra = ptr[0]; // Ra[h] const double dec = ptr[1]; // Dec[deg] const double woff = ptr[4]; // Wobble offset [deg] const double wang = ptr[5]; // Wobble angle [deg] fDriveControlSourceName = d.Ptr(6*8); ostringstream out; out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << fDriveControlSourceName << '\n'; out << setprecision(5); out << "#ffffff\t" << ra << '\n'; out << "#ffffff\t" << dec << '\n'; out << setprecision(3); out << "#ffffff\t" << woff << '\n'; out << "#ffffff\t" << wang << '\n'; ofstream(fPath+"/source.txt") << out.str(); return GetCurrentState(); } int HandleFeedbackCalibration(const EventImp &d) { if (!CheckDataSize(d, "Feedback:Calibration", 3*4*416)) { fFeedbackCalibration.clear(); return GetCurrentState(); } const float *ptr = d.Ptr(); fFeedbackCalibration.assign(ptr+2*416, ptr+3*416); return GetCurrentState(); } int HandleFeedbackDeviation(const EventImp &d) { if (!CheckDataSize(d, "Feedback:Deviation", 2*4*416+8)) return GetCurrentState(); const float *ptr = d.Ptr(); vector dev(ptr+416, ptr+416+320); fFeedbackTempOffset = ptr[2*416]; fFeedbackUserOffset = ptr[2*416+1]; for (int i=0; i<320; i++) dev[i] -= fFeedbackTempOffset+fFeedbackUserOffset; // Write the 160 patch values to a file WriteBinary(d, "feedback-deviation", dev, 1); const Statistics stat(dev, 3); ostringstream out; out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << fFeedbackUserOffset << '\n'; out << setprecision(3); out << kHtmlWhite << '\t' << fFeedbackTempOffset << '\n'; out << kHtmlWhite << '\t' << stat.min << '\n'; out << kHtmlWhite << '\t' << stat.med << '\n'; out << kHtmlWhite << '\t' << stat.avg << '\n'; out << kHtmlWhite << '\t' << stat.max << '\n'; ofstream(fPath+"/feedback.txt") << out.str(); return GetCurrentState(); } int HandleBiasVoltage(const EventImp &d) { if (!CheckDataSize(d, "BiasControl:Voltage", 1664)) { fBiasControlVoltageVec.clear(); return GetCurrentState(); } fBiasControlVoltageVec.assign(d.Ptr(), d.Ptr()+320); const Statistics stat(fBiasControlVoltageVec); fBiasControlVoltageMed = stat.med; vector val(320, 0); for (int i=0; i<320; i++) { const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group(); val[idx] = fBiasControlVoltageVec[i]; } if (fDimBiasControl.state()==BIAS::kVoltageOn) WriteBinary(d, "biascontrol-voltage", val, 10, 65); else WriteBinary(d, "biascontrol-voltage", val, 75); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << stat.min << '\n'; out << kHtmlWhite << '\t' << stat.med << '\n'; out << kHtmlWhite << '\t' << stat.avg << '\n'; out << kHtmlWhite << '\t' << stat.max << '\n'; ofstream(fPath+"/voltage.txt") << out.str(); return GetCurrentState(); } int HandleBiasCurrent(const EventImp &d) { if (!CheckDataSize(d, "BiasControl:Current", 832)) return GetCurrentState(); // Convert dac counts to uA vector v(320); for (int i=0; i<320; i++) v[i] = d.Ptr()[i] * 5000./4096; const bool cal = fFeedbackCalibration.size()>0 && fBiasControlVoltageVec.size()>0; double power_tot = 0; double power_apd = 0; // 3900 Ohm/n + 1000 Ohm + 1100 Ohm (with n=4 or n=5) const double R[2] = { 3075, 2870 }; // Calibrate the data (subtract offset) if (cal) for (int i=0; i<320; i++) { // Measued current minus leakage current (bias crate calibration) v[i] -= fBiasControlVoltageVec[i]/fFeedbackCalibration[i]*1e6; // Total power participated in the camera at the G-APD // and the serial resistors (total voltage minus voltage // drop at resistors in bias crate) power_tot += v[i]*(fBiasControlVoltageVec[i] - 1100e-6*v[i])*1e-6; // Group index (0 or 1) of the of the pixel (4 or 5 pixel patch) const int g = fPixelMap.hv(i).group(); // Current per G-APD v[i] /= g ? 5 : 4; // Power consumption per G-APD if (i!=66 && i!=191 && i!=193) power_apd += v[i]*(fBiasControlVoltageVec[i]-R[g]*v[i]*1e-6)*1e-6; } // Divide by number of summed channels, concert to mW power_apd /= 317e-3; // [mW] if (power_tot<1e-3) power_tot = 0; if (power_apd<1e-3) power_apd = 0; // Get the maximum of each patch vector val(320, 0); for (int i=0; i<320; i++) { const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group(); val[idx] = v[i]; } // Write the 160 patch values to a file WriteBinary(d, "biascontrol-current", val, 100); const Statistics stat(v, 0, 3); // Exclude the three crazy channels fBiasControlCurrentMed = stat.med; fBiasControlCurrentMax = stat.max; // Store a history of the last 60 entries fBiasControlCurrentHist.push_back(fBiasControlCurrentMed); if (fBiasControlCurrentHist.size()>360) fBiasControlCurrentHist.pop_front(); // write the history to a file WriteBinary(d, "biascontrol-current-hist", fBiasControlCurrentHist, 100); const string col0 = cal ? kHtmlGreen : kHtmlWhite; string col1 = col0; string col2 = col0; string col3 = col0; string col4 = col0; if (cal && stat.min>65) col1 = kYellow; if (cal && stat.min>80) col1 = kRed; if (cal && stat.med>65) col2 = kYellow; if (cal && stat.med>80) col2 = kRed; if (cal && stat.avg>65) col3 = kYellow; if (cal && stat.avg>80) col3 = kRed; if (cal && stat.max>65) col4 = kYellow; if (cal && stat.max>80) col4 = kRed; ostringstream out; out << setprecision(2); out << d.GetJavaDate() << '\n'; out << col0 << '\t' << (cal?"yes":"no") << '\n'; out << col1 << '\t' << stat.min << '\n'; out << col2 << '\t' << stat.med << '\n'; out << col3 << '\t' << stat.avg << '\n'; out << col4 << '\t' << stat.max << '\n'; out << kHtmlWhite << '\t' << power_tot << "W [" << power_apd << "mW]\n"; ofstream(fPath+"/current.txt") << out.str(); return GetCurrentState(); } int HandleFadEvents(const EventImp &d) { if (!CheckDataSize(d, "FadControl:Events", 4*4)) { fFadControlNumEvents = -1; return GetCurrentState(); } fFadControlNumEvents = d.Get(); return GetCurrentState(); } int HandleFadConnections(const EventImp &d) { if (!CheckDataSize(d, "FadControl:Connections", 41)) { //fStatusEventBuilderLabel->setText("Offline"); return GetCurrentState(); } string rc(40, '-'); // orange/red [45] const uint8_t *ptr = d.Ptr(); int c[4] = { '.', '.', '.', '.' }; for (int i=0; i<40; i++) { const uint8_t stat1 = ptr[i]&3; const uint8_t stat2 = ptr[i]>>3; if (stat1==0 && stat2==0) rc[i] = '.'; // gray [46] else if (stat1>=2 && stat2==8) rc[i] = stat1==2?'+':'*'; // green [43] : check [42] if (rc[i](20)<0) return GetCurrentState(); fFtmControlTriggerRateCam = d.Get(20); const float *brates = d.Ptr(24); // Board rate const float *prates = d.Ptr(24+160); // Patch rate // Store a history of the last 60 entries fFtmControlTriggerRateHist.push_back(fFtmControlTriggerRateCam); if (fFtmControlTriggerRateHist.size()>60) fFtmControlTriggerRateHist.pop_front(); // FIXME: Add statistics for all kind of rates WriteBinary(d, "ftmcontrol-triggerrate-hist", fFtmControlTriggerRateHist, 100); WriteBinary(d, "ftmcontrol-boardrates", vector(brates, brates+40), 10); WriteBinary(d, "ftmcontrol-patchrates", vector(prates, prates+160), 10); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << fFtmControlTriggerRateCam << '\n'; ofstream(fPath+"/trigger.txt") << out.str(); const Statistics bstat(vector(brates, brates+40)); const Statistics pstat(vector(prates, prates+160)); out.str(""); out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << bstat.min << '\n'; out << kHtmlWhite << '\t' << bstat.med << '\n'; out << kHtmlWhite << '\t' << bstat.avg << '\n'; out << kHtmlWhite << '\t' << bstat.max << '\n'; ofstream(fPath+"/boardrates.txt") << out.str(); out.str(""); out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << pstat.min << '\n'; out << kHtmlWhite << '\t' << pstat.med << '\n'; out << kHtmlWhite << '\t' << pstat.avg << '\n'; out << kHtmlWhite << '\t' << pstat.max << '\n'; ofstream(fPath+"/patchrates.txt") << out.str(); return GetCurrentState(); } int HandleFtmStaticData(const EventImp &d) { if (!CheckDataSize(d, "FtmControl:StaticData", 740)) return GetCurrentState(); const uint16_t *ptr = d.Ptr(260); vector vec(ptr, ptr+160); WriteBinary(d, "ftmcontrol-thresholds", vec, 1000); const Statistics stat(vec); ostringstream out; out << d.GetJavaDate() << '\n'; out << kHtmlWhite << '\t' << stat.min << '\n'; out << kHtmlWhite << '\t' << stat.med << '\n'; out << kHtmlWhite << '\t' << stat.avg << '\n'; out << kHtmlWhite << '\t' << stat.max << '\n'; ofstream(fPath+"/thresholds.txt") << out.str(); return GetCurrentState(); } int HandleFtmFtuList(const EventImp &d) { if (!CheckDataSize(d, "FtmControl:FtuList", sizeof(FTM::DimFtuList))) return GetCurrentState(); const FTM::DimFtuList &sdata = d.Ref(); ostringstream out; out << d.GetJavaDate() << '\n'; int cnt = 0; for (int i=0; i<4; i++) { out << kHtmlWhite << '\t'; for (int j=0; j<10; j++) if (sdata.IsActive(i*10+j)) { if (sdata.fPing[i*10+j]==1) { out << '*'; cnt++; } else out << sdata.fPing[i*10+j]; } else out << '-'; out << '\n'; } fFtmControlFtuOk = cnt==40; ofstream(fPath+"/ftu.txt") << out.str(); return GetCurrentState(); } int HandleFadEventData(const EventImp &d) { if (!CheckDataSize(d, "FadControl:EventData", 23040)) return GetCurrentState(); //const float *avg = d.Ptr(); //const float *rms = d.Ptr(1440*sizeof(float)); const float *dat = d.Ptr(1440*sizeof(float)*2); //const float *pos = d.Ptr(1440*sizeof(float)*3); vector max(320, -2); for (int i=0; i<1440; i++) { if (i%9==8) continue; const int idx = (fPixelMap.hw(i).hw()/9)*2+fPixelMap.hw(i).group(); const double v = dat[i]/1000; if (v>max[idx]) max[idx]=v; } switch (d.GetQoS()) { case 0: WriteBinary(d, "fadcontrol-eventdata", max, 2, -1); break; case 1: WriteBinary(d, "fadcontrol-eventdata", max, 2, 0); break; default: WriteBinary(d, "fadcontrol-eventdata", max, 0.25, 0); break; } return GetCurrentState(); } int HandleFscTemperature(const EventImp &d) { if (!CheckDataSize(d, "FscControl:Temperature", 240)) return GetCurrentState(); const float *ptr = d.Ptr(4); double avg = 0; double rms = 0; double min = 99; double max = -99; int num = 0; for (const float *t=ptr; tmax) max = *t; if (*t0) { fFscControlTemperatureHist.push_back(avg-fMagicWeatherHist[kTemp].back()); if (fFscControlTemperatureHist.size()>300) fFscControlTemperatureHist.pop_front(); } const Statistics stat(fFscControlTemperatureHist); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << fFscControlHumidityAvg << '\n'; out << "#ffffff\t" << min << '\n'; out << "#ffffff\t" << avg << '\n'; out << "#ffffff\t" << max << '\n'; out << "#ffffff\t" << stat.min << '\n'; out << "#ffffff\t" << stat.avg << '\n'; out << "#ffffff\t" << stat.max << '\n'; ofstream(fPath+"/fsc.txt") << out.str(); WriteBinary(d, "fsccontrol-temperature-hist", fFscControlTemperatureHist, 10); return GetCurrentState(); } int HandleFscHumidity(const EventImp &d) { if (!CheckDataSize(d, "FscControl:Humidity", 5*4)) return GetCurrentState(); const float *ptr = d.Ptr(4); double avg = 0; int num = 0; for (const float *t=ptr; t0) { avg += *t; num++; } fFscControlHumidityAvg = avg/num; return GetCurrentState(); } int HandleRateScanData(const EventImp &d) { if (!CheckDataSize(d, "RateScan:Data", 824)) return GetCurrentState(); const uint64_t id = d.Get(); const float *rate = d.Ptr(20); if (fRateScanDataId!=id) { for (int i=0; i<41; i++) fRateScanDataHist[i].clear(); fRateScanDataId = id; } fRateScanDataHist[0].push_back(log10(rate[0])); double max = 0; for (int i=1; i<41; i++) { fRateScanDataHist[i].push_back(log10(rate[i])); if (rate[i]>max) max = rate[i]; } fRateScanBoard ++; fRateScanBoard %= 40; WriteBinary(d, "ratescan-hist", fRateScanDataHist[0], 10, -2); WriteBinary(d, "ratescan-board", fRateScanDataHist[fRateScanBoard+1], 10, -2); ostringstream out; out << setprecision(3); out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << pow(10, fRateScanDataHist[0].back()) << '\n'; out << "#ffffff\t" << max << '\n'; ofstream(fPath+"/ratecan.txt") << out.str(); out.str(""); out << d.GetJavaDate() << '\n'; out << "#ffffff\t" << int(fRateScanBoard) << '\n'; out << "#ffffff\t" << pow(10, fRateScanDataHist[fRateScanBoard+1].back()) << '\n'; ofstream(fPath+"/ratecan_board.txt") << out.str(); return GetCurrentState(); } // ------------------------------------------------------------------- void HandleDoTest(const EventImp &d) { ostringstream out; out << d.GetJavaDate() << '\t' << fDimControl.online() << '\n'; switch (d.GetQoS()) { case -3: out << kHtmlWhite << "\tNot running\n"; break; case -2: out << kHtmlBlue << "\tLoading\n"; break; case -1: out << kHtmlBlue << "\tStarted\n"; break; default: out << kHtmlGreen << "\tRunning [" << d.GetQoS() << "]\n"; break; } ofstream(fPath+"/dotest.txt") << out.str(); } // ------------------------------------------------------------------- bool CheckEventSize(size_t has, const char *name, size_t size) { if (has==size) return true; ostringstream msg; msg << name << " - Received event has " << has << " bytes, but expected " << size << "."; Fatal(msg); return false; } int Print() const { Out() << fDimDNS << endl; Out() << fDimMcp << endl; Out() << fDimControl << endl; Out() << fDimDataLogger << endl; Out() << fDimDriveControl << endl; Out() << fDimFadControl << endl; Out() << fDimFtmControl << endl; Out() << fDimBiasControl << endl; Out() << fDimFeedback << endl; Out() << fDimRateControl << endl; Out() << fDimFscControl << endl; Out() << fDimMagicWeather << endl; Out() << fDimRateScan << endl; Out() << fDimChatServer << endl; return GetCurrentState(); } string GetStateHtml(const DimState &state, int green) const { if (!state.online()) return kHtmlWhite+"\t—\n"; if (&state==&fDimControl) { ostringstream out; out << kHtmlGreen << '\t'; return kHtmlGreen+'\t'+(state.state()==-3?"Idle":state.msg)+'\n'; } const State rc = state.description(); // Sate not found in list, server online (-3: offline; -2: not found) if (rc.index==-2) { ostringstream out; out << kHtmlWhite << '\t' << state.state() << '\n'; return out.str(); } //ostringstream msg; //msg << kHtmlWhite << '\t' << rc.name << " [" << rc.index << "]\n"; //return msg.str(); if (rc.index<1) return kHtmlWhite + "\t—\n"; return (rc.index=5) // Idle { string col = kHtmlBlue; if (fMcpConfigurationState!= 5 && // Idle fMcpConfigurationState!=11 && // Trigger On fMcpConfigurationState!=12) // Taking Data col = kHtmlYellow; else if (fDimFadControl.state()==FAD::kWritingData) col = kHtmlGreen; out << col << '\t'; if (fDimRateControl.state()!=5 && fDimRateScan.state()!=5) { switch (fMcpConfigurationState) { // kStateIdle case 5: out << "Idle [" << fMcpConfigurationName << "]"; break; // Configuring1 - Configuring3 case 7: case 8: case 9: out << "Configuring [" << fMcpConfigurationName << "]"; break; // Configured case 10: out << "Configured [" << fMcpConfigurationName << "]"; break; // TriggerOn / Taking Data case 11: case 12: out << fMcpConfigurationName; break; } } else if (fDimRateControl.state()==5/*kStateSettingGlobalThreshold*/) out << "Calibrating threshold"; else if (fDimRateScan.state()==5/*kStateSettingGlobalThreshold*/) out << "Rate scan in progress"; if (fMcpConfigurationState>10 && fDimRateControl.state()!=5) { if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12) out << " ["; if (fMcpConfigurationMaxEvents>0) { if (fFadControlNumEvents>0 && fMcpConfigurationState==12) out << fMcpConfigurationMaxEvents-fFadControlNumEvents; else out << fMcpConfigurationMaxEvents; } if (fMcpConfigurationMaxEvents>0 && (fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12)) out << '/'; if (fMcpConfigurationMaxTime>0) { if (fMcpConfigurationState==12) { const uint32_t dt = (Time()-fMcpConfigurationRunStart).total_seconds(); if (dt>fMcpConfigurationMaxTime) out << "---"; else out << fMcpConfigurationMaxTime-dt << 's'; } else out << fMcpConfigurationMaxTime << 's'; } else { if (fMcpConfigurationState==12) { ostringstream d; d << Time()-fMcpConfigurationRunStart; out << d.str().substr(3, 5); } } if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12) out << ']'; } } else out << kHtmlWhite; out << '\n'; // ------------------ Drive ----------------- if (fDimDriveControl.state()>=5) // Armed, Moving, Tracking { const double dev = fDriveControlTrackingDevHist.size()>0 ? fDriveControlTrackingDevHist.back() : 0; const State rc = fDimDriveControl.description(); string col = kHtmlGreen; if (rc.index==6) // Moving col = kHtmlBlue; if (rc.index==5) // Armed col = kHtmlWhite; if (rc.index==7) // Tracking { if (dev>60) // ~1.5mm col = kHtmlYellow; if (dev>100) // ~1/4 of a pixel ~ 2.5mm col = kHtmlRed; } out << col << '\t'; //out << rc.name << '\t'; out << fDriveControlPointingZd << '\t'; out << fDriveControlPointingAz << '\t'; if (fDimDriveControl.state()==7) { out << fDriveControlSourceName << '\t'; out << setprecision(2); out << dev << '\n'; out << setprecision(3); } else out << "\t\n"; } else out << kHtmlWhite << '\n'; // ------------------- FSC ------------------ if (fDimFscControl.state()>1 && fFscControlTemperatureHist.size()>0) { out << kHtmlGreen << '\t' << fFscControlTemperatureHist.back() << '\n'; } else out << kHtmlWhite << '\n'; // --------------- MagicWeather ------------- if (fDimMagicWeather.state()==3 && fMagicWeatherHist[kWeatherBegin].size()>0) { /* const float diff = fMagicWeatherHist[kTemp].back()-fMagicWeatherHist[kDew].back(); string col1 = kHtmlRed; if (diff>0.3) col1 = kHtmlYellow; if (diff>0.7) col1 = kHtmlGreen; */ const float wind = fMagicWeatherHist[kGusts].back(); const float hum = fMagicWeatherHist[kHum].back(); string col = kHtmlGreen; if (wind>35 || hum>95) col = kHtmlYellow; if (wind>50 || hum>98) col = kHtmlRed; out << col << '\t'; out << fMagicWeatherHist[kHum].back() << '\t'; out << setprecision(2); out << fMagicWeatherHist[kGusts].back() << '\n'; out << setprecision(3); } else out << kHtmlWhite << "\n"; // --------------- FtmControl ------------- if (fDimFtmControl.state()==FTM::kTriggerOn) { string col = kHtmlGreen; if (fFtmControlTriggerRateCam<15) col = kHtmlYellow; if (fFtmControlTriggerRateCam>100) col = kHtmlRed; out << col << '\t' << fFtmControlTriggerRateCam << '\n'; } else out << kHtmlWhite << '\n'; // --------------- BiasControl ------------- if (fDimBiasControl.state()==BIAS::kRamping || fDimBiasControl.state()==BIAS::kOverCurrent || fDimBiasControl.state()==BIAS::kVoltageOn || fDimBiasControl.state()==BIAS::kVoltageOff) { const bool off = fDimBiasControl.state()==BIAS::kVoltageOff; const bool oc = fDimBiasControl.state()==BIAS::kOverCurrent; string col = fBiasControlVoltageMed>3?kHtmlGreen:kHtmlWhite; if (fBiasControlCurrentMax>65) col = kHtmlYellow; if (fBiasControlCurrentMax>80) col = kHtmlRed; // Bias in overcurrent => Red if (fDimBiasControl.state()==BIAS::kOverCurrent) col = kHtmlRed; // MCP in ReadyForDatataking/Configuring/Configured/TriggerOn/TakingData // and Bias not in "data-taking state' => Red if (fMcpConfigurationState>5 && fDimBiasControl.state()!=BIAS::kVoltageOn && fDimBiasControl.state()!=BIAS::kVoltageOff) col = kHtmlRed; const bool cal = fFeedbackCalibration.size(); // Feedback is currently calibrating => Blue if (fDimFeedback.state()==13) { out << kHtmlBlue << '\t'; out << "***\t"; out << "***\t"; } else { out << setprecision(2); out << col << '\t'; out << (off ? 0 : fBiasControlCurrentMed) << '\t'; if (oc) out << "(OC) "; else { if (cal) out << (off ? 0 : fBiasControlCurrentMax); else out << "— "; } out << '\t'; out << setprecision(3); } out << (off ? 0 : fBiasControlVoltageMed) << '\n'; } else out << kHtmlWhite << '\n'; // ------------------------------------------ ofstream(fPath+"/fact.txt") << out.str(); // ========================================== out.str(""); out << now.JavaDate() << '\t' << fDimControl.online() << '\n'; if (!fDimDNS.online()) out << kHtmlWhite << "\tOffline\n\n\n\n\n\n\n\n\n\n\n\n"; else { out << kHtmlGreen << '\t' << fDimDNS.version() << '\n'; out << GetStateHtml(fDimMcp, 4); out << GetStateHtml(fDimControl, 0); out << GetStateHtml(fDimDataLogger, 1); out << GetStateHtml(fDimDriveControl, 2); out << GetStateHtml(fDimFadControl, FAD::kConnected); out << GetStateHtml(fDimFtmControl, FTM::kConnected); out << GetStateHtml(fDimBiasControl, BIAS::kConnected); out << GetStateHtml(fDimFeedback, 4); out << GetStateHtml(fDimRateControl, 4); out << GetStateHtml(fDimFscControl, 2); out << GetStateHtml(fDimMagicWeather, 2); out << GetStateHtml(fDimRateScan, 4); out << GetStateHtml(fDimChatServer, 1); } ofstream(fPath+"/status.txt") << out.str(); return kStateRunning; } public: StateMachineSmartFACT(ostream &out=cout) : StateMachineDim(out, "SMART_FACT"), fPath("www/smartfact/data"), fMcpConfigurationMaxTime(0), fMcpConfigurationMaxEvents(0), fBiasControlVoltageMed(0), fBiasControlCurrentMax(0), fFscControlHumidityAvg(0), fRateScanDataId(0), fRateScanBoard(0), // --- fDimMcp ("MCP"), fDimDataLogger ("DATA_LOGGER"), fDimDriveControl("DRIVE_CONTROL"), fDimMagicWeather("MAGIC_WEATHER"), fDimFeedback ("FEEDBACK"), fDimBiasControl ("BIAS_CONTROL"), fDimFtmControl ("FTM_CONTROL"), fDimFadControl ("FAD_CONTROL"), fDimFscControl ("FSC_CONTROL"), fDimRateControl ("RATE_CONTROL"), fDimRateScan ("RATE_SCAN"), fDimChatServer ("CHAT_SERVER") { fDimDNS.Subscribe(*this); fDimControl.Subscribe(*this); fDimMcp.Subscribe(*this); fDimDataLogger.Subscribe(*this); fDimDriveControl.Subscribe(*this); fDimMagicWeather.Subscribe(*this); fDimFeedback.Subscribe(*this); fDimBiasControl.Subscribe(*this); fDimFtmControl.Subscribe(*this); fDimFadControl.Subscribe(*this); fDimFscControl.Subscribe(*this); fDimRateControl.Subscribe(*this); fDimRateScan.Subscribe(*this); fDimChatServer.Subscribe(*this); Subscribe("DIM_CONTROL/MESSAGE") (bind(&StateMachineSmartFACT::HandleDimControlMessage, this, placeholders::_1)); Subscribe("MCP/CONFIGURATION") (bind(&StateMachineSmartFACT::HandleMcpConfiguration, this, placeholders::_1)); Subscribe("DRIVE_CONTROL/POINTING_POSITION") (bind(&StateMachineSmartFACT::HandleDrivePointing, this, placeholders::_1)); Subscribe("DRIVE_CONTROL/TRACKING_POSITION") (bind(&StateMachineSmartFACT::HandleDriveTracking, this, placeholders::_1)); Subscribe("DRIVE_CONTROL/SOURCE_POSITION") (bind(&StateMachineSmartFACT::HandleDriveSource, this, placeholders::_1)); Subscribe("FSC_CONTROL/TEMPERATURE") (bind(&StateMachineSmartFACT::HandleFscTemperature, this, placeholders::_1)); Subscribe("FSC_CONTROL/HUMIDITY") (bind(&StateMachineSmartFACT::HandleFscHumidity, this, placeholders::_1)); Subscribe("MAGIC_WEATHER/DATA") (bind(&StateMachineSmartFACT::HandleMagicWeatherData, this, placeholders::_1)); Subscribe("FEEDBACK/DEVIATION") (bind(&StateMachineSmartFACT::HandleFeedbackDeviation, this, placeholders::_1)); Subscribe("FEEDBACK/CALIBRATION") (bind(&StateMachineSmartFACT::HandleFeedbackCalibration, this, placeholders::_1)); Subscribe("BIAS_CONTROL/VOLTAGE") (bind(&StateMachineSmartFACT::HandleBiasVoltage, this, placeholders::_1)); Subscribe("BIAS_CONTROL/CURRENT") (bind(&StateMachineSmartFACT::HandleBiasCurrent, this, placeholders::_1)); Subscribe("FAD_CONTROL/CONNECTIONS") (bind(&StateMachineSmartFACT::HandleFadConnections, this, placeholders::_1)); Subscribe("FAD_CONTROL/EVENTS") (bind(&StateMachineSmartFACT::HandleFadEvents, this, placeholders::_1)); Subscribe("FTM_CONTROL/TRIGGER_RATES") (bind(&StateMachineSmartFACT::HandleFtmTriggerRates, this, placeholders::_1)); Subscribe("FTM_CONTROL/STATIC_DATA") (bind(&StateMachineSmartFACT::HandleFtmStaticData, this, placeholders::_1)); Subscribe("FTM_CONTROL/FTU_LIST") (bind(&StateMachineSmartFACT::HandleFtmFtuList, this, placeholders::_1)); Subscribe("RATE_SCAN/DATA") (bind(&StateMachineSmartFACT::HandleRateScanData, this, placeholders::_1)); Subscribe("FAD_CONTROL/EVENT_DATA") (bind(&StateMachineSmartFACT::HandleFadEventData, this, placeholders::_1)); // ================================================================= // State names AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable", "The Dim DNS is not reachable."); AddStateName(kStateRunning, "Running", ""); // ================================================================= AddEvent("PRINT") (bind(&StateMachineSmartFACT::Print, this)) ("Print a list of the states of all connected servers."); } int EvalOptions(Configuration &conf) { if (!fPixelMap.Read(conf.Get("pixel-map-file"))) { Error("Reading mapping table from "+conf.Get("pixel-map-file")+" failed."); return 1; } fPath = conf.Get("path"); fDimControl.SetCallback(bind(&StateMachineSmartFACT::HandleControlStateChange, this, placeholders::_1)); fDimControl.AddCallback("dotest.dim", bind(&StateMachineSmartFACT::HandleDoTest, this, placeholders::_1)); return -1; } }; // ------------------------------------------------------------------------ #include "Main.h" template int RunShell(Configuration &conf) { return Main::execute(conf); } void SetupConfiguration(Configuration &conf) { po::options_description control("Smart FACT"); control.add_options() ("pixel-map-file", var("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage") ("path", var("www/smartfact/data"), "Output path for the data-files") ; conf.AddOptions(control); } /* Extract usage clause(s) [if any] for SYNOPSIS. Translators: "Usage" and "or" here are patterns (regular expressions) which are used to match the usage synopsis in program output. An example from cp (GNU coreutils) which contains both strings: Usage: cp [OPTION]... [-T] SOURCE DEST or: cp [OPTION]... SOURCE... DIRECTORY or: cp [OPTION]... -t DIRECTORY SOURCE... */ void PrintUsage() { cout << "SmartFACT is a tool writing the files needed for the SmartFACT web interface.\n" "\n" "The default is that the program is started without user intercation. " "All actions are supposed to arrive as DimCommands. Using the -c " "option, a local shell can be initialized. With h or help a short " "help message about the usuage can be brought to the screen.\n" "\n" "Usage: smartfact [-c type] [OPTIONS]\n" " or: smartfact [OPTIONS]\n"; cout << endl; } void PrintHelp() { Main::PrintHelp(); /* Additional help text which is printed after the configuration options goes here */ /* cout << "bla bla bla" << endl << endl; cout << endl; cout << "Environment:" << endl; cout << "environment" << endl; cout << endl; cout << "Examples:" << endl; cout << "test exam" << endl; cout << endl; cout << "Files:" << endl; cout << "files" << endl; cout << endl; */ } int main(int argc, const char* argv[]) { Configuration conf(argv[0]); conf.SetPrintUsage(PrintUsage); Main::SetupConfiguration(conf); SetupConfiguration(conf); if (!conf.DoParse(argc, argv, PrintHelp)) return -1; //try { // No console access at all if (!conf.Has("console")) { // if (conf.Get("no-dim")) // return RunShell(conf); // else return RunShell(conf); } // Cosole access w/ and w/o Dim /* if (conf.Get("no-dim")) { if (conf.Get("console")==0) return RunShell(conf); else return RunShell(conf); } else */ { if (conf.Get("console")==0) return RunShell(conf); else return RunShell(conf); } } /*catch (std::exception& e) { cerr << "Exception: " << e.what() << endl; return -1; }*/ return 0; }