unit-test-client.c 20 KB

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