LCOV - code coverage report
Current view: top level - apps/xt1121DCDU - xt1121DCDU.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 3.9 % 181 7
Test Date: 2026-04-15 19:34:29 Functions: 7.1 % 28 2

            Line data    Source code
       1              : /** \file xt1121DCDU.hpp
       2              :   * \brief The MagAO-X xt1121-based D.C. Distribution Unit controller.
       3              :   *
       4              :   * \author Jared R. Males (jaredmales@gmail.com)
       5              :   *
       6              :   * \ingroup xt1121DCDU_files
       7              :   */
       8              : 
       9              : #ifndef xt1121DCDU_hpp
      10              : #define xt1121DCDU_hpp
      11              : 
      12              : 
      13              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      14              : #include "../../magaox_git_version.h"
      15              : 
      16              : /** \defgroup xt1121DCDU xt1121-based DC distribution unit
      17              :   * \brief Control of MagAO-X D.C. power distrubition via the xt1121 DIO module.
      18              :   *
      19              :   * <a href="../handbook/operating/software/apps/xt1121DCDU.html">Application Documentation</a>
      20              :   *
      21              :   * \ingroup apps
      22              :   *
      23              :   */
      24              : 
      25              : /** \defgroup xt1121DCDU_files xt1121 DCDU Files
      26              :   * \ingroup xt1121DCDU
      27              :   */
      28              : 
      29              : namespace MagAOX
      30              : {
      31              : namespace app
      32              : {
      33              : 
      34              : /// MagAO-X application to control D.C. distribution via an xt1121 DIO unit.
      35              : /** The device outlets are organized into channels.  See \ref dev::outletController for details of configuring the channels.
      36              :   *
      37              :   *
      38              :   * \ingroup xt1121DCDU
      39              :   */
      40              : class xt1121DCDU : public MagAOXApp<>, public dev::outletController<xt1121DCDU>
      41              : {
      42              : 
      43              : protected:
      44              : 
      45              :    std::string m_deviceName; ///< The device address
      46              : 
      47              :    std::vector<int> m_channelNumbers; ///< Vector of outlet numbers, used to construct the channel names to monitor as outlets 0-7.
      48              : 
      49              :    int m_outletStateDelay {5000}; ///< The maximum time to wait for an outlet to change state [msec].
      50              : 
      51              : 
      52              :    pcf::IndiProperty ip_ch0;
      53              :    pcf::IndiProperty ip_ch1;
      54              :    pcf::IndiProperty ip_ch2;
      55              :    pcf::IndiProperty ip_ch3;
      56              :    pcf::IndiProperty ip_ch4;
      57              :    pcf::IndiProperty ip_ch5;
      58              :    pcf::IndiProperty ip_ch6;
      59              :    pcf::IndiProperty ip_ch7;
      60              : 
      61              : 
      62              : 
      63              : public:
      64              : 
      65              :    /// Default c'tor.
      66              :    xt1121DCDU();
      67              : 
      68              :    /// D'tor, declared and defined for noexcept.
      69            1 :    ~xt1121DCDU() noexcept
      70            1 :    {}
      71              : 
      72              :    /// Setup the configuration system (called by MagAOXApp::setup())
      73              :    virtual void setupConfig();
      74              : 
      75              :    /// load the configuration system results (called by MagAOXApp::setup())
      76              :    virtual void loadConfig();
      77              : 
      78              :    /// Startup functions
      79              :    /** Setsup the INDI vars.
      80              :      * Checks if the device was found during loadConfig.
      81              :      */
      82              :    virtual int appStartup();
      83              : 
      84              :    /// Implementation of the FSM for the xt1121 DCDU.
      85              :    virtual int appLogic();
      86              : 
      87              :    /// Do any needed shutdown tasks.  Currently nothing in this app.
      88              :    virtual int appShutdown();
      89              : 
      90              :    /// Update a single outlet state
      91              :    /**
      92              :      *
      93              :      * \returns 0 on success
      94              :      * \returns -1 on error
      95              :      */
      96              :    virtual int updateOutletState( int outletNum /**< [in] the outlet number to update */);
      97              : 
      98              :    /// Turn on an outlet.
      99              :    /**
     100              :      * \returns 0 on success
     101              :      * \returns -1 on error
     102              :      */
     103              :    virtual int turnOutletOn( int outletNum /**< [in] the outlet number to turn on */);
     104              : 
     105              :    /// Turn off an outlet.
     106              :    /**
     107              :      * \returns 0 on success
     108              :      * \returns -1 on error
     109              :      */
     110              :    virtual int turnOutletOff( int outletNum /**< [in] the outlet number to turn off */);
     111              : 
     112              : protected:
     113              : 
     114              :    ///Helper function to get the xt1121Ctrl channel name for the given channel number.
     115              :    /**
     116              :      * \returns chXX where XX is 00 to 15, set by chno.
     117              :      * \returns empty string if chno is not valid.
     118              :      */
     119              :    std::string xtChannelName( int chno);
     120              : 
     121              :    ///Helper function to get a pointer to the right INDI property for an outlet number.
     122              :    /**
     123              :      * \returns a pointer to one of the INDI properties if outletNum is valid
     124              :      * \returns nullptr if outletNum is not valid.
     125              :      */
     126              :    pcf::IndiProperty * xtChannelProperty( int outletNum /**< [in] the outlet number */);
     127              : 
     128            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch0);
     129            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch1);
     130            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch2);
     131            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch3);
     132            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch4);
     133            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch5);
     134            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch6);
     135            0 :    INDI_SETCALLBACK_DECL(xt1121DCDU, ip_ch7);
     136              : };
     137              : 
     138            3 : xt1121DCDU::xt1121DCDU() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     139              : {
     140            1 :    m_firstOne = true;
     141            1 :    m_powerMgtEnabled = true;
     142              : 
     143            1 :    setNumberOfOutlets(8);
     144              : 
     145            1 :    return;
     146            0 : }
     147              : 
     148            0 : void xt1121DCDU::setupConfig()
     149              : {
     150            0 :    config.add("device.name", "", "device.name", argType::Required, "device", "name", false, "string", "The device INDI name.");
     151              : 
     152            0 :    config.add("device.channelNumbers", "", "device.channelNumbers", argType::Required, "device", "channelNumbers", false, "vector<int>", "The channel numbers to use for the outlets, in order.");
     153              : 
     154              : 
     155            0 :    dev::outletController<xt1121DCDU>::setupConfig(config);
     156              : 
     157            0 : }
     158              : 
     159              : 
     160            0 : void xt1121DCDU::loadConfig()
     161              : {
     162            0 :    config(m_deviceName, "device.name");
     163              : 
     164            0 :    m_channelNumbers = {0,1,2,3,4,5,6,7};
     165            0 :    config(m_channelNumbers, "device.channelNumbers");
     166              : 
     167            0 :    dev::outletController<xt1121DCDU>::loadConfig(config);
     168              : 
     169            0 : }
     170              : 
     171              : 
     172              : 
     173            0 : int xt1121DCDU::appStartup()
     174              : {
     175            0 :    if(m_channelNumbers.size() != 8)
     176              :    {
     177            0 :       return log<text_log,-1>("Something other than 8 channel numbers specified.", logPrio::LOG_CRITICAL);
     178              :    }
     179              : 
     180            0 :    REG_INDI_SETPROP(ip_ch0, m_deviceName, xtChannelName(m_channelNumbers[0]));
     181            0 :    REG_INDI_SETPROP(ip_ch1, m_deviceName, xtChannelName(m_channelNumbers[1]));
     182            0 :    REG_INDI_SETPROP(ip_ch2, m_deviceName, xtChannelName(m_channelNumbers[2]));
     183            0 :    REG_INDI_SETPROP(ip_ch3, m_deviceName, xtChannelName(m_channelNumbers[3]));
     184            0 :    REG_INDI_SETPROP(ip_ch4, m_deviceName, xtChannelName(m_channelNumbers[4]));
     185            0 :    REG_INDI_SETPROP(ip_ch5, m_deviceName, xtChannelName(m_channelNumbers[5]));
     186            0 :    REG_INDI_SETPROP(ip_ch6, m_deviceName, xtChannelName(m_channelNumbers[6]));
     187            0 :    REG_INDI_SETPROP(ip_ch7, m_deviceName, xtChannelName(m_channelNumbers[7]));
     188              : 
     189            0 :    if(dev::outletController<xt1121DCDU>::setupINDI() < 0)
     190              :    {
     191            0 :       return log<text_log,-1>("Error setting up INDI for outlet control.", logPrio::LOG_CRITICAL);
     192              :    }
     193              : 
     194            0 :    state(stateCodes::NOTCONNECTED);
     195              : 
     196            0 :    return 0;
     197              : }
     198              : 
     199            0 : int xt1121DCDU::appLogic()
     200              : {
     201            0 :    if( state() == stateCodes::POWERON )
     202              :    {
     203            0 :       state(stateCodes::READY);
     204              :    }
     205              : 
     206              : 
     207            0 :    if(state() == stateCodes::READY)
     208              :    {
     209            0 :       std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
     210            0 :       if( !lock.owns_lock() )
     211              :       {
     212            0 :          return 0;
     213              :       }
     214              : 
     215            0 :       int rv = updateOutletStates();
     216              : 
     217            0 :       if(rv < 0) return log<software_error,-1>({__FILE__, __LINE__});
     218              : 
     219            0 :       dev::outletController<xt1121DCDU>::updateINDI();
     220              : 
     221            0 :       return 0;
     222            0 :    }
     223              : 
     224            0 :    state(stateCodes::FAILURE);
     225            0 :    log<text_log>("appLogic fell through", logPrio::LOG_CRITICAL);
     226            0 :    return -1;
     227              : 
     228              : }
     229              : 
     230            0 : int xt1121DCDU::appShutdown()
     231              : {
     232              :    //don't bother
     233            0 :    return 0;
     234              : }
     235              : 
     236            0 : int xt1121DCDU::updateOutletState( int outletNum )
     237              : {
     238            0 :    pcf::IndiProperty * ip = xtChannelProperty(outletNum);
     239              : 
     240            0 :    if(ip == nullptr)
     241              :    {
     242            0 :       return log<software_error, -1>({__FILE__, __LINE__, "bad outlet number"});
     243              :    }
     244              : 
     245            0 :    int os = OUTLET_STATE_UNKNOWN;
     246            0 :    if(ip->find("current"))
     247              :    {
     248            0 :       if((*ip)["current"].get<int>() == 0) os = OUTLET_STATE_OFF;
     249            0 :       else if((*ip)["current"].get<int>() == 1) os = OUTLET_STATE_ON;
     250              :    }
     251              : 
     252            0 :    m_outletStates[outletNum] = os;
     253              : 
     254            0 :    return 0;
     255              : 
     256              : }
     257              : 
     258            0 : int xt1121DCDU::turnOutletOn( int outletNum )
     259              : {
     260            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);  //Lock the mutex before doing anything
     261              : 
     262            0 :    pcf::IndiProperty * ip = xtChannelProperty(outletNum);
     263              : 
     264            0 :    if(ip == nullptr)
     265              :    {
     266            0 :       return log<software_error, -1>({__FILE__, __LINE__, "bad outlet number"});
     267              :    }
     268              : 
     269            0 :    return sendNewProperty(*ip, "target", 1);
     270              : 
     271            0 : }
     272              : 
     273            0 : int xt1121DCDU::turnOutletOff( int outletNum )
     274              : {
     275            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);  //Lock the mutex before doing anything
     276              : 
     277            0 :    pcf::IndiProperty * ip = xtChannelProperty(outletNum);
     278              : 
     279            0 :    if(ip == nullptr)
     280              :    {
     281            0 :       return log<software_error, -1>({__FILE__, __LINE__, "bad outlet number"});
     282              :    }
     283              : 
     284            0 :    return sendNewProperty(*ip, "target", 0);
     285              : 
     286            0 : }
     287              : 
     288            0 : std::string xt1121DCDU::xtChannelName( int chno)
     289              : {
     290            0 :    switch(chno)
     291              :    {
     292            0 :       case 0:
     293            0 :          return "ch00";
     294            0 :       case 1:
     295            0 :          return "ch01";
     296            0 :       case 2:
     297            0 :          return "ch02";
     298            0 :       case 3:
     299            0 :          return "ch03";
     300            0 :       case 4:
     301            0 :          return "ch04";
     302            0 :       case 5:
     303            0 :          return "ch05";
     304            0 :       case 6:
     305            0 :          return "ch06";
     306            0 :       case 7:
     307            0 :          return "ch07";
     308            0 :       case 8:
     309            0 :          return "ch08";
     310            0 :       case 9:
     311            0 :          return "ch09";
     312            0 :       case 10:
     313            0 :          return "ch10";
     314            0 :       case 11:
     315            0 :          return "ch11";
     316            0 :       case 12:
     317            0 :          return "ch12";
     318            0 :       case 13:
     319            0 :          return "ch13";
     320            0 :       case 14:
     321            0 :          return "ch14";
     322            0 :       case 15:
     323            0 :          return "ch15";
     324            0 :       case 16:
     325            0 :          return "ch16";
     326            0 :       default:
     327            0 :          return "";
     328              :    }
     329              : }
     330            0 : pcf::IndiProperty * xt1121DCDU::xtChannelProperty( int outletNum )
     331              : {
     332            0 :    switch(outletNum)
     333              :    {
     334            0 :       case 0:
     335            0 :          return &ip_ch0;
     336            0 :       case 1:
     337            0 :          return &ip_ch1;
     338            0 :       case 2:
     339            0 :          return &ip_ch2;
     340            0 :       case 3:
     341            0 :          return &ip_ch3;
     342            0 :       case 4:
     343            0 :          return &ip_ch4;
     344            0 :       case 5:
     345            0 :          return &ip_ch5;
     346            0 :       case 6:
     347            0 :          return &ip_ch6;
     348            0 :       case 7:
     349            0 :          return &ip_ch7;
     350            0 :       default:
     351            0 :          return nullptr;
     352              :    }
     353              : }
     354              : 
     355            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch0)(const pcf::IndiProperty &ipRecv)
     356              : {
     357            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     358            0 :    ip_ch0 = ipRecv;
     359              : 
     360            0 :    return updateOutletState(0);
     361            0 : }
     362              : 
     363            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch1)(const pcf::IndiProperty &ipRecv)
     364              : {
     365            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     366            0 :    ip_ch1 = ipRecv;
     367              : 
     368            0 :    return updateOutletState(1);
     369            0 : }
     370              : 
     371            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch2)(const pcf::IndiProperty &ipRecv)
     372              : {
     373            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     374            0 :    ip_ch2 = ipRecv;
     375              : 
     376            0 :    return updateOutletState(2);
     377            0 : }
     378              : 
     379            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch3)(const pcf::IndiProperty &ipRecv)
     380              : {
     381            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     382            0 :    ip_ch3 = ipRecv;
     383              : 
     384            0 :    return updateOutletState(3);
     385            0 : }
     386              : 
     387            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch4)(const pcf::IndiProperty &ipRecv)
     388              : {
     389            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     390            0 :    ip_ch4 = ipRecv;
     391              : 
     392            0 :    return updateOutletState(4);
     393            0 : }
     394              : 
     395            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch5)(const pcf::IndiProperty &ipRecv)
     396              : {
     397            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     398            0 :    ip_ch5 = ipRecv;
     399              : 
     400            0 :    return updateOutletState(5);
     401            0 : }
     402              : 
     403            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch6)(const pcf::IndiProperty &ipRecv)
     404              : {
     405            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     406            0 :    ip_ch6 = ipRecv;
     407              : 
     408            0 :    return updateOutletState(6);
     409            0 : }
     410              : 
     411            0 : INDI_SETCALLBACK_DEFN(xt1121DCDU, ip_ch7)(const pcf::IndiProperty &ipRecv)
     412              : {
     413            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     414            0 :    ip_ch7 = ipRecv;
     415              : 
     416            0 :    return updateOutletState(7);
     417            0 : }
     418              : 
     419              : } //namespace app
     420              : } //namespace MagAOX
     421              : 
     422              : #endif //xt1121DCDU_hpp
        

Generated by: LCOV version 2.0-1