LCOV - code coverage report
Current view: top level - libMagAOX/modbus - modbus.cpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 208 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 20 0

            Line data    Source code
       1              : 
       2              : 
       3              : #include "modbus.hpp"
       4              : 
       5              : 
       6            0 : modbus::modbus( const std::string & host,
       7              :                 uint16_t port
       8            0 :               ) : PORT {port}, HOST{host} {}
       9              : 
      10            0 : modbus::modbus(const std::string & host) : HOST{host} {}
      11              : 
      12            0 : modbus::~modbus(void) {
      13            0 : }
      14              : 
      15            0 : void modbus::modbus_set_slave_id(int id) {
      16            0 :     _slaveid = id;
      17            0 : }
      18              : 
      19            0 : bool modbus::modbus_connect() {
      20            0 :     if(HOST == "" || PORT == 0) {
      21              :         //std::cout << "Missing Host and Port" << std::endl;
      22            0 :         return false;
      23              :     } else {
      24              :         //std::cout << "Found Proper Host "<< HOST << " and Port " <<PORT <<std::endl;
      25              :     }
      26              : 
      27            0 :     _socket = socket(AF_INET, SOCK_STREAM, 0);
      28            0 :     if(_socket == -1) {
      29              :         //std::cout <<"Error Opening Socket" <<std::endl;
      30            0 :         return false;
      31              :     } else {
      32              :         //std::cout <<"Socket Opened Successfully" << std::endl;
      33              :     }
      34              : 
      35            0 :     _server.sin_family = AF_INET;
      36            0 :     _server.sin_addr.s_addr = inet_addr(HOST.c_str());
      37            0 :     _server.sin_port = htons(PORT);
      38              : 
      39            0 :     if (connect(_socket, (struct sockaddr*)&_server, sizeof(_server)) < 0) {
      40              :         //std::cout<< "Connection Error" << std::endl;
      41            0 :         return false;
      42              :     }
      43              : 
      44              :     //std::cout<< "Connected" <<std::endl;
      45            0 :     _connected = true;
      46            0 :     return true;
      47              : }
      48              : 
      49            0 : void modbus::modbus_close() {
      50            0 :     close(_socket);
      51              :     //std::cout <<"Socket Closed" <<std::endl;
      52            0 : }
      53              : 
      54            0 : void modbus::modbus_build_request(uint8_t *to_send, int address, int func) {
      55            0 :     to_send[0] = (uint8_t) _msg_id >> 8;
      56            0 :     to_send[1] = (uint8_t) (_msg_id & 0x00FF);
      57            0 :     to_send[2] = 0;
      58            0 :     to_send[3] = 0;
      59            0 :     to_send[4] = 0;
      60            0 :     to_send[6] = (uint8_t) _slaveid;
      61            0 :     to_send[7] = (uint8_t) func;
      62            0 :     to_send[8] = (uint8_t) (address >> 8);
      63            0 :     to_send[9] = (uint8_t) (address & 0x00FF);
      64            0 : }
      65              : 
      66            0 : void modbus::modbus_write(int address, int amount, int func, uint16_t *value) {
      67            0 :     if(func == WRITE_COIL || func == WRITE_REG) {
      68              :         uint8_t to_send[12];
      69            0 :         modbus_build_request(to_send, address, func);
      70            0 :         to_send[5] = 6;
      71            0 :         to_send[10] = (uint8_t) (value[0] >> 8);
      72            0 :         to_send[11] = (uint8_t) (value[0] & 0x00FF);
      73            0 :         modbus_send(to_send, 12);
      74            0 :     } else if(func == WRITE_REGS){
      75            0 :         uint8_t to_send[13 + 2 * amount];
      76            0 :         modbus_build_request(to_send, address, func);
      77            0 :         to_send[5] = (uint8_t) (5 + 2 * amount);
      78            0 :         to_send[10] = (uint8_t) (amount >> 8);
      79            0 :         to_send[11] = (uint8_t) (amount & 0x00FF);
      80            0 :         to_send[12] = (uint8_t) (2 * amount);
      81            0 :         for(int i = 0; i < amount; i++) {
      82            0 :             to_send[13 + 2 * i] = (uint8_t) (value[i] >> 8);
      83            0 :             to_send[14 + 2 * i] = (uint8_t) (value[i] & 0x00FF);
      84              :         }
      85            0 :         modbus_send(to_send, 13 + 2 * amount);
      86            0 :     } else if(func == WRITE_COILS) {
      87            0 :         uint8_t to_send[14 + (amount -1) / 8 ];
      88            0 :         modbus_build_request(to_send, address, func);
      89            0 :         to_send[5] = (uint8_t) (7 + (amount -1) / 8);
      90            0 :         to_send[10] = (uint8_t) (amount >> 8);
      91            0 :         to_send[11] = (uint8_t) (amount >> 8);
      92            0 :         to_send[12] = (uint8_t) ((amount + 7) / 8);
      93            0 :         for(int i = 0; i < amount; i++) {
      94            0 :             to_send[13 + (i - 1) / 8] += (uint8_t) (value[i] << (i % 8));
      95              :         }
      96            0 :         modbus_send(to_send, 14 + (amount - 1) / 8);
      97            0 :     }
      98            0 : }
      99              : 
     100            0 : void modbus::modbus_read(int address, int amount, int func){
     101              :     uint8_t to_send[12];
     102            0 :     modbus_build_request(to_send, address, func);
     103            0 :     to_send[5] = 6;
     104            0 :     to_send[10] = (uint8_t) (amount >> 8);
     105            0 :     to_send[11] = (uint8_t) (amount & 0x00FF);
     106            0 :     modbus_send(to_send, 12);
     107            0 : }
     108              : 
     109            0 : void modbus::modbus_read_holding_registers(int address, int amount, uint16_t *buffer) {
     110            0 :     if(_connected) {
     111            0 :         if(amount > 65535 || address > 65535) {
     112            0 :             throw modbus_amount_exception();
     113              :         }
     114            0 :         modbus_read(address, amount, READ_REGS);
     115              :         uint8_t to_rec[MAX_MSG_LENGTH];
     116            0 :         modbus_receive(to_rec);
     117              :         try {
     118            0 :             modbus_error_handle(to_rec, READ_REGS);
     119            0 :             for(int i = 0; i < amount; i++) {
     120            0 :                 buffer[i] = ((uint16_t)to_rec[9 + 2 * i]) << 8;
     121            0 :                 buffer[i] += (uint16_t) to_rec[10 + 2 * i];
     122              :             }
     123            0 :         } catch (std::exception &e) {
     124            0 :             throw; //e;
     125            0 :         }
     126              :     } else {
     127            0 :         throw modbus_connect_exception();
     128              :     }
     129            0 : }
     130              : 
     131            0 : void modbus::modbus_read_input_registers(int address, int amount, uint16_t *buffer) {
     132            0 :     if(_connected){
     133            0 :         if(amount > 65535 || address > 65535) {
     134            0 :             throw modbus_amount_exception();
     135              :         }
     136            0 :         modbus_read(address, amount, READ_INPUT_REGS);
     137              :         uint8_t to_rec[MAX_MSG_LENGTH];
     138            0 :         modbus_receive(to_rec);
     139              :         try {
     140            0 :             modbus_error_handle(to_rec, READ_INPUT_REGS);
     141            0 :             for(int i = 0; i < amount; i++) {
     142            0 :                 buffer[i] = ((uint16_t)to_rec[9 + 2 * i]) << 8;
     143            0 :                 buffer[i] += (uint16_t) to_rec[10 + 2 * i];
     144              :             }
     145            0 :         } catch (std::exception &e) {
     146            0 :             throw; //e;
     147            0 :         }
     148              :     } else {
     149            0 :         throw modbus_connect_exception();
     150              :     }
     151            0 : }
     152              : 
     153            0 : void modbus::modbus_read_coils(int address, int amount, bool *buffer) {
     154            0 :     if(_connected) {
     155            0 :         if(amount > 2040 || address > 65535) {
     156            0 :             throw modbus_amount_exception();
     157              :         }
     158            0 :         modbus_read(address, amount, READ_COILS);
     159              :         uint8_t to_rec[MAX_MSG_LENGTH];
     160            0 :         modbus_receive(to_rec);
     161              :         try {
     162            0 :             modbus_error_handle(to_rec, READ_COILS);
     163            0 :             for(int i = 0; i < amount; i++) {
     164            0 :                 buffer[i] = (bool) ((to_rec[9 + i / 8] >> (i % 8)) & 1);
     165              :             }
     166            0 :         } catch (std::exception &e) {
     167            0 :             throw; //e;
     168            0 :         }
     169              :     } else {
     170            0 :         throw modbus_connect_exception();
     171              :     }
     172            0 : }
     173              : 
     174            0 : void modbus::modbus_read_input_bits(int address, int amount, bool* buffer) {
     175            0 :     if(_connected) {
     176            0 :         if(amount > 2040 || address > 65535) {
     177            0 :             throw modbus_amount_exception();
     178              :         }
     179            0 :         modbus_read(address, amount, READ_INPUT_BITS);
     180              :         uint8_t to_rec[MAX_MSG_LENGTH];
     181            0 :         modbus_receive(to_rec);
     182              :         try {
     183            0 :             modbus_error_handle(to_rec, READ_INPUT_BITS);
     184            0 :             for(int i = 0; i < amount; i++) {
     185            0 :                 buffer[i] = (bool) ((to_rec[9 + i / 8] >> (i % 8)) & 1);
     186              :             }
     187            0 :         } catch (std::exception &e) {
     188            0 :             throw; //e;
     189            0 :         }
     190              :     } else {
     191            0 :         throw modbus_connect_exception();
     192              :     }
     193            0 : }
     194              : 
     195            0 : void modbus::modbus_write_coil(int address, bool to_write) {
     196            0 :     if(_connected) {
     197            0 :         if(address > 65535) {
     198            0 :             throw modbus_amount_exception();
     199              :         }
     200            0 :         int value = to_write * 0xFF00;
     201            0 :         modbus_write(address, 1, WRITE_COIL, (uint16_t *)&value);
     202              :         uint8_t to_rec[MAX_MSG_LENGTH];
     203            0 :         modbus_receive(to_rec);
     204              :         try{
     205            0 :             modbus_error_handle(to_rec, WRITE_COIL);
     206            0 :         } catch (std::exception &e) {
     207            0 :             throw; //e;
     208            0 :         }
     209              :     } else {
     210            0 :         throw modbus_connect_exception();
     211              :     }
     212            0 : }
     213              : 
     214            0 : void modbus::modbus_write_register(int address, uint16_t value) {
     215            0 :     if(_connected) {
     216            0 :         if(address > 65535) {
     217            0 :             throw modbus_amount_exception();
     218              :         }
     219            0 :         modbus_write(address, 1, WRITE_REG, &value);
     220              :         uint8_t to_rec[MAX_MSG_LENGTH];
     221            0 :         modbus_receive(to_rec);
     222              :         try{
     223            0 :             modbus_error_handle(to_rec, WRITE_COIL);
     224            0 :         } catch (std::exception &e) {
     225            0 :             throw; //e;
     226            0 :         }
     227              :     } else {
     228            0 :         throw modbus_connect_exception();
     229              :     }
     230            0 : }
     231              : 
     232            0 : void modbus::modbus_write_coils(int address, int amount, bool *value) {
     233            0 :     if(_connected) {
     234            0 :         if(address > 65535 || amount > 65535) {
     235            0 :             throw modbus_amount_exception();
     236              :         }
     237            0 :         uint16_t temp[amount];
     238            0 :         for(int i = 0; i < 4; i++) {
     239            0 :             temp[i] = (uint16_t)value[i];
     240              :         }
     241            0 :         modbus_write(address, amount, WRITE_COILS,  temp);
     242              :         uint8_t to_rec[MAX_MSG_LENGTH];
     243            0 :         modbus_receive(to_rec);
     244              :         try{
     245            0 :             modbus_error_handle(to_rec, WRITE_COILS);
     246            0 :         } catch (std::exception &e) {
     247            0 :             throw; //e;
     248            0 :         }
     249            0 :     } else {
     250            0 :         throw modbus_connect_exception();
     251              :     }
     252            0 : }
     253              : 
     254            0 : void modbus::modbus_write_registers(int address, int amount, uint16_t *value) {
     255            0 :     if(_connected) {
     256            0 :         if(address > 65535 || amount > 65535) {
     257            0 :             throw modbus_amount_exception();
     258              :         }
     259            0 :         modbus_write(address, amount, WRITE_REGS, value);
     260              :         uint8_t to_rec[MAX_MSG_LENGTH];
     261            0 :         modbus_receive(to_rec);
     262              :         try{
     263            0 :             modbus_error_handle(to_rec, WRITE_REGS);
     264            0 :         } catch (std::exception &e) {
     265            0 :             throw; //e;
     266            0 :         }
     267              :     } else {
     268            0 :         throw modbus_connect_exception();
     269              :     }
     270            0 : }
     271              : 
     272            0 : ssize_t modbus::modbus_send(uint8_t *to_send, int length) {
     273            0 :     _msg_id++;
     274            0 :     return send(_socket, to_send, (size_t)length, 0);
     275              : }
     276              : 
     277            0 : ssize_t modbus::modbus_receive(uint8_t *buffer) {
     278            0 :     return recv(_socket, (char *) buffer, MAX_MSG_LENGTH, 0);
     279              : }
     280              : 
     281            0 : void modbus::modbus_error_handle(uint8_t *msg, int func) {
     282            0 :     if(msg[7] == func + 0x80) {
     283            0 :         switch(msg[8]){
     284            0 :             case EX_ILLEGAL_FUNCTION:
     285            0 :                 throw modbus_illegal_function_exception();
     286            0 :             case EX_ILLEGAL_ADDRESS:
     287            0 :                 throw modbus_illegal_address_exception();
     288            0 :             case EX_ILLEGAL_VALUE:
     289            0 :                 throw modbus_illegal_data_value_exception();
     290            0 :             case EX_SERVER_FAILURE:
     291            0 :                 throw modbus_server_failure_exception();
     292            0 :             case EX_ACKNOWLEDGE:
     293            0 :                 throw modbus_acknowledge_exception();
     294            0 :             case EX_SERVER_BUSY:
     295            0 :                 throw modbus_server_busy_exception();
     296            0 :             case EX_GATEWAY_PROBLEMP:
     297              :             case EX_GATEWYA_PROBLEMF:
     298            0 :                 throw modbus_gateway_exception();
     299            0 :             default:
     300            0 :                 break;
     301              :         }
     302              :     }
     303            0 : }
        

Generated by: LCOV version 2.0-1