Skip to content

TCP · RTU · ASCII

Modbus

Build Modbus TCP, RTU and ASCII clients, servers and TCP-to-RTU/ASCII gateways, driven by one JSON command interface.

What it does

  • Modbus TCP, RTU and ASCII transports.
  • Client, server and TCP-to-RTU/ASCII gateway roles.
  • 19 function codes and 15 diagnostics sub-functions.
  • Server data model: the four tables, file records, FIFO queues and device identification objects.
  • Trace of the last 1000 requests and frames, frame decoding and diagnostics counters.
  • Save and restore the configuration and data model as a JSON project file.

Example

Each binding shows code from a real example file in the examples folder of the PDComm SDK. The source file and line range appear above the code.

Modbus client in C

Source: examples/modbus/client.c:82-111
snprintf(configure, sizeof(configure),
         "{\"action\":\"configure\",\"config\":{\"transport\":\"tcp\",\"role\":\"client\","
         "\"address\":%s,\"port\":\"\",\"unit\":1,\"baud\":19200,\"parity\":\"even\","
         "\"stop_bits\":1,\"timeout_ms\":1000,\"security\":%s}}",
         address, security);

pdcomm_modbus_handle endpoint = 0;
if (pdcomm_modbus_endpoint_create(&endpoint) != PDCOMM_MODBUS_OK) {
  fputs("Cannot create the Modbus endpoint\n", stderr);
  return 1;
}
/* Configure, connect, write 42 to holding register 0 (function 06), then
 * read that register back (function 03). Each step needs the previous one. */
const char *steps[] = {configure, "{\"action\":\"connect\"}",
                       "{\"action\":\"request\",\"pdu\":\"060000002A\"}",
                       "{\"action\":\"request\",\"pdu\":\"0300000001\"}"};
char *reply = NULL;
int passed = 1;
for (size_t step = 0; passed && step < sizeof(steps) / sizeof(steps[0]); ++step) {
  free(reply);
  reply = call(endpoint, steps[step]);
  passed = reply != NULL;
  if (passed && step >= 2)
    printf("%s -> %s\n", steps[step], reply);
}
/* {"ok":true,"result":{"response":[3,2,0,42],"source":"wire","status":"success"}} */
passed = passed && strstr(reply, "\"response\":[3,2,0,42]") != NULL;
free(reply);
free(call(endpoint, "{\"action\":\"disconnect\"}"));
pdcomm_modbus_release(endpoint);

From the C example: pass JSON commands to pdcomm_modbus_call() to configure and connect a TCP client, write 42 to holding register 0 (function 06) and read it back (function 03). Run it against the Modbus simulator as the server.