unit-test-client.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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. int main(void)
  25. {
  26. uint8_t *tab_rp_bits;
  27. uint16_t *tab_rp_registers;
  28. uint16_t *tab_rp_registers_bad;
  29. modbus_t *ctx;
  30. int is_mode_rtu = FALSE;
  31. int i;
  32. uint8_t value;
  33. int address;
  34. int nb_points;
  35. int rc;
  36. float real;
  37. struct timeval timeout_begin_old;
  38. struct timeval timeout_begin_new;
  39. /*
  40. ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'N', 8, 1);
  41. modbus_set_slave(ctx, SERVER_ID);
  42. is_mode_rtu = TRUE;
  43. */
  44. /* TCP */
  45. ctx = modbus_new_tcp("127.0.0.1", 1502);
  46. if (ctx == NULL) {
  47. fprintf(stderr, "Unable to initialize TCP Modbus\n");
  48. return -1;
  49. }
  50. modbus_set_debug(ctx, TRUE);
  51. if (modbus_connect(ctx) == -1) {
  52. fprintf(stderr, "Connection failed: %s\n",
  53. modbus_strerror(errno));
  54. modbus_free(ctx);
  55. return -1;
  56. }
  57. /* Allocate and initialize the memory to store the bits */
  58. nb_points = (UT_BITS_NB_POINTS > UT_INPUT_BITS_NB_POINTS) ?
  59. UT_BITS_NB_POINTS : UT_INPUT_BITS_NB_POINTS;
  60. tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  61. memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));
  62. /* Allocate and initialize the memory to store the registers */
  63. nb_points = (UT_REGISTERS_NB_POINTS >
  64. UT_INPUT_REGISTERS_NB_POINTS) ?
  65. UT_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  66. tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  67. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  68. printf("** UNIT TESTING **\n");
  69. printf("\nTEST WRITE/READ:\n");
  70. /** COIL BITS **/
  71. /* Single */
  72. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON);
  73. printf("1/2 modbus_write_bit: ");
  74. if (rc == 1) {
  75. printf("OK\n");
  76. } else {
  77. printf("FAILED\n");
  78. goto close;
  79. }
  80. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
  81. printf("2/2 modbus_read_bits: ");
  82. if (rc != 1) {
  83. printf("FAILED (nb points %d)\n", rc);
  84. goto close;
  85. }
  86. if (tab_rp_bits[0] != ON) {
  87. printf("FAILED (%0X = != %0X)\n", tab_rp_bits[0], ON);
  88. goto close;
  89. }
  90. printf("OK\n");
  91. /* End single */
  92. /* Multiple bits */
  93. {
  94. uint8_t tab_value[UT_BITS_NB_POINTS];
  95. modbus_set_bits_from_bytes(tab_value, 0, UT_BITS_NB_POINTS,
  96. UT_BITS_TAB);
  97. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  98. UT_BITS_NB_POINTS, tab_value);
  99. printf("1/2 modbus_write_bits: ");
  100. if (rc == UT_BITS_NB_POINTS) {
  101. printf("OK\n");
  102. } else {
  103. printf("FAILED\n");
  104. goto close;
  105. }
  106. }
  107. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  108. UT_BITS_NB_POINTS, tab_rp_bits);
  109. printf("2/2 modbus_read_bits: ");
  110. if (rc != UT_BITS_NB_POINTS) {
  111. printf("FAILED (nb points %d)\n", rc);
  112. goto close;
  113. }
  114. i = 0;
  115. address = UT_BITS_ADDRESS;
  116. nb_points = UT_BITS_NB_POINTS;
  117. while (nb_points > 0) {
  118. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  119. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  120. if (value != UT_BITS_TAB[i]) {
  121. printf("FAILED (%0X != %0X)\n",
  122. value, UT_BITS_TAB[i]);
  123. goto close;
  124. }
  125. nb_points -= nb_bits;
  126. i++;
  127. }
  128. printf("OK\n");
  129. /* End of multiple bits */
  130. /** DISCRETE INPUTS **/
  131. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  132. UT_INPUT_BITS_NB_POINTS, tab_rp_bits);
  133. printf("1/1 modbus_read_input_bits: ");
  134. if (rc != UT_INPUT_BITS_NB_POINTS) {
  135. printf("FAILED (nb points %d)\n", rc);
  136. goto close;
  137. }
  138. i = 0;
  139. address = UT_INPUT_BITS_ADDRESS;
  140. nb_points = UT_INPUT_BITS_NB_POINTS;
  141. while (nb_points > 0) {
  142. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  143. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  144. if (value != UT_INPUT_BITS_TAB[i]) {
  145. printf("FAILED (%0X != %0X)\n",
  146. value, UT_INPUT_BITS_TAB[i]);
  147. goto close;
  148. }
  149. nb_points -= nb_bits;
  150. i++;
  151. }
  152. printf("OK\n");
  153. /** HOLDING REGISTERS **/
  154. /* Single register */
  155. rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x1234);
  156. printf("1/2 modbus_write_register: ");
  157. if (rc == 1) {
  158. printf("OK\n");
  159. } else {
  160. printf("FAILED\n");
  161. goto close;
  162. }
  163. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  164. 1, tab_rp_registers);
  165. printf("2/2 modbus_read_registers: ");
  166. if (rc != 1) {
  167. printf("FAILED (nb points %d)\n", rc);
  168. goto close;
  169. }
  170. if (tab_rp_registers[0] != 0x1234) {
  171. printf("FAILED (%0X != %0X)\n",
  172. tab_rp_registers[0], 0x1234);
  173. goto close;
  174. }
  175. printf("OK\n");
  176. /* End of single register */
  177. /* Many registers */
  178. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  179. UT_REGISTERS_NB_POINTS,
  180. UT_REGISTERS_TAB);
  181. printf("1/5 modbus_write_registers: ");
  182. if (rc == UT_REGISTERS_NB_POINTS) {
  183. printf("OK\n");
  184. } else {
  185. printf("FAILED\n");
  186. goto close;
  187. }
  188. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  189. UT_REGISTERS_NB_POINTS,
  190. tab_rp_registers);
  191. printf("2/5 modbus_read_registers: ");
  192. if (rc != UT_REGISTERS_NB_POINTS) {
  193. printf("FAILED (nb points %d)\n", rc);
  194. goto close;
  195. }
  196. for (i=0; i < UT_REGISTERS_NB_POINTS; i++) {
  197. if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
  198. printf("FAILED (%0X != %0X)\n",
  199. tab_rp_registers[i],
  200. UT_REGISTERS_TAB[i]);
  201. goto close;
  202. }
  203. }
  204. printf("OK\n");
  205. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  206. 0, tab_rp_registers);
  207. printf("3/5 modbus_read_registers (0): ");
  208. if (rc != 0) {
  209. printf("FAILED (nb points %d)\n", rc);
  210. goto close;
  211. }
  212. printf("OK\n");
  213. nb_points = (UT_REGISTERS_NB_POINTS >
  214. UT_INPUT_REGISTERS_NB_POINTS) ?
  215. UT_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  216. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  217. /* Write registers to zero from tab_rp_registers and read registers to
  218. tab_rp_registers. They should be same as UT_REGISTERS_TAB. */
  219. rc = modbus_read_and_write_registers(ctx,
  220. UT_REGISTERS_ADDRESS,
  221. UT_REGISTERS_NB_POINTS,
  222. tab_rp_registers,
  223. UT_REGISTERS_ADDRESS,
  224. UT_REGISTERS_NB_POINTS,
  225. tab_rp_registers);
  226. printf("4/5 modbus_read_and_write_registers, read part: ");
  227. if (rc != UT_REGISTERS_NB_POINTS) {
  228. printf("FAILED (nb points %d)\n", rc);
  229. goto close;
  230. }
  231. for (i=0; i < UT_REGISTERS_NB_POINTS; i++) {
  232. if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
  233. printf("FAILED (%0X != %0X)\n",
  234. tab_rp_registers[i],
  235. UT_REGISTERS_TAB[i]);
  236. goto close;
  237. }
  238. }
  239. printf("OK\n");
  240. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  241. UT_REGISTERS_NB_POINTS,
  242. tab_rp_registers);
  243. printf("5/5 modbus_read_and_write_registers, write part: ");
  244. if (rc != UT_REGISTERS_NB_POINTS) {
  245. printf("FAILED (nb points %d)\n", rc);
  246. goto close;
  247. }
  248. for (i=0; i < UT_REGISTERS_NB_POINTS; i++) {
  249. if (tab_rp_registers[i] != 0) {
  250. printf("FAILED (%0X != %0X)\n",
  251. tab_rp_registers[i],
  252. UT_REGISTERS_TAB[i]);
  253. goto close;
  254. }
  255. }
  256. printf("OK\n");
  257. /* End of many registers */
  258. /** INPUT REGISTERS **/
  259. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  260. UT_INPUT_REGISTERS_NB_POINTS,
  261. tab_rp_registers);
  262. printf("1/1 modbus_read_input_registers: ");
  263. if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
  264. printf("FAILED (nb points %d)\n", rc);
  265. goto close;
  266. }
  267. for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
  268. if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  269. printf("FAILED (%0X != %0X)\n",
  270. tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  271. goto close;
  272. }
  273. }
  274. printf("OK\n");
  275. printf("\nTEST FLOATS\n");
  276. /** FLOAT **/
  277. printf("1/2 Set float: ");
  278. modbus_set_float(UT_REAL, tab_rp_registers);
  279. if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  280. tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  281. printf("OK\n");
  282. } else {
  283. printf("FAILED (%x != %x)\n",
  284. *((uint32_t *)tab_rp_registers), UT_IREAL);
  285. goto close;
  286. }
  287. printf("2/2 Get float: ");
  288. real = modbus_get_float(tab_rp_registers);
  289. if (real == UT_REAL) {
  290. printf("OK\n");
  291. } else {
  292. printf("FAILED (%f != %f)\n", real, UT_REAL);
  293. goto close;
  294. }
  295. printf("\nAt this point, error messages doesn't mean the test has failed\n");
  296. /** ILLEGAL DATA ADDRESS **/
  297. printf("\nTEST ILLEGAL DATA ADDRESS:\n");
  298. /* The mapping begins at 0 and ending at address + nb_points so
  299. * the addresses below are not valid. */
  300. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  301. UT_BITS_NB_POINTS + 1,
  302. 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_POINTS + 1,
  312. tab_rp_bits);
  313. printf("* modbus_read_input_bits: ");
  314. if (rc == -1 && errno == EMBXILADD)
  315. printf("OK\n");
  316. else {
  317. printf("FAILED\n");
  318. goto close;
  319. }
  320. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  321. UT_REGISTERS_NB_POINTS + 1,
  322. tab_rp_registers);
  323. printf("* modbus_read_registers: ");
  324. if (rc == -1 && errno == EMBXILADD)
  325. printf("OK\n");
  326. else {
  327. printf("FAILED\n");
  328. goto close;
  329. }
  330. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  331. UT_INPUT_REGISTERS_NB_POINTS + 1,
  332. tab_rp_registers);
  333. printf("* modbus_read_input_registers: ");
  334. if (rc == -1 && errno == EMBXILADD)
  335. printf("OK\n");
  336. else {
  337. printf("FAILED\n");
  338. goto close;
  339. }
  340. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS, ON);
  341. printf("* modbus_write_bit: ");
  342. if (rc == -1 && errno == EMBXILADD) {
  343. printf("OK\n");
  344. } else {
  345. printf("FAILED\n");
  346. goto close;
  347. }
  348. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS,
  349. UT_BITS_NB_POINTS,
  350. tab_rp_bits);
  351. printf("* modbus_write_coils: ");
  352. if (rc == -1 && errno == EMBXILADD) {
  353. printf("OK\n");
  354. } else {
  355. printf("FAILED\n");
  356. goto close;
  357. }
  358. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS +
  359. UT_REGISTERS_NB_POINTS,
  360. UT_REGISTERS_NB_POINTS,
  361. tab_rp_registers);
  362. printf("* modbus_write_registers: ");
  363. if (rc == -1 && errno == EMBXILADD) {
  364. printf("OK\n");
  365. } else {
  366. printf("FAILED\n");
  367. goto close;
  368. }
  369. /** TOO MANY DATA **/
  370. printf("\nTEST TOO MANY DATA ERROR:\n");
  371. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, MODBUS_MAX_READ_BITS + 1,
  372. tab_rp_bits);
  373. printf("* modbus_read_bits: ");
  374. if (rc == -1 && errno == EMBMDATA) {
  375. printf("OK\n");
  376. } else {
  377. printf("FAILED\n");
  378. goto close;
  379. }
  380. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  381. MODBUS_MAX_READ_BITS + 1,
  382. tab_rp_bits);
  383. printf("* modbus_read_input_bits: ");
  384. if (rc == -1 && errno == EMBMDATA) {
  385. printf("OK\n");
  386. } else {
  387. printf("FAILED\n");
  388. goto close;
  389. }
  390. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  391. MODBUS_MAX_READ_REGISTERS + 1,
  392. tab_rp_registers);
  393. printf("* modbus_read_registers: ");
  394. if (rc == -1 && errno == EMBMDATA) {
  395. printf("OK\n");
  396. } else {
  397. printf("FAILED\n");
  398. goto close;
  399. }
  400. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  401. MODBUS_MAX_READ_REGISTERS + 1,
  402. tab_rp_registers);
  403. printf("* modbus_read_input_registers: ");
  404. if (rc == -1 && errno == EMBMDATA) {
  405. printf("OK\n");
  406. } else {
  407. printf("FAILED\n");
  408. goto close;
  409. }
  410. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  411. MODBUS_MAX_WRITE_BITS + 1,
  412. tab_rp_bits);
  413. printf("* modbus_write_bits: ");
  414. if (rc == -1 && errno == EMBMDATA) {
  415. printf("OK\n");
  416. } else {
  417. goto close;
  418. printf("FAILED\n");
  419. }
  420. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  421. MODBUS_MAX_WRITE_REGISTERS + 1,
  422. tab_rp_registers);
  423. printf("* modbus_write_registers: ");
  424. if (rc == -1 && errno == EMBMDATA) {
  425. printf("OK\n");
  426. } else {
  427. printf("FAILED\n");
  428. goto close;
  429. }
  430. /** SLAVE REPLY **/
  431. printf("\nTEST SLAVE REPLY:\n");
  432. modbus_set_slave(ctx, 18);
  433. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  434. UT_REGISTERS_NB_POINTS,
  435. tab_rp_registers);
  436. printf("1/4 No or response from slave %d: ", 18);
  437. if (is_mode_rtu) {
  438. /* No response in RTU mode */
  439. if (rc == -1 && errno == ETIMEDOUT) {
  440. printf("OK\n");
  441. } else {
  442. printf("FAILED\n");
  443. goto close;
  444. }
  445. } else {
  446. /* Response in TCP mode */
  447. if (rc == UT_REGISTERS_NB_POINTS) {
  448. printf("OK\n");
  449. } else {
  450. printf("FAILED\n");
  451. goto close;
  452. }
  453. }
  454. modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
  455. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  456. UT_REGISTERS_NB_POINTS,
  457. tab_rp_registers);
  458. printf("2/4 Reply after a broadcast query: ");
  459. if (rc == UT_REGISTERS_NB_POINTS) {
  460. printf("OK\n");
  461. } else {
  462. printf("FAILED\n");
  463. goto close;
  464. }
  465. /* Restore slave */
  466. if (is_mode_rtu) {
  467. modbus_set_slave(ctx, SERVER_ID);
  468. } else {
  469. modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
  470. }
  471. printf("3/4 Report slave ID: \n");
  472. /* tab_rp_bits is used to store bytes */
  473. rc = modbus_report_slave_id(ctx, tab_rp_bits);
  474. if (rc == -1) {
  475. printf("FAILED\n");
  476. goto close;
  477. }
  478. if ((is_mode_rtu && tab_rp_bits[0] == SERVER_ID)
  479. || tab_rp_bits[0] == 0xFF) {
  480. printf("OK\n");
  481. } else {
  482. printf("FAILED\n");
  483. goto close;
  484. }
  485. /* Save original timeout */
  486. modbus_get_timeout_begin(ctx, &timeout_begin_old);
  487. /* Define a new and too short timeout */
  488. timeout_begin_new.tv_sec = 0;
  489. timeout_begin_new.tv_usec = 0;
  490. modbus_set_timeout_begin(ctx, &timeout_begin_new);
  491. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  492. UT_REGISTERS_NB_POINTS,
  493. tab_rp_registers);
  494. printf("4/4 Too short timeout: ");
  495. if (rc == -1 && errno == ETIMEDOUT) {
  496. printf("OK\n");
  497. } else {
  498. printf("FAILED\n");
  499. goto close;
  500. }
  501. /* Restore original timeout */
  502. modbus_set_timeout_begin(ctx, &timeout_begin_old);
  503. /** BAD RESPONSE **/
  504. printf("\nTEST BAD RESPONSE ERROR:\n");
  505. /* Allocate only the required space */
  506. tab_rp_registers_bad = (uint16_t *) malloc(
  507. UT_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
  508. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  509. UT_REGISTERS_NB_POINTS_SPECIAL,
  510. tab_rp_registers_bad);
  511. printf("* modbus_read_registers: ");
  512. if (rc == -1 && errno == EMBBADDATA) {
  513. printf("OK\n");
  514. } else {
  515. printf("FAILED\n");
  516. goto close;
  517. }
  518. free(tab_rp_registers_bad);
  519. printf("\nALL TESTS PASS WITH SUCCESS.\n");
  520. close:
  521. /* Free the memory */
  522. free(tab_rp_bits);
  523. free(tab_rp_registers);
  524. /* Close the connection */
  525. modbus_close(ctx);
  526. modbus_free(ctx);
  527. return 0;
  528. }