unit-test-client.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  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. TCP_PI,
  27. RTU
  28. };
  29. int main(int argc, char *argv[])
  30. {
  31. uint8_t *tab_rp_bits;
  32. uint16_t *tab_rp_registers;
  33. uint16_t *tab_rp_registers_bad;
  34. modbus_t *ctx;
  35. int i;
  36. uint8_t value;
  37. int address;
  38. int nb_points;
  39. int rc;
  40. float real;
  41. struct timeval old_response_timeout;
  42. struct timeval response_timeout;
  43. int use_backend;
  44. if (argc > 1) {
  45. if (strcmp(argv[1], "tcp") == 0) {
  46. use_backend = TCP;
  47. } else if (strcmp(argv[1], "tcppi") == 0) {
  48. use_backend = TCP_PI;
  49. } else if (strcmp(argv[1], "rtu") == 0) {
  50. use_backend = RTU;
  51. } else {
  52. printf("Usage:\n %s [tcp|tcppi|rtu] - Modbus client for unit testing\n\n", argv[0]);
  53. exit(1);
  54. }
  55. } else {
  56. /* By default */
  57. use_backend = TCP;
  58. }
  59. if (use_backend == TCP) {
  60. ctx = modbus_new_tcp("127.0.0.1", 1502);
  61. } else if (use_backend == TCP_PI) {
  62. ctx = modbus_new_tcp_pi("::1", "1502");
  63. } else {
  64. ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1);
  65. }
  66. if (ctx == NULL) {
  67. fprintf(stderr, "Unable to allocate libmodbus context\n");
  68. return -1;
  69. }
  70. modbus_set_debug(ctx, TRUE);
  71. if (use_backend == RTU) {
  72. modbus_set_slave(ctx, SERVER_ID);
  73. }
  74. if (modbus_connect(ctx) == -1) {
  75. fprintf(stderr, "Connection failed: %s\n",
  76. modbus_strerror(errno));
  77. modbus_free(ctx);
  78. return -1;
  79. }
  80. /* Allocate and initialize the memory to store the bits */
  81. nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB;
  82. tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  83. memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));
  84. /* Allocate and initialize the memory to store the registers */
  85. nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ?
  86. UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
  87. tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  88. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  89. printf("** UNIT TESTING **\n");
  90. printf("\nTEST WRITE/READ:\n");
  91. /** COIL BITS **/
  92. /* Single */
  93. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON);
  94. printf("1/2 modbus_write_bit: ");
  95. if (rc == 1) {
  96. printf("OK\n");
  97. } else {
  98. printf("FAILED\n");
  99. goto close;
  100. }
  101. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
  102. printf("2/2 modbus_read_bits: ");
  103. if (rc != 1) {
  104. printf("FAILED (nb points %d)\n", rc);
  105. goto close;
  106. }
  107. if (tab_rp_bits[0] != ON) {
  108. printf("FAILED (%0X = != %0X)\n", tab_rp_bits[0], ON);
  109. goto close;
  110. }
  111. printf("OK\n");
  112. /* End single */
  113. /* Multiple bits */
  114. {
  115. uint8_t tab_value[UT_BITS_NB];
  116. modbus_set_bits_from_bytes(tab_value, 0, UT_BITS_NB, UT_BITS_TAB);
  117. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  118. UT_BITS_NB, tab_value);
  119. printf("1/2 modbus_write_bits: ");
  120. if (rc == UT_BITS_NB) {
  121. printf("OK\n");
  122. } else {
  123. printf("FAILED\n");
  124. goto close;
  125. }
  126. }
  127. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB, tab_rp_bits);
  128. printf("2/2 modbus_read_bits: ");
  129. if (rc != UT_BITS_NB) {
  130. printf("FAILED (nb points %d)\n", rc);
  131. goto close;
  132. }
  133. i = 0;
  134. address = UT_BITS_ADDRESS;
  135. nb_points = UT_BITS_NB;
  136. while (nb_points > 0) {
  137. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  138. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  139. if (value != UT_BITS_TAB[i]) {
  140. printf("FAILED (%0X != %0X)\n", 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, tab_rp_bits);
  151. printf("1/1 modbus_read_input_bits: ");
  152. if (rc != UT_INPUT_BITS_NB) {
  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;
  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", value, UT_INPUT_BITS_TAB[i]);
  164. goto close;
  165. }
  166. nb_points -= nb_bits;
  167. i++;
  168. }
  169. printf("OK\n");
  170. /** HOLDING REGISTERS **/
  171. /* Single register */
  172. rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x1234);
  173. printf("1/2 modbus_write_register: ");
  174. if (rc == 1) {
  175. printf("OK\n");
  176. } else {
  177. printf("FAILED\n");
  178. goto close;
  179. }
  180. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  181. 1, tab_rp_registers);
  182. printf("2/2 modbus_read_registers: ");
  183. if (rc != 1) {
  184. printf("FAILED (nb points %d)\n", rc);
  185. goto close;
  186. }
  187. if (tab_rp_registers[0] != 0x1234) {
  188. printf("FAILED (%0X != %0X)\n",
  189. tab_rp_registers[0], 0x1234);
  190. goto close;
  191. }
  192. printf("OK\n");
  193. /* End of single register */
  194. /* Many registers */
  195. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  196. UT_REGISTERS_NB, UT_REGISTERS_TAB);
  197. printf("1/5 modbus_write_registers: ");
  198. if (rc == UT_REGISTERS_NB) {
  199. printf("OK\n");
  200. } else {
  201. printf("FAILED\n");
  202. goto close;
  203. }
  204. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  205. UT_REGISTERS_NB, tab_rp_registers);
  206. printf("2/5 modbus_read_registers: ");
  207. if (rc != UT_REGISTERS_NB) {
  208. printf("FAILED (nb points %d)\n", rc);
  209. goto close;
  210. }
  211. for (i=0; i < UT_REGISTERS_NB; i++) {
  212. if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
  213. printf("FAILED (%0X != %0X)\n",
  214. tab_rp_registers[i],
  215. UT_REGISTERS_TAB[i]);
  216. goto close;
  217. }
  218. }
  219. printf("OK\n");
  220. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  221. 0, tab_rp_registers);
  222. printf("3/5 modbus_read_registers (0): ");
  223. if (rc != 0) {
  224. printf("FAILED (nb points %d)\n", rc);
  225. goto close;
  226. }
  227. printf("OK\n");
  228. nb_points = (UT_REGISTERS_NB >
  229. UT_INPUT_REGISTERS_NB) ?
  230. UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
  231. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  232. /* Write registers to zero from tab_rp_registers and store read registers
  233. into tab_rp_registers. So the read registers must set to 0, except the
  234. first one because there is an offset of 1 register on write. */
  235. rc = modbus_read_and_write_registers(ctx,
  236. UT_REGISTERS_ADDRESS, UT_REGISTERS_NB,
  237. tab_rp_registers,
  238. UT_REGISTERS_ADDRESS + 1,
  239. UT_REGISTERS_NB - 1,
  240. tab_rp_registers);
  241. printf("4/5 modbus_read_and_write_registers: ");
  242. if (rc != UT_REGISTERS_NB) {
  243. printf("FAILED (nb points %d != %d)\n", rc, UT_REGISTERS_NB);
  244. goto close;
  245. }
  246. if (tab_rp_registers[0] != UT_REGISTERS_TAB[0]) {
  247. printf("FAILED (%0X != %0X)\n",
  248. tab_rp_registers[0], UT_REGISTERS_TAB[0]);
  249. }
  250. for (i=1; i < UT_REGISTERS_NB; i++) {
  251. if (tab_rp_registers[i] != 0) {
  252. printf("FAILED (%0X != %0X)\n",
  253. tab_rp_registers[i], 0);
  254. goto close;
  255. }
  256. }
  257. printf("OK\n");
  258. /* End of many registers */
  259. /** INPUT REGISTERS **/
  260. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  261. UT_INPUT_REGISTERS_NB,
  262. tab_rp_registers);
  263. printf("1/1 modbus_read_input_registers: ");
  264. if (rc != UT_INPUT_REGISTERS_NB) {
  265. printf("FAILED (nb points %d)\n", rc);
  266. goto close;
  267. }
  268. for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
  269. if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  270. printf("FAILED (%0X != %0X)\n",
  271. tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  272. goto close;
  273. }
  274. }
  275. printf("OK\n");
  276. printf("\nTEST FLOATS\n");
  277. /** FLOAT **/
  278. printf("1/2 Set float: ");
  279. modbus_set_float(UT_REAL, tab_rp_registers);
  280. if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  281. tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  282. printf("OK\n");
  283. } else {
  284. printf("FAILED (%x != %x)\n",
  285. *((uint32_t *)tab_rp_registers), UT_IREAL);
  286. goto close;
  287. }
  288. printf("2/2 Get float: ");
  289. real = modbus_get_float(tab_rp_registers);
  290. if (real == UT_REAL) {
  291. printf("OK\n");
  292. } else {
  293. printf("FAILED (%f != %f)\n", real, UT_REAL);
  294. goto close;
  295. }
  296. printf("\nAt this point, error messages doesn't mean the test has failed\n");
  297. /** ILLEGAL DATA ADDRESS **/
  298. printf("\nTEST ILLEGAL DATA ADDRESS:\n");
  299. /* The mapping begins at 0 and ends at address + nb_points so
  300. * the addresses are not valid. */
  301. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  302. UT_BITS_NB + 1, tab_rp_bits);
  303. printf("* modbus_read_bits: ");
  304. if (rc == -1 && errno == EMBXILADD) {
  305. printf("OK\n");
  306. } else {
  307. printf("FAILED\n");
  308. goto close;
  309. }
  310. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  311. UT_INPUT_BITS_NB + 1, tab_rp_bits);
  312. printf("* modbus_read_input_bits: ");
  313. if (rc == -1 && errno == EMBXILADD)
  314. printf("OK\n");
  315. else {
  316. printf("FAILED\n");
  317. goto close;
  318. }
  319. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  320. UT_REGISTERS_NB + 1, tab_rp_registers);
  321. printf("* modbus_read_registers: ");
  322. if (rc == -1 && errno == EMBXILADD)
  323. printf("OK\n");
  324. else {
  325. printf("FAILED\n");
  326. goto close;
  327. }
  328. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  329. UT_INPUT_REGISTERS_NB + 1,
  330. tab_rp_registers);
  331. printf("* modbus_read_input_registers: ");
  332. if (rc == -1 && errno == EMBXILADD)
  333. printf("OK\n");
  334. else {
  335. printf("FAILED\n");
  336. goto close;
  337. }
  338. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS + UT_BITS_NB, ON);
  339. printf("* modbus_write_bit: ");
  340. if (rc == -1 && errno == EMBXILADD) {
  341. printf("OK\n");
  342. } else {
  343. printf("FAILED\n");
  344. goto close;
  345. }
  346. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB,
  347. UT_BITS_NB, tab_rp_bits);
  348. printf("* modbus_write_coils: ");
  349. if (rc == -1 && errno == EMBXILADD) {
  350. printf("OK\n");
  351. } else {
  352. printf("FAILED\n");
  353. goto close;
  354. }
  355. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
  356. UT_REGISTERS_NB, tab_rp_registers);
  357. printf("* modbus_write_registers: ");
  358. if (rc == -1 && errno == EMBXILADD) {
  359. printf("OK\n");
  360. } else {
  361. printf("FAILED\n");
  362. goto close;
  363. }
  364. /** TOO MANY DATA **/
  365. printf("\nTEST TOO MANY DATA ERROR:\n");
  366. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  367. MODBUS_MAX_READ_BITS + 1, tab_rp_bits);
  368. printf("* modbus_read_bits: ");
  369. if (rc == -1 && errno == EMBMDATA) {
  370. printf("OK\n");
  371. } else {
  372. printf("FAILED\n");
  373. goto close;
  374. }
  375. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  376. MODBUS_MAX_READ_BITS + 1, tab_rp_bits);
  377. printf("* modbus_read_input_bits: ");
  378. if (rc == -1 && errno == EMBMDATA) {
  379. printf("OK\n");
  380. } else {
  381. printf("FAILED\n");
  382. goto close;
  383. }
  384. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  385. MODBUS_MAX_READ_REGISTERS + 1,
  386. tab_rp_registers);
  387. printf("* modbus_read_registers: ");
  388. if (rc == -1 && errno == EMBMDATA) {
  389. printf("OK\n");
  390. } else {
  391. printf("FAILED\n");
  392. goto close;
  393. }
  394. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  395. MODBUS_MAX_READ_REGISTERS + 1,
  396. tab_rp_registers);
  397. printf("* modbus_read_input_registers: ");
  398. if (rc == -1 && errno == EMBMDATA) {
  399. printf("OK\n");
  400. } else {
  401. printf("FAILED\n");
  402. goto close;
  403. }
  404. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  405. MODBUS_MAX_WRITE_BITS + 1, tab_rp_bits);
  406. printf("* modbus_write_bits: ");
  407. if (rc == -1 && errno == EMBMDATA) {
  408. printf("OK\n");
  409. } else {
  410. goto close;
  411. printf("FAILED\n");
  412. }
  413. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  414. MODBUS_MAX_WRITE_REGISTERS + 1,
  415. tab_rp_registers);
  416. printf("* modbus_write_registers: ");
  417. if (rc == -1 && errno == EMBMDATA) {
  418. printf("OK\n");
  419. } else {
  420. printf("FAILED\n");
  421. goto close;
  422. }
  423. /** SLAVE REPLY **/
  424. printf("\nTEST SLAVE REPLY:\n");
  425. modbus_set_slave(ctx, INVALID_SERVER_ID);
  426. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  427. UT_REGISTERS_NB, tab_rp_registers);
  428. if (use_backend == RTU) {
  429. const int RAW_REQ_LENGTH = 6;
  430. uint8_t raw_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0xFF, 0xFF };
  431. int req_length;
  432. uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
  433. /* No response in RTU mode */
  434. printf("1/4-A No response from slave %d: ", INVALID_SERVER_ID);
  435. if (rc == -1 && errno == ETIMEDOUT) {
  436. printf("OK\n");
  437. } else {
  438. printf("FAILED\n");
  439. goto close;
  440. }
  441. /* Send an invalid query with a wrong slave ID */
  442. req_length = modbus_send_raw_request(
  443. ctx, raw_req,
  444. RAW_REQ_LENGTH * sizeof(uint8_t));
  445. rc = modbus_receive_confirmation(ctx, rsp);
  446. printf("1/4-B No response from slave %d with invalid request: ",
  447. INVALID_SERVER_ID);
  448. if (rc == -1 && errno == ETIMEDOUT) {
  449. printf("OK\n");
  450. } else {
  451. printf("FAILED (%d)\n", rc);
  452. goto close;
  453. }
  454. } else {
  455. /* Response in TCP mode */
  456. printf("1/4 Response from slave %d: ", 18);
  457. if (rc == UT_REGISTERS_NB) {
  458. printf("OK\n");
  459. } else {
  460. printf("FAILED\n");
  461. goto close;
  462. }
  463. }
  464. rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
  465. if (rc == -1) {
  466. printf("Invalid broacast address\n");
  467. goto close;
  468. }
  469. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  470. UT_REGISTERS_NB, tab_rp_registers);
  471. printf("2/4 Reply after a broadcast query: ");
  472. if (rc == UT_REGISTERS_NB) {
  473. printf("OK\n");
  474. } else {
  475. printf("FAILED\n");
  476. goto close;
  477. }
  478. /* Restore slave */
  479. if (use_backend == RTU) {
  480. modbus_set_slave(ctx, SERVER_ID);
  481. } else {
  482. modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
  483. }
  484. printf("3/4 Report slave ID: \n");
  485. /* tab_rp_bits is used to store bytes */
  486. rc = modbus_report_slave_id(ctx, tab_rp_bits);
  487. if (rc == -1) {
  488. printf("FAILED\n");
  489. goto close;
  490. }
  491. if (((use_backend == RTU) && (tab_rp_bits[0] == SERVER_ID))
  492. || tab_rp_bits[0] == 0xFF) {
  493. printf("OK\n");
  494. } else {
  495. printf("FAILED\n");
  496. goto close;
  497. }
  498. /* Save original timeout */
  499. modbus_get_response_timeout(ctx, &old_response_timeout);
  500. /* Define a new and too short timeout */
  501. response_timeout.tv_sec = 0;
  502. response_timeout.tv_usec = 0;
  503. modbus_set_response_timeout(ctx, &response_timeout);
  504. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  505. UT_REGISTERS_NB, tab_rp_registers);
  506. printf("4/4 Too short timeout: ");
  507. if (rc == -1 && errno == ETIMEDOUT) {
  508. printf("OK\n");
  509. } else {
  510. printf("FAILED (can fail on slow systems or Windows)\n");
  511. }
  512. /* Restore original timeout */
  513. modbus_set_response_timeout(ctx, &old_response_timeout);
  514. /* Wait for data before flushing */
  515. usleep(500000);
  516. modbus_flush(ctx);
  517. /** BAD RESPONSE **/
  518. printf("\nTEST BAD RESPONSE ERROR:\n");
  519. /* Allocate only the required space */
  520. tab_rp_registers_bad = (uint16_t *) malloc(
  521. UT_REGISTERS_NB_SPECIAL * sizeof(uint16_t));
  522. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  523. UT_REGISTERS_NB_SPECIAL, 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, tab_rp_registers);
  536. printf("* modbus_read_registers at special address: ");
  537. if (rc == -1 && errno == EMBXSBUSY) {
  538. printf("OK\n");
  539. } else {
  540. printf("FAILED\n");
  541. goto close;
  542. }
  543. /** RAW REQUEST */
  544. printf("\nTEST RAW REQUEST:\n");
  545. {
  546. const int RAW_REQ_LENGTH = 6;
  547. uint8_t raw_req[] = { (use_backend == RTU) ? SERVER_ID : 0xFF,
  548. 0x03, 0x00, 0x01, 0x0, 0x05 };
  549. int req_length;
  550. uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
  551. req_length = modbus_send_raw_request(ctx, raw_req,
  552. RAW_REQ_LENGTH * sizeof(uint8_t));
  553. printf("* modbus_send_raw_request: ");
  554. if ((use_backend == RTU && req_length == (RAW_REQ_LENGTH + 2)) ||
  555. ((use_backend == TCP || use_backend == TCP_PI) &&
  556. req_length == (RAW_REQ_LENGTH + 6))) {
  557. printf("OK\n");
  558. } else {
  559. printf("FAILED (%d)\n", req_length);
  560. goto close;
  561. }
  562. printf("* modbus_receive_confirmation: ");
  563. rc = modbus_receive_confirmation(ctx, rsp);
  564. if ((use_backend == RTU && rc == 15) ||
  565. ((use_backend == TCP || use_backend == TCP_PI) &&
  566. rc == 19)) {
  567. printf("OK\n");
  568. } else {
  569. printf("FAILED (%d)\n", rc);
  570. goto close;
  571. }
  572. }
  573. printf("\nALL TESTS PASS WITH SUCCESS.\n");
  574. close:
  575. /* Free the memory */
  576. free(tab_rp_bits);
  577. free(tab_rp_registers);
  578. /* Close the connection */
  579. modbus_close(ctx);
  580. modbus_free(ctx);
  581. return 0;
  582. }