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