1 /*
2 * Copyright © 2008-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdio.h>
8 #ifndef _MSC_VER
9 #include <unistd.h>
10 #include <sys/time.h>
11 #endif
12 #include <string.h>
13 #include <stdlib.h>
14 #include <time.h>
15 #include <errno.h>
16
17 #include <modbus.h>
18
19 #define G_MSEC_PER_SEC 1000
20
gettime_ms(void)21 static uint32_t gettime_ms(void)
22 {
23 struct timeval tv;
24 #if !defined(_MSC_VER)
25 gettimeofday(&tv, NULL);
26 return (uint32_t) tv.tv_sec * 1000 + tv.tv_usec / 1000;
27 #else
28 return GetTickCount();
29 #endif
30 }
31
32 enum {
33 TCP,
34 RTU
35 };
36
37 /* Tests based on PI-MBUS-300 documentation */
main(int argc,char * argv[])38 int main(int argc, char *argv[])
39 {
40 uint8_t *tab_bit;
41 uint16_t *tab_reg;
42 modbus_t *ctx;
43 int i;
44 int nb_points;
45 double elapsed;
46 uint32_t start;
47 uint32_t end;
48 uint32_t bytes;
49 uint32_t rate;
50 int rc;
51 int n_loop;
52 int use_backend;
53
54 if (argc > 1) {
55 if (strcmp(argv[1], "tcp") == 0) {
56 use_backend = TCP;
57 n_loop = 100000;
58 } else if (strcmp(argv[1], "rtu") == 0) {
59 use_backend = RTU;
60 n_loop = 100;
61 } else {
62 printf("Usage:\n %s [tcp|rtu] - Modbus client to measure data bandwith\n\n", argv[0]);
63 exit(1);
64 }
65 } else {
66 /* By default */
67 use_backend = TCP;
68 n_loop = 100000;
69 }
70
71 if (use_backend == TCP) {
72 ctx = modbus_new_tcp("127.0.0.1", 1502);
73 } else {
74 ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1);
75 modbus_set_slave(ctx, 1);
76 }
77 if (modbus_connect(ctx) == -1) {
78 fprintf(stderr, "Connection failed: %s\n",
79 modbus_strerror(errno));
80 modbus_free(ctx);
81 return -1;
82 }
83
84 /* Allocate and initialize the memory to store the status */
85 tab_bit = (uint8_t *) malloc(MODBUS_MAX_READ_BITS * sizeof(uint8_t));
86 memset(tab_bit, 0, MODBUS_MAX_READ_BITS * sizeof(uint8_t));
87
88 /* Allocate and initialize the memory to store the registers */
89 tab_reg = (uint16_t *) malloc(MODBUS_MAX_READ_REGISTERS * sizeof(uint16_t));
90 memset(tab_reg, 0, MODBUS_MAX_READ_REGISTERS * sizeof(uint16_t));
91
92 printf("READ BITS\n\n");
93
94 nb_points = MODBUS_MAX_READ_BITS;
95 start = gettime_ms();
96 for (i=0; i<n_loop; i++) {
97 rc = modbus_read_bits(ctx, 0, nb_points, tab_bit);
98 if (rc == -1) {
99 fprintf(stderr, "%s\n", modbus_strerror(errno));
100 return -1;
101 }
102 }
103 end = gettime_ms();
104 elapsed = end - start;
105
106 rate = (n_loop * nb_points) * G_MSEC_PER_SEC / (end - start);
107 printf("Transfert rate in points/seconds:\n");
108 printf("* %d points/s\n", rate);
109 printf("\n");
110
111 bytes = n_loop * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
112 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
113 printf("Values:\n");
114 printf("* %d x %d values\n", n_loop, nb_points);
115 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
116 printf("* %d KiB/s\n", rate);
117 printf("\n");
118
119 /* TCP: Query and reponse header and values */
120 bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
121 printf("Values and TCP Modbus overhead:\n");
122 printf("* %d x %d bytes\n", n_loop, bytes);
123 bytes = n_loop * bytes;
124 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
125 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
126 printf("* %d KiB/s\n", rate);
127 printf("\n\n");
128
129 printf("READ REGISTERS\n\n");
130
131 nb_points = MODBUS_MAX_READ_REGISTERS;
132 start = gettime_ms();
133 for (i=0; i<n_loop; i++) {
134 rc = modbus_read_registers(ctx, 0, nb_points, tab_reg);
135 if (rc == -1) {
136 fprintf(stderr, "%s\n", modbus_strerror(errno));
137 return -1;
138 }
139 }
140 end = gettime_ms();
141 elapsed = end - start;
142
143 rate = (n_loop * nb_points) * G_MSEC_PER_SEC / (end - start);
144 printf("Transfert rate in points/seconds:\n");
145 printf("* %d registers/s\n", rate);
146 printf("\n");
147
148 bytes = n_loop * nb_points * sizeof(uint16_t);
149 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
150 printf("Values:\n");
151 printf("* %d x %d values\n", n_loop, nb_points);
152 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
153 printf("* %d KiB/s\n", rate);
154 printf("\n");
155
156 /* TCP:Query and reponse header and values */
157 bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
158 printf("Values and TCP Modbus overhead:\n");
159 printf("* %d x %d bytes\n", n_loop, bytes);
160 bytes = n_loop * bytes;
161 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
162 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
163 printf("* %d KiB/s\n", rate);
164 printf("\n\n");
165
166 printf("WRITE AND READ REGISTERS\n\n");
167
168 nb_points = MODBUS_MAX_WR_WRITE_REGISTERS;
169 start = gettime_ms();
170 for (i=0; i<n_loop; i++) {
171 rc = modbus_write_and_read_registers(ctx,
172 0, nb_points, tab_reg,
173 0, nb_points, tab_reg);
174 if (rc == -1) {
175 fprintf(stderr, "%s\n", modbus_strerror(errno));
176 return -1;
177 }
178 }
179 end = gettime_ms();
180 elapsed = end - start;
181
182 rate = (n_loop * nb_points) * G_MSEC_PER_SEC / (end - start);
183 printf("Transfert rate in points/seconds:\n");
184 printf("* %d registers/s\n", rate);
185 printf("\n");
186
187 bytes = n_loop * nb_points * sizeof(uint16_t);
188 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
189 printf("Values:\n");
190 printf("* %d x %d values\n", n_loop, nb_points);
191 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
192 printf("* %d KiB/s\n", rate);
193 printf("\n");
194
195 /* TCP:Query and reponse header and values */
196 bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
197 printf("Values and TCP Modbus overhead:\n");
198 printf("* %d x %d bytes\n", n_loop, bytes);
199 bytes = n_loop * bytes;
200 rate = bytes / 1024 * G_MSEC_PER_SEC / (end - start);
201 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
202 printf("* %d KiB/s\n", rate);
203 printf("\n");
204
205 /* Free the memory */
206 free(tab_bit);
207 free(tab_reg);
208
209 /* Close the connection */
210 modbus_close(ctx);
211 modbus_free(ctx);
212
213 return 0;
214 }
215