unit-test-server.c
Go to the documentation of this file.
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 
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <modbus.h>
24 
25 #include "unit-test.h"
26 
27 enum {
28  TCP,
31 };
32 
33 int main(int argc, char*argv[])
34 {
35  int socket;
36  modbus_t *ctx;
38  int rc;
39  int i;
40  int use_backend;
41  uint8_t *query;
42  int header_length;
43 
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 server for unit testing\n\n", argv[0]);
53  return -1;
54  }
55  } else {
56  /* By default */
57  use_backend = TCP;
58  }
59 
60  if (use_backend == TCP) {
61  ctx = modbus_new_tcp("127.0.0.1", 1502);
62  query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
63  } else if (use_backend == TCP_PI) {
64  ctx = modbus_new_tcp_pi("::0", "1502");
65  query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
66  } else {
67  ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
69  query = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
70  }
71  header_length = modbus_get_header_length(ctx);
72 
73  modbus_set_debug(ctx, TRUE);
74 
75  mb_mapping = modbus_mapping_new(
76  UT_BITS_ADDRESS + UT_BITS_NB,
77  UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,
78  UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
79  UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);
80  if (mb_mapping == NULL) {
81  fprintf(stderr, "Failed to allocate the mapping: %s\n",
82  modbus_strerror(errno));
83  modbus_free(ctx);
84  return -1;
85  }
86 
87  /* Examples from PI_MODBUS_300.pdf.
88  Only the read-only input values are assigned. */
89 
92  UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
93  UT_INPUT_BITS_TAB);
94 
96  for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
97  mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
98  UT_INPUT_REGISTERS_TAB[i];;
99  }
100 
101  if (use_backend == TCP) {
102  socket = modbus_tcp_listen(ctx, 1);
103  modbus_tcp_accept(ctx, &socket);
104  } else if (use_backend == TCP_PI) {
105  socket = modbus_tcp_pi_listen(ctx, 1);
106  modbus_tcp_pi_accept(ctx, &socket);
107  } else {
108  rc = modbus_connect(ctx);
109  if (rc == -1) {
110  fprintf(stderr, "Unable to connect %s\n", modbus_strerror(errno));
111  modbus_free(ctx);
112  return -1;
113  }
114  }
115 
116  for (;;) {
117  rc = modbus_receive(ctx, query);
118  if (rc == -1) {
119  /* Connection closed by the client or error */
120  break;
121  }
122 
123  /* Read holding registers */
124  if (query[header_length] == 0x03) {
125  if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3)
126  == UT_REGISTERS_NB_SPECIAL) {
127  printf("Set an incorrect number of values\n");
128  MODBUS_SET_INT16_TO_INT8(query, header_length + 3,
129  UT_REGISTERS_NB_SPECIAL - 1);
130  } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
131  == UT_REGISTERS_ADDRESS_SPECIAL) {
132  printf("Reply to this special register address by an exception\n");
133  modbus_reply_exception(ctx, query,
135  continue;
136  }
137  }
138 
139  rc = modbus_reply(ctx, query, rc, mb_mapping);
140  if (rc == -1) {
141  break;
142  }
143  }
144 
145  printf("Quit the loop: %s\n", modbus_strerror(errno));
146 
147  if (use_backend == TCP) {
148  close(socket);
149  }
150  modbus_mapping_free(mb_mapping);
151  free(query);
152  modbus_free(ctx);
153 
154  return 0;
155 }
modbus_mapping_t * modbus_mapping_new(int nb_coil_status, int nb_input_status, int nb_holding_registers, int nb_input_registers)
Definition: modbus.c:1547
int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code)
Definition: modbus.c:982
#define MODBUS_RTU_MAX_ADU_LENGTH
Definition: modbus-rtu.h:29
int main(int argc, char *argv[])
int modbus_receive(modbus_t *ctx, uint8_t *req)
Definition: modbus.c:460
uint8_t * tab_input_bits
Definition: modbus.h:133
#define MODBUS_TCP_MAX_ADU_LENGTH
Definition: modbus-tcp.h:41
void modbus_free(modbus_t *ctx)
Definition: modbus.c:1528
#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value)
Definition: modbus.h:205
void modbus_set_debug(modbus_t *ctx, int boolean)
Definition: modbus.c:1537
int modbus_set_slave(modbus_t *ctx, int slave)
Definition: modbus.c:1465
int modbus_reply(modbus_t *ctx, const uint8_t *req, int req_length, modbus_mapping_t *mb_mapping)
Definition: modbus.c:641
int modbus_tcp_accept(modbus_t *ctx, int *socket)
Definition: modbus-tcp.c:524
#define SERVER_ID
#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index)
Definition: modbus.h:204
int modbus_tcp_pi_accept(modbus_t *ctx, int *socket)
Definition: modbus-tcp.c:545
int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
Definition: modbus-tcp.c:387
modbus_t * ctx
const char * modbus_strerror(int errnum)
Definition: modbus.c:53
int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
Definition: modbus-tcp.c:430
void modbus_set_bits_from_bytes(uint8_t *dest, int index, unsigned int nb_bits, const uint8_t *tab_byte)
Definition: modbus-data.c:41
uint16_t * tab_input_registers
Definition: modbus.h:134
int modbus_get_header_length(modbus_t *ctx)
Definition: modbus.c:1510
void modbus_mapping_free(modbus_mapping_t *mb_mapping)
Definition: modbus.c:1625
#define TRUE
Definition: modbus.h:52
modbus_t * modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)
Definition: modbus-rtu.c:917
modbus_t * modbus_new_tcp_pi(const char *node, const char *service)
Definition: modbus-tcp.c:689
int modbus_connect(modbus_t *ctx)
Definition: modbus.c:1515
modbus_mapping_t * mb_mapping
modbus_t * modbus_new_tcp(const char *ip_address, int port)
Definition: modbus-tcp.c:636


libmodbus
Author(s):
autogenerated on Sat Nov 21 2020 03:17:32