LCOV - code coverage report
Current view: top level - apps/xt1121Ctrl - xt1121Ctrl.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 277 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 42 0

            Line data    Source code
       1              : /** \file xt1121Ctrl.hpp
       2              :   * \brief The MagAO-X Acromag XT 1121digital I/O controller.
       3              :   *
       4              :   * \author Jared R. Males (jaredmales@gmail.com)
       5              :   *
       6              :   * \ingroup xt1121Ctrl_files
       7              :   */
       8              : 
       9              : #ifndef xt1121Ctrl_hpp
      10              : #define xt1121Ctrl_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              : #include "xtChannels.hpp"
      17              : 
      18              : namespace MagAOX
      19              : {
      20              : namespace app
      21              : {
      22              : 
      23              : 
      24              : /** \defgroup xt1121Ctrl Acromag xt1121Controller
      25              :   * \brief Control of an Acromag xt1121digital I/O module
      26              :   *
      27              :   * <a href="../handbook/operating/software/apps/xt1121Ctrl.html">Application Documentation</a>
      28              :   *
      29              :   * \ingroup apps
      30              :   *
      31              :   */
      32              : 
      33              : /** \defgroup xt1121Ctrl_files Acromag xt1121Controller Files
      34              :   * \ingroup xt1121Ctrl
      35              :   */
      36              : 
      37              : /** MagAO-X application to control an Acromag xt1121digital i/o module
      38              :   *
      39              :   * \ingroup xt1121Ctrl
      40              :   *
      41              :   */
      42              : class xt1121Ctrl : public MagAOXApp<>, public xt1121Channels
      43              : {
      44              : 
      45              : protected:
      46              : 
      47              :    /** \name configurable parameters
      48              :      *@{
      49              :      */
      50              : 
      51              :    std::string m_address; ///< The I.P. address of the device
      52              : 
      53              :    uint16_t m_port {502}; ///< The port to use.  Default is 502 for modbus.
      54              : 
      55              :    ///@}
      56              : 
      57              :    modbus * m_mb {nullptr}; ///< The modbus protocol communication object
      58              : 
      59              : public:
      60              : 
      61              :    ///Default c'tor
      62              :    xt1121Ctrl();
      63              : 
      64              :    ///Destructor
      65              :    ~xt1121Ctrl() noexcept;
      66              : 
      67              :    /// Setup the configuration system (called by MagAOXApp::setup())
      68              :    virtual void setupConfig();
      69              : 
      70              :    /// load the configuration system results (called by MagAOXApp::setup())
      71              :    virtual void loadConfig();
      72              : 
      73              :    /// Startup functions
      74              :    /** Sets up the INDI vars.
      75              :      *
      76              :      */
      77              :    virtual int appStartup();
      78              : 
      79              :    /// Implementation of the FSM for the Siglent SDG
      80              :    virtual int appLogic();
      81              : 
      82              :    /// Implementation of the on-power-off FSM logic
      83              :    virtual int onPowerOff();
      84              : 
      85              :    /// Implementation of the while-powered-off FSM
      86              :    virtual int whilePowerOff();
      87              : 
      88              :    /// Do any needed shutdown tasks.  Currently nothing in this app.
      89              :    virtual int appShutdown();
      90              : 
      91              :    /// Get the current state of the outlets.
      92              :    /**
      93              :      * \returns 0 on success
      94              :      * \returns -1 on error
      95              :      */
      96              :    int getState();
      97              : 
      98              :    //INDI:
      99              : protected:
     100              :    //declare our properties
     101              :    pcf::IndiProperty m_indiP_ch00;
     102              :    pcf::IndiProperty m_indiP_ch01;
     103              :    pcf::IndiProperty m_indiP_ch02;
     104              :    pcf::IndiProperty m_indiP_ch03;
     105              :    pcf::IndiProperty m_indiP_ch04;
     106              :    pcf::IndiProperty m_indiP_ch05;
     107              :    pcf::IndiProperty m_indiP_ch06;
     108              :    pcf::IndiProperty m_indiP_ch07;
     109              :    pcf::IndiProperty m_indiP_ch08;
     110              :    pcf::IndiProperty m_indiP_ch09;
     111              :    pcf::IndiProperty m_indiP_ch10;
     112              :    pcf::IndiProperty m_indiP_ch11;
     113              :    pcf::IndiProperty m_indiP_ch12;
     114              :    pcf::IndiProperty m_indiP_ch13;
     115              :    pcf::IndiProperty m_indiP_ch14;
     116              :    pcf::IndiProperty m_indiP_ch15;
     117              : 
     118              : public:
     119              : 
     120              :    /// Callback worker to actually set or clear a channel and send it to the device
     121              :    /** Contains the target/current logic, and calls the xtChannels::setRegisters
     122              :      * function, and then the modbus write_registers.
     123              :      *
     124              :      * \returns 0 on success
     125              :      * \returns -1 on error
     126              :      */
     127              :    int channelSetCallback( size_t chNo,                     ///< [in] The channel number to set
     128              :                            pcf::IndiProperty & ipToSet,     ///< [in] The corresponding local INDI property
     129              :                            const pcf::IndiProperty & ipRecv ///< [in] The received INDI property
     130              :                          );
     131              : 
     132            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch00);
     133            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch01);
     134            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch02);
     135            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch03);
     136            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch04);
     137            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch05);
     138            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch06);
     139            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch07);
     140            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch08);
     141            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch09);
     142            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch10);
     143            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch11);
     144            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch12);
     145            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch13);
     146            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch14);
     147            0 :    INDI_NEWCALLBACK_DECL(xt1121Ctrl, m_indiP_ch15);
     148              : };
     149              : 
     150              : inline
     151              : xt1121Ctrl::xt1121Ctrl() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     152              : {
     153              :    m_powerMgtEnabled = true;
     154              :    m_powerOnWait = 2; //set default.
     155              :    return;
     156              : }
     157              : 
     158              : inline
     159            0 : xt1121Ctrl::~xt1121Ctrl() noexcept
     160              : {
     161            0 :    if(m_mb)
     162              :    {
     163            0 :       delete m_mb;
     164              :    };
     165              : 
     166            0 :    return;
     167            0 : }
     168              : 
     169              : inline
     170            0 : void xt1121Ctrl::setupConfig()
     171              : {
     172            0 :    config.add("device.address", "", "device.address", argType::Required, "device", "address", true, "string", "The device I.P. address.");
     173            0 :    config.add("device.port", "", "device.port", argType::Required, "device", "port", true, "int", "The device port.  Default is 502.");
     174              :    //config.add("device.powerOnWait", "", "device.powerOnWait", argType::Required, "device", "powerOnWait", false, "int", "Time after power-on to begin attempting connections [sec].  Default is 2 sec.");
     175            0 :    config.add("device.inputOnly", "", "device.inputOnly", argType::Required, "device", "inputOnly", false, "vector<int>", "List of channels which are input-only.");
     176              : 
     177            0 : }
     178              : 
     179              : 
     180              : ///\todo mxlib loadConfig needs to return int to propagate errors!
     181              : 
     182              : inline
     183            0 : void xt1121Ctrl::loadConfig()
     184              : {
     185            0 :    config(m_address, "device.address");
     186            0 :    config(m_port, "device.port");
     187              : 
     188            0 :    std::vector<int> ino;
     189            0 :    config(ino, "device.inputOnly");
     190              : 
     191            0 :    for(size_t i=0; i< ino.size();++i)
     192              :    {
     193            0 :       if(setInputOnly(ino[i]) != 0)
     194              :       {
     195            0 :          log<text_log>("Error setting channel " + std::to_string(i) + " to input only.", logPrio::LOG_ERROR);
     196              :       }
     197              :    }
     198            0 : }
     199              : 
     200              : 
     201              : 
     202              : inline
     203            0 : int xt1121Ctrl::appStartup()
     204              : {
     205              :    // set up the  INDI properties
     206            0 :    REG_INDI_NEWPROP(m_indiP_ch00, "ch00", pcf::IndiProperty::Number);
     207            0 :    m_indiP_ch00.add (pcf::IndiElement("current"));
     208            0 :    m_indiP_ch00["current"].set(-1);
     209            0 :    m_indiP_ch00.add (pcf::IndiElement("target"));
     210              : 
     211            0 :    REG_INDI_NEWPROP(m_indiP_ch01, "ch01", pcf::IndiProperty::Number);
     212            0 :    m_indiP_ch01.add (pcf::IndiElement("current"));
     213            0 :    m_indiP_ch01["current"].set(-1);
     214            0 :    m_indiP_ch01.add (pcf::IndiElement("target"));
     215              : 
     216            0 :    REG_INDI_NEWPROP(m_indiP_ch02, "ch02", pcf::IndiProperty::Number);
     217            0 :    m_indiP_ch02.add (pcf::IndiElement("current"));
     218            0 :    m_indiP_ch02["current"].set(-1);
     219            0 :    m_indiP_ch02.add (pcf::IndiElement("target"));
     220              : 
     221            0 :    REG_INDI_NEWPROP(m_indiP_ch03, "ch03", pcf::IndiProperty::Number);
     222            0 :    m_indiP_ch03.add (pcf::IndiElement("current"));
     223            0 :    m_indiP_ch03["current"].set(-1);
     224            0 :    m_indiP_ch03.add (pcf::IndiElement("target"));
     225              : 
     226            0 :    REG_INDI_NEWPROP(m_indiP_ch04, "ch04", pcf::IndiProperty::Number);
     227            0 :    m_indiP_ch04.add (pcf::IndiElement("current"));
     228            0 :    m_indiP_ch04["current"].set(-1);
     229            0 :    m_indiP_ch04.add (pcf::IndiElement("target"));
     230              : 
     231            0 :    REG_INDI_NEWPROP(m_indiP_ch05, "ch05", pcf::IndiProperty::Number);
     232            0 :    m_indiP_ch05.add (pcf::IndiElement("current"));
     233            0 :    m_indiP_ch05["current"].set(-1);
     234            0 :    m_indiP_ch05.add (pcf::IndiElement("target"));
     235              : 
     236            0 :    REG_INDI_NEWPROP(m_indiP_ch06, "ch06", pcf::IndiProperty::Number);
     237            0 :    m_indiP_ch06.add (pcf::IndiElement("current"));
     238            0 :    m_indiP_ch06["current"].set(-1);
     239            0 :    m_indiP_ch06.add (pcf::IndiElement("target"));
     240              : 
     241            0 :    REG_INDI_NEWPROP(m_indiP_ch07, "ch07", pcf::IndiProperty::Number);
     242            0 :    m_indiP_ch07.add (pcf::IndiElement("current"));
     243            0 :    m_indiP_ch07["current"].set(-1);
     244            0 :    m_indiP_ch07.add (pcf::IndiElement("target"));
     245              : 
     246            0 :    REG_INDI_NEWPROP(m_indiP_ch08, "ch08", pcf::IndiProperty::Number);
     247            0 :    m_indiP_ch08.add (pcf::IndiElement("current"));
     248            0 :    m_indiP_ch08["current"].set(-1);
     249            0 :    m_indiP_ch08.add (pcf::IndiElement("target"));
     250              : 
     251            0 :    REG_INDI_NEWPROP(m_indiP_ch09, "ch09", pcf::IndiProperty::Number);
     252            0 :    m_indiP_ch09.add (pcf::IndiElement("current"));
     253            0 :    m_indiP_ch09["current"].set(-1);
     254            0 :    m_indiP_ch09.add (pcf::IndiElement("target"));
     255              : 
     256            0 :    REG_INDI_NEWPROP(m_indiP_ch10, "ch10", pcf::IndiProperty::Number);
     257            0 :    m_indiP_ch10.add (pcf::IndiElement("current"));
     258            0 :    m_indiP_ch10["current"].set(-1);
     259            0 :    m_indiP_ch10.add (pcf::IndiElement("target"));
     260              : 
     261            0 :    REG_INDI_NEWPROP(m_indiP_ch11, "ch11", pcf::IndiProperty::Number);
     262            0 :    m_indiP_ch11.add (pcf::IndiElement("current"));
     263            0 :    m_indiP_ch11["current"].set(-1);
     264            0 :    m_indiP_ch11.add (pcf::IndiElement("target"));
     265              : 
     266            0 :    REG_INDI_NEWPROP(m_indiP_ch12, "ch12", pcf::IndiProperty::Number);
     267            0 :    m_indiP_ch12.add (pcf::IndiElement("current"));
     268            0 :    m_indiP_ch12["current"].set(-1);
     269            0 :    m_indiP_ch12.add (pcf::IndiElement("target"));
     270              : 
     271            0 :    REG_INDI_NEWPROP(m_indiP_ch13, "ch13", pcf::IndiProperty::Number);
     272            0 :    m_indiP_ch13.add (pcf::IndiElement("current"));
     273            0 :    m_indiP_ch13["current"].set(-1);
     274            0 :    m_indiP_ch13.add (pcf::IndiElement("target"));
     275              : 
     276            0 :    REG_INDI_NEWPROP(m_indiP_ch14, "ch14", pcf::IndiProperty::Number);
     277            0 :    m_indiP_ch14.add (pcf::IndiElement("current"));
     278            0 :    m_indiP_ch14["current"].set(-1);
     279            0 :    m_indiP_ch14.add (pcf::IndiElement("target"));
     280              : 
     281            0 :    REG_INDI_NEWPROP(m_indiP_ch15, "ch15", pcf::IndiProperty::Number);
     282            0 :    m_indiP_ch15.add (pcf::IndiElement("current"));
     283            0 :    m_indiP_ch15["current"].set(-1);
     284            0 :    m_indiP_ch15.add (pcf::IndiElement("target"));
     285              : 
     286              : 
     287            0 :    return 0;
     288              : 
     289              : }
     290              : 
     291              : 
     292              : 
     293              : inline
     294            0 : int xt1121Ctrl::appLogic()
     295              : {
     296            0 :    if( state() == stateCodes::POWERON )
     297              :    {
     298            0 :       if(!powerOnWaitElapsed())
     299              :       {
     300            0 :         return 0;
     301              :       }
     302              : 
     303            0 :       state(stateCodes::NOTCONNECTED);
     304              :    }
     305              : 
     306            0 :    if( state() == stateCodes::NOTCONNECTED || state() == stateCodes::ERROR)
     307              :    {
     308            0 :       std::string response;
     309              : 
     310              :       //Might have gotten here because of a power off.
     311            0 :       if(m_powerState == 0) return 0;
     312              : 
     313            0 :       m_mb = new(std::nothrow) modbus(m_address, m_port);
     314              : 
     315            0 :       if(m_mb == nullptr)
     316              :       {
     317            0 :          return log<software_critical, -1>({__FILE__, __LINE__, "allocation failure"});
     318              :       }
     319              : 
     320            0 :       m_mb->modbus_set_slave_id(1);
     321              : 
     322            0 :       if( m_mb->modbus_connect() == false)
     323              :       {
     324            0 :          if(!stateLogged())
     325              :          {
     326            0 :             log<text_log>("connect failed at " + m_address + ":" + std::to_string(m_port));
     327              :          }
     328            0 :          delete m_mb;
     329            0 :          m_mb = nullptr;
     330            0 :          return 0;
     331              :       }
     332              : 
     333            0 :       state(stateCodes::CONNECTED);
     334            0 :       log<text_log>("connected to " + m_address + ":" + std::to_string(m_port));
     335            0 :    }
     336              : 
     337            0 :    if( state() == stateCodes::CONNECTED )
     338              :    {
     339              :       //Get a lock
     340            0 :       std::unique_lock<std::mutex> lock(m_indiMutex);
     341              : 
     342            0 :       if( getState() == 0 )
     343              :       {
     344            0 :          state(stateCodes::READY);
     345            0 :          return 0;
     346              :       }
     347              :       else
     348              :       {
     349            0 :          state(stateCodes::ERROR);
     350            0 :          return log<software_error,0>({__FILE__,__LINE__});
     351              :       }
     352            0 :    }
     353              : 
     354            0 :    if( state() == stateCodes::READY || state() == stateCodes::OPERATING )
     355              :    {
     356              :       //Get a lock if we can
     357            0 :       std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
     358              : 
     359              :       //but don't wait for it, just go back around.
     360            0 :       if(!lock.owns_lock()) return 0;
     361              : 
     362            0 :       if(getState() < 0)
     363              :       {
     364            0 :          if(m_powerState == 0) return 0;
     365              : 
     366            0 :          state(stateCodes::ERROR);
     367            0 :          return 0;
     368              :       }
     369              : 
     370            0 :      return 0;
     371            0 :    }
     372              : 
     373              :    //Fall through check?
     374              : 
     375            0 :    return 0;
     376              : 
     377              : }
     378              : 
     379              : inline
     380            0 : int xt1121Ctrl::onPowerOff()
     381              : {
     382            0 :    std::lock_guard<std::mutex> lock(m_indiMutex);
     383              : 
     384            0 :    updateIfChanged(m_indiP_ch00, "current", -1);
     385            0 :    updateIfChanged(m_indiP_ch00, "target", -1);
     386              : 
     387            0 :    updateIfChanged(m_indiP_ch01, "current", -1);
     388            0 :    updateIfChanged(m_indiP_ch01, "target", -1);
     389              : 
     390            0 :    updateIfChanged(m_indiP_ch02, "current", -1);
     391            0 :    updateIfChanged(m_indiP_ch02, "target", -1);
     392              : 
     393            0 :    updateIfChanged(m_indiP_ch03, "current", -1);
     394            0 :    updateIfChanged(m_indiP_ch03, "target", -1);
     395              : 
     396            0 :    updateIfChanged(m_indiP_ch04, "current", -1);
     397            0 :    updateIfChanged(m_indiP_ch04, "target", -1);
     398              : 
     399            0 :    updateIfChanged(m_indiP_ch05, "current", -1);
     400            0 :    updateIfChanged(m_indiP_ch05, "target", -1);
     401              : 
     402            0 :    updateIfChanged(m_indiP_ch06, "current", -1);
     403            0 :    updateIfChanged(m_indiP_ch06, "target", -1);
     404              : 
     405            0 :    updateIfChanged(m_indiP_ch07, "current", -1);
     406            0 :    updateIfChanged(m_indiP_ch07, "target", -1);
     407              : 
     408            0 :    updateIfChanged(m_indiP_ch08, "current", -1);
     409            0 :    updateIfChanged(m_indiP_ch08, "target", -1);
     410              : 
     411            0 :    updateIfChanged(m_indiP_ch09, "current", -1);
     412            0 :    updateIfChanged(m_indiP_ch09, "target", -1);
     413              : 
     414            0 :    updateIfChanged(m_indiP_ch10, "current", -1);
     415            0 :    updateIfChanged(m_indiP_ch10, "target", -1);
     416              : 
     417            0 :    updateIfChanged(m_indiP_ch11, "current", -1);
     418            0 :    updateIfChanged(m_indiP_ch11, "target", -1);
     419              : 
     420            0 :    updateIfChanged(m_indiP_ch12, "current", -1);
     421            0 :    updateIfChanged(m_indiP_ch12, "target", -1);
     422              : 
     423            0 :    updateIfChanged(m_indiP_ch13, "current", -1);
     424            0 :    updateIfChanged(m_indiP_ch13, "target", -1);
     425              : 
     426            0 :    updateIfChanged(m_indiP_ch14, "current", -1);
     427            0 :    updateIfChanged(m_indiP_ch14, "target", -1);
     428              : 
     429            0 :    updateIfChanged(m_indiP_ch15, "current", -1);
     430            0 :    updateIfChanged(m_indiP_ch15, "target", -1);
     431              : 
     432              : 
     433            0 :    return 0;
     434            0 : }
     435              : 
     436              : inline
     437            0 : int xt1121Ctrl::whilePowerOff()
     438              : {
     439            0 :    return 0;
     440              : }
     441              : 
     442              : inline
     443            0 : int xt1121Ctrl::appShutdown()
     444              : {
     445            0 :    if(m_mb) m_mb->modbus_close();
     446            0 :    return 0;
     447              : }
     448              : 
     449              : 
     450              : 
     451              : inline
     452            0 : int xt1121Ctrl::getState()
     453              : {
     454              :    uint16_t input_regs[numRegisters];
     455              : 
     456              :    try
     457              :    {
     458              :       ///\todo this hangs if power goes off during call
     459            0 :       m_mb->modbus_read_input_registers(0,numRegisters,input_regs);
     460              :    }
     461            0 :    catch(std::exception & e)
     462              :    {
     463            0 :       if(m_powerState == 0) return 0; //due to power off
     464              : 
     465            0 :       return log<software_error,-1>({__FILE__, __LINE__, std::string("Exception caught: ") + e.what()});
     466            0 :    }
     467              : 
     468            0 :    if( readRegisters(input_regs) !=0 )
     469              :    {
     470            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     471              :    }
     472              : 
     473            0 :    updateIfChanged(m_indiP_ch00, "current", channel(0));
     474            0 :    updateIfChanged(m_indiP_ch01, "current", channel(1));
     475            0 :    updateIfChanged(m_indiP_ch02, "current", channel(2));
     476            0 :    updateIfChanged(m_indiP_ch03, "current", channel(3));
     477            0 :    updateIfChanged(m_indiP_ch04, "current", channel(4));
     478            0 :    updateIfChanged(m_indiP_ch05, "current", channel(5));
     479            0 :    updateIfChanged(m_indiP_ch06, "current", channel(6));
     480            0 :    updateIfChanged(m_indiP_ch07, "current", channel(7));
     481            0 :    updateIfChanged(m_indiP_ch08, "current", channel(8));
     482            0 :    updateIfChanged(m_indiP_ch09, "current", channel(9));
     483            0 :    updateIfChanged(m_indiP_ch10, "current", channel(10));
     484            0 :    updateIfChanged(m_indiP_ch11, "current", channel(11));
     485            0 :    updateIfChanged(m_indiP_ch12, "current", channel(12));
     486            0 :    updateIfChanged(m_indiP_ch13, "current", channel(13));
     487            0 :    updateIfChanged(m_indiP_ch14, "current", channel(14));
     488            0 :    updateIfChanged(m_indiP_ch15, "current", channel(15));
     489              : 
     490            0 :    return 0;
     491              : 
     492              : 
     493              : }
     494              : 
     495              : 
     496            0 : int xt1121Ctrl::channelSetCallback( size_t chNo,
     497              :                                     pcf::IndiProperty & ipToSet,
     498              :                                     const pcf::IndiProperty & ipRecv
     499              :                                   )
     500              : {
     501            0 :    int current = -1, target = -1;
     502              : 
     503            0 :    if(ipRecv.find("current"))
     504              :    {
     505            0 :       current = ipRecv["current"].get<unsigned>();
     506              :    }
     507              : 
     508            0 :    if(ipRecv.find("target"))
     509              :    {
     510            0 :       target = ipRecv["target"].get<unsigned>();
     511              :    }
     512              : 
     513            0 :    if(target == -1) target = current;
     514              : 
     515            0 :    if(target < 0) return 0;
     516              : 
     517              :    //Lock the mutex, waiting if necessary
     518            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     519              : 
     520            0 :    if(target == 0) clearChannel(chNo);
     521            0 :    else setChannel(chNo);
     522              : 
     523            0 :    target = channel(chNo); //This checks for inputOnly
     524              : 
     525            0 :    updateIfChanged(ipToSet, "target", target);
     526              : 
     527              :    uint16_t input_regs[numRegisters];
     528              : 
     529            0 :    if( setRegisters(input_regs) !=0 )
     530              :    {
     531            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     532              :    }
     533              : 
     534              :    try
     535              :    {
     536            0 :       m_mb->modbus_write_registers(0,numRegisters,input_regs);
     537              :    }
     538            0 :    catch(std::exception & e)
     539              :    {
     540            0 :       if(m_powerState == 0) return 0; //due to power off
     541              : 
     542            0 :       return log<software_error,-1>({__FILE__, __LINE__, std::string("Exception caught: ") + e.what()});
     543            0 :    }
     544              : 
     545              : 
     546            0 :    log<text_log>("Set channel " + std::to_string(chNo) + " to " + std::to_string(target));
     547              : 
     548            0 :    return 0;
     549              : 
     550            0 : }
     551              : 
     552            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch00)(const pcf::IndiProperty &ipRecv)
     553              : {
     554            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch00, ipRecv);
     555              : 
     556            0 :     return channelSetCallback(0, m_indiP_ch00, ipRecv);
     557              : 
     558              :     return -1;
     559              : }
     560              : 
     561            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch01)(const pcf::IndiProperty &ipRecv)
     562              : {
     563            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch01, ipRecv);
     564              : 
     565            0 :     return channelSetCallback(1, m_indiP_ch01, ipRecv);
     566              : 
     567              :     return -1;
     568              : }
     569              : 
     570            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch02)(const pcf::IndiProperty &ipRecv)
     571              : {
     572            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch02, ipRecv);
     573              : 
     574            0 :     return channelSetCallback(2, m_indiP_ch02, ipRecv);
     575              : 
     576              :     return -1;
     577              : }
     578              : 
     579            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch03)(const pcf::IndiProperty &ipRecv)
     580              : {
     581            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch03, ipRecv);
     582              : 
     583            0 :     return channelSetCallback(3, m_indiP_ch03, ipRecv);
     584              : 
     585              :     return -1;
     586              : }
     587              : 
     588            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch04)(const pcf::IndiProperty &ipRecv)
     589              : {
     590            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch04, ipRecv);
     591              : 
     592            0 :     return channelSetCallback(4, m_indiP_ch04, ipRecv);
     593              : 
     594              :     return -1;
     595              : }
     596              : 
     597            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch05)(const pcf::IndiProperty &ipRecv)
     598              : {
     599            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch05, ipRecv);
     600              : 
     601            0 :     return channelSetCallback(5, m_indiP_ch05, ipRecv);
     602              : 
     603              :     return -1;
     604              : }
     605              : 
     606            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch06)(const pcf::IndiProperty &ipRecv)
     607              : {
     608            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch06, ipRecv);
     609              : 
     610            0 :     return channelSetCallback(6, m_indiP_ch06, ipRecv);
     611              : 
     612              :     return -1;
     613              : }
     614              : 
     615            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch07)(const pcf::IndiProperty &ipRecv)
     616              : {
     617            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch07, ipRecv);
     618              : 
     619            0 :     return channelSetCallback(7, m_indiP_ch07, ipRecv);
     620              : 
     621              :     return -1;
     622              : }
     623              : 
     624            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch08)(const pcf::IndiProperty &ipRecv)
     625              : {
     626            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch08, ipRecv);
     627              : 
     628            0 :     return channelSetCallback(8, m_indiP_ch08, ipRecv);
     629              : 
     630              :     return -1;
     631              : }
     632              : 
     633            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch09)(const pcf::IndiProperty &ipRecv)
     634              : {
     635            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch09, ipRecv);
     636              : 
     637            0 :     return channelSetCallback(9, m_indiP_ch09, ipRecv);
     638              : 
     639              :     return -1;
     640              : }
     641              : 
     642            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch10)(const pcf::IndiProperty &ipRecv)
     643              : {
     644            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch10, ipRecv);
     645              : 
     646            0 :     return channelSetCallback(10, m_indiP_ch10, ipRecv);
     647              : 
     648              :     return -1;
     649              : }
     650              : 
     651            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch11)(const pcf::IndiProperty &ipRecv)
     652              : {
     653            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch11, ipRecv);
     654              : 
     655            0 :     return channelSetCallback(11, m_indiP_ch11, ipRecv);
     656              : 
     657              :     return -1;
     658              : }
     659              : 
     660            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch12)(const pcf::IndiProperty &ipRecv)
     661              : {
     662            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch12, ipRecv);
     663              : 
     664            0 :     return channelSetCallback(12, m_indiP_ch12, ipRecv);
     665              : 
     666              :     return -1;
     667              : }
     668              : 
     669            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch13)(const pcf::IndiProperty &ipRecv)
     670              : {
     671            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch13, ipRecv);
     672              : 
     673            0 :     return channelSetCallback(13, m_indiP_ch13, ipRecv);
     674              : 
     675              :     return -1;
     676              : }
     677              : 
     678            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch14)(const pcf::IndiProperty &ipRecv)
     679              : {
     680            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch14, ipRecv);
     681              : 
     682            0 :     return channelSetCallback(14, m_indiP_ch14, ipRecv);
     683              : 
     684              :     return -1;
     685              : }
     686              : 
     687            0 : INDI_NEWCALLBACK_DEFN(xt1121Ctrl, m_indiP_ch15)(const pcf::IndiProperty &ipRecv)
     688              : {
     689            0 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_ch15, ipRecv);
     690              : 
     691            0 :     return channelSetCallback(15, m_indiP_ch15, ipRecv);
     692              : 
     693              :     return -1;
     694              : }
     695              : 
     696              : 
     697              : }//namespace app
     698              : } //namespace MagAOX
     699              : #endif
        

Generated by: LCOV version 2.0-1