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

            Line data    Source code
       1              : /** \file indiTSAccumulator.hpp
       2              :   * \brief The MagAO-X indiTSAccumulator header file
       3              :   *
       4              :   * \ingroup indiTSAccumulator_files
       5              :   */
       6              : 
       7              : #ifndef indiTSAccumulator_hpp
       8              : #define indiTSAccumulator_hpp
       9              : 
      10              : #include <map>
      11              : 
      12              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      13              : #include "../../magaox_git_version.h"
      14              : 
      15              : /** \defgroup indiTSAccumulator
      16              :   * \brief The indiTSAccumulator application to do YYYYYYY
      17              :   *
      18              :   * <a href="../handbook/operating/software/apps/indiTSAccumulator.html">Application Documentation</a>
      19              :   *
      20              :   * \ingroup apps
      21              :   *
      22              :   */
      23              : 
      24              : /** \defgroup indiTSAccumulator_files
      25              :   * \ingroup indiTSAccumulator
      26              :   */
      27              : 
      28              : namespace MagAOX
      29              : {
      30              : namespace app
      31              : {
      32              : 
      33              : /// The MagAO-X indiTSAccumulator
      34              : /** An application to accumulate a time-series from an INDI element.
      35              :   *
      36              :   * \ingroup indiTSAccumulator
      37              :   */
      38              : class indiTSAccumulator : public MagAOXApp<true>
      39              : {
      40              : 
      41              :    //Give the test harness access.
      42              :    friend class indiTSAccumulator_test;
      43              : 
      44              : protected:
      45              : 
      46              :    /** \name Configurable Parameters
      47              :      *@{
      48              :      */
      49              : 
      50              :    int m_maxEntries {36000};
      51              : 
      52              :    ///@}
      53              : 
      54              :    struct element
      55              :    {
      56              :       std::string m_name;
      57              : 
      58              :       timespec m_lastUpdate {0,0};
      59              : 
      60              :       IMAGE * m_imageStream {nullptr};
      61              : 
      62            0 :       explicit element(const std::string & el) : m_name{el}
      63            0 :       {}
      64              :    };
      65              : 
      66              :    struct property
      67              :    {
      68              :       pcf::IndiProperty m_property;
      69              :       std::vector<element> m_elements;
      70              :    };
      71              : 
      72              :    std::map<std::string, property> m_properties;
      73              : 
      74              : 
      75            0 :    static int st_setCallBack_all( void * app, const pcf::IndiProperty &ipRecv)
      76              :    {
      77            0 :       return static_cast<indiTSAccumulator *>(app)->setCallBack_all(ipRecv);
      78              :    }
      79              : 
      80              : 
      81              : 
      82              : public:
      83              :    /// Default c'tor.
      84              :    indiTSAccumulator();
      85              : 
      86              :    /// D'tor, declared and defined for noexcept.
      87            0 :    ~indiTSAccumulator() noexcept
      88            0 :    {}
      89              : 
      90              :    virtual void setupConfig();
      91              : 
      92              :    /// Implementation of loadConfig logic, separated for testing.
      93              :    /** This is called by loadConfig().
      94              :      */
      95              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
      96              : 
      97              :    virtual void loadConfig();
      98              : 
      99              :    /// Startup function
     100              :    /**
     101              :      *
     102              :      */
     103              :    virtual int appStartup();
     104              : 
     105              :    /// Implementation of the FSM for indiTSAccumulator.
     106              :    /**
     107              :      * \returns 0 on no critical error
     108              :      * \returns -1 on an error requiring shutdown
     109              :      */
     110              :    virtual int appLogic();
     111              : 
     112              :    /// Shutdown the app.
     113              :    /**
     114              :      *
     115              :      */
     116              :    virtual int appShutdown();
     117              : 
     118              : pcf::IndiProperty prop;
     119              :    int setCallBack_all( const pcf::IndiProperty &ipRecv );
     120              : 
     121              : };
     122              : 
     123            0 : indiTSAccumulator::indiTSAccumulator() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     124              : {
     125              : 
     126            0 :    return;
     127            0 : }
     128              : 
     129            0 : void indiTSAccumulator::setupConfig()
     130              : {
     131            0 :    config.add("elements", "", "elements", argType::Required, "", "elements", false, "vector<string>", "Comma separated List of elements specified as device.property.element.");
     132            0 : }
     133              : 
     134            0 : int indiTSAccumulator::loadConfigImpl( mx::app::appConfigurator & _config )
     135              : {
     136            0 :    std::vector<std::string> elements;
     137            0 :    _config(elements, "elements");
     138              : 
     139            0 :    if(elements.size() < 1)
     140              :    {
     141            0 :       log<text_log>("no elements specified", logPrio::LOG_CRITICAL);
     142            0 :       m_shutdown = true;
     143            0 :       return -1;
     144              :    }
     145              : 
     146            0 :    for(size_t n = 0; n < elements.size(); ++n)
     147              :    {
     148            0 :       size_t p1 = elements[n].find('.');
     149            0 :       if(p1 == std::string::npos)
     150              :       {
     151            0 :          log<text_log>("error parsing " + elements[n] + ": no . found", logPrio::LOG_CRITICAL);
     152            0 :          m_shutdown = true;
     153            0 :          return -1;
     154              :       }
     155            0 :       size_t p2 = elements[n].find('.', p1+1);
     156            0 :       if(p2 == std::string::npos)
     157              :       {
     158            0 :          log<text_log>("error parsing " + elements[n] + ": second . not found", logPrio::LOG_CRITICAL);
     159            0 :          m_shutdown = true;
     160            0 :          return -1;
     161              :       }
     162              : 
     163              :       try
     164              :       {
     165            0 :          std::string devName = elements[n].substr(0,p1);
     166            0 :          std::string propName = elements[n].substr(p1+1, p2-p1-1);
     167            0 :          std::string elName = elements[n].substr(p2+1);
     168            0 :          std::string key = devName + "." + propName;
     169              : 
     170            0 :          m_properties[key].m_property.setDevice(devName);
     171            0 :          m_properties[key].m_property.setName(propName);
     172            0 :          m_properties[key].m_elements.push_back(element(elName));
     173            0 :       }
     174            0 :       catch(const std::exception& e)
     175              :       {
     176            0 :          log<software_critical>({__FILE__, __LINE__, std::string("Exception caught: ") + e.what() + " [on element " + std::to_string(n) + "]"});
     177            0 :          m_shutdown = true;
     178            0 :          return -1;
     179            0 :       }
     180              :    }
     181              : 
     182            0 :    return 0;
     183            0 : }
     184              : 
     185            0 : void indiTSAccumulator::loadConfig()
     186              : {
     187            0 :    loadConfigImpl(config);
     188            0 : }
     189              : 
     190            0 : int indiTSAccumulator::appStartup()
     191              : {
     192            0 :    for(auto it = m_properties.begin(); it != m_properties.end(); ++it)
     193              :    {
     194              :       //Have to make these pass-by-const-referencable
     195            0 :       std::string devName = it->second.m_property.getDevice();
     196            0 :       std::string propName = it->second.m_property.getName();
     197            0 :       if( registerIndiPropertySet( it->second.m_property, devName, propName, st_setCallBack_all) < 0 )
     198              :       {
     199            0 :          log<software_critical>({__FILE__, __LINE__, "Error inserting property: " + devName + "." + propName});
     200            0 :          return -1;
     201              :       }
     202              : 
     203            0 :       for(size_t n=0; n < it->second.m_elements.size(); ++n)
     204              :       {
     205            0 :          it->second.m_elements[n].m_imageStream = (IMAGE *) malloc(sizeof(IMAGE));
     206              : 
     207            0 :          uint32_t imsize[3] = {0,0,0};
     208            0 :          imsize[0] = 1;
     209            0 :          imsize[1] = 1;
     210            0 :          imsize[2] = m_maxEntries;
     211            0 :          std::string shmimName = devName + "." + propName + "." + it->second.m_elements[n].m_name;
     212              : 
     213            0 :          std::cerr << "Creating: " << shmimName << " " << imsize[0] << " " << imsize[1] << " " << imsize[2] << "\n";
     214              : 
     215            0 :          ImageStreamIO_createIm_gpu(it->second.m_elements[n].m_imageStream, shmimName.c_str(), 3, imsize, IMAGESTRUCT_FLOAT, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
     216              : 
     217            0 :          it->second.m_elements[n].m_imageStream->md->cnt1 = it->second.m_elements[n].m_imageStream->md->size[2] - 1;
     218              : 
     219            0 :          it->second.m_elements[n].m_imageStream->md->atime = {0,0};
     220            0 :          it->second.m_elements[n].m_imageStream->md->writetime = {0,0};
     221              : 
     222            0 :          for(size_t m = 0; m < it->second.m_elements[n].m_imageStream->md->size[2]; ++m )
     223              :          {
     224            0 :             it->second.m_elements[n].m_imageStream->cntarray[m] = std::numeric_limits<uint64_t>::max();
     225            0 :             it->second.m_elements[n].m_imageStream->atimearray[m] = {0,0};
     226            0 :             it->second.m_elements[n].m_imageStream->writetimearray[m] = {0,0};
     227              :          }
     228            0 :       }
     229            0 :    }
     230              : 
     231            0 :    return 0;
     232              : }
     233              : 
     234            0 : int indiTSAccumulator::appLogic()
     235              : {
     236            0 :    return 0;
     237              : }
     238              : 
     239            0 : int indiTSAccumulator::appShutdown()
     240              : {
     241            0 :    return 0;
     242              : }
     243              : 
     244            0 : int indiTSAccumulator::setCallBack_all( const pcf::IndiProperty &ipRecv )
     245              : {
     246            0 :    std::string key = ipRecv.createUniqueKey();
     247            0 :    if(m_properties.count(key) > 0)
     248              :    {
     249            0 :       if(ipRecv.getType() != pcf::IndiProperty::Number)
     250              :       {
     251            0 :          log<text_log>(key + " is not a Number property.  Can't time-series this.", logPrio::LOG_WARNING);
     252            0 :          return -1; //only numbers are supported for now.
     253              :       }
     254              : 
     255              :       //Now look for this property's elements
     256            0 :       for(size_t n=0; n < m_properties[key].m_elements.size(); ++n)
     257              :       {
     258            0 :          if(!ipRecv.find( m_properties[key].m_elements[n].m_name)) continue;
     259              : 
     260            0 :          IMAGE * image = m_properties[key].m_elements[n].m_imageStream;
     261              : 
     262            0 :          if(image == nullptr)
     263              :          {
     264            0 :             log<software_error>({__FILE__, __LINE__, "Image for " + key + "." + m_properties[key].m_elements[n].m_name + " is nullptr"});
     265            0 :             continue;
     266              :          }
     267              : 
     268              :          timespec ts;
     269            0 :          ts.tv_sec = ipRecv.getTimeStamp().getTimeValSecs();
     270            0 :          ts.tv_nsec = ipRecv.getTimeStamp().getTimeValMicros()*1000;
     271              : 
     272            0 :          if(ts.tv_sec != image->md->atime.tv_sec || ts.tv_nsec != image->md->atime.tv_nsec)
     273              :          {
     274              :             //Get the value as a float
     275            0 :             float val = ipRecv[ m_properties[key].m_elements[n].m_name].get<float>();
     276              : 
     277              :             //Get cnt1 and rollover if needed
     278            0 :             uint64_t cnt1 = image->md->cnt1 + 1;
     279            0 :             if(cnt1 >= image->md->size[2]) cnt1 = 0;
     280              : 
     281              :             //Set the writing flag
     282            0 :             image->md->write=1;
     283              : 
     284              :             //Set the times
     285            0 :             clock_gettime(CLOCK_REALTIME, &image->md->writetime);
     286            0 :             image->writetimearray[cnt1] = image->md->writetime;
     287              : 
     288            0 :             image->md->atime = ts;
     289            0 :             image->atimearray[cnt1] = ts;
     290              : 
     291              :             //Set the value
     292            0 :             image->array.F[cnt1] = val;
     293              : 
     294              :             //Now update counters
     295            0 :             image->md->cnt0++;
     296            0 :             image->cntarray[cnt1] = image->md->cnt0;
     297            0 :             image->md->cnt1 = cnt1;
     298              : 
     299              :             //And post
     300            0 :             image->md->write=0;
     301            0 :             ImageStreamIO_sempost(image,-1);
     302            0 :             std::cerr << ipRecv.createUniqueKey() << " " << ts.tv_sec << " " << ts.tv_nsec << "\n";
     303              :          }
     304              :       }
     305              :    }
     306              : 
     307            0 :    return 0;
     308            0 : }
     309              : 
     310              : } //namespace app
     311              : } //namespace MagAOX
     312              : 
     313              : #endif //indiTSAccumulator_hpp
        

Generated by: LCOV version 2.0-1