LCOV - code coverage report
Current view: top level - libMagAOX/modbus - modbus.cpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 221 0
Test Date: 2026-04-15 19:34:29 Functions: 0.0 % 21 0

            Line data    Source code
       1              : 
       2              : 
       3              : #include "modbus.hpp"
       4              : 
       5            0 : modbus::modbus( const std::string &host, uint16_t port ) : PORT{ port }, HOST{ host }
       6              : {
       7            0 : }
       8              : 
       9            0 : modbus::modbus( const std::string &host ) : HOST{ host }
      10              : {
      11            0 : }
      12              : 
      13            0 : modbus::~modbus( void )
      14              : {
      15            0 : }
      16              : 
      17            0 : void modbus::modbus_set_slave_id( int id )
      18              : {
      19            0 :     _slaveid = id;
      20            0 : }
      21              : 
      22            0 : bool modbus::modbus_connect()
      23              : {
      24            0 :     if( HOST == "" || PORT == 0 )
      25              :     {
      26              :         // std::cout << "Missing Host and Port" << std::endl;
      27            0 :         return false;
      28              :     }
      29              :     else
      30              :     {
      31              :         // std::cout << "Found Proper Host "<< HOST << " and Port " <<PORT <<std::endl;
      32              :     }
      33              : 
      34            0 :     _socket = socket( AF_INET, SOCK_STREAM, 0 );
      35            0 :     if( _socket == -1 )
      36              :     {
      37              :         // std::cout <<"Error Opening Socket" <<std::endl;
      38            0 :         return false;
      39              :     }
      40              :     else
      41              :     {
      42              :         // std::cout <<"Socket Opened Successfully" << std::endl;
      43              :     }
      44              : 
      45            0 :     _server.sin_family      = AF_INET;
      46            0 :     _server.sin_addr.s_addr = inet_addr( HOST.c_str() );
      47            0 :     _server.sin_port        = htons( PORT );
      48              : 
      49            0 :     if( connect( _socket, (struct sockaddr *)&_server, sizeof( _server ) ) < 0 )
      50              :     {
      51              :         // std::cout<< "Connection Error" << std::endl;
      52            0 :         return false;
      53              :     }
      54              : 
      55              :     // std::cout<< "Connected" <<std::endl;
      56            0 :     _connected = true;
      57            0 :     return true;
      58              : }
      59              : 
      60            0 : void modbus::modbus_close()
      61              : {
      62            0 :     close( _socket );
      63              :     // std::cout <<"Socket Closed" <<std::endl;
      64            0 : }
      65              : 
      66            0 : bool modbus::modbus_set_timeouts( int seconds, int microseconds )
      67              : {
      68            0 :     if( !_connected || _socket < 0 )
      69              :     {
      70            0 :         return false;
      71              :     }
      72              : 
      73              :     struct timeval timeout;
      74            0 :     timeout.tv_sec  = seconds;
      75            0 :     timeout.tv_usec = microseconds;
      76              : 
      77            0 :     if( setsockopt( _socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof( timeout ) ) != 0 )
      78              :     {
      79            0 :         return false;
      80              :     }
      81              : 
      82            0 :     if( setsockopt( _socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof( timeout ) ) != 0 )
      83              :     {
      84            0 :         return false;
      85              :     }
      86              : 
      87            0 :     return true;
      88              : }
      89              : 
      90            0 : void modbus::modbus_build_request( uint8_t *to_send, int address, int func )
      91              : {
      92            0 :     to_send[0] = (uint8_t)_msg_id >> 8;
      93            0 :     to_send[1] = (uint8_t)( _msg_id & 0x00FF );
      94            0 :     to_send[2] = 0;
      95            0 :     to_send[3] = 0;
      96            0 :     to_send[4] = 0;
      97            0 :     to_send[6] = (uint8_t)_slaveid;
      98            0 :     to_send[7] = (uint8_t)func;
      99            0 :     to_send[8] = (uint8_t)( address >> 8 );
     100            0 :     to_send[9] = (uint8_t)( address & 0x00FF );
     101            0 : }
     102              : 
     103            0 : void modbus::modbus_write( int address, int amount, int func, uint16_t *value )
     104              : {
     105            0 :     if( func == WRITE_COIL || func == WRITE_REG )
     106              :     {
     107              :         uint8_t to_send[12];
     108            0 :         modbus_build_request( to_send, address, func );
     109            0 :         to_send[5]  = 6;
     110            0 :         to_send[10] = (uint8_t)( value[0] >> 8 );
     111            0 :         to_send[11] = (uint8_t)( value[0] & 0x00FF );
     112            0 :         modbus_send( to_send, 12 );
     113            0 :     }
     114            0 :     else if( func == WRITE_REGS )
     115              :     {
     116            0 :         uint8_t to_send[13 + 2 * amount];
     117            0 :         modbus_build_request( to_send, address, func );
     118            0 :         to_send[5]  = (uint8_t)( 5 + 2 * amount );
     119            0 :         to_send[10] = (uint8_t)( amount >> 8 );
     120            0 :         to_send[11] = (uint8_t)( amount & 0x00FF );
     121            0 :         to_send[12] = (uint8_t)( 2 * amount );
     122            0 :         for( int i = 0; i < amount; i++ )
     123              :         {
     124            0 :             to_send[13 + 2 * i] = (uint8_t)( value[i] >> 8 );
     125            0 :             to_send[14 + 2 * i] = (uint8_t)( value[i] & 0x00FF );
     126              :         }
     127            0 :         modbus_send( to_send, 13 + 2 * amount );
     128            0 :     }
     129            0 :     else if( func == WRITE_COILS )
     130              :     {
     131            0 :         uint8_t to_send[14 + ( amount - 1 ) / 8];
     132            0 :         modbus_build_request( to_send, address, func );
     133            0 :         to_send[5]  = (uint8_t)( 7 + ( amount - 1 ) / 8 );
     134            0 :         to_send[10] = (uint8_t)( amount >> 8 );
     135            0 :         to_send[11] = (uint8_t)( amount >> 8 );
     136            0 :         to_send[12] = (uint8_t)( ( amount + 7 ) / 8 );
     137            0 :         for( int i = 0; i < amount; i++ )
     138              :         {
     139            0 :             to_send[13 + ( i - 1 ) / 8] += (uint8_t)( value[i] << ( i % 8 ) );
     140              :         }
     141            0 :         modbus_send( to_send, 14 + ( amount - 1 ) / 8 );
     142            0 :     }
     143            0 : }
     144              : 
     145            0 : void modbus::modbus_read( int address, int amount, int func )
     146              : {
     147              :     uint8_t to_send[12];
     148            0 :     modbus_build_request( to_send, address, func );
     149            0 :     to_send[5]  = 6;
     150            0 :     to_send[10] = (uint8_t)( amount >> 8 );
     151            0 :     to_send[11] = (uint8_t)( amount & 0x00FF );
     152            0 :     modbus_send( to_send, 12 );
     153            0 : }
     154              : 
     155            0 : void modbus::modbus_read_holding_registers( int address, int amount, uint16_t *buffer )
     156              : {
     157            0 :     if( _connected )
     158              :     {
     159            0 :         if( amount > 65535 || address > 65535 )
     160              :         {
     161            0 :             throw modbus_amount_exception();
     162              :         }
     163            0 :         modbus_read( address, amount, READ_REGS );
     164              :         uint8_t to_rec[MAX_MSG_LENGTH];
     165            0 :         modbus_receive( to_rec );
     166              :         try
     167              :         {
     168            0 :             modbus_error_handle( to_rec, READ_REGS );
     169            0 :             for( int i = 0; i < amount; i++ )
     170              :             {
     171            0 :                 buffer[i] = ( (uint16_t)to_rec[9 + 2 * i] ) << 8;
     172            0 :                 buffer[i] += (uint16_t)to_rec[10 + 2 * i];
     173              :             }
     174              :         }
     175            0 :         catch( std::exception &e )
     176              :         {
     177            0 :             throw; // e;
     178            0 :         }
     179              :     }
     180              :     else
     181              :     {
     182            0 :         throw modbus_connect_exception();
     183              :     }
     184            0 : }
     185              : 
     186            0 : void modbus::modbus_read_input_registers( int address, int amount, uint16_t *buffer )
     187              : {
     188            0 :     if( _connected )
     189              :     {
     190            0 :         if( amount > 65535 || address > 65535 )
     191              :         {
     192            0 :             throw modbus_amount_exception();
     193              :         }
     194            0 :         modbus_read( address, amount, READ_INPUT_REGS );
     195              :         uint8_t to_rec[MAX_MSG_LENGTH];
     196            0 :         modbus_receive( to_rec );
     197              :         try
     198              :         {
     199            0 :             modbus_error_handle( to_rec, READ_INPUT_REGS );
     200            0 :             for( int i = 0; i < amount; i++ )
     201              :             {
     202            0 :                 buffer[i] = ( (uint16_t)to_rec[9 + 2 * i] ) << 8;
     203            0 :                 buffer[i] += (uint16_t)to_rec[10 + 2 * i];
     204              :             }
     205              :         }
     206            0 :         catch( std::exception &e )
     207              :         {
     208            0 :             throw; // e;
     209            0 :         }
     210              :     }
     211              :     else
     212              :     {
     213            0 :         throw modbus_connect_exception();
     214              :     }
     215            0 : }
     216              : 
     217            0 : void modbus::modbus_read_coils( int address, int amount, bool *buffer )
     218              : {
     219            0 :     if( _connected )
     220              :     {
     221            0 :         if( amount > 2040 || address > 65535 )
     222              :         {
     223            0 :             throw modbus_amount_exception();
     224              :         }
     225            0 :         modbus_read( address, amount, READ_COILS );
     226              :         uint8_t to_rec[MAX_MSG_LENGTH];
     227            0 :         modbus_receive( to_rec );
     228              :         try
     229              :         {
     230            0 :             modbus_error_handle( to_rec, READ_COILS );
     231            0 :             for( int i = 0; i < amount; i++ )
     232              :             {
     233            0 :                 buffer[i] = (bool)( ( to_rec[9 + i / 8] >> ( i % 8 ) ) & 1 );
     234              :             }
     235              :         }
     236            0 :         catch( std::exception &e )
     237              :         {
     238            0 :             throw; // e;
     239            0 :         }
     240              :     }
     241              :     else
     242              :     {
     243            0 :         throw modbus_connect_exception();
     244              :     }
     245            0 : }
     246              : 
     247            0 : void modbus::modbus_read_input_bits( int address, int amount, bool *buffer )
     248              : {
     249            0 :     if( _connected )
     250              :     {
     251            0 :         if( amount > 2040 || address > 65535 )
     252              :         {
     253            0 :             throw modbus_amount_exception();
     254              :         }
     255            0 :         modbus_read( address, amount, READ_INPUT_BITS );
     256              :         uint8_t to_rec[MAX_MSG_LENGTH];
     257            0 :         modbus_receive( to_rec );
     258              :         try
     259              :         {
     260            0 :             modbus_error_handle( to_rec, READ_INPUT_BITS );
     261            0 :             for( int i = 0; i < amount; i++ )
     262              :             {
     263            0 :                 buffer[i] = (bool)( ( to_rec[9 + i / 8] >> ( i % 8 ) ) & 1 );
     264              :             }
     265              :         }
     266            0 :         catch( std::exception &e )
     267              :         {
     268            0 :             throw; // e;
     269            0 :         }
     270              :     }
     271              :     else
     272              :     {
     273            0 :         throw modbus_connect_exception();
     274              :     }
     275            0 : }
     276              : 
     277            0 : void modbus::modbus_write_coil( int address, bool to_write )
     278              : {
     279            0 :     if( _connected )
     280              :     {
     281            0 :         if( address > 65535 )
     282              :         {
     283            0 :             throw modbus_amount_exception();
     284              :         }
     285            0 :         int value = to_write * 0xFF00;
     286            0 :         modbus_write( address, 1, WRITE_COIL, (uint16_t *)&value );
     287              :         uint8_t to_rec[MAX_MSG_LENGTH];
     288            0 :         modbus_receive( to_rec );
     289              :         try
     290              :         {
     291            0 :             modbus_error_handle( to_rec, WRITE_COIL );
     292              :         }
     293            0 :         catch( std::exception &e )
     294              :         {
     295            0 :             throw; // e;
     296            0 :         }
     297              :     }
     298              :     else
     299              :     {
     300            0 :         throw modbus_connect_exception();
     301              :     }
     302            0 : }
     303              : 
     304            0 : void modbus::modbus_write_register( int address, uint16_t value )
     305              : {
     306            0 :     if( _connected )
     307              :     {
     308            0 :         if( address > 65535 )
     309              :         {
     310            0 :             throw modbus_amount_exception();
     311              :         }
     312            0 :         modbus_write( address, 1, WRITE_REG, &value );
     313              :         uint8_t to_rec[MAX_MSG_LENGTH];
     314            0 :         modbus_receive( to_rec );
     315              :         try
     316              :         {
     317            0 :             modbus_error_handle( to_rec, WRITE_COIL );
     318              :         }
     319            0 :         catch( std::exception &e )
     320              :         {
     321            0 :             throw; // e;
     322            0 :         }
     323              :     }
     324              :     else
     325              :     {
     326            0 :         throw modbus_connect_exception();
     327              :     }
     328            0 : }
     329              : 
     330            0 : void modbus::modbus_write_coils( int address, int amount, bool *value )
     331              : {
     332            0 :     if( _connected )
     333              :     {
     334            0 :         if( address > 65535 || amount > 65535 )
     335              :         {
     336            0 :             throw modbus_amount_exception();
     337              :         }
     338            0 :         uint16_t temp[amount];
     339            0 :         for( int i = 0; i < 4; i++ )
     340              :         {
     341            0 :             temp[i] = (uint16_t)value[i];
     342              :         }
     343            0 :         modbus_write( address, amount, WRITE_COILS, temp );
     344              :         uint8_t to_rec[MAX_MSG_LENGTH];
     345            0 :         modbus_receive( to_rec );
     346              :         try
     347              :         {
     348            0 :             modbus_error_handle( to_rec, WRITE_COILS );
     349              :         }
     350            0 :         catch( std::exception &e )
     351              :         {
     352            0 :             throw; // e;
     353            0 :         }
     354            0 :     }
     355              :     else
     356              :     {
     357            0 :         throw modbus_connect_exception();
     358              :     }
     359            0 : }
     360              : 
     361            0 : void modbus::modbus_write_registers( int address, int amount, uint16_t *value )
     362              : {
     363            0 :     if( _connected )
     364              :     {
     365            0 :         if( address > 65535 || amount > 65535 )
     366              :         {
     367            0 :             throw modbus_amount_exception();
     368              :         }
     369            0 :         modbus_write( address, amount, WRITE_REGS, value );
     370              :         uint8_t to_rec[MAX_MSG_LENGTH];
     371            0 :         modbus_receive( to_rec );
     372              :         try
     373              :         {
     374            0 :             modbus_error_handle( to_rec, WRITE_REGS );
     375              :         }
     376            0 :         catch( std::exception &e )
     377              :         {
     378            0 :             throw; // e;
     379            0 :         }
     380              :     }
     381              :     else
     382              :     {
     383            0 :         throw modbus_connect_exception();
     384              :     }
     385            0 : }
     386              : 
     387            0 : ssize_t modbus::modbus_send( uint8_t *to_send, int length )
     388              : {
     389            0 :     _msg_id++;
     390            0 :     return send( _socket, to_send, (size_t)length, 0 );
     391              : }
     392              : 
     393            0 : ssize_t modbus::modbus_receive( uint8_t *buffer )
     394              : {
     395            0 :     return recv( _socket, (char *)buffer, MAX_MSG_LENGTH, 0 );
     396              : }
     397              : 
     398            0 : void modbus::modbus_error_handle( uint8_t *msg, int func )
     399              : {
     400            0 :     if( msg[7] == func + 0x80 )
     401              :     {
     402            0 :         switch( msg[8] )
     403              :         {
     404            0 :         case EX_ILLEGAL_FUNCTION:
     405            0 :             throw modbus_illegal_function_exception();
     406            0 :         case EX_ILLEGAL_ADDRESS:
     407            0 :             throw modbus_illegal_address_exception();
     408            0 :         case EX_ILLEGAL_VALUE:
     409            0 :             throw modbus_illegal_data_value_exception();
     410            0 :         case EX_SERVER_FAILURE:
     411            0 :             throw modbus_server_failure_exception();
     412            0 :         case EX_ACKNOWLEDGE:
     413            0 :             throw modbus_acknowledge_exception();
     414            0 :         case EX_SERVER_BUSY:
     415            0 :             throw modbus_server_busy_exception();
     416            0 :         case EX_GATEWAY_PROBLEMP:
     417              :         case EX_GATEWYA_PROBLEMF:
     418            0 :             throw modbus_gateway_exception();
     419            0 :         default:
     420            0 :             break;
     421              :         }
     422              :     }
     423            0 : }
        

Generated by: LCOV version 2.0-1