10#include "../../libMagAOX/libMagAOX.hpp"  
   11#include "../../magaox_git_version.h" 
   13#include "tmcController.hpp" 
   34template<
class parentT>
 
   43                             const std::string & 
msg,  
 
   45                             const std::string & file, 
 
   49        std::stringstream logs;
 
   50        logs << src << 
": " << 
msg << 
" [ libftdi1: " << ftdi_get_error_string(m_ftdi) << 
" ] ";
 
   52        parentT::template log<software_error>({file.c_str(), ln, 0, rv, logs.str()});
 
 
   59                              const std::string & 
msg,  
 
   60                              const std::string & file, 
 
   65        parentT::template log<software_error>({file.c_str(), ln, src + 
": " + 
msg});
 
 
 
  202    config.add(
"axis1.serial", 
"", 
"axis1.serial", argType::Required, 
"axis1", 
"serial", 
false, 
"string", 
"USB serial number");
 
  203    config.add(
"axis2.serial", 
"", 
"axis2.serial", argType::Required, 
"axis2", 
"serial", 
false, 
"string", 
"USB serial number");
 
 
  290            elevatedPrivileges 
elPriv(
this);
 
  296            elevatedPrivileges 
elPriv(
this);
 
  304                std::stringstream 
logs1;
 
  309                std::stringstream 
logs2;
 
  317        else if(
rv1 == -3 && 
rv2 == -3)
 
  328                    std::stringstream 
logs1;
 
  344                    std::stringstream 
logs2;
 
  367            elevatedPrivileges 
elPriv(
this);
 
  378            std::cerr << 
"tmcController::connectFailed\n";
 
  384            elevatedPrivileges 
elPriv(
this);
 
  427            if(!
lock.owns_lock()) 
return 0;
 
  459            if(!
lock.owns_lock()) 
return 0;
 
  489            if(!
lock.owns_lock()) 
return 0;
 
 
  545    tmcController::HWInfo 
hwi;
 
  557    std::stringstream 
logs1;
 
  562    rv = 
m_kAxis1.mod_set_chanenablestate(0x01, tmcController::EnableState::disabled);
 
  585    tmcController::KMMIParams 
par;
 
  596    par.DispBrightness = 0;
 
  625    tmcController::TPZIOSettings 
tios;
 
  635    tios.VoltageLimit = tmcController::VoltLimit::V150;
 
 
  667    int rv = 
m_kAxis1.mod_set_chanenablestate(0x01, tmcController::EnableState::enabled);
 
 
  686    int rv = 
m_kAxis1.mod_set_chanenablestate(0x01, tmcController::EnableState::disabled);
 
 
  735    tmcController::HWInfo 
hwi;
 
  747    std::stringstream 
logs1;
 
  752    rv = 
m_kAxis2.mod_set_chanenablestate(0x01, tmcController::EnableState::disabled);
 
  775    tmcController::KMMIParams 
par;
 
  786    par.DispBrightness = 0;
 
  816    tmcController::TPZIOSettings 
tios;
 
  826    tios.VoltageLimit = tmcController::VoltLimit::V150;
 
 
  858    int rv = 
m_kAxis2.mod_set_chanenablestate(0x01, tmcController::EnableState::enabled);
 
 
  877    int rv = 
m_kAxis2.mod_set_chanenablestate(0x01, tmcController::EnableState::disabled);
 
 
 1018    if( 
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
 
 1020        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1021        updateSwitchIfChanged(m_indiP_axis1_identify, 
"request", pcf::IndiElement::On, 
INDI_BUSY);
 
 1022        return m_kAxis1.mod_identify();
 
 
 1035    if( 
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
 
 1037        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1038        if(axis1Enable() < 0)
 
 1040            if(m_powerState == 0) 
return 0;
 
 1041            return log<
software_error,-1>({__FILE__, __LINE__, 
"axis 1 enable error in INDI callback"});
 
 1046        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1047        if(axis1Disable() < 0)
 
 1049            if(m_powerState == 0) 
return 0;
 
 1050            log<
software_error,-1>({__FILE__, __LINE__, 
"axis 1 disable error in INDI callback"});
 
 
 1065    indiTargetUpdate(m_indiP_axis1_voltage, target, 
ipRecv, 
true);
 
 1067    std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1068    if(axis1Voltage(target) < 0)
 
 1070        if(m_powerState == 0) 
return 0;
 
 1071        return log<
software_error,-1>({__FILE__, __LINE__, 
"axis 1 voltage error in INDI callback"});
 
 
 1084    if( 
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
 
 1086        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1087        updateSwitchIfChanged(m_indiP_axis2_identify, 
"request", pcf::IndiElement::On, 
INDI_BUSY);
 
 1088        return m_kAxis2.mod_identify();
 
 
 1101    if( 
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
 
 1103        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1104        if(axis2Enable() < 0)
 
 1106            if(m_powerState == 0) 
return 0;
 
 1107            return log<
software_error,-1>({__FILE__, __LINE__, 
"axis 2 enable error in INDI callback"});
 
 1112        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1113        if(axis2Disable() < 0)
 
 1115            if(m_powerState == 0) 
return 0;
 
 1116            return log<
software_error,-1>({__FILE__, __LINE__, 
"axis 2 disable error in INDI callback"});
 
 
 1130    indiTargetUpdate(m_indiP_axis2_voltage, target, 
ipRecv, 
true);
 
 1132    std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1133    if(axis2Voltage(target) < 0)
 
 1135        if(m_powerState == 0) 
return 0;
 
 1136        return log<
software_error,-1>({__FILE__, __LINE__, 
"axis 2 voltage error in INDI callback"});
 
 
 1149    if( 
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
 
 1151        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1155            updateSwitchIfChanged(m_indiP_set, 
"toggle", pcf::IndiElement::On, 
INDI_BUSY);
 
 1161            if(m_powerState == 0) 
return 0;
 
 1162            return log<
software_error,-1>({__FILE__, __LINE__, 
"set error in INDI callback"});
 
 1167        std::lock_guard<std::mutex> guard(m_indiMutex);
 
 1171            updateSwitchIfChanged(m_indiP_set, 
"toggle", pcf::IndiElement::Off, 
INDI_BUSY);
 
 1177            if(m_powerState == 0) 
return 0;
 
 1178            return log<
software_error,-1>({__FILE__, __LINE__, 
"rest error in INDI callback"});
 
 
The base-class for XWCTk 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_powerState
Current power state, 1=On, 0=Off, -1=Unk.
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.
std::mutex m_indiMutex
Mutex for locking INDI communications.
The MagAO-X K-Cube Controller.
kcubeCtrl()
Default c'tor.
pcf::IndiProperty m_indiP_axis2_identify
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis1_enable)
virtual int appShutdown()
Shutdown the app.
pcf::IndiProperty m_indiP_axis1_enable
pcf::IndiProperty m_indiP_axis2_voltage
virtual int appStartup()
Startup function.
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis2_enable)
tmcCon< kcubeCtrl > m_kAxis2
virtual void setupConfig()
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis1_voltage)
~kcubeCtrl() noexcept
D'tor, declared and defined for noexcept.
pcf::IndiProperty m_indiP_axis2_enable
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_set)
pcf::IndiProperty m_indiP_axis1_voltage
tmcCon< kcubeCtrl > m_kAxis1
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis2_voltage)
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis2_identify)
int axis1Voltage(float &v)
pcf::IndiProperty m_indiP_set
friend class kcubeCtrl_test
pcf::IndiProperty m_indiP_axis1_identify
virtual int appLogic()
Implementation of the FSM for kcubeCtrl.
virtual void loadConfig()
INDI_NEWCALLBACK_DECL(kcubeCtrl, m_indiP_axis1_identify)
int axis2Voltage(float &v)
Local derivation of tmcController to implement MagAO-X logging.
virtual void otherErrmsg(const std::string &src, const std::string &msg, const std::string &file, int line)
Print a message to MagAO-X logs describing an error.
virtual void ftdiErrmsg(const std::string &src, const std::string &msg, int rv, const std::string &file, int line)
Print a message to MagAO-X logs describing an error from an \libftdi1 function.
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ 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.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
const pcf::IndiProperty & ipRecv
std::unique_lock< std::mutex > lock(m_indiMutex)
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.