7 #ifndef cacaoInterface_hpp
8 #define cacaoInterface_hpp
10 #include "../../libMagAOX/libMagAOX.hpp"
11 #include "../../magaox_git_version.h"
131 const std::string & param,
132 const std::string & val
138 const std::string & param,
143 const std::string & param );
146 const std::string & param );
277 config.add(
"loop.number",
"",
"loop.number", argType::Required,
"loop",
"number",
false,
"string",
"the loop number");
323 createStandardIndiNumber<float>(
m_indiP_loopGain,
"loop_gain", 0.0, 10.0, 0.01,
"%0.3f",
"Loop Gain",
"Loop Controls");
326 createStandardIndiNumber<float>(
m_indiP_multCoeff,
"loop_multcoeff", 0.0, 1.0, 0.001,
"%0.3f",
"Mult. Coefficient",
"Loop Controls");
329 createStandardIndiNumber<float>(
m_indiP_maxLim,
"loop_max_limit", 0.0, 10.0, 0.001,
"%0.3f",
"Max. Limit",
"Loop Controls");
334 log<software_error>({__FILE__, __LINE__});
349 if(pthread_tryjoin_np(
m_fmThread.native_handle(),0) == 0)
351 log<software_critical>({__FILE__, __LINE__,
"cacao file monitoring thread has exited"});
369 log<software_error>({__FILE__, __LINE__});
429 const std::string & param,
430 const std::string & val
433 std::string comout =
"setval " + fps +
"-" +
m_loopNumber +
"." + param +
" " + val +
"\n";
435 int wfd = open(
m_fpsFifo.c_str(), O_WRONLY);
438 log<software_error>({__FILE__, __LINE__, errno,
"error opening " +
m_fpsFifo});
442 int w = write(wfd, comout.c_str(), comout.size());
444 if(w != (
int) comout.size())
446 log<software_error>({__FILE__, __LINE__, errno,
"error on write to " +
m_fpsFifo});
458 const std::string & param,
462 return setFPSVal( fps, param, std::to_string(val));
466 const std::string & param
471 std::string comout =
"fwrval " + fps +
"-" +
m_loopNumber +
"." + param +
" " + outfile +
"\n";
473 int wfd = open(
m_fpsFifo.c_str(), O_WRONLY);
476 log<software_error>({__FILE__, __LINE__, errno,
"error opening " +
m_fpsFifo});
480 int w = write(wfd, comout.c_str(), comout.size());
482 if(w != (
int) comout.size())
484 log<software_error>({__FILE__, __LINE__, errno,
"error on write to " +
m_fpsFifo});
494 while(rfd < 0 && nr < 20)
496 rfd = open(outfile.c_str(), O_RDONLY);
498 mx::sys::milliSleep(10);
501 int r = read(rfd, inbuff,
sizeof(inbuff));
505 log<software_error>({__FILE__, __LINE__, errno,
"error on read from " +
m_fpsFifo});
511 remove(outfile.c_str());
515 std::string instr = inbuff;
517 size_t ned = instr.find_last_not_of(
" \t\r\n");
519 if(ned == std::string::npos || ned == 0)
521 log<software_error>({__FILE__, __LINE__,
"got empty result from " +
m_fpsFifo});
525 size_t nst = instr.rfind(
' ', ned);
527 if(nst == 0 || nst == std::string::npos || ned <= nst)
529 log<software_error>({__FILE__, __LINE__,
"bad format in result from " +
m_fpsFifo});
533 return instr.substr(nst+1);
537 const std::string & param
542 std::string comout =
"fwrval " + fps +
"-" +
m_loopNumber +
"." + param +
" " + outfile +
"\n";
544 int wfd = open(
m_fpsFifo.c_str(), O_WRONLY);
547 log<software_error>({__FILE__, __LINE__, errno,
"error opening " +
m_fpsFifo});
551 int w = write(wfd, comout.c_str(), comout.size());
553 if(w != (
int) comout.size())
555 log<software_error>({__FILE__, __LINE__, errno,
"error on write to " +
m_fpsFifo});
564 while(rfd < 0 && nr < 20)
566 rfd = open(outfile.c_str(), O_RDONLY);
568 mx::sys::milliSleep(10);
571 int r = read(rfd, inbuff,
sizeof(inbuff));
577 log<software_error>({__FILE__, __LINE__, errno,
"error on read from " +
m_fpsFifo});
581 remove(outfile.c_str());
585 std::string instr = inbuff;
587 size_t ned = instr.find_last_not_of(
" \t\r\n");
589 if(ned == std::string::npos || ned == 0)
591 log<software_error>({__FILE__, __LINE__,
"got empty result from " +
m_fpsFifo});
595 size_t nst = instr.rfind(
' ', ned);
597 if(nst == 0 || nst == std::string::npos || ned <= nst)
599 log<software_error>({__FILE__, __LINE__,
"bad format in result from " +
m_fpsFifo});
603 return instr.substr(nst);
609 std::string calsrc =
"/milk/shm/aol" +
m_loopNumber +
"_calib_source.txt";
623 calsrc +=
"/calib_dir.txt";
627 return log<
software_error, -1>({__FILE__, __LINE__, errno,
"cacaoInterface::getAOCalib failed to open: " + calsrc});
629 std::string aoCalDir;
642 std::string nameFile =
m_aoCalDir +
"/LOOPNAME";
646 return log<
software_error, -1>({__FILE__, __LINE__, errno,
"cacaoInterface::getAOCalib failed to open: " + nameFile});
653 calsrc =
"/milk/shm/aol" +
m_loopNumber +
"_calib_loaded.txt";
657 return log<
software_error, -1>({__FILE__, __LINE__, errno,
"cacaoInterface::getAOCalib failed to open: " + calsrc});
659 std::string aoCalLoadTime;
660 fin >> aoCalLoadTime;
680 return log<
software_error, -1>({__FILE__, __LINE__, errno,
"cacaoInterface::getAOCalib failed to open: " + calsrc});
723 if(
setFPSVal(
"mfilt",
"loopON", std::string(
"ON")) != 0)
737 if(
setFPSVal(
"mfilt",
"loopON", std::string(
"OFF")) != 0)
757 if(
setFPSVal(
"mfilt",
"loopZERO", std::string(
"ON")) != 0)
805 catch(
const std::exception& e)
831 mx::sys::milliSleep(250);
842 if(!
ipRecv.find(
"toggle"))
return 0;
844 std::unique_lock<std::mutex>
lock(m_indiMutex);
846 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
850 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off)
855 log<software_error>({__FILE__,__LINE__,
"switch state fall through."});
866 if(
ipRecv.find(
"current"))
868 current =
ipRecv[
"current"].get<
double>();
873 target =
ipRecv[
"target"].get<
double>();
876 if(target == -1) target = current;
883 std::lock_guard<std::mutex> guard(m_indiMutex);
885 m_gain_target = target;
896 if(!
ipRecv.find(
"request"))
return 0;
898 std::unique_lock<std::mutex>
lock(m_indiMutex);
900 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
915 if(
ipRecv.find(
"current"))
917 current =
ipRecv[
"current"].get<
double>();
922 target =
ipRecv[
"target"].get<
double>();
925 if(target == -1) target = current;
932 std::lock_guard<std::mutex> guard(m_indiMutex);
934 m_multCoeff_target = target;
937 return setMultCoeff();
947 if(
ipRecv.find(
"current"))
949 current =
ipRecv[
"current"].get<
double>();
954 target =
ipRecv[
"target"].get<
double>();
957 if(target == -1) target = current;
964 std::lock_guard<std::mutex> guard(m_indiMutex);
965 m_maxLim_target = target;
986 static uint8_t
state {0};
987 static float gain {-1000};
988 static float multcoef {0};
989 static float limit {0};
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.
int createStandardIndiRequestSw(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 request element.
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.
int shutdown()
Get the value of the shutdown flag.
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.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
int createROIndiText(pcf::IndiProperty &prop, const std::string &propName, const std::string &elName, const std::string &propLabel="", const std::string &propGroup="", const std::string &elLabel="")
Create a standard ReadOnly INDI Text property, with at least one element.
std::mutex m_indiMutex
Mutex for locking INDI communications.
int threadStart(std::thread &thrd, bool &thrdInit, pid_t &tpid, pcf::IndiProperty &thProp, int thrdPrio, const std::string &cpuset, const std::string &thrdName, thisPtr *thrdThis, Function &&thrdStart)
Start a thread, using this class's privileges to set priority, etc.
The MagAO-X CACAO Interface.
int setMultCoeff()
Set loop multiplication coefficient to the value of m_multCoeff_target;.
pcf::IndiProperty m_indiP_loopZero
int m_loopState
The loop state. 0 = off, 1 = paused (on, 0 gain), 2 = on.
int checkLoopProcesses()
Check if the loop processes are running.
INDI_NEWCALLBACK_DECL(cacaoInterface, m_indiP_maxLim)
bool m_fmThreadInit
Initialization flag for the file monitoring thread.
virtual int appLogic()
Implementation of the FSM for cacaoInterface.
std::string getFPSValNum(const std::string &fps, const std::string ¶m)
void fmThreadExec()
File monitoring thread function.
float m_gain_target
The target loop gain.
static void fmThreadStart(cacaoInterface *c)
File monitoring thread starter function.
INDI_NEWCALLBACK_DECL(cacaoInterface, m_indiP_loopZero)
pcf::IndiProperty m_indiP_loop
int loopOn()
Turn the loop on.
int setFPSVal(const std::string &fps, const std::string ¶m, const std::string &val)
std::vector< float > m_modeBlockLims
pcf::IndiProperty m_indiP_loopState
bool m_loopProcesses
Status of the loop processes.
float m_maxLim
The current max limit.
INDI_NEWCALLBACK_DECL(cacaoInterface, m_indiP_multCoeff)
pcf::IndiProperty m_fmThreadProp
The property to hold the f.m. thread details.
std::vector< float > m_modeBlockGains
int m_fmThreadPrio
Priority of the filemonitoring thread.
std::vector< float > m_modeBlockMCs
int setGain()
Set loop gain to the value of m_gain_target;.
std::string m_aoCalArchiveTime
virtual void setupConfig()
float m_gain
The current loop gain.
std::string m_loopName
the loop name
~cacaoInterface() noexcept
D'tor, declared and defined for noexcept.
std::string m_aoCalLoadTime
std::string getFPSValStr(const std::string &fps, const std::string ¶m)
int recordLoopGain(bool force=false)
std::vector< int > m_modeBlockStart
std::thread m_fmThread
The file monitoring thread.
virtual int appStartup()
Startup function.
friend class cacaoInterface_test
int getAOCalib()
Get the calibration details.
int setMaxLim()
Set loop max lim to the value of m_maxLim_target;.
virtual int appShutdown()
Shutdown the app.
float m_maxLim_target
The target max limit.
float m_multCoeff
The current multiplicative coefficient (1-leak)
dev::telemeter< cacaoInterface > telemeterT
std::mutex m_modeBlockMutex
int recordTelem(const telem_loopgain *)
pcf::IndiProperty m_indiP_maxLim
INDI_NEWCALLBACK_DECL(cacaoInterface, m_indiP_loopState)
std::string m_loopNumber
The loop number, X in aolX. We keep it a string because that's how it gets used.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pid_t m_fmThreadID
File monitor thread PID.
std::vector< int > m_modeBlockN
int loopOff()
Turn the loop off.
pcf::IndiProperty m_indiP_loopProcesses
pcf::IndiProperty m_indiP_multCoeff
float m_multCoeff_target
The target multiplicative coefficient (1-leak)
pcf::IndiProperty m_indiP_loopGain
int loopZero()
Zero the loop control channel.
bool m_loopProcesses_stat
What the cacao status file says the state of loop processes is.
virtual void loadConfig()
cacaoInterface()
Default c'tor.
INDI_NEWCALLBACK_DECL(cacaoInterface, m_indiP_loopGain)
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ OPERATING
The device is operating, other than homing.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
int addTextElement(pcf::IndiProperty &prop, const std::string &name, const std::string &label="")
Add a standard INDI Text element.
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
const pcf::IndiProperty & ipRecv
updateIfChanged(m_indiP_angle, "target", m_angle)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
std::unique_lock< std::mutex > lock(m_indiMutex)
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_INFO
Informational. The info log level is the lowest level recorded during normal operations.
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
A device base class 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 appStartup()
Starts the telemetry log thread.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Software CRITICAL log entry.
Log entry recording the build-time git state.