You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.0 KiB

  1. From a00ab52931a587cf29c53a945e9295b4d7fe41ba Mon Sep 17 00:00:00 2001
  2. From: Daniel Golle <daniel@makrotopia.org>
  3. Date: Thu, 28 Mar 2019 01:52:04 +0100
  4. Subject: [PATCH] Add support for RS485 to modbus plugin
  5. Allow setting up RS485 mode for Modbus-RTU
  6. ---
  7. src/collectd.conf.pod | 6 +++++
  8. src/modbus.c | 55 +++++++++++++++++++++++++++++++++++++++----
  9. 2 files changed, 57 insertions(+), 4 deletions(-)
  10. --- a/src/collectd.conf.pod
  11. +++ b/src/collectd.conf.pod
  12. @@ -4234,6 +4234,12 @@ For Modbus/RTU, specifies the path to th
  13. For Modbus/RTU, specifies the baud rate of the serial device.
  14. Note, connections currently support only 8/N/1.
  15. +=item B<UARTType> I<UARTType>
  16. +
  17. +For Modbus/RTU, specifies the type of the serial device.
  18. +RS232, RS422 and RS485 are supported. Defaults to RS232.
  19. +Available only on Linux systems with libmodbus>=2.9.4.
  20. +
  21. =item B<Interval> I<Interval>
  22. Sets the interval (in seconds) in which the values will be collected from this
  23. --- a/src/modbus.c
  24. +++ b/src/modbus.c
  25. @@ -95,6 +95,12 @@ enum mb_conntype_e /* {{{ */
  26. MBCONN_RTU }; /* }}} */
  27. typedef enum mb_conntype_e mb_conntype_t;
  28. +enum mb_uarttype_e /* {{{ */
  29. +{ UARTTYPE_RS232,
  30. + UARTTYPE_RS422,
  31. + UARTTYPE_RS485 }; /* }}} */
  32. +typedef enum mb_uarttype_e mb_uarttype_t;
  33. +
  34. struct mb_data_s;
  35. typedef struct mb_data_s mb_data_t;
  36. struct mb_data_s /* {{{ */
  37. @@ -124,8 +130,9 @@ struct mb_host_s /* {{{ */
  38. char host[DATA_MAX_NAME_LEN];
  39. char node[NI_MAXHOST]; /* TCP hostname or RTU serial device */
  40. /* char service[NI_MAXSERV]; */
  41. - int port; /* for Modbus/TCP */
  42. - int baudrate; /* for Modbus/RTU */
  43. + int port; /* for Modbus/TCP */
  44. + int baudrate; /* for Modbus/RTU */
  45. + mb_uarttype_t uarttype; /* UART type for Modbus/RTU */
  46. mb_conntype_t conntype;
  47. cdtime_t interval;
  48. @@ -390,6 +397,22 @@ static int mb_init_connection(mb_host_t
  49. return status;
  50. }
  51. +#if defined(linux) && LIBMODBUS_VERSION_CHECK(2, 9, 4)
  52. + switch (host->uarttype) {
  53. + case UARTTYPE_RS485:
  54. + if (modbus_rtu_set_serial_mode(host->connection, MODBUS_RTU_RS485))
  55. + DEBUG("Modbus plugin: Setting RS485 mode failed.");
  56. + break;
  57. + case UARTTYPE_RS422:
  58. + /* libmodbus doesn't say anything about full-duplex symmetric RS422 UART */
  59. + break;
  60. + case UARTTYPE_RS232:
  61. + break;
  62. + default:
  63. + DEBUG("Modbus plugin: Invalid UART type!.");
  64. + }
  65. +#endif /* defined(linux) && LIBMODBUS_VERSION_CHECK(2, 9, 4) */
  66. +
  67. return 0;
  68. } /* }}} int mb_init_connection */
  69. #endif /* !LEGACY_LIBMODBUS */
  70. @@ -951,11 +974,35 @@ static int mb_config_add_host(oconfig_it
  71. status = -1;
  72. } else if (strcasecmp("Device", child->key) == 0) {
  73. status = cf_util_get_string_buffer(child, host->node, sizeof(host->node));
  74. - if (status == 0)
  75. + if (status == 0) {
  76. host->conntype = MBCONN_RTU;
  77. + host->uarttype = UARTTYPE_RS232;
  78. + }
  79. } else if (strcasecmp("Baudrate", child->key) == 0)
  80. status = cf_util_get_int(child, &host->baudrate);
  81. - else if (strcasecmp("Interval", child->key) == 0)
  82. + else if (strcasecmp("UARTType", child->key) == 0) {
  83. +#if defined(linux) && !LEGACY_LIBMODBUS && LIBMODBUS_VERSION_CHECK(2, 9, 4)
  84. + char buffer[NI_MAXHOST];
  85. + status = cf_util_get_string_buffer(child, buffer, sizeof(buffer));
  86. + if (status != 0)
  87. + break;
  88. + if (strncmp(buffer, "RS485", 6) == 0)
  89. + host->uarttype = UARTTYPE_RS485;
  90. + else if (strncmp(buffer, "RS422", 6) == 0)
  91. + host->uarttype = UARTTYPE_RS422;
  92. + else if (strncmp(buffer, "RS232", 6) == 0)
  93. + host->uarttype = UARTTYPE_RS232;
  94. + else {
  95. + ERROR("Modbus plugin: The UARTType \"%s\" is unknown.", buffer);
  96. + status = -1;
  97. + break;
  98. + }
  99. +#else
  100. + ERROR("Modbus plugin: Option `UARTType' not supported. Please "
  101. + "upgrade libmodbus to at least 2.9.4");
  102. + return -1;
  103. +#endif
  104. + } else if (strcasecmp("Interval", child->key) == 0)
  105. status = cf_util_get_cdtime(child, &host->interval);
  106. else if (strcasecmp("Slave", child->key) == 0)
  107. /* Don't set status: Gracefully continue if a slave fails. */