LCOV - code coverage report
Current view: top level - mscb/include - mscbxx.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 160 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 14 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         mscbxx.h
       4              :   Created by:   Stefan Ritt
       5              : 
       6              :   Contents:     Implementation of MSCB++ API
       7              : 
       8              : \********************************************************************/
       9              : 
      10              : /****
      11              : 
      12              : Usage of MSCB++ Example:
      13              : 
      14              :    #include <mscbxx.h>
      15              : 
      16              :    // connect to node 10 at submaster mscb123
      17              :    midas::mscb m("mscb123", 10);
      18              : 
      19              :    // print node info and all variables
      20              :    std::cout << m << std::endl;
      21              : 
      22              :    // refresh all variables
      23              :    m.read_range();
      24              :    std::cout << m[5] << std::endl;      // index access
      25              :    std::cout << m["In0"] << std::endl;  // name access
      26              : 
      27              :    // write value to MSCB
      28              :    m[5] = 1.234;
      29              : 
      30              :    // get index of a variable
      31              :    int i = m.idx("In0");
      32              : 
      33              :  ****/
      34              : #ifndef _MSCBXX_HXX
      35              : #define _MSCBXX_HXX
      36              : 
      37              : #include <string>
      38              : #include <stdexcept>
      39              : #include <iostream>
      40              : #include <iomanip>
      41              : #include <vector>
      42              : #include <map>
      43              : #include <string>
      44              : #include <cstring>
      45              : #include <cstdint>
      46              : #include <unordered_map>
      47              : 
      48              : #include "mscb.h"
      49              : #include "mexcept.h"
      50              : 
      51              : /*------------------------------------------------------------------*/
      52              : 
      53              : /**
      54              : MIDAS Data Type Definitions                             min      max    */
      55              : #define TID_BYTE      1       /**< DEPRECATED, use TID_UINT8 instead    */
      56              : #define TID_UINT8     1       /**< unsigned byte         0       255    */
      57              : #define TID_SBYTE     2       /**< DEPRECATED, use TID_INT8 instead     */
      58              : #define TID_INT8      2       /**< signed byte         -128      127    */
      59              : #define TID_CHAR      3       /**< single character      0       255    */
      60              : #define TID_WORD      4       /**< DEPRECATED, use TID_UINT16 instead   */
      61              : #define TID_UINT16    4       /**< two bytes             0      65535   */
      62              : #define TID_SHORT     5       /**< DEPRECATED, use TID_INT16 instead    */
      63              : #define TID_INT16     5       /**< signed word        -32768    32767   */
      64              : #define TID_DWORD     6       /**< DEPRECATED, use TID_UINT32 instead   */
      65              : #define TID_UINT32    6       /**< four bytes            0      2^32-1  */
      66              : #define TID_INT       7       /**< DEPRECATED, use TID_INT32 instead    */
      67              : #define TID_INT32     7       /**< signed dword        -2^31    2^31-1  */
      68              : #define TID_BOOL      8       /**< four bytes bool       0        1     */
      69              : #define TID_FLOAT     9       /**< 4 Byte float format                  */
      70              : #define TID_DOUBLE   10       /**< 8 Byte float format                  */
      71              : #define TID_STRING   12       /**< zero terminated string               */
      72              : 
      73              : /*------------------------------------------------------------------*/
      74              : 
      75              : namespace midas {
      76              : 
      77              :    class mscb;
      78              : 
      79              :    class u_mscb {
      80              :    private:
      81              :       // union to hold data
      82              :       union {
      83              :          uint8_t m_uint8;
      84              :          int8_t m_int8;
      85              :          uint16_t m_uint16;
      86              :          int16_t m_int16;
      87              :          uint32_t m_uint32;
      88              :          int32_t m_int32;
      89              :          uint64_t m_uint64;
      90              :          int64_t m_int64;
      91              :          bool m_bool;
      92              :          float m_float;
      93              :          double m_double;
      94              :          std::string *m_string;
      95              :          uint8_t m_data[8];
      96              :       };
      97              : 
      98              :       int m_tid;
      99              :       int m_size;
     100              :       int m_fd;
     101              :       int m_node_address;
     102              :       int m_var_index;
     103              : 
     104              :    public:
     105            0 :       u_mscb(int fd, int adr, int index, int tid, int size) :
     106            0 :          m_string{}, m_tid{tid}, m_size{size}, m_fd{fd},
     107            0 :          m_node_address{adr}, m_var_index{index} {};
     108              : 
     109              :       // Destructor
     110            0 :       ~u_mscb() {};
     111              : 
     112              :       // getters & setters
     113              :       int get_tid() { return m_tid; }
     114              : 
     115              :       // get value as certain type
     116              :       template<typename T>
     117              :       T get() {
     118              :          if (m_tid == TID_UINT8)
     119              :             return (T) m_uint8;
     120              :          else if (m_tid == TID_INT8)
     121              :             return (T) m_int8;
     122              :          else if (m_tid == TID_UINT16)
     123              :             return (T) m_uint16;
     124              :          else if (m_tid == TID_INT16)
     125              :             return (T) m_int16;
     126              :          else if (m_tid == TID_UINT32)
     127              :             return (T) m_uint32;
     128              :          else if (m_tid == TID_INT32)
     129              :             return (T) m_int32;
     130              :          else if (m_tid == TID_BOOL)
     131              :             return (T) m_bool;
     132              :          else if (m_tid == TID_FLOAT)
     133              :             return (T) m_float;
     134              :          else if (m_tid == TID_DOUBLE)
     135              :             return (T) m_double;
     136              :          else
     137              :             mthrow("Invalid type ID " + std::to_string(m_tid));
     138              :       }
     139              : 
     140              :       // get value as string
     141              :       void get(std::string &s) {
     142              :          if (m_tid == TID_UINT8)
     143              :             s = std::to_string(m_uint8);
     144              :          else if (m_tid == TID_INT8)
     145              :             s = std::to_string(m_int8);
     146              :          else if (m_tid == TID_UINT16)
     147              :             s = std::to_string(m_uint16);
     148              :          else if (m_tid == TID_INT16)
     149              :             s = std::to_string(m_int16);
     150              :          else if (m_tid == TID_UINT32)
     151              :             s = std::to_string(m_uint32);
     152              :          else if (m_tid == TID_INT32)
     153              :             s = std::to_string(m_int32);
     154              :          else if (m_tid == TID_BOOL)
     155              :             s = std::string(m_bool ? "true" : "false");
     156              :          else if (m_tid == TID_FLOAT)
     157              :             s = std::to_string(m_float);
     158              :          else if (m_tid == TID_DOUBLE)
     159              :             s = std::to_string(m_double);
     160              :          else if (m_tid == TID_STRING)
     161              :             s = *m_string;
     162              :          else
     163              :             mthrow("Invalid type ID " + std::to_string(m_tid));
     164              :       }
     165              : 
     166            0 :       void set_string(char* s) {
     167            0 :          if (m_string == nullptr)
     168            0 :             m_string = new std::string(s);
     169              :          else
     170            0 :             *m_string = s;
     171            0 :       }
     172              : 
     173            0 :       void set_data(const unsigned char *pdata) {
     174            0 :          std::memset(m_data, 0, sizeof(m_data));
     175            0 :          std::memcpy(m_data, pdata, m_size);
     176            0 :       }
     177              : 
     178              :       // write value to MSCB node
     179            0 :       int write(void) {
     180            0 :          if (m_tid == TID_STRING)
     181            0 :             mscb_write(m_fd, m_node_address, m_var_index, (void *)m_string->c_str(), m_size);
     182              :          else
     183            0 :             mscb_write(m_fd, m_node_address, m_var_index, &m_uint8, m_size);
     184            0 :          return 1;
     185              :       }
     186              : 
     187              :       // overload conversion operator
     188              :       template<typename T>
     189            0 :       operator T() {
     190            0 :          if (m_tid == TID_UINT8)
     191            0 :             return (T) m_uint8;
     192            0 :          else if (m_tid == TID_INT8)
     193            0 :             return (T) m_int8;
     194            0 :          else if (m_tid == TID_UINT16)
     195            0 :             return (T) m_uint16;
     196            0 :          else if (m_tid == TID_INT16)
     197            0 :             return (T) m_int16;
     198            0 :          else if (m_tid == TID_UINT32)
     199            0 :             return (T) m_uint32;
     200            0 :          else if (m_tid == TID_INT32)
     201            0 :             return (T) m_int32;
     202            0 :          else if (m_tid == TID_BOOL)
     203            0 :             return (T) m_bool;
     204            0 :          else if (m_tid == TID_FLOAT)
     205            0 :             return (T) m_float;
     206            0 :          else if (m_tid == TID_DOUBLE)
     207            0 :             return (T) m_double;
     208              :          else
     209            0 :             mthrow("Invalid type ID " + std::to_string(m_tid));
     210              :       }
     211              : 
     212              :       // string conversion operator
     213              :       operator std::string() {
     214              :          std::string s;
     215              :          get(s);
     216              :          return s;
     217              :       }
     218              : 
     219              :       // overload stream out operator
     220              :       friend std::ostream &operator<<(std::ostream &output, u_mscb &m) {
     221              :          std::string s = m;
     222              :          output << s;
     223              :          return output;
     224              :       };
     225              : 
     226              :       // Overload the Assignment Operators
     227              :       uint8_t operator=(uint8_t v) {
     228              :          if (m_tid == TID_UINT8)
     229              :             m_uint8 = (uint8_t)v;
     230              :          else if (m_tid == TID_INT8)
     231              :             m_int8 = (int8_t)v;
     232              :          else if (m_tid == TID_UINT16)
     233              :             m_uint16 = (uint16_t)v;
     234              :          else if (m_tid == TID_INT16)
     235              :             m_int16 = (int16_t)v;
     236              :          else if (m_tid == TID_UINT32)
     237              :             m_uint32 = (uint32_t)v;
     238              :          else if (m_tid == TID_INT32)
     239              :             m_int32 = (int32_t)v;
     240              :          else if (m_tid == TID_FLOAT)
     241              :             m_float = (float)v;
     242              :          else if (m_tid == TID_DOUBLE)
     243              :             m_double = (double)v;
     244              :          else if (m_tid == TID_BOOL)
     245              :             m_bool = (double)v;
     246              :          else
     247              :             mthrow("Invalid data type \"uint8_t\" for variable of type " + std::to_string(m_tid));
     248              :          write();
     249              :          return v;
     250              :       }
     251              :       int8_t operator=(int8_t v) {
     252              :          if (m_tid == TID_UINT8)
     253              :             m_uint8 = (uint8_t)v;
     254              :          else if (m_tid == TID_INT8)
     255              :             m_int8 = (int8_t)v;
     256              :          else if (m_tid == TID_UINT16)
     257              :             m_uint16 = (uint16_t)v;
     258              :          else if (m_tid == TID_INT16)
     259              :             m_int16 = (int16_t)v;
     260              :          else if (m_tid == TID_UINT32)
     261              :             m_uint32 = (uint32_t)v;
     262              :          else if (m_tid == TID_INT32)
     263              :             m_int32 = (int32_t)v;
     264              :          else if (m_tid == TID_FLOAT)
     265              :             m_float = (float)v;
     266              :          else if (m_tid == TID_DOUBLE)
     267              :             m_double = (double)v;
     268              :          else if (m_tid == TID_BOOL)
     269              :             m_bool = (double)v;
     270              :          else
     271              :             mthrow("Invalid data type \"int8_t\" for variable of type " + std::to_string(m_tid));
     272              :          write();
     273              :          return v;
     274              :       }
     275              :       uint16_t operator=(uint16_t v) {
     276              :          if (m_tid == TID_UINT8)
     277              :             m_uint8 = (uint8_t)v;
     278              :          else if (m_tid == TID_INT8)
     279              :             m_int8 = (int8_t)v;
     280              :          else if (m_tid == TID_UINT16)
     281              :             m_uint16 = (uint16_t)v;
     282              :          else if (m_tid == TID_INT16)
     283              :             m_int16 = (int16_t)v;
     284              :          else if (m_tid == TID_UINT32)
     285              :             m_uint32 = (uint32_t)v;
     286              :          else if (m_tid == TID_INT32)
     287              :             m_int32 = (int32_t)v;
     288              :          else if (m_tid == TID_FLOAT)
     289              :             m_float = (float)v;
     290              :          else if (m_tid == TID_DOUBLE)
     291              :             m_double = (double)v;
     292              :          else if (m_tid == TID_BOOL)
     293              :             m_bool = (double)v;
     294              :          else
     295              :             mthrow("Invalid data type \"uint16_t\" for variable of type " + std::to_string(m_tid));
     296              :          write();
     297              :          return v;
     298              :       }
     299              :       int16_t operator=(int16_t v) {
     300              :          if (m_tid == TID_UINT8)
     301              :             m_uint8 = (uint8_t)v;
     302              :          else if (m_tid == TID_INT8)
     303              :             m_int8 = (int8_t)v;
     304              :          else if (m_tid == TID_UINT16)
     305              :             m_uint16 = (uint16_t)v;
     306              :          else if (m_tid == TID_INT16)
     307              :             m_int16 = (int16_t)v;
     308              :          else if (m_tid == TID_UINT32)
     309              :             m_uint32 = (uint32_t)v;
     310              :          else if (m_tid == TID_INT32)
     311              :             m_int32 = (int32_t)v;
     312              :          else if (m_tid == TID_FLOAT)
     313              :             m_float = (float)v;
     314              :          else if (m_tid == TID_DOUBLE)
     315              :             m_double = (double)v;
     316              :          else if (m_tid == TID_BOOL)
     317              :             m_bool = (double)v;
     318              :          else
     319              :             mthrow("Invalid data type \"int16_t\" for variable of type " + std::to_string(m_tid));
     320              :          write();
     321              :          return v;
     322              :       }
     323              :       uint32_t operator=(uint32_t v) {
     324              :          if (m_tid == TID_UINT8)
     325              :             m_uint8 = (uint8_t)v;
     326              :          else if (m_tid == TID_INT8)
     327              :             m_int8 = (int8_t)v;
     328              :          else if (m_tid == TID_UINT16)
     329              :             m_uint16 = (uint16_t)v;
     330              :          else if (m_tid == TID_INT16)
     331              :             m_int16 = (int16_t)v;
     332              :          else if (m_tid == TID_UINT32)
     333              :             m_uint32 = (uint32_t)v;
     334              :          else if (m_tid == TID_INT32)
     335              :             m_int32 = (int32_t)v;
     336              :          else if (m_tid == TID_FLOAT)
     337              :             m_float = (float)v;
     338              :          else if (m_tid == TID_DOUBLE)
     339              :             m_double = (double)v;
     340              :          else if (m_tid == TID_BOOL)
     341              :             m_bool = (double)v;
     342              :          else
     343              :             mthrow("Invalid data type \"uint32_t\" for variable of type " + std::to_string(m_tid));
     344              :          write();
     345              :          return v;
     346              :       }
     347              :       int32_t operator=(int32_t v) {
     348              :          if (m_tid == TID_UINT8)
     349              :             m_uint8 = (uint8_t)v;
     350              :          else if (m_tid == TID_INT8)
     351              :             m_int8 = (int8_t)v;
     352              :          else if (m_tid == TID_UINT16)
     353              :             m_uint16 = (uint16_t)v;
     354              :          else if (m_tid == TID_INT16)
     355              :             m_int16 = (int16_t)v;
     356              :          else if (m_tid == TID_UINT32)
     357              :             m_uint32 = (uint32_t)v;
     358              :          else if (m_tid == TID_INT32)
     359              :             m_int32 = (int32_t)v;
     360              :          else if (m_tid == TID_FLOAT)
     361              :             m_float = (float)v;
     362              :          else if (m_tid == TID_DOUBLE)
     363              :             m_double = (double)v;
     364              :          else if (m_tid == TID_BOOL)
     365              :             m_bool = (double)v;
     366              :          else
     367              :             mthrow("Invalid data type \"int32_t\" for variable of type " + std::to_string(m_tid));
     368              :          write();
     369              :          return v;
     370              :       }
     371              :       bool operator=(bool v) {
     372              :          if (m_tid == TID_UINT8)
     373              :             m_uint8 = (uint8_t)v;
     374              :          else if (m_tid == TID_INT8)
     375              :             m_int8 = (int8_t)v;
     376              :          else if (m_tid == TID_UINT16)
     377              :             m_uint16 = (uint16_t)v;
     378              :          else if (m_tid == TID_INT16)
     379              :             m_int16 = (int16_t)v;
     380              :          else if (m_tid == TID_UINT32)
     381              :             m_uint32 = (uint32_t)v;
     382              :          else if (m_tid == TID_INT32)
     383              :             m_int32 = (int32_t)v;
     384              :          else if (m_tid == TID_FLOAT)
     385              :             m_float = (float)v;
     386              :          else if (m_tid == TID_DOUBLE)
     387              :             m_double = (double)v;
     388              :          else if (m_tid == TID_BOOL)
     389              :             m_bool = (double)v;
     390              :          else
     391              :             mthrow("Invalid data type \"bool\" for variable of type " + std::to_string(m_tid));
     392              :          write();
     393              :          return v;
     394              :       }
     395            0 :       float operator=(float v) {
     396            0 :          if (m_tid == TID_UINT8)
     397            0 :             m_uint8 = (uint8_t)v;
     398            0 :          else if (m_tid == TID_INT8)
     399            0 :             m_int8 = (int8_t)v;
     400            0 :          else if (m_tid == TID_UINT16)
     401            0 :             m_uint16 = (uint16_t)v;
     402            0 :          else if (m_tid == TID_INT16)
     403            0 :             m_int16 = (int16_t)v;
     404            0 :          else if (m_tid == TID_UINT32)
     405            0 :             m_uint32 = (uint32_t)v;
     406            0 :          else if (m_tid == TID_INT32)
     407            0 :             m_int32 = (int32_t)v;
     408            0 :          else if (m_tid == TID_FLOAT)
     409            0 :             m_float = (float)v;
     410            0 :          else if (m_tid == TID_DOUBLE)
     411            0 :             m_double = (double)v;
     412            0 :          else if (m_tid == TID_BOOL)
     413            0 :             m_bool = (double)v;
     414              :          else
     415            0 :             mthrow("Invalid data type \"float\" for variable of type " + std::to_string(m_tid));
     416            0 :          write();
     417            0 :          return v;
     418              :       }
     419              :       double operator=(double v) {
     420              :          if (m_tid == TID_UINT8)
     421              :             m_uint8 = (uint8_t)v;
     422              :          else if (m_tid == TID_INT8)
     423              :             m_int8 = (int8_t)v;
     424              :          else if (m_tid == TID_UINT16)
     425              :             m_uint16 = (uint16_t)v;
     426              :          else if (m_tid == TID_INT16)
     427              :             m_int16 = (int16_t)v;
     428              :          else if (m_tid == TID_UINT32)
     429              :             m_uint32 = (uint32_t)v;
     430              :          else if (m_tid == TID_INT32)
     431              :             m_int32 = (int32_t)v;
     432              :          else if (m_tid == TID_FLOAT)
     433              :             m_float = (float)v;
     434              :          else if (m_tid == TID_DOUBLE)
     435              :             m_double = (double)v;
     436              :          else if (m_tid == TID_BOOL)
     437              :             m_bool = (double)v;
     438              :          else
     439              :             mthrow("Invalid data type \"double\" for variable of type " + std::to_string(m_tid));
     440              :          write();
     441              :          return v;
     442              :       }
     443              :       const char *operator=(const char *v) {
     444              :          if (m_tid != TID_STRING)
     445              :             mthrow("Invalid data type \"const char *\" for variable of type " + std::to_string(m_tid));
     446              :          *m_string = std::string(v);
     447              :          write();
     448              :          return v;
     449              :       }
     450              :       std::string *operator=(std::string * v) {
     451              :          if (m_tid != TID_STRING)
     452              :             mthrow("Invalid data type \"std::string *\" for variable of type " + std::to_string(m_tid));
     453              :          *m_string = *v;
     454              :          write();
     455              :          return v;
     456              :       }
     457              :       std::string operator=(std::string v) {
     458              :          if (m_tid != TID_STRING)
     459              :             mthrow("Invalid data type \"std::string\" for variable of type " + std::to_string(m_tid));
     460              :          *m_string = v;
     461              :          write();
     462              :          return v;
     463              :       }
     464              : 
     465              :    };
     466              : 
     467              :    class mscb {
     468              :    private:
     469              :       std::string m_submaster;
     470              :       std::string m_password;
     471              :       int m_debug;
     472              :       int m_node_address;
     473              : 
     474              :       int m_fd;
     475              : 
     476              :       int m_protocol_version;
     477              :       int m_n_variables;
     478              :       int m_group_address;
     479              :       int m_revision;
     480              :       std::string m_node_name;
     481              :       std::string m_rtc;
     482              :       unsigned int m_uptime;
     483              : 
     484              :       std::vector<MSCB_INFO_VAR> m_var;
     485              : 
     486              :       std::vector<u_mscb> m_data;
     487              : 
     488              :       std::unordered_map<std::string, int> m_map;
     489              : 
     490              :       std::map<int, std::string> m_prefixMap;
     491              :       std::map<int, std::string> m_unitTable;
     492              : 
     493              :    public:
     494            0 :       mscb(std::string submaster, int address, std::string password = "", int debug = 0) {
     495            0 :          m_submaster = submaster;
     496            0 :          m_password = password;
     497            0 :          m_node_address = address;
     498            0 :          m_debug = debug;
     499              : 
     500            0 :          if (m_submaster.empty())
     501            0 :             mthrow("Please specify MSCB submaster to mscb() constructor");
     502              : 
     503              :          char str[80];
     504            0 :          strncpy(str, m_submaster.c_str(), sizeof(str)-1);
     505              : 
     506              :          // connect to submaster
     507            0 :          m_fd = mscb_init(str, sizeof(str), m_password.c_str(), m_debug);
     508            0 :          if (m_fd == EMSCB_WRONG_PASSWORD)
     509            0 :             mthrow("Wrong password for MSCB submaster \"" + m_submaster + "\"");
     510            0 :          if (m_fd == EMSCB_COMM_ERROR)
     511            0 :             mthrow("Cannot communicate with MSCB submaster \"" + m_submaster + "\"");
     512            0 :          if (m_fd == EMSCB_PROTOCOL_VERSION)
     513            0 :             mthrow("Submaster \"" + m_submaster + "\" runs old protocol version, please upgrade");
     514            0 :          if (m_fd == EMSCB_NOT_FOUND)
     515            0 :             mthrow("Submaster \"" + m_submaster + "\" not found, please check IP address");
     516            0 :          if (m_fd == EMSCB_LOCKED)
     517            0 :             mthrow("MSCB submaster  \\\"\" + m_submaster + \"\\\" is locked by other process");
     518            0 :          if (m_fd < 0)
     519            0 :             mthrow("Submaster \"" + m_submaster + "\" not found, please check IP address");
     520              : 
     521              :          // get general info
     522              :          MSCB_INFO info;
     523            0 :          int status = mscb_info(m_fd, m_node_address, &info);
     524            0 :          if (status != 1) {
     525              :             // device might be stuck, so ping it to clear communication buffers
     526            0 :             mscb_ping(m_fd, m_node_address, 0, 10);
     527            0 :             status = mscb_info(m_fd, m_node_address, &info);
     528            0 :             if (status != 1)
     529            0 :                mthrow("Cannot find MSCB node " + m_submaster + ":" + std::to_string(m_node_address));
     530              :          }
     531              : 
     532            0 :          m_protocol_version = info.protocol_version;
     533            0 :          m_n_variables = info.n_variables;
     534            0 :          m_group_address = info.group_address;
     535            0 :          m_revision = info.revision;
     536            0 :          m_node_name = std::string(info.node_name);
     537            0 :          m_rtc = std::string((char *) info.rtc);
     538              : 
     539              :          // get uptime
     540              :          unsigned int uptime;
     541            0 :          mscb_uptime(m_fd, m_node_address, &uptime);
     542            0 :          m_uptime = uptime;
     543              : 
     544              :          // read variable definitions
     545            0 :          for (int i = 0; i < m_n_variables; i++) {
     546              : 
     547              :             MSCB_INFO_VAR info_var;
     548            0 :             mscb_info_variable(m_fd, m_node_address, i, &info_var);
     549            0 :             m_var.push_back(info_var);
     550            0 :             info_var.name[8] = 0;
     551            0 :             m_map[info_var.name] = i;
     552              : 
     553              :             // set tid from info
     554            0 :             int tid = 0;
     555            0 :             if (m_var[i].unit == UNIT_STRING)
     556            0 :                tid = TID_STRING;
     557            0 :             else if (m_var[i].flags & MSCBF_FLOAT)
     558            0 :                tid = TID_FLOAT;
     559            0 :             else if (m_var[i].flags & MSCBF_SIGNED) {
     560            0 :                if (m_var[i].width == 1)
     561            0 :                   tid = TID_INT8;
     562            0 :                else if (m_var[i].width == 2)
     563            0 :                   tid = TID_INT16;
     564            0 :                else if (m_var[i].width == 4)
     565            0 :                   tid = TID_INT32;
     566              :             } else {
     567            0 :                if (m_var[i].width == 1)
     568            0 :                   tid = TID_UINT8;
     569            0 :                else if (m_var[i].width == 2)
     570            0 :                   tid = TID_UINT16;
     571            0 :                else if (m_var[i].width == 4)
     572            0 :                   tid = TID_UINT32;
     573              :             }
     574              : 
     575            0 :             u_mscb d(m_fd, m_node_address, i, tid, m_var[i].width);
     576            0 :             m_data.push_back(d);
     577            0 :          }
     578              : 
     579            0 :          read_range();
     580            0 :       }
     581              : 
     582              :       void set_max_retry(int i) { mscb_set_max_retry(i); }
     583              :       void set_max_eth_retry(int i) { mscb_set_eth_max_retry(m_fd, i); }
     584              : 
     585              :       // Getter
     586              :       std::string get_node_name() { return m_node_name; }
     587            0 :       std::string get_submaster() { return m_submaster; }
     588            0 :       int get_node_address() { return m_node_address; }
     589              :       int get_protocol_version() { return m_protocol_version; }
     590              :       int get_n_variables() { return m_n_variables; }
     591              : 
     592              :       std::string get_unit(int i) {
     593              :          std::string s = "";
     594              :          if (i < 0 || i >= m_n_variables)
     595              :             mthrow("Invalid index \"" + std::to_string(i) + "\" in get_unit()");
     596              : 
     597              :          if (m_var[i].prefix)
     598              :             s += g_prefixMap[(int8_t)m_var[i].prefix];
     599              :          s += g_unitTable[m_var[i].unit];
     600              :          return s;
     601              :       }
     602              : 
     603            0 :       std::string get_unit_short(int i) {
     604            0 :          std::string s = "";
     605            0 :          if (i < 0 || i >= m_n_variables)
     606            0 :             mthrow("Invalid index \"" + std::to_string(i) + "\" in get_unit()");
     607              : 
     608            0 :          if (m_var[i].prefix)
     609            0 :             s += g_prefixMapShort[(int8_t)m_var[i].prefix];
     610            0 :          s += g_unitTableShort[m_var[i].unit];
     611            0 :          return s;
     612            0 :       }
     613              : 
     614            0 :       int read_range(int i1 = 0, int i2 = 0) {
     615              :          // read range of variables from i1 to i2 (including)
     616              :          unsigned char data[1024], *pdata;
     617              : 
     618            0 :          if (i1 == 0 && i2 == 0)
     619            0 :             i2 = m_n_variables-1;
     620              : 
     621            0 :          int size = sizeof(data);
     622            0 :          int status = mscb_read_range(m_fd, m_node_address, i1, i2, data, &size);
     623            0 :          if (status != MSCB_SUCCESS)
     624            0 :             return status;
     625              : 
     626            0 :          pdata = data;
     627            0 :          for (int i = i1; i <= i2; i++) {
     628              : 
     629            0 :             if (m_var[i].width == 2)
     630            0 :                WORD_SWAP(pdata);
     631            0 :             if (m_var[i].width == 4)
     632            0 :                DWORD_SWAP(pdata);
     633              : 
     634            0 :             if (m_var[i].unit == UNIT_STRING)
     635            0 :                m_data[i].set_string((char *) pdata);
     636              :             else
     637            0 :                m_data[i].set_data(pdata);
     638              : 
     639            0 :             pdata += m_var[i].width;
     640              :          }
     641              : 
     642            0 :          return status;
     643              :       }
     644              : 
     645              :       // overload stream out operator
     646              :       friend std::ostream &operator<<(std::ostream &output, mscb &m) {
     647              :          output << "Submaster         : " << m.m_submaster << std::endl;
     648              :          output << "Node name         : " << m.m_node_name << std::endl;
     649              :          output << "Node address      : " << m.m_node_address <<
     650              :             " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') <<  m.m_node_address << ")" <<
     651              :             std::dec << std::endl;
     652              :          output << "Group address     : " << m.m_group_address <<
     653              :             " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') <<  m.m_group_address << ")" <<
     654              :             std::dec << std::endl;
     655              :          output << "Protocol version  : " << m.m_protocol_version << std::endl;
     656              :          output << "Revision          : " << m.m_revision <<
     657              :             " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') <<  m.m_revision << ")" <<
     658              :             std::dec << std::endl;
     659              :          output << "Uptime            : ";
     660              : 
     661              :          output << m.m_uptime / (3600 * 24) << "d ";
     662              :          output << std::setw(2) << std::setfill('0') << (m.m_uptime % (3600 * 24)) / 3600 << "h ";
     663              :          output << std::setw(2) << std::setfill('0') << (m.m_uptime % 3600) / 60 << "m ";
     664              :          output << std::setw(2) << std::setfill('0') << m.m_uptime % 60 << "s ";
     665              :          output << std::endl;
     666              : 
     667              :          for (int i=0 ; i<m.m_n_variables ; i++) {
     668              :             output << std::dec << std::setw(2) << i << ": " <<
     669              :             std::setw(16) << std::setfill(' ') << std::left << m.m_var[i].name << std::dec;
     670              : 
     671              :             if (m.m_var[i].width == 0)
     672              :                output << " 0bit ";
     673              :             else if (m.m_var[i].width == 1)
     674              :                output << " 8bit ";
     675              :             else if (m.m_var[i].width == 2)
     676              :                output << "16bit ";
     677              :             else if (m.m_var[i].width == 3)
     678              :                output << "24bit ";
     679              :             else if (m.m_var[i].width == 4)
     680              :                output << "32bit ";
     681              :             else if (m.m_var[i].width == 8)
     682              :                output << "64bit ";
     683              :             else
     684              :                output << "      ";
     685              : 
     686              :             if (m.m_var[i].flags & MSCBF_FLOAT)
     687              :                output << "F ";
     688              :             else if (m.m_var[i].flags & MSCBF_SIGNED)
     689              :                output << "S ";
     690              :             else
     691              :                output << "U ";
     692              : 
     693              :             output << std::right << std::setw(16);
     694              : 
     695              :             if (m.m_var[i].flags & MSCBF_FLOAT)
     696              :                output << (float)m.m_data[i];
     697              :             else
     698              :                output << m.m_data[i];
     699              :             if (!(m.m_var[i].flags & MSCBF_SIGNED) &&
     700              :                 !(m.m_var[i].flags & MSCBF_FLOAT) &&
     701              :                 !(m.m_var[i].unit == UNIT_STRING)) {
     702              :                output << " (0x";
     703              :                output << std::hex << std::setw(m.m_var[i].width * 2) << std::setfill('0');
     704              :                output << m.m_data[i] << ")" << std::dec;
     705              :             }
     706              :             output << " ";
     707              : 
     708              :             // evaluate prefix
     709              :             if (m.m_var[i].prefix) {
     710              :                if (m.m_prefixMap.count((int8_t)m.m_var[i].prefix) > 0)
     711              :                   output << m.m_prefixMap[(int8_t)m.m_var[i].prefix];
     712              :             }
     713              : 
     714              :             // evaluate unit
     715              :             if (m.m_var[i].unit && m.m_var[i].unit != UNIT_STRING) {
     716              :                if (m.m_unitTable.count(m.m_var[i].unit) > 0)
     717              :                   output << m.m_unitTable[m.m_var[i].unit];
     718              :             }
     719              : 
     720              :             output << std::endl;
     721              :          }
     722              : 
     723              :          output << std::dec << std::setw(0) << std::setfill(' ');
     724              :          return output;
     725              :       };
     726              : 
     727              :       // overload [<int>] operator
     728            0 :       u_mscb& operator[](int index) {
     729            0 :          if (index < 0 || index >= m_n_variables)
     730            0 :             mthrow("Invalid index \"" + std::to_string(index) + "\" for MSCB node \"" +
     731              :             m_node_name + "\" which has only " + std::to_string(m_n_variables) + " variables");
     732            0 :          return m_data[index];
     733              :       }
     734              : 
     735            0 :       int idx(const std::string& var_name) {
     736            0 :          if (m_map.count(var_name) == 0)
     737            0 :             mthrow("Variable \"" + var_name + "\" not found in MSCB node \"" + m_node_name + "\"");
     738              : 
     739            0 :          return m_map[var_name];
     740              :       }
     741              : 
     742              :       // overload [<std::string>] operator
     743              :       u_mscb& operator[](std::string var_name) {
     744              : 
     745              :          int index = idx(var_name);
     746              :          return m_data[index];
     747              :       }
     748              : 
     749              :       std::vector<u_mscb> vec(int i1, int i2) {
     750              :          std::vector<u_mscb> v;
     751              : 
     752              :          for (int i = i1 ; i<=i2 ; i++)
     753              :             v.push_back(m_data[i]);
     754              : 
     755              :          return v;
     756              :       }
     757              : 
     758              :    };
     759              : }
     760              : 
     761              : #endif
        

Generated by: LCOV version 2.0-1