8000 Several problems using ModbusClientTCPasync · Issue #228 · eModbus/eModbus · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Several problems using ModbusClientTCPasync #228
Open
@mcuadros

Description

@mcuadros

Describe the bug

Working on my project using ModbusClientTCPasync with syncRequest I run into several problems, this problems caused memory leaks and restastarts under a heavy usage in 30mins or so.

Due to my own deadlines, I couldn't open proper issues here, and I tried to fixed by my own, now it's working with my fork after 10h, and more than 1M requests done.

Here is the list of problems I found and the solutions I applied, the solutions are dirty and for my only use case of eModbus, since are the works of debuging the codebase for 40h with the goal of making it work to reach my deadlines.

  • When a syncRequest fails doesn't return until lost patience is met (1min), so I implemented an isConnected method to handle the connection by hand and avoid making request to a disconnected client. 020187e
  • Disconnect doesn't clean properly the internal queues 020187e#diff-97e9b5de8eb31838da2befd02446dc1c5bf735f09e9ae051f205044c5aa38882R194-R205
  • waitSync leaks synResponses even when lostPatience is triggered or the request is successful (I don't know how), I solved cleaning the map at the end of waitSync (I am using maxInFlight 1) d0c9155
  • ModbusClientTCPasync gets in an invalid state when an error happens, and all the subsequent requests errors since the client can't connect again. I solved it by reading the state directly from AsyncClient.state() 02bf261

Example code

My code base is extensive and I don't have to make a standalone code to make it work. So here are a few snippset to understand the configuration related to the client

void MasterBrick::asClient(TokenGenerator *generator)
{
  _client = new ModbusClientTCPasync(brick->getIP(), 502);
  _client->setMaxInflightRequests(1);
  _client->setTimeout(500);
  _client->setIdleTimeout(500); 
  _generator = generator;
}
template <typename... Args>
ModbusMessage MasterBrick::_doRequest(Args&&... args)
{
  _client->connect();
  int timeout = millis() + 500;
  while (!_client->isConnected()) {
    if (timeout > millis()) {
      _client->disconnect(true);
      delay(10);
      continue;
    }
    
    LOG_E("brick=%d, request error: not connected\n", brick->address());
    ModbusMessage response;
    response.setError(brick->address(), 0, TIMEOUT);

    return response;
  }
 
  LOG_D("brick=%d, making request\n", xPortGetCoreID(), brick->address());
  auto start = millis();
  auto response = _client->syncRequest(_generator->generate(), brick->address(), std::forward<Args>(args) ...);
  Error err = response.getError();
  if (err != SUCCESS) {
    _stats.error();

    ModbusError e(err);
    int elpased =  millis()-start;
    LOG_E("brick=%d, elpased=%dms, request error: %02X - %s\n", brick->address(), elpased, (int)e, (const char *)e);

    delay(10);
    return response;
  }

  _stats.success(millis() - start);
  return response;
}

Additional context
I just wanted to report this since maybe you found it helpful, I don't have much time now to contribute back, but at least I reported some possible bugs.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0