7 #ifndef observerCtrl_hpp
8 #define observerCtrl_hpp
12 #include "../../libMagAOX/libMagAOX.hpp"
13 #include "../../magaox_git_version.h"
162 config.add(
"stream.writers",
"",
"stream.writers", argType::Required,
"stream",
"writers",
false,
"string",
"The device names of the stream writers to control.");
171 std::vector<std::string> sections;
173 _config.unusedSections(sections);
175 if( sections.size() == 0 )
181 for(
size_t i=0; i< sections.size(); ++i)
183 bool pfoaSet = _config.isSetUnused(mx::app::iniFile::makeKey(sections[i],
"pfoa" ));
184 if( !pfoaSet )
continue;
186 std::string email = sections[i];
189 _config.configUnused(pfoa, mx::app::iniFile::makeKey(sections[i],
"pfoa" ));
191 std::string fullName;
192 _config.configUnused(fullName, mx::app::iniFile::makeKey(sections[i],
"full_name" ));
194 std::string institution;
195 _config.configUnused(institution, mx::app::iniFile::makeKey(sections[i],
"institution" ));
197 std::string sanitizedEmail =
"";
198 for(
size_t n = 0; n < email.size(); ++n)
200 if(email[n] ==
'@') {
201 sanitizedEmail = sanitizedEmail +
"-at-";
202 }
else if(email[n] ==
'.') {
203 sanitizedEmail = sanitizedEmail +
"-dot-";
205 sanitizedEmail.push_back(email[n]);
234 std::vector<std::string> sanitizedEmails;
235 std::vector<std::string> emails;
238 sanitizedEmails.push_back(
it->second.m_sanitizedEmail);
239 emails.push_back(
it->second.m_email);
244 log<software_critical>({__FILE__, __LINE__});
250 log<software_critical>({__FILE__, __LINE__});
257 log<software_critical>({__FILE__, __LINE__});
264 log<software_critical>({__FILE__, __LINE__});
274 m_indiP_sws = pcf::IndiProperty(pcf::IndiProperty::Switch);
288 log<software_critical>({__FILE__, __LINE__});
304 std::unique_lock<std::mutex> lock(
m_indiMutex, std::try_to_lock);
323 log<software_error>({__FILE__, __LINE__});
344 pcf::IndiProperty ip(pcf::IndiProperty::Switch);
347 ip.setName(
"writing");
348 ip.add(pcf::IndiElement(
"toggle"));
349 ip[
"toggle"].setSwitchState(pcf::IndiElement::On);
370 pcf::IndiProperty ip(pcf::IndiProperty::Switch);
373 ip.setName(
"writing");
374 ip.add(pcf::IndiElement(
"toggle"));
375 ip[
"toggle"].setSwitchState(pcf::IndiElement::Off);
390 std::string newEmail =
"";
391 for(
auto it=m_observers.begin();
it != m_observers.end(); ++
it)
393 if(!
ipRecv.find(
it->second.m_sanitizedEmail))
continue;
395 if(
ipRecv[
it->second.m_sanitizedEmail].getSwitchState() == pcf::IndiElement::On)
403 newEmail =
it->first;
413 std::unique_lock<std::mutex> lock(m_indiMutex);
415 m_currentObserver = m_observers[newEmail];
417 for(
auto it = m_observers.begin();
it!=m_observers.end();++
it)
423 log<logger::observer>({m_currentObserver.m_fullName,m_currentObserver.m_pfoa, m_currentObserver.m_email, m_currentObserver.m_institution});
434 std::unique_lock<std::mutex> lock(m_indiMutex);
436 if( indiTargetUpdate( m_indiP_obsName, target,
ipRecv,
true) < 0)
438 log<software_error>({__FILE__,__LINE__});
451 if(!
ipRecv.find(
"toggle"))
return 0;
453 std::unique_lock<std::mutex> lock(m_indiMutex);
455 recordObserver(
true);
456 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
461 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off)
474 if(m_observing ==
true)
480 for(
size_t n =0; n < m_streamWriters.size(); ++n)
482 if(!
ipRecv.find(m_streamWriters[n]))
continue;
505 static std::string last_email;
506 static std::string last_obsName;
507 static bool last_observing;
The base-class for MagAO-X applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::mutex m_indiMutex
Mutex for locking INDI communications.
std::string configName()
Get the config name.
int createStandardIndiSelectionSw(pcf::IndiProperty &prop, const std::string &name, const std::vector< std::string > &elements, const std::vector< std::string > &elementLabels, const std::string &label="", const std::string &group="")
Create a standard R/W INDI selection (one of many) switch with vector of elements and element labels.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
int createStandardIndiText(pcf::IndiProperty &prop, const std::string &propName, const std::string &label="", const std::string &group="")
Create a standard R/W INDI Text property with target and current elements.
The MagAO-X Observer Controller.
pcf::IndiProperty m_indiP_observer
pcf::IndiProperty m_indiP_obsName
int recordTelem(const telem_observer *)
std::string m_sanitizedEmail
virtual int appLogic()
Implementation of the FSM for observerCtrl.
INDI_NEWCALLBACK_DECL(observerCtrl, m_indiP_observing)
pcf::IndiProperty m_indiP_observers
int recordObserver(bool force=false)
std::string m_institution
INDI_NEWCALLBACK_DECL(observerCtrl, m_indiP_sws)
~observerCtrl() noexcept
D'tor, declared and defined for noexcept.
INDI_NEWCALLBACK_DECL(observerCtrl, m_indiP_obsName)
INDI_NEWCALLBACK_DECL(observerCtrl, m_indiP_observers)
virtual void loadConfig()
std::vector< std::string > m_streamWriters
The stream writers to stop and start.
virtual int appStartup()
Startup function.
pcf::IndiProperty m_indiP_observing
pcf::IndiProperty m_indiP_obslog
observerCtrl()
Default c'tor.
virtual int appShutdown()
Shutdown the app.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
friend class observerCtrl_test
observer m_currentObserver
std::map< std::string, observer > observerMapT
pcf::IndiProperty m_indiP_sws
virtual void setupConfig()
#define REG_INDI_NEWPROP_NOCB(prop, propName, type)
Register a NEW INDI property with the class, with no callback.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ READY
The device is ready for operation, but is not operating.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
const pcf::IndiProperty & ipRecv
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
A device which saves telemetry.
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int appLogic()
Perform telemeter application logic.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Log entry recording the build-time git state.