unit-test-client.c 18 KB

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