unit-test-client.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*
  2. * Copyright © 2008-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <errno.h>
  22. #include <modbus.h>
  23. #include "unit-test.h"
  24. enum {
  25. TCP,
  26. RTU
  27. };
  28. int main(int argc, char *argv[])
  29. {
  30. uint8_t *tab_rp_bits;
  31. uint16_t *tab_rp_registers;
  32. uint16_t *tab_rp_registers_bad;
  33. modbus_t *ctx;
  34. int i;
  35. uint8_t value;
  36. int address;
  37. int nb_points;
  38. int rc;
  39. float real;
  40. struct timeval timeout_begin_old;
  41. struct timeval timeout_begin_new;
  42. int use_backend;
  43. if (argc > 1) {
  44. if (strcmp(argv[1], "tcp") == 0) {
  45. use_backend = TCP;
  46. } else if (strcmp(argv[1], "rtu") == 0) {
  47. use_backend = RTU;
  48. } else {
  49. printf("Usage:\n %s [tcp|rtu] - Modbus client for unit testing\n\n", argv[0]);
  50. exit(1);
  51. }
  52. } else {
  53. /* By default */
  54. use_backend = TCP;
  55. }
  56. if (use_backend == TCP) {
  57. ctx = modbus_new_tcp("127.0.0.1", 1502);
  58. } else {
  59. ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1);
  60. }
  61. if (ctx == NULL) {
  62. fprintf(stderr, "Unable to allocate libmodbus context\n");
  63. return -1;
  64. }
  65. modbus_set_debug(ctx, TRUE);
  66. if (use_backend == RTU) {
  67. modbus_set_slave(ctx, SERVER_ID);
  68. }
  69. if (modbus_connect(ctx) == -1) {
  70. fprintf(stderr, "Connection failed: %s\n",
  71. modbus_strerror(errno));
  72. modbus_free(ctx);
  73. return -1;
  74. }
  75. /* Allocate and initialize the memory to store the bits */
  76. nb_points = (UT_BITS_NB_POINTS > UT_INPUT_BITS_NB_POINTS) ?
  77. UT_BITS_NB_POINTS : UT_INPUT_BITS_NB_POINTS;
  78. tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  79. memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));
  80. /* Allocate and initialize the memory to store the registers */
  81. nb_points = (UT_REGISTERS_NB_POINTS >
  82. UT_INPUT_REGISTERS_NB_POINTS) ?
  83. UT_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  84. tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  85. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  86. printf("** UNIT TESTING **\n");
  87. printf("\nTEST WRITE/READ:\n");
  88. /** COIL BITS **/
  89. /* Single */
  90. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON);
  91. printf("1/2 modbus_write_bit: ");
  92. if (rc == 1) {
  93. printf("OK\n");
  94. } else {
  95. printf("FAILED\n");
  96. goto close;
  97. }
  98. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
  99. printf("2/2 modbus_read_bits: ");
  100. if (rc != 1) {
  101. printf("FAILED (nb points %d)\n", rc);
  102. goto close;
  103. }
  104. if (tab_rp_bits[0] != ON) {
  105. printf("FAILED (%0X = != %0X)\n", tab_rp_bits[0], ON);
  106. goto close;
  107. }
  108. printf("OK\n");
  109. /* End single */
  110. /* Multiple bits */
  111. {
  112. uint8_t tab_value[UT_BITS_NB_POINTS];
  113. modbus_set_bits_from_bytes(tab_value, 0, UT_BITS_NB_POINTS,
  114. UT_BITS_TAB);
  115. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  116. UT_BITS_NB_POINTS, tab_value);
  117. printf("1/2 modbus_write_bits: ");
  118. if (rc == UT_BITS_NB_POINTS) {
  119. printf("OK\n");
  120. } else {
  121. printf("FAILED\n");
  122. goto close;
  123. }
  124. }
  125. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  126. UT_BITS_NB_POINTS, tab_rp_bits);
  127. printf("2/2 modbus_read_bits: ");
  128. if (rc != UT_BITS_NB_POINTS) {
  129. printf("FAILED (nb points %d)\n", rc);
  130. goto close;
  131. }
  132. i = 0;
  133. address = UT_BITS_ADDRESS;
  134. nb_points = UT_BITS_NB_POINTS;
  135. while (nb_points > 0) {
  136. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  137. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  138. if (value != UT_BITS_TAB[i]) {
  139. printf("FAILED (%0X != %0X)\n",
  140. value, UT_BITS_TAB[i]);
  141. goto close;
  142. }
  143. nb_points -= nb_bits;
  144. i++;
  145. }
  146. printf("OK\n");
  147. /* End of multiple bits */
  148. /** DISCRETE INPUTS **/
  149. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  150. UT_INPUT_BITS_NB_POINTS, tab_rp_bits);
  151. printf("1/1 modbus_read_input_bits: ");
  152. if (rc != UT_INPUT_BITS_NB_POINTS) {
  153. printf("FAILED (nb points %d)\n", rc);
  154. goto close;
  155. }
  156. i = 0;
  157. address = UT_INPUT_BITS_ADDRESS;
  158. nb_points = UT_INPUT_BITS_NB_POINTS;
  159. while (nb_points > 0) {
  160. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  161. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  162. if (value != UT_INPUT_BITS_TAB[i]) {
  163. printf("FAILED (%0X != %0X)\n",
  164. value, UT_INPUT_BITS_TAB[i]);
  165. goto close;
  166. }
  167. nb_points -= nb_bits;
  168. i++;
  169. }
  170. printf("OK\n");
  171. /** HOLDING REGISTERS **/
  172. /* Single register */
  173. rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x1234);
  174. printf("1/2 modbus_write_register: ");
  175. if (rc == 1) {
  176. printf("OK\n");
  177. } else {
  178. printf("FAILED\n");
  179. goto close;
  180. }
  181. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  182. 1, tab_rp_registers);
  183. printf("2/2 modbus_read_registers: ");
  184. if (rc != 1) {
  185. printf("FAILED (nb points %d)\n", rc);
  186. goto close;
  187. }
  188. if (tab_rp_registers[0] != 0x1234) {
  189. printf("FAILED (%0X != %0X)\n",
  190. tab_rp_registers[0], 0x1234);
  191. goto close;
  192. }
  193. printf("OK\n");
  194. /* End of single register */
  195. /* Many registers */
  196. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  197. UT_REGISTERS_NB_POINTS,
  198. UT_REGISTERS_TAB);
  199. printf("1/5 modbus_write_registers: ");
  200. if (rc == UT_REGISTERS_NB_POINTS) {
  201. printf("OK\n");
  202. } else {
  203. printf("FAILED\n");
  204. goto close;
  205. }
  206. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  207. UT_REGISTERS_NB_POINTS,
  208. tab_rp_registers);
  209. printf("2/5 modbus_read_registers: ");
  210. if (rc != UT_REGISTERS_NB_POINTS) {
  211. printf("FAILED (nb points %d)\n", rc);
  212. goto close;
  213. }
  214. for (i=0; i < UT_REGISTERS_NB_POINTS; i++) {
  215. if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
  216. printf("FAILED (%0X != %0X)\n",
  217. tab_rp_registers[i],
  218. UT_REGISTERS_TAB[i]);
  219. goto close;
  220. }
  221. }
  222. printf("OK\n");
  223. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  224. 0, tab_rp_registers);
  225. printf("3/5 modbus_read_registers (0): ");
  226. if (rc != 0) {
  227. printf("FAILED (nb points %d)\n", rc);
  228. goto close;
  229. }
  230. printf("OK\n");
  231. nb_points = (UT_REGISTERS_NB_POINTS >
  232. UT_INPUT_REGISTERS_NB_POINTS) ?
  233. UT_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  234. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  235. /* Write registers to zero from tab_rp_registers and store read registers
  236. into tab_rp_registers. So the read registers must set to 0, except the
  237. first one because there is an offset of 1 register on write. */
  238. rc = modbus_read_and_write_registers(ctx,
  239. UT_REGISTERS_ADDRESS,
  240. UT_REGISTERS_NB_POINTS,
  241. tab_rp_registers,
  242. UT_REGISTERS_ADDRESS + 1,
  243. UT_REGISTERS_NB_POINTS - 1,
  244. tab_rp_registers);
  245. printf("4/5 modbus_read_and_write_registers: ");
  246. if (rc != UT_REGISTERS_NB_POINTS) {
  247. printf("FAILED (nb points %d != %d)\n", rc, UT_REGISTERS_NB_POINTS);
  248. goto close;
  249. }
  250. if (tab_rp_registers[0] != UT_REGISTERS_TAB[0]) {
  251. printf("FAILED (%0X != %0X)\n",
  252. tab_rp_registers[0], UT_REGISTERS_TAB[0]);
  253. }
  254. for (i=1; i < UT_REGISTERS_NB_POINTS; i++) {
  255. if (tab_rp_registers[i] != 0) {
  256. printf("FAILED (%0X != %0X)\n",
  257. tab_rp_registers[i], 0);
  258. goto close;
  259. }
  260. }
  261. printf("OK\n");
  262. /* End of many registers */
  263. /** INPUT REGISTERS **/
  264. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  265. UT_INPUT_REGISTERS_NB_POINTS,
  266. tab_rp_registers);
  267. printf("1/1 modbus_read_input_registers: ");
  268. if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
  269. printf("FAILED (nb points %d)\n", rc);
  270. goto close;
  271. }
  272. for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
  273. if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  274. printf("FAILED (%0X != %0X)\n",
  275. tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  276. goto close;
  277. }
  278. }
  279. printf("OK\n");
  280. printf("\nTEST FLOATS\n");
  281. /** FLOAT **/
  282. printf("1/2 Set float: ");
  283. modbus_set_float(UT_REAL, tab_rp_registers);
  284. if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  285. tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  286. printf("OK\n");
  287. } else {
  288. printf("FAILED (%x != %x)\n",
  289. *((uint32_t *)tab_rp_registers), UT_IREAL);
  290. goto close;
  291. }
  292. printf("2/2 Get float: ");
  293. real = modbus_get_float(tab_rp_registers);
  294. if (real == UT_REAL) {
  295. printf("OK\n");
  296. } else {
  297. printf("FAILED (%f != %f)\n", real, UT_REAL);
  298. goto close;
  299. }
  300. printf("\nAt this point, error messages doesn't mean the test has failed\n");
  301. /** ILLEGAL DATA ADDRESS **/
  302. printf("\nTEST ILLEGAL DATA ADDRESS:\n");
  303. /* The mapping begins at 0 and ends at address + nb_points so
  304. * the addresses are not valid. */
  305. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  306. UT_BITS_NB_POINTS + 1,
  307. tab_rp_bits);
  308. printf("* modbus_read_bits: ");
  309. if (rc == -1 && errno == EMBXILADD) {
  310. printf("OK\n");
  311. } else {
  312. printf("FAILED\n");
  313. goto close;
  314. }
  315. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  316. UT_INPUT_BITS_NB_POINTS + 1,
  317. tab_rp_bits);
  318. printf("* modbus_read_input_bits: ");
  319. if (rc == -1 && errno == EMBXILADD)
  320. printf("OK\n");
  321. else {
  322. printf("FAILED\n");
  323. goto close;
  324. }
  325. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  326. UT_REGISTERS_NB_POINTS + 1,
  327. tab_rp_registers);
  328. printf("* modbus_read_registers: ");
  329. if (rc == -1 && errno == EMBXILADD)
  330. printf("OK\n");
  331. else {
  332. printf("FAILED\n");
  333. goto close;
  334. }
  335. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  336. UT_INPUT_REGISTERS_NB_POINTS + 1,
  337. tab_rp_registers);
  338. printf("* modbus_read_input_registers: ");
  339. if (rc == -1 && errno == EMBXILADD)
  340. printf("OK\n");
  341. else {
  342. printf("FAILED\n");
  343. goto close;
  344. }
  345. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS, ON);
  346. printf("* modbus_write_bit: ");
  347. if (rc == -1 && errno == EMBXILADD) {
  348. printf("OK\n");
  349. } else {
  350. printf("FAILED\n");
  351. goto close;
  352. }
  353. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS,
  354. UT_BITS_NB_POINTS,
  355. tab_rp_bits);
  356. printf("* modbus_write_coils: ");
  357. if (rc == -1 && errno == EMBXILADD) {
  358. printf("OK\n");
  359. } else {
  360. printf("FAILED\n");
  361. goto close;
  362. }
  363. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS +
  364. UT_REGISTERS_NB_POINTS,
  365. UT_REGISTERS_NB_POINTS,
  366. tab_rp_registers);
  367. printf("* modbus_write_registers: ");
  368. if (rc == -1 && errno == EMBXILADD) {
  369. printf("OK\n");
  370. } else {
  371. printf("FAILED\n");
  372. goto close;
  373. }
  374. /** TOO MANY DATA **/
  375. printf("\nTEST TOO MANY DATA ERROR:\n");
  376. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, MODBUS_MAX_READ_BITS + 1,
  377. tab_rp_bits);
  378. printf("* modbus_read_bits: ");
  379. if (rc == -1 && errno == EMBMDATA) {
  380. printf("OK\n");
  381. } else {
  382. printf("FAILED\n");
  383. goto close;
  384. }
  385. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  386. MODBUS_MAX_READ_BITS + 1,
  387. tab_rp_bits);
  388. printf("* modbus_read_input_bits: ");
  389. if (rc == -1 && errno == EMBMDATA) {
  390. printf("OK\n");
  391. } else {
  392. printf("FAILED\n");
  393. goto close;
  394. }
  395. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  396. MODBUS_MAX_READ_REGISTERS + 1,
  397. tab_rp_registers);
  398. printf("* modbus_read_registers: ");
  399. if (rc == -1 && errno == EMBMDATA) {
  400. printf("OK\n");
  401. } else {
  402. printf("FAILED\n");
  403. goto close;
  404. }
  405. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  406. MODBUS_MAX_READ_REGISTERS + 1,
  407. tab_rp_registers);
  408. printf("* modbus_read_input_registers: ");
  409. if (rc == -1 && errno == EMBMDATA) {
  410. printf("OK\n");
  411. } else {
  412. printf("FAILED\n");
  413. goto close;
  414. }
  415. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  416. MODBUS_MAX_WRITE_BITS + 1,
  417. tab_rp_bits);
  418. printf("* modbus_write_bits: ");
  419. if (rc == -1 && errno == EMBMDATA) {
  420. printf("OK\n");
  421. } else {
  422. goto close;
  423. printf("FAILED\n");
  424. }
  425. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  426. MODBUS_MAX_WRITE_REGISTERS + 1,
  427. tab_rp_registers);
  428. printf("* modbus_write_registers: ");
  429. if (rc == -1 && errno == EMBMDATA) {
  430. printf("OK\n");
  431. } else {
  432. printf("FAILED\n");
  433. goto close;
  434. }
  435. /** SLAVE REPLY **/
  436. printf("\nTEST SLAVE REPLY:\n");
  437. modbus_set_slave(ctx, 18);
  438. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  439. UT_REGISTERS_NB_POINTS,
  440. tab_rp_registers);
  441. if (use_backend == RTU) {
  442. /* No response in RTU mode */
  443. printf("1/4 No response from slave %d: ", 18);
  444. if (rc == -1 && errno == ETIMEDOUT) {
  445. printf("OK\n");
  446. } else {
  447. printf("FAILED\n");
  448. goto close;
  449. }
  450. } else {
  451. /* Response in TCP mode */
  452. printf("1/4 Response from slave %d: ", 18);
  453. if (rc == UT_REGISTERS_NB_POINTS) {
  454. printf("OK\n");
  455. } else {
  456. printf("FAILED\n");
  457. goto close;
  458. }
  459. }
  460. rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
  461. if (rc == -1) {
  462. printf("Invalid broacast address\n");
  463. goto close;
  464. }
  465. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  466. UT_REGISTERS_NB_POINTS,
  467. tab_rp_registers);
  468. printf("2/4 Reply after a broadcast query: ");
  469. if (rc == UT_REGISTERS_NB_POINTS) {
  470. printf("OK\n");
  471. } else {
  472. printf("FAILED\n");
  473. goto close;
  474. }
  475. /* Restore slave */
  476. if (use_backend == RTU) {
  477. modbus_set_slave(ctx, SERVER_ID);
  478. } else {
  479. modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
  480. }
  481. printf("3/4 Report slave ID: \n");
  482. /* tab_rp_bits is used to store bytes */
  483. rc = modbus_report_slave_id(ctx, tab_rp_bits);
  484. if (rc == -1) {
  485. printf("FAILED\n");
  486. goto close;
  487. }
  488. if (((use_backend == RTU) && (tab_rp_bits[0] == SERVER_ID))
  489. || tab_rp_bits[0] == 0xFF) {
  490. printf("OK\n");
  491. } else {
  492. printf("FAILED\n");
  493. goto close;
  494. }
  495. /* Save original timeout */
  496. modbus_get_timeout_begin(ctx, &timeout_begin_old);
  497. /* Define a new and too short timeout */
  498. timeout_begin_new.tv_sec = 0;
  499. timeout_begin_new.tv_usec = 0;
  500. modbus_set_timeout_begin(ctx, &timeout_begin_new);
  501. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  502. UT_REGISTERS_NB_POINTS,
  503. tab_rp_registers);
  504. printf("4/4 Too short timeout: ");
  505. if (rc == -1 && errno == ETIMEDOUT) {
  506. printf("OK\n");
  507. } else {
  508. printf("FAILED\n");
  509. goto close;
  510. }
  511. /* Restore original timeout */
  512. modbus_set_timeout_begin(ctx, &timeout_begin_old);
  513. /* Wait for data before flushing */
  514. usleep(100);
  515. modbus_flush(ctx);
  516. /** BAD RESPONSE **/
  517. printf("\nTEST BAD RESPONSE ERROR:\n");
  518. /* Allocate only the required space */
  519. tab_rp_registers_bad = (uint16_t *) malloc(
  520. UT_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
  521. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  522. UT_REGISTERS_NB_POINTS_SPECIAL,
  523. tab_rp_registers_bad);
  524. printf("* modbus_read_registers: ");
  525. if (rc == -1 && errno == EMBBADDATA) {
  526. printf("OK\n");
  527. } else {
  528. printf("FAILED\n");
  529. goto close;
  530. }
  531. free(tab_rp_registers_bad);
  532. /** MANUAL EXCEPTION **/
  533. printf("\nTEST MANUAL EXCEPTION:\n");
  534. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SPECIAL,
  535. UT_REGISTERS_NB_POINTS,
  536. tab_rp_registers);
  537. printf("* modbus_read_registers at special address: ");
  538. if (rc == -1 && errno == EMBXSBUSY) {
  539. printf("OK\n");
  540. } else {
  541. printf("FAILED\n");
  542. goto close;
  543. }
  544. printf("\nALL TESTS PASS WITH SUCCESS.\n");
  545. close:
  546. /* Free the memory */
  547. free(tab_rp_bits);
  548. free(tab_rp_registers);
  549. /* Close the connection */
  550. modbus_close(ctx);
  551. modbus_free(ctx);
  552. return 0;
  553. }