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

            Line data    Source code
       1              : /** \file koolanceCtrl.hpp
       2              :   * \brief The MagAO-X Koolance Controller header file
       3              :   *
       4              :   * \ingroup koolanceCtrl_files
       5              :   */
       6              : 
       7              : #ifndef koolanceCtrl_hpp
       8              : #define koolanceCtrl_hpp
       9              : 
      10              : 
      11              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      12              : #include "../../magaox_git_version.h"
      13              : 
      14              : /** \defgroup koolanceCtrl
      15              :   * \brief The MagAO-X application to monitor and control a Koolance cooler
      16              :   *
      17              :   * <a href="../handbook/operating/software/apps/koolanceCtrl.html">Application Documentation</a>
      18              :   *
      19              :   * \ingroup apps
      20              :   *
      21              :   */
      22              : 
      23              : /** \defgroup koolanceCtrl_files
      24              :   * \ingroup koolanceCtrl
      25              :   */
      26              : 
      27              : namespace MagAOX
      28              : {
      29              : namespace app
      30              : {
      31              : 
      32              : /// The MagAO-X Koolance Controller
      33              : /** This application will monitor a Koolance v1 or v2 protocol controller.  If v2, will also allow
      34              :   * changing of pump and fan settings via INDI.
      35              :   *
      36              :   * \ingroup koolanceCtrl
      37              :   */
      38              : class koolanceCtrl : public MagAOXApp<true>, public tty::usbDevice, public dev::telemeter<koolanceCtrl>
      39              : {
      40              : 
      41              :    //Give the test harness access.
      42              :    friend class koolanceCtrl_test;
      43              : 
      44              :    friend class dev::telemeter<koolanceCtrl>;
      45              : protected:
      46              : 
      47              :    /** \name Configurable Parameters
      48              :      *@{
      49              :      */
      50              : 
      51              :    //here add parameters which will be config-able at runtime
      52              : 
      53              :    ///@}
      54              : 
      55              :    size_t m_protocolChars {0}; ///< Will be set to 43 if protocol 1, and set to 51 if protocol 2.
      56              : 
      57              :    bool m_indiSetup {false}; ///< Whether or not INDI has been set up after initial protocol determination.
      58              : 
      59              :    float m_liqTemp {0}; ///< The liquid temperature
      60              :    float m_flowRate {0}; ///< The flow rate
      61              :    int m_pumpLvl {0}; ///< The pump power level, 1-10
      62              :    int m_pumpRPM {0}; ///< The pump RPM
      63              :    int m_fanRPM {0}; ///< The fan RPM
      64              :    int m_fanLvl {0}; ///< The fan power level, 0-100
      65              : 
      66              : 
      67              : 
      68              : public:
      69              :    /// Default c'tor.
      70              :    koolanceCtrl();
      71              : 
      72              :    /// D'tor, declared and defined for noexcept.
      73            0 :    ~koolanceCtrl() noexcept
      74            0 :    {}
      75              : 
      76              :    virtual void setupConfig();
      77              : 
      78              :    /// Implementation of loadConfig logic, separated for testing.
      79              :    /** This is called by loadConfig().
      80              :      */
      81              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
      82              : 
      83              :    virtual void loadConfig();
      84              : 
      85              :    /// Startup function
      86              :    /**
      87              :      *
      88              :      */
      89              :    virtual int appStartup();
      90              : 
      91              :    /// Implementation of the FSM for koolanceCtrl.
      92              :    /**
      93              :      * \returns 0 on no critical error
      94              :      * \returns -1 on an error requiring shutdown
      95              :      */
      96              :    virtual int appLogic();
      97              : 
      98              :    /// Shutdown the app.
      99              :    /**
     100              :      *
     101              :      */
     102              :    virtual int appShutdown();
     103              : 
     104              :    /// Initial connection to controller
     105              :    /** Determine protocol in use based on number of characters in response
     106              :      * and sets up INDI appropriately.
     107              :      *
     108              :      * Calls to this function should be mutexed.
     109              :      *
     110              :      * \returns 0 on success
     111              :      * \returns -1 on an error
     112              :      */
     113              :    int initialConnect();
     114              : 
     115              :    /// Get status from controller and updated INDI.
     116              :    /**
     117              :      *
     118              :      * Calls to this function should be mutexed.
     119              :      *
     120              :      * \returns 0 on success
     121              :      * \returns -1 on an error
     122              :      */
     123              :    int getStatus();
     124              : 
     125              :    /// Set the pump level
     126              :    /**
     127              :      * Calls to this function should be mutexed.
     128              :      *
     129              :      * \returns 0 on success
     130              :      * \returns -1 on an error
     131              :      */
     132              :    int setPumpLvl(int lvl /**< [in] the new level */);
     133              : 
     134              :    /// Set the fan level
     135              :    /**
     136              :      * Calls to this function should be mutexed.
     137              :      *
     138              :      * \returns 0 on success
     139              :      * \returns -1 on an error
     140              :      */
     141              :    int setFanLvl(int lvl /**< [in] the new level */);
     142              : 
     143              :    /** \name INDI
     144              :      *
     145              :      *@{
     146              :      */
     147              : protected:
     148              :    //declare our properties
     149              :    pcf::IndiProperty m_indiP_status;
     150              :    pcf::IndiProperty m_indiP_pumplvl;
     151              :    pcf::IndiProperty m_indiP_fanlvl;
     152              : 
     153              : public:
     154            0 :    INDI_NEWCALLBACK_DECL(koolanceCtrl, m_indiP_pumplvl);
     155            0 :    INDI_NEWCALLBACK_DECL(koolanceCtrl, m_indiP_fanlvl);
     156              : 
     157              :    ///@}
     158              : 
     159              :    /** \name Telemeter Interface
     160              :      *
     161              :      * @{
     162              :      */
     163              :    int checkRecordTimes();
     164              : 
     165              :    int recordTelem( const telem_cooler * );
     166              : 
     167              :    int recordCooler(bool force = false);
     168              : 
     169              :    ///@}
     170              : 
     171              : 
     172              : };
     173              : 
     174            0 : koolanceCtrl::koolanceCtrl() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     175              : {
     176            0 :    return;
     177            0 : }
     178              : 
     179            0 : void koolanceCtrl::setupConfig()
     180              : {
     181            0 :    tty::usbDevice::setupConfig(config);
     182              : 
     183            0 :    dev::telemeter<koolanceCtrl>::setupConfig(config);
     184              : 
     185            0 : }
     186              : 
     187            0 : int koolanceCtrl::loadConfigImpl( mx::app::appConfigurator & _config )
     188              : {
     189            0 :    this->m_baudRate = B9600; //default for a Koolance controller.  Will be overridden by any config setting.
     190              : 
     191            0 :    int rv = tty::usbDevice::loadConfig(_config);
     192              : 
     193            0 :    if(rv != 0 && rv != TTY_E_NODEVNAMES && rv != TTY_E_DEVNOTFOUND) //Ignore error if not plugged in
     194              :    {
     195            0 :       log<software_error>( {__FILE__, __LINE__, rv, tty::ttyErrorString(rv)});
     196              :    }
     197              : 
     198            0 :    return 0;
     199              : }
     200              : 
     201            0 : void koolanceCtrl::loadConfig()
     202              : {
     203            0 :    loadConfigImpl(config);
     204              : 
     205            0 :    dev::telemeter<koolanceCtrl>::loadConfig(config);
     206            0 : }
     207              : 
     208            0 : int koolanceCtrl::appStartup()
     209              : {
     210            0 :    if( state() == stateCodes::UNINITIALIZED )
     211              :    {
     212            0 :       log<text_log>( "In appStartup but in state UNINITIALIZED.", logPrio::LOG_CRITICAL );
     213            0 :       return -1;
     214              :    }
     215              : 
     216              :    // set up the  INDI properties
     217            0 :    REG_INDI_NEWPROP_NOCB(m_indiP_status, "status", pcf::IndiProperty::Number);
     218            0 :    m_indiP_status.add(pcf::IndiElement("liquid_temp"));
     219            0 :    m_indiP_status.add(pcf::IndiElement("flow_rate"));
     220            0 :    m_indiP_status.add(pcf::IndiElement("pump_rpm"));
     221            0 :    m_indiP_status.add(pcf::IndiElement("fan_rpm"));
     222              : 
     223            0 :    if(dev::telemeter<koolanceCtrl>::appStartup() < 0)
     224              :    {
     225            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     226              :    }
     227              : 
     228            0 :    state(stateCodes::NODEVICE);
     229            0 :    return 0;
     230              : }
     231              : 
     232            0 : int koolanceCtrl::appLogic()
     233              : {
     234              : 
     235            0 :    if( state() == stateCodes::NODEVICE )
     236              :    {
     237            0 :       int rv = tty::usbDevice::getDeviceName();
     238            0 :       if(rv < 0 && rv != TTY_E_DEVNOTFOUND && rv != TTY_E_NODEVNAMES)
     239              :       {
     240            0 :          state(stateCodes::FAILURE);
     241            0 :          if(!stateLogged())
     242              :          {
     243            0 :             log<software_critical>({__FILE__, __LINE__, rv, tty::ttyErrorString(rv)});
     244              :          }
     245            0 :          return -1;
     246              :       }
     247              : 
     248            0 :       if(rv == TTY_E_DEVNOTFOUND || rv == TTY_E_NODEVNAMES)
     249              :       {
     250            0 :          state(stateCodes::NODEVICE);
     251              : 
     252            0 :          if(!stateLogged())
     253              :          {
     254            0 :             std::stringstream logs;
     255            0 :             logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " not found in udev";
     256            0 :             log<text_log>(logs.str());
     257            0 :          }
     258            0 :          return 0;
     259              :       }
     260              :       else
     261              :       {
     262            0 :          std::stringstream logs;
     263            0 :          logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " found in udev as " << m_deviceName;
     264            0 :          log<text_log>(logs.str());
     265              : 
     266            0 :          state(stateCodes::NOTCONNECTED);
     267            0 :       }
     268              :    }
     269              : 
     270            0 :    if( state() == stateCodes::NOTCONNECTED )
     271              :    {
     272            0 :       int rv = 0;
     273              :       {
     274            0 :          elevatedPrivileges ep(this);
     275            0 :          rv = connect();
     276            0 :       }
     277              : 
     278            0 :       if(rv < 0)
     279              :       {
     280            0 :          int nrv = tty::usbDevice::getDeviceName();
     281            0 :          if(nrv < 0 && nrv != TTY_E_DEVNOTFOUND && nrv != TTY_E_NODEVNAMES)
     282              :          {
     283            0 :             state(stateCodes::FAILURE);
     284            0 :             if(!stateLogged()) log<software_critical>({__FILE__, __LINE__, nrv, tty::ttyErrorString(nrv)});
     285            0 :             return -1;
     286              :          }
     287              : 
     288            0 :          if(nrv == TTY_E_DEVNOTFOUND || nrv == TTY_E_NODEVNAMES)
     289              :          {
     290            0 :             state(stateCodes::NODEVICE);
     291              : 
     292            0 :             if(!stateLogged())
     293              :             {
     294            0 :                std::stringstream logs;
     295            0 :                logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " no longer found in udev";
     296            0 :                log<text_log>(logs.str());
     297            0 :             }
     298            0 :             return 0;
     299              :          }
     300              : 
     301              :          //if connect failed, and there is a device, then we have some other problem.
     302            0 :          sleep(1); //wait to see if power state updates
     303            0 :          if(m_powerState == 0) return 0;
     304              : 
     305              :          //Ok we can't figure this out, die.
     306            0 :          state(stateCodes::FAILURE);
     307            0 :          if(!stateLogged()) log<software_error>({__FILE__,__LINE__,rv, tty::ttyErrorString(rv)});
     308            0 :          return -1;
     309              : 
     310              :       }
     311              :       else
     312              :       {
     313            0 :          std::unique_lock<std::mutex> lock(m_indiMutex);
     314            0 :          if(initialConnect () == 0)
     315              :          {
     316            0 :             state(stateCodes::CONNECTED);
     317              :          }
     318              :          else
     319              :          {
     320            0 :             if(!stateLogged())
     321              :             {
     322            0 :                log<text_log>("no response from device");
     323              :             }
     324            0 :             return 0;
     325              :          }
     326            0 :       }
     327              : 
     328            0 :       if(state() == stateCodes::CONNECTED)
     329              :       {
     330            0 :          std::stringstream logs;
     331            0 :          logs << "Connected to koolance system on " << m_deviceName;
     332            0 :          log<text_log>(logs.str());
     333            0 :          state(stateCodes::READY);
     334            0 :          return 0;
     335            0 :       }
     336              : 
     337              :    }
     338              : 
     339            0 :    if( state() == stateCodes::READY )
     340              :    {
     341              :       { //mutex scope
     342            0 :          std::unique_lock<std::mutex> lock(m_indiMutex);
     343            0 :          if(getStatus() < 0)
     344              :          {
     345            0 :             log<software_error>({__FILE__,__LINE__});
     346              :          }
     347            0 :       }
     348              : 
     349            0 :       if(telemeter<koolanceCtrl>::appLogic() < 0)
     350              :       {
     351            0 :          log<software_error>({__FILE__, __LINE__});
     352            0 :          return 0;
     353              :       }
     354            0 :       return 0;
     355              :    }
     356              : 
     357            0 :    return 0;
     358              : }
     359              : 
     360            0 : int koolanceCtrl::appShutdown()
     361              : {
     362            0 :    dev::telemeter<koolanceCtrl>::appShutdown();
     363            0 :    return 0;
     364              : }
     365              : 
     366              : 
     367              : 
     368            0 : int koolanceCtrl::initialConnect()
     369              : {
     370              :    int rv;
     371              : 
     372            0 :    std::vector<unsigned char> com;
     373            0 :    com.resize(3, '\0');
     374            0 :    com[0] = 0xCF;
     375            0 :    com[1] = 0x01;
     376            0 :    com[2] = 0x08;
     377              : 
     378            0 :    rv = write(m_fileDescrip, com.data(), com.size());
     379              : 
     380            0 :    if(rv < 0)
     381              :    {
     382            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from write"});
     383            0 :       ::close(m_fileDescrip);
     384            0 :       m_fileDescrip = 0;
     385            0 :       state(stateCodes::NOTCONNECTED);
     386              : 
     387            0 :       return -1;
     388              :    }
     389              : 
     390            0 :    std::vector<unsigned char> resp;
     391            0 :    resp.resize(51);
     392              : 
     393            0 :    mx::sys::milliSleep(1000); //Sleep for a long time to make sure device responds
     394              :    int readBytes;
     395            0 :    rv = tty::ttyReadRaw(resp, readBytes, m_fileDescrip, 1000); ///\todo needs to be iodevice
     396              : 
     397            0 :    if(rv < 0)
     398              :    {
     399            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from read"});
     400            0 :       ::close(m_fileDescrip);
     401            0 :       m_fileDescrip = 0;
     402            0 :       state(stateCodes::NOTCONNECTED);
     403              : 
     404            0 :       return -1;
     405              :    }
     406              : 
     407            0 :    if(readBytes == 43)
     408              :    {
     409            0 :       log<text_log>("found protocol 1 device");
     410            0 :       m_protocolChars = 43;
     411              :    }
     412            0 :    else if(readBytes == 51)
     413              :    {
     414            0 :       log<text_log>("found protocol 2 device");
     415            0 :       m_protocolChars = 51;
     416              :    }
     417              :    else
     418              :    {
     419            0 :       return -1;
     420              :    }
     421              : 
     422            0 :    if(!m_indiSetup)
     423              :    {
     424            0 :       if(readBytes == 43)
     425              :       {
     426            0 :           REG_INDI_NEWPROP_NOCB(m_indiP_pumplvl, "pump_level", pcf::IndiProperty::Number);
     427            0 :           m_indiP_pumplvl.add(pcf::IndiElement("current"));
     428              : 
     429            0 :           REG_INDI_NEWPROP_NOCB(m_indiP_fanlvl, "fan_level", pcf::IndiProperty::Number);
     430            0 :           m_indiP_fanlvl.add(pcf::IndiElement("current"));
     431              :       }
     432              :       else
     433              :       {
     434            0 :          createStandardIndiNumber<int>( m_indiP_pumplvl, "pump_level", 1, 10, 1, "%d", "Pump Level", "Lab");
     435            0 :          registerIndiPropertyNew( m_indiP_pumplvl, INDI_NEWCALLBACK(m_indiP_pumplvl));
     436              : 
     437            0 :          createStandardIndiNumber<int>( m_indiP_fanlvl, "fan_level", 0, 100, 1, "%d", "Fan Level", "Lab");
     438            0 :          registerIndiPropertyNew( m_indiP_fanlvl, INDI_NEWCALLBACK(m_indiP_fanlvl));
     439              :       }
     440              : 
     441            0 :       m_indiSetup = true;
     442              :    }
     443              : 
     444            0 :    return 0;
     445            0 : }
     446              : 
     447            0 : int koolanceCtrl::getStatus()
     448              : {
     449              :    int rv;
     450              : 
     451            0 :    std::vector<unsigned char> com;
     452            0 :    com.resize(3, '\0');
     453            0 :    com[0] = 0xCF;
     454            0 :    com[1] = 0x01;
     455            0 :    com[2] = 0x08;
     456              : 
     457            0 :    rv = write(m_fileDescrip, com.data(), com.size());
     458              : 
     459            0 :    if(rv < 0)
     460              :    {
     461            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from write"});
     462            0 :       ::close(m_fileDescrip);
     463            0 :       m_fileDescrip = 0;
     464            0 :       state(stateCodes::NOTCONNECTED);
     465              : 
     466            0 :       return -1;
     467              :    }
     468              : 
     469            0 :    std::string resp;
     470              : 
     471            0 :    rv = tty::ttyRead(resp, m_protocolChars, m_fileDescrip, 1000); ///\todo needs to be iodevice
     472              : 
     473            0 :    if(rv < 0)
     474              :    {
     475            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from read"});
     476            0 :       ::close(m_fileDescrip);
     477            0 :       m_fileDescrip = 0;
     478            0 :       state(stateCodes::NOTCONNECTED);
     479              : 
     480            0 :       return -1;
     481              :    }
     482              : 
     483            0 :    if(resp.size() == m_protocolChars)
     484              :    {
     485            0 :       m_liqTemp = ((float) (( (unsigned char)resp[2] << 8) + (unsigned char)resp[3]-2000)) / 10.0;
     486            0 :       m_flowRate = ( (float) ((unsigned char)resp[12] << 8) + (unsigned char)resp[13])  / 10.0;
     487            0 :       m_fanRPM = ((unsigned char)resp[8] << 8) + (unsigned char)resp[9];
     488            0 :       m_pumpRPM = ((unsigned char)resp[10] << 8) + (unsigned char)resp[11];
     489            0 :       m_fanLvl = (unsigned char)resp[15];
     490            0 :       m_pumpLvl = (unsigned char)resp[17];
     491              : 
     492            0 :       recordCooler();
     493              : //       std::cout << std::dec;
     494              : //       std::cout << "liq. temp: " << m_liqTemp << " C\n";
     495              : //       std::cout << "flow rate: " << m_flowRate << " LPM\n";
     496              : //       std::cout << "pump lvl:  " << m_pumpLvl << "\n";
     497              : //       std::cout << "pump speed:" << m_pumpRPM << " RPM\n";
     498              : //       std::cout << "fan lvl:  " << m_fanLvl << "\n";
     499              : //       std::cout << "fan speed:" << m_fanRPM << " RPM\n";
     500              : 
     501            0 :       updateIfChanged(m_indiP_status, "liquid_temp", m_liqTemp);
     502            0 :       updateIfChanged(m_indiP_status, "flow_rate", m_flowRate);
     503            0 :       updateIfChanged(m_indiP_status, "pump_rpm", m_pumpRPM);
     504            0 :       updateIfChanged(m_indiP_status, "fan_rpm", m_fanRPM);
     505            0 :       updateIfChanged(m_indiP_pumplvl, "current", m_pumpLvl);
     506            0 :       updateIfChanged(m_indiP_fanlvl, "current", m_fanLvl);
     507              : 
     508            0 :       return 0;
     509              :    }
     510              :    else
     511              :    {
     512            0 :       log<software_error>({__FILE__,__LINE__, std::string("wrong response size (") + std::to_string(resp.size()) + ") returned"});
     513            0 :       ::close(m_fileDescrip);
     514            0 :       m_fileDescrip = 0;
     515            0 :       state(stateCodes::NOTCONNECTED);
     516              : 
     517            0 :       return -1;
     518              :    }
     519            0 : }
     520              : 
     521            0 : int koolanceCtrl::setPumpLvl( int lvl )
     522              : {
     523            0 :    if(m_protocolChars == 43) return 0;
     524              : 
     525              :    int rv;
     526              : 
     527            0 :    std::vector<unsigned char> com;
     528            0 :    com.resize(m_protocolChars, '\0');
     529            0 :    com[0] = 0xCF;
     530            0 :    com[1] = 0x04;
     531              : 
     532            0 :    com[15] = m_fanLvl;
     533            0 :    com[17] = lvl;
     534              : 
     535              :    //Disable most stuff.
     536            0 :    for(size_t n = 20; n <m_protocolChars-1; ++n) com[n] = 0xAA;
     537              : 
     538              :    //Preserve units
     539            0 :    if(m_protocolChars > 43)
     540              :    {
     541            0 :       com[44] = 0;
     542            0 :       com[45] = 0x0001;
     543            0 :       com[46] = 0;
     544            0 :       com[47] = 0;
     545            0 :       com[48] = 0;
     546            0 :       com[49] = 0;
     547              :    }
     548              : 
     549            0 :    int checksum = 0;
     550            0 :    for(size_t n = 0; n <m_protocolChars-1; ++n) checksum += com[n];
     551            0 :    com[m_protocolChars-1] = checksum % 0x64;
     552              : 
     553            0 :    rv = write(m_fileDescrip, com.data(), com.size());
     554              : 
     555            0 :    if(rv < 0)
     556              :    {
     557            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from write"});
     558            0 :       ::close(m_fileDescrip);
     559            0 :       m_fileDescrip = 0;
     560            0 :       state(stateCodes::NOTCONNECTED);
     561              : 
     562            0 :       return -1;
     563              :    }
     564              : 
     565            0 :    log<text_log>("set pump level to " + std::to_string(lvl));
     566              : 
     567            0 :    return 0;
     568            0 : }
     569              : 
     570            0 : int koolanceCtrl::setFanLvl( int lvl )
     571              : {
     572            0 :    if(m_protocolChars == 43) return 0;
     573              : 
     574              :    int rv;
     575              : 
     576            0 :    std::vector<unsigned char> com;
     577            0 :    com.resize(m_protocolChars, '\0');
     578            0 :    com[0] = 0xCF;
     579            0 :    com[1] = 0x04;
     580              : 
     581            0 :    com[15] = lvl;
     582            0 :    com[17] = m_pumpLvl;
     583              : 
     584              :    //Disable most stuff.
     585            0 :    for(size_t n = 20; n <m_protocolChars-1; ++n) com[n] = 0xAA;
     586              : 
     587              :    //Preserve units
     588            0 :    if(m_protocolChars > 43)
     589              :    {
     590            0 :       com[44] = 0;
     591            0 :       com[45] = 0x0001;
     592            0 :       com[46] = 0;
     593            0 :       com[47] = 0;
     594            0 :       com[48] = 0;
     595            0 :       com[49] = 0;
     596              :    }
     597              : 
     598            0 :    int checksum = 0;
     599            0 :    for(size_t n = 0; n <m_protocolChars-1; ++n) checksum += com[n];
     600            0 :    com[m_protocolChars-1] = checksum % 0x64;
     601              : 
     602            0 :    rv = write(m_fileDescrip, com.data(), com.size());
     603              : 
     604            0 :    if(rv < 0)
     605              :    {
     606            0 :       log<software_error>({__FILE__,__LINE__, errno, "error from write"});
     607            0 :       ::close(m_fileDescrip);
     608            0 :       m_fileDescrip = 0;
     609            0 :       state(stateCodes::NOTCONNECTED);
     610              : 
     611            0 :       return -1;
     612              :    }
     613              : 
     614            0 :    log<text_log>("set fan level to " + std::to_string(lvl));
     615              : 
     616            0 :    return 0;
     617            0 : }
     618              : 
     619            0 : INDI_NEWCALLBACK_DEFN(koolanceCtrl, m_indiP_pumplvl)(const pcf::IndiProperty &ipRecv)
     620              : {
     621            0 :    if(ipRecv.getName() != m_indiP_pumplvl.getName())
     622              :    {
     623            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
     624            0 :       return -1;
     625              :    }
     626              : 
     627            0 :    int lvl = -1;
     628              : 
     629            0 :    if( ipRecv.find("current") )
     630              :    {
     631            0 :       lvl = ipRecv["current"].get<int>();
     632              :    }
     633              : 
     634            0 :    if( ipRecv.find("target") )
     635              :    {
     636            0 :       lvl = ipRecv["target"].get<int>();
     637              :    }
     638              : 
     639            0 :    if(lvl < 1 || lvl > 10)
     640              :    {
     641            0 :       log<software_error>({__FILE__,__LINE__, "Pump level out of range"});
     642            0 :       return 0;
     643              :    }
     644              : 
     645            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     646            0 :    updateIfChanged(m_indiP_pumplvl, "target", lvl);
     647            0 :    return setPumpLvl(lvl);
     648              : 
     649              : 
     650            0 : }
     651              : 
     652            0 : INDI_NEWCALLBACK_DEFN(koolanceCtrl, m_indiP_fanlvl)(const pcf::IndiProperty &ipRecv)
     653              : {
     654            0 :    if(ipRecv.getName() != m_indiP_fanlvl.getName())
     655              :    {
     656            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
     657            0 :       return -1;
     658              :    }
     659              : 
     660              : 
     661            0 :    int lvl = -1;
     662              : 
     663            0 :    if( ipRecv.find("current") )
     664              :    {
     665            0 :       lvl = ipRecv["current"].get<int>();
     666              :    }
     667              : 
     668            0 :    if( ipRecv.find("target") )
     669              :    {
     670            0 :       lvl = ipRecv["target"].get<int>();
     671              :    }
     672              : 
     673            0 :    if(lvl < 0 || lvl > 100)
     674              :    {
     675            0 :       log<software_error>({__FILE__,__LINE__, "Fan level out of range"});
     676            0 :       return 0;
     677              :    }
     678              : 
     679            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     680            0 :    updateIfChanged(m_indiP_fanlvl, "target", lvl);
     681            0 :    return setFanLvl(lvl);
     682              : 
     683              :    return 0;
     684            0 : }
     685              : 
     686              : inline
     687            0 : int koolanceCtrl::checkRecordTimes()
     688              : {
     689            0 :    return telemeter<koolanceCtrl>::checkRecordTimes(telem_cooler());
     690              : }
     691              : 
     692              : inline
     693            0 : int koolanceCtrl::recordTelem( const telem_cooler * )
     694              : {
     695            0 :    return recordCooler(true);
     696              : }
     697              : 
     698              : inline
     699            0 : int koolanceCtrl::recordCooler( bool force )
     700              : {
     701              :    static float last_liqTemp = std::numeric_limits<float>::max();
     702              :    static float last_flowRate = std::numeric_limits<float>::max();
     703              :    static int last_pumpLvl = std::numeric_limits<int>::max();
     704              :    static int last_pumpRPM = std::numeric_limits<int>::max();
     705              :    static int last_fanRPM = std::numeric_limits<int>::max();
     706              :    static int last_fanLvl = std::numeric_limits<int>::max();
     707              : 
     708            0 :    if( m_liqTemp != last_liqTemp || m_flowRate != last_flowRate || m_pumpLvl != last_pumpLvl ||
     709            0 :           m_pumpRPM != last_pumpRPM || m_fanRPM != last_fanRPM || m_fanLvl != last_fanLvl || force )
     710              :    {
     711            0 :       telem<telem_cooler>({m_liqTemp, m_flowRate, (uint8_t) m_pumpLvl, (uint16_t) m_pumpRPM, (uint8_t) m_fanLvl, (uint16_t) m_fanRPM});
     712              : 
     713            0 :       last_liqTemp = m_liqTemp;
     714            0 :       last_flowRate = m_flowRate;
     715            0 :       last_pumpLvl = m_pumpLvl;
     716            0 :       last_pumpRPM = m_pumpRPM;
     717            0 :       last_fanLvl = m_fanLvl;
     718            0 :       last_fanRPM = m_fanRPM;
     719              :    }
     720              : 
     721            0 :    return 0;
     722              : }
     723              : 
     724              : } //namespace app
     725              : } //namespace MagAOX
     726              : 
     727              : #endif //koolanceCtrl_hpp
        

Generated by: LCOV version 2.0-1