Esempio n. 1
0
static int ctx_set_byte_timeout(lua_State *L)
{
	ctx_t *ctx = ctx_check(L, 1);
	int opt = luaL_checkinteger(L, 2);
	int opt2 = luaL_optinteger(L, 3, 0);

#if LIBMODBUS_VERSION_CHECK(3,1,0)
	modbus_set_byte_timeout(ctx->modbus, opt, opt2);
#else
	struct timeval t = { opt, opt2 };
	modbus_set_byte_timeout(ctx->modbus, &t);
#endif

	return 0;
}
    modbus_ctrl::modbus_ctrl(modbus_t* context) :
        next_write_time(0),
        shadow_registers()
    {
        this->context = context;
        if(context == NULL)
        {
            throw modbus_exception();
        }
        
        //set timeout
        struct timeval timeout_end;
        struct timeval timeout_begin;
        modbus_get_byte_timeout(context, &timeout_end);
        timeout_end.tv_usec = TIMEOUT_END;
        modbus_set_byte_timeout(context, &timeout_end);

        modbus_get_response_timeout(context, &timeout_begin);
        timeout_begin.tv_usec = TIMEOUT_BEGIN;
        modbus_set_response_timeout(context, &timeout_begin);
        
        //connect
        if(modbus_connect(context) == -1)
        {
            throw modbus_exception();
        }
    }
Esempio n. 3
0
// Function for changing Modbus bytes timeout
void ModbusClientV1::change_byte_timeout(int sec, int usec)
{
	struct timeval t;

	modbus_get_byte_timeout(ctx, &t);
	printTimeTV("Initial byte timeout", &t);
	t.tv_sec = sec;
	t.tv_usec = usec;
	modbus_set_byte_timeout(ctx, &t);
	modbus_get_byte_timeout(ctx, &t);
	printTimeTV("New byte timeout", &t);
}
Esempio n. 4
0
void ModbusMaster::readRegisterList(QList<quint16> registerList)
{
    QMap<quint16, ModbusResult> resultMap;

    quint32 success = 0;
    quint32 error = 0;

    /* Open port */
    modbus_t * pCtx = openPort(_pSettingsModel->ipAddress(), _pSettingsModel->port());
    if (pCtx)
    {
        /* Set modbus slave */
        modbus_set_slave(pCtx, _pSettingsModel->slaveId());

        // Disable byte time-out
        uint32_t sec = -1;
        uint32_t usec = 0;
        modbus_set_byte_timeout(pCtx, sec, usec);

        // Set response timeout
        sec = _pSettingsModel->timeout() / 1000;
        usec = (_pSettingsModel->timeout() % 1000) * 1000uL;
        modbus_set_response_timeout(pCtx, sec, usec);

        // Do optimized reads
        qint32 regIndex = 0;
        while (regIndex < registerList.size())
        {
            quint32 count = 0;

            // get number of subsequent registers
            if (
                    ((registerList.size() - regIndex) > 1)
                    && (_pSettingsModel->consecutiveMax() > 1)
                )
            {
                bool bSubsequent;
                do
                {
                    bSubsequent = false;

                    // if next is current + 1, dan subsequent = true
                    if (registerList.at(regIndex + count + 1) == registerList.at(regIndex + count) + 1)
                    {
                        bSubsequent = true;
                        count++;
                    }

                    // Break loop when end of list
                    if ((regIndex + count) >= ((uint)registerList.size() - 1))
                    {
                        break;
                    }

                    // Limit number of register in 1 read
                    if (count > (_pSettingsModel->consecutiveMax() - 1u - 1u))
                    {
                        break;
                    }

                } while(bSubsequent == true);
            }

            // At least one register
            count++;

            // Read registers
            QList<quint16> registerDataList;
            qint32 returnCode = readRegisters(pCtx, registerList.at(regIndex) - 40001, count, &registerDataList);
            if (returnCode == 0)
            {
                success++;
                for (uint i = 0; i < count; i++)
                {
                    const quint16 registerAddr = registerList.at(regIndex) + i;
                    const ModbusResult result = ModbusResult(registerDataList[i], true);
                    resultMap.insert(registerAddr, result);
                }
            }
            else
            {                
                /* only split on specific modbus exception (invalid value and invalid address) */
                if (
                        (returnCode == (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS))
                        || (returnCode == (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE))
                    )
                {

                    /* Consecutive read failed */
                    if (count == 1)
                    {
                        /* Log error */
                        error++;
                        const quint16 registerAddr = registerList.at(regIndex);
                        const ModbusResult result = ModbusResult(0, false);
                        resultMap.insert(registerAddr, result);
                    }
                    else
                    {
                        error++;

                        /* More than one => read all separately */
                        for (quint32 i = 0; i < count; i++)
                        {
                            const quint16 registerAddr = registerList.at(regIndex + i);
                            if (readRegisters(pCtx, registerAddr - 40001, 1, &registerDataList) == 0)
                            {
                                success++;
                                const ModbusResult result = ModbusResult(registerDataList[0], true);
                                resultMap.insert(registerAddr, result);
                            }
                            else
                            {
                                /* Log error */
                                error++;
                                const ModbusResult result = ModbusResult(0, false);
                                resultMap.insert(registerAddr, result);
                            }
                        }
                    }
                }
                else
                {
                    error++;

                    for (qint32 i = 0; i < registerList.size(); i++)
                    {

                        const quint16 registerAddr = registerList.at(i);
                        const ModbusResult result = ModbusResult(0, false);
                        resultMap.insert(registerAddr,result);
                    }

                    break;
                }
            }

            // Set register index to next register
            regIndex += count;
        }

        closePort(pCtx); /* Close port */
    }
    else
    {
        error++;

        for (qint32 i = 0; i < registerList.size(); i++)
        {
            const quint16 registerAddr = registerList.at(i);
            const ModbusResult result = ModbusResult(0, false);
            resultMap.insert(registerAddr,result);
        }
    }

    _pGuiModel->setCommunicationStats(_pGuiModel->communicationSuccessCount() + success, _pGuiModel->communicationErrorCount() + error);

    emit modbusPollDone(resultMap);
}
int settimeouts(void){

  modbus_set_byte_timeout(ctx,TIMEOUTDURATION,0);
  modbus_set_response_timeout(ctx,TIMEOUTDURATION,0);
return 1;
}
Esempio n. 6
0
bool RbCtrlIface::connectModbus( int retryCount/*=-1*/)
{
    // >>>>> Simulation?
    if(mSimulActive)
    {
        ROS_WARN_STREAM( "ModBus replies are simulated!" );

        ros::Duration(1).sleep(); // sleep for a second
        return true;
    }
    // <<<<< Simulation?

    if( !mModbus )
    {
        ROS_FATAL_STREAM( "ModBus data structure not initialized!" );
        return false;
    }

    // Closing to reset active connections

    //modbus_close( mModbus);

    if( modbus_connect( mModbus ) == -1 )
    {
        ROS_FATAL_STREAM( "Modbus connection failed" );
        mBoardConnected = false;
        return false;
    }

    int res=-1;
    // res = modbus_flush( mModbus );

    ros::Duration(1).sleep(); // sleep for a second

    timeval new_timeout;
    new_timeout.tv_sec = 2;
    new_timeout.tv_usec = 0;
    modbus_set_response_timeout( mModbus, &new_timeout );
    modbus_set_byte_timeout( mModbus, &new_timeout );

    res = modbus_set_slave( mModbus, mBoardIdx );
    if( res != 0 )
    {
        ROS_FATAL_STREAM(  "modbus_set_slave error -> " <<  modbus_strerror( errno ) );

        modbus_flush( mModbus );

        mBoardConnected = false;
        return false;
    }

    int tryCount=0;
    bool ok = false;
    mBoardConnected = true;

    while(1)
    {
        ROS_WARN_STREAM( "- testBoardConnection - Attempt: " << (tryCount+1) );
        ok = testBoardConnection();
        tryCount++;

        if( tryCount==retryCount || ok )
            break;
        else
            ROS_WARN_STREAM( "Trying again...");
    }

    if( !ok )
    {
        ROS_FATAL_STREAM( "Error on modbus: " << modbus_strerror( errno ) );
        mBoardConnected = false;
        return false;
    }

    return true;
}
Esempio n. 7
0
retCode get_tx_connection(const int this_mb_tx_num, int *ret_connected)
{
    char *fnct_name = "get_tx_connection";
    int ret;
    mb_tx_t   *this_mb_tx;
    mb_link_t *this_mb_link;
    int        this_mb_link_num;
    struct timeval timeout;

    if (this_mb_tx_num < 0 || this_mb_tx_num > gbl.tot_mb_tx) {
        ERR(gbl.init_dbg, "parameter out of range this_mb_tx_num[%d]", this_mb_tx_num);
        return retERR;
    }
    this_mb_tx = &gbl.mb_tx[this_mb_tx_num];

    if (ret_connected == NULL) {
        ERR(this_mb_tx->cfg_debug, "NULL pointer");
        return retERR;
    }

    this_mb_link_num = this_mb_tx->mb_link_num;
    if (this_mb_link_num < 0 || this_mb_link_num >= gbl.tot_mb_links) {
        ERR(this_mb_tx->cfg_debug, "parameter out of range this_mb_link_num[%d]", this_mb_link_num);
        return retERR;
    }
    this_mb_link = &gbl.mb_links[this_mb_link_num];

    *ret_connected = 0; //defaults to not connected

    if (modbus_get_socket(this_mb_link->modbus) < 0) {
        ret = modbus_connect(this_mb_link->modbus);
        if (ret != 0 || modbus_get_socket(this_mb_link->modbus) < 0) {
            modbus_set_socket(this_mb_link->modbus, -1); //some times ret was < 0 and fd > 0
            ERR(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] cannot connect to link, ret[%d] fd[%d]",
                this_mb_tx_num, this_mb_tx->mb_link_num, ret, modbus_get_socket(this_mb_link->modbus));
            return retOK; //not connected
        }
        DBG(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] new connection -> fd[%d]",
            this_mb_tx_num, this_mb_tx->mb_link_num, modbus_get_socket(this_mb_link->modbus));
    }
    else {
        DBG(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] already connected to fd[%d]",
            this_mb_tx_num, this_mb_tx->mb_link_num, modbus_get_socket(this_mb_link->modbus));
    }

    //set slave id according to each mb_tx
    ret = modbus_set_slave(this_mb_link->modbus, this_mb_tx->mb_tx_slave_id);
    if (ret != 0) {
        ERR(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] cannot set slave [%d]",
            this_mb_tx_num, this_mb_tx->mb_link_num, this_mb_tx->mb_tx_slave_id);
        return retOK; //not connected
    }

    //set the low level mb_link debug according to each mb_tx
    modbus_set_debug(this_mb_link->modbus, this_mb_tx->protocol_debug);

    //set response and byte timeout according to each mb_tx
    timeout.tv_sec  = this_mb_tx->mb_response_timeout_ms / 1000;
    timeout.tv_usec = (this_mb_tx->mb_response_timeout_ms % 1000) * 1000;
#if (LIBMODBUS_VERSION_CHECK(3, 1, 2))
    modbus_set_response_timeout(this_mb_link->modbus, timeout.tv_sec, timeout.tv_usec);
#else
    modbus_set_response_timeout(this_mb_link->modbus, &timeout);
#endif
    //DBG(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] response timeout [%d] ([%d] [%d])",
    //    this_mb_tx_num, this_mb_tx->mb_link_num, this_mb_tx->mb_response_timeout_ms,
    //    (int) timeout.tv_sec, (int) timeout.tv_usec);

    timeout.tv_sec  = this_mb_tx->mb_byte_timeout_ms / 1000;
    timeout.tv_usec = (this_mb_tx->mb_byte_timeout_ms % 1000) * 1000;
#if (LIBMODBUS_VERSION_CHECK(3, 1, 2))
    modbus_set_byte_timeout(this_mb_link->modbus, timeout.tv_sec, timeout.tv_usec);
#else
    modbus_set_byte_timeout(this_mb_link->modbus, &timeout);
#endif
    //DBG(this_mb_tx->cfg_debug, "mb_tx_num[%d] mb_links[%d] byte timeout [%d] ([%d] [%d])",
    //    this_mb_tx_num, this_mb_tx->mb_link_num, this_mb_tx->mb_byte_timeout_ms,
    //    (int) timeout.tv_sec, (int) timeout.tv_usec);

    *ret_connected = 1; //is connected (fd >= 0)
    return retOK;
}
Esempio n. 8
0
/*
 * 
 * MAIN process
 * 
 */ 
int main(int argc, char* argv[])
{   
   char serial_port[32] = SERIAL_PORT_PREFIX;
   int  baud_rate;
   int  num_slaves;
   int  i, k;
   

   if ((argc < 6) || ((argc>6) && (argc<NUM_REG_PER_SLAVE+5)))
   {
      printf("Usage:\n\n");
      printf("  Single slave (passthrough) mode:\n");
      printf("  mbrtud <serial dev> <baudrate> <num_regs> <reg_offset> <slave addr>\n");
      printf("      serial dev: name of the serial device used for connection to the Modbus converter (e.g. USB0 or S0)\n");
      printf("      baudrate:   baudrate used for serial connection\n");
      printf("      num_regs:   number of consecutive registers to read\n");
      printf("      reg_offset: register address offset to add for slave request\n");
      printf("      slave addr: address of Modbus slave device\n\n");
      printf("  Multiple slave (register mapping) mode:\n");
      printf("  mbrtud <serial dev> <baudrate> <num_regs> <reg 1> ... <reg %d> <slave addr> [<slave addr> ...]\n", NUM_REG_PER_SLAVE);
      printf("      serial dev: name of the serial device used for connection to the Modbus converter (e.g. USB0 or S0)\n");
      printf("      baudrate:   baudrate used for serial connection\n");
      printf("      num_regs:   number of consecutive registers to read\n");
      printf("      reg x:      register map to use for slave request\n");
      printf("      slave addr: address of Modbus slave devices (up to %d)\n", MAX_SLAVES);
      return 0;
   }

   openlog("mbrtud", LOG_PID|LOG_CONS, LOG_USER);
   syslog(LOG_DAEMON | LOG_NOTICE, "Starting Modbus RTU daemon (version %s)\n", VERSION);
   
   /* Install signal handler for SIGTERM and SIGINT ("CTRL C") to be used to terminate */
   signal(SIGTERM, doExit);
   signal(SIGINT, doExit);
   
   /* Get input parameters */
   i=1;
   strcat(serial_port, argv[i++]);
   baud_rate = atoi(argv[i++]);
   num_regs = atoi(argv[i++]);
   
   if (argc == 6)
   {
      /* Single slave (passthrough) mode */
      mode=MODE_SINGLESLAVE;
      reg_offset = atoi(argv[i++]);
      slave_addr_table[0] = atoi(argv[i++]);
   }
   else
   {
      /* Multiple slave (register mapping) mode */
      mode=MODE_MULTISLAVE;
      for (k=0; (i<argc)&&(k<NUM_REG_PER_SLAVE); i++, k++)
         custom_reg_table[k] = atoi(argv[i]);
      
      memset(slave_addr_table, 0, sizeof(slave_addr_table));
      for (k=0; (i<argc)&&(k<MAX_SLAVES); i++, k++)
         slave_addr_table[k] = atoi(argv[i]);
      num_slaves = k;
   }

   /* Init the Modbus RTU connection */
   mb = modbus_new_rtu(serial_port, baud_rate, 'N', 8, 1);
   if (mb == NULL)
   {
      syslog(LOG_DAEMON | LOG_ERR, "Unable to create RTU485 context\n");
      modbus_free(mb);
      return 1;
   }
        
   if (modbus_connect(mb) == -1) 
   {
      syslog(LOG_DAEMON | LOG_ERR, "Connection failed: %s\n", 
                                    modbus_strerror(errno));
      return 2;
   }
   
   /* Set Modbus timeouts */
   modbus_set_response_timeout(mb, 20, 0); 
   modbus_set_byte_timeout(mb, 1, 0);
   
   /* Specific setting for direction control of the RS485 transceiver */
   if (strstr(serial_port, "USB") == NULL)
   {
      /* Enable RS485 direction control via RTS line */
      if (modbus_rtu_set_rts(mb, MODBUS_RTU_RTS_DOWN) == -1)
      {
         syslog(LOG_DAEMON | LOG_ERR, "Setting RTS mode failed: %s\n", 
                                       modbus_strerror(errno));
         modbus_free(mb);
         return 3;
      }
      
      /* Set RTS control delay (before and after transmission) */
      if (DEFAULT_RTS_DELAY > 0)
      {
         if (modbus_rtu_set_rts_delay(mb, DEFAULT_RTS_DELAY) == -1)
         {
            syslog(LOG_DAEMON | LOG_ERR, "Setting RTS delay failed: %s\n", 
                                          modbus_strerror(errno));
            modbus_free(mb);
            return 4;
         }
      }
      
      syslog(LOG_DAEMON | LOG_NOTICE, "using direction control via RTS line");
   }
   
   //modbus_set_debug(mb, TRUE);
   
   syslog(LOG_DAEMON | LOG_NOTICE, "Using Modbus connection on serial port %s at %dbaud", 
                                    serial_port, baud_rate);
   if (mode == MODE_SINGLESLAVE)
   {
      syslog(LOG_DAEMON | LOG_NOTICE, "Single slave mode - slave address: %d", slave_addr_table[0]);
   }
   else
   {
      syslog(LOG_DAEMON | LOG_NOTICE, "Multiple slave mode - register map for each slave:");
      syslog(LOG_DAEMON | LOG_NOTICE, "   Reg | Id ");
      syslog(LOG_DAEMON | LOG_NOTICE, "   ---------");
      for (i=0; i<NUM_REG_PER_SLAVE; i++)
         syslog(LOG_DAEMON | LOG_NOTICE, "   %02d  | %02d", i+1, custom_reg_table[i]);
      
      syslog(LOG_DAEMON | LOG_NOTICE, "List of slaves:");
      for (i=0; i<num_slaves; i++)
         syslog(LOG_DAEMON | LOG_NOTICE, "   slave %d: %d (regs[%d...%d])\n", 
                i+1, 
                slave_addr_table[i],
                i*NUM_REG_PER_SLAVE+1,
                i*NUM_REG_PER_SLAVE+NUM_REG_PER_SLAVE);
   }
   
   /* Start Modbus TCP server loop */
   modbustcp_server(MODBUS_SLAVE_ADDRESS,  // Modbus slave address
                    read_register_handler, // Read register handler
                    write_register_handler // Write register handler
   );
   
   return 0;
}