Browse Source

The slave only listen when concerned (slave ID or broadcast)

- MAJOR changes to the API (see MIGRATION)
- New unit tests
- Removed TODO list
- Updated NEWS & MIGRATION files
Stéphane Raimbault 16 năm trước cách đây
mục cha
commit
cdc536c9ad

+ 25 - 18
MIGRATION

@@ -1,36 +1,43 @@
-=============================
-Migration from the 2.0 series
-=============================
+=============================================
+Migration notes from the 2.0 series (for 2.2)
+=============================================
 
-modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and
-requires a new argument, the maximal number of connections:
+1 - modbus_init_rtu/tcp takes a new argument: the slave and it is only required
+    in that function (eg. read_coil_status doesn't receive the slave ID in
+    argument anymore). If you need to use different slaves with the same
+    connection (eg. RS485), you can copy modbus_param_t or set
+    modbus_param_t.slave to a different value when required.
+
+2 - modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and
+    requires a new argument, the maximal number of connections:
 
 int modbus_slave_init_tcp(modbus_param_t *mb_param, int nb_connection);
 
 
-New function modbus_slave_accept_tcp() to etablish a new connection (previously
-in modbus_init_listen_tcp()):
+3 - New function modbus_slave_accept_tcp() to etablish a new connection
+    (previously in modbus_init_listen_tcp()):
 
 int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
 
 
-modbus_listen() has been renamed to modbus_slave_receive() and requires a new
-argument, the socket file descriptor to listen on. If the sockfd is -1, the
-internal fd of modbus_param_t is used:
+4 - modbus_listen() has been renamed to modbus_slave_receive() and requires a
+    new argument, the socket file descriptor to listen on. If the sockfd is -1,
+    the internal fd of modbus_param_t is used:
 
 int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
                          uint8_t *query, int *query_length);
 
 
-If you use the HEADER_LENGTH_ defines, their values have been incremented by 1
-to reflect the PDU and ADU of the Modbus protocol and to reduce the CPU
-consumption:
- - HEADER_LENGTH_RTU           0 -> 1
- - HEADER_LENGTH_TCP           6 -> 7
+5 - If you use the HEADER_LENGTH_ defines, their values have been incremented by
+    1 to reflect the PDU and ADU of the Modbus protocol and to reduce the CPU
+    consumption:
+     - HEADER_LENGTH_RTU           0 -> 1
+     - HEADER_LENGTH_TCP           6 -> 7
+
 
-===================================
-Migration notes from the 1.2 series
-===================================
+=============================================
+Migration notes from the 1.2 series (for 2.0)
+=============================================
 
 Init
 ====

+ 4 - 0
NEWS

@@ -1,7 +1,11 @@
 libmodbus 2.2.0 (2009-05-01)
 ============================
 - New API for slave server (see MIGRATION)
+- New slave server able to handle multiple connections
+- Slave only replies to broadcast queries or queries with its slave ID
+- Improved Modbus protocol conformance
 - modbus_param_t is smaller (2 int removed)
+- Faster
 
 libmodbus 2.0.3 (2009-03-22)
 ============================

+ 0 - 4
TODO

@@ -1,4 +0,0 @@
-Features
-* broadcasting
-* slave must listen only request sent for him
-

+ 43 - 41
src/modbus.c

@@ -259,16 +259,16 @@ static int build_query_basis_tcp(int slave, int function,
         return PRESET_QUERY_LENGTH_TCP;
 }
 
-static int build_query_basis(modbus_param_t *mb_param, int slave,
+static int build_query_basis(modbus_param_t *mb_param,
                              int function, int start_addr,
                              int nb, uint8_t *query)
 {
         if (mb_param->type_com == RTU)
-                return build_query_basis_rtu(slave, function, start_addr,
-                                             nb, query);
+                return build_query_basis_rtu(mb_param->slave, function, 
+                                             start_addr, nb, query);
         else
-                return build_query_basis_tcp(slave, function, start_addr,
-                                             nb, query);
+                return build_query_basis_tcp(mb_param->slave, function,
+                                             start_addr, nb, query);
 }
 
 /* Builds a RTU response header */
@@ -798,7 +798,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
    If an error occurs, this function construct the response
    accordingly.
 */
-void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
+void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
                          int query_length, modbus_mapping_t *mb_mapping)
 {
         int offset = TAB_HEADER_LENGTH[mb_param->type_com];
@@ -808,6 +808,14 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
         uint8_t response[MAX_MESSAGE_LENGTH];
         int resp_length = 0;
         sft_t sft;
+        
+	if (slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) {
+                // Ignores the query (not for me)
+                if (mb_param->debug) {
+                        printf("Dropped request from slave %d (!= %d)\n", slave, mb_param->slave);
+                }
+		return;
+	}
 
         sft.slave = slave;
         sft.function = function;
@@ -987,7 +995,7 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
 }
 
 /* Reads IO status */
-static int read_io_status(modbus_param_t *mb_param, int slave, int function,
+static int read_io_status(modbus_param_t *mb_param, int function,
                           int start_addr, int nb, uint8_t *data_dest)
 {
         int ret;
@@ -996,7 +1004,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
         uint8_t query[MIN_QUERY_LENGTH];
         uint8_t response[MAX_MESSAGE_LENGTH];
 
-        query_length = build_query_basis(mb_param, slave, function,
+        query_length = build_query_basis(mb_param, function,
                                          start_addr, nb, query);
 
         ret = modbus_send(mb_param, query, query_length);
@@ -1029,7 +1037,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
 
 /* Reads the boolean status of coils and sets the array elements
    in the destination to TRUE or FALSE. */
-int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
+int read_coil_status(modbus_param_t *mb_param, int start_addr,
                      int nb, uint8_t *data_dest)
 {
         int status;
@@ -1040,7 +1048,7 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
                 return TOO_MANY_DATA;
         }
 
-        status = read_io_status(mb_param, slave, FC_READ_COIL_STATUS,
+        status = read_io_status(mb_param, FC_READ_COIL_STATUS,
                                 start_addr, nb, data_dest);
 
         if (status > 0)
@@ -1051,7 +1059,7 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
 
 
 /* Same as read_coil_status but reads the slaves input table */
-int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
+int read_input_status(modbus_param_t *mb_param, int start_addr,
                       int nb, uint8_t *data_dest)
 {
         int status;
@@ -1062,7 +1070,7 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
                 return TOO_MANY_DATA;
         }
 
-        status = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS,
+        status = read_io_status(mb_param, FC_READ_INPUT_STATUS,
                                 start_addr, nb, data_dest);
 
         if (status > 0)
@@ -1072,7 +1080,7 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
 }
 
 /* Reads the data from a modbus slave and put that data into an array */
-static int read_registers(modbus_param_t *mb_param, int slave, int function,
+static int read_registers(modbus_param_t *mb_param, int function,
                           int start_addr, int nb, uint16_t *data_dest)
 {
         int ret;
@@ -1086,7 +1094,7 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
                 return TOO_MANY_DATA;
         }
 
-        query_length = build_query_basis(mb_param, slave, function,
+        query_length = build_query_basis(mb_param, function,
                                          start_addr, nb, query);
 
         ret = modbus_send(mb_param, query, query_length);
@@ -1111,7 +1119,7 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
 
 /* Reads the holding registers in a slave and put the data into an
    array */
-int read_holding_registers(modbus_param_t *mb_param, int slave,
+int read_holding_registers(modbus_param_t *mb_param,
                            int start_addr, int nb, uint16_t *data_dest)
 {
         int status;
@@ -1122,15 +1130,15 @@ int read_holding_registers(modbus_param_t *mb_param, int slave,
                 return TOO_MANY_DATA;
         }
 
-        status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,
+        status = read_registers(mb_param, FC_READ_HOLDING_REGISTERS,
                                 start_addr, nb, data_dest);
         return status;
 }
 
 /* Reads the input registers in a slave and put the data into
    an array */
-int read_input_registers(modbus_param_t *mb_param, int slave,
-                         int start_addr, int nb, uint16_t *data_dest)
+int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
+                         uint16_t *data_dest)
 {
         int status;
 
@@ -1140,7 +1148,7 @@ int read_input_registers(modbus_param_t *mb_param, int slave,
                 return TOO_MANY_DATA;
         }
 
-        status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,
+        status = read_registers(mb_param, FC_READ_INPUT_REGISTERS,
                                 start_addr, nb, data_dest);
 
         return status;
@@ -1148,14 +1156,14 @@ int read_input_registers(modbus_param_t *mb_param, int slave,
 
 /* Sends a value to a register in a slave.
    Used by force_single_coil and preset_single_register */
-static int set_single(modbus_param_t *mb_param, int slave, int function,
+static int set_single(modbus_param_t *mb_param, int function,
                       int addr, int value)
 {
         int ret;
         int query_length;
         uint8_t query[MIN_QUERY_LENGTH];
 
-        query_length = build_query_basis(mb_param, slave, function,
+        query_length = build_query_basis(mb_param, function,
                                          addr, value, query);
 
         ret = modbus_send(mb_param, query, query_length);
@@ -1170,35 +1178,32 @@ static int set_single(modbus_param_t *mb_param, int slave, int function,
 }
 
 /* Turns ON or OFF a single coil in the slave device */
-int force_single_coil(modbus_param_t *mb_param, int slave,
-                      int coil_addr, int state)
+int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state)
 {
         int status;
 
         if (state)
                 state = 0xFF00;
 
-        status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL,
+        status = set_single(mb_param, FC_FORCE_SINGLE_COIL,
                             coil_addr, state);
 
         return status;
 }
 
 /* Sets a value in one holding register in the slave device */
-int preset_single_register(modbus_param_t *mb_param, int slave,
-                           int reg_addr, int value)
+int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value)
 {
         int status;
 
-        status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER,
+        status = set_single(mb_param, FC_PRESET_SINGLE_REGISTER,
                             reg_addr, value);
 
         return status;
 }
 
 /* Sets/resets the coils in the slave from an array in argument */
-int force_multiple_coils(modbus_param_t *mb_param, int slave,
-                         int start_addr, int nb,
+int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
                          const uint8_t *data_src)
 {
         int ret;
@@ -1216,8 +1221,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
                 return TOO_MANY_DATA;
         }
 
-        query_length = build_query_basis(mb_param, slave,
-                                         FC_FORCE_MULTIPLE_COILS,
+        query_length = build_query_basis(mb_param, FC_FORCE_MULTIPLE_COILS,
                                          start_addr, nb, query);
         byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
         query[query_length++] = byte_count;
@@ -1250,8 +1254,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
 }
 
 /* Copies the values in the slave from the array given in argument */
-int preset_multiple_registers(modbus_param_t *mb_param, int slave,
-                              int start_addr, int nb,
+int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
                               const uint16_t *data_src)
 {
         int ret;
@@ -1267,8 +1270,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
                 return TOO_MANY_DATA;
         }
 
-        query_length = build_query_basis(mb_param, slave,
-                                         FC_PRESET_MULTIPLE_REGISTERS,
+        query_length = build_query_basis(mb_param, FC_PRESET_MULTIPLE_REGISTERS,
                                          start_addr, nb, query);
         byte_count = nb * 2;
         query[query_length++] = byte_count;
@@ -1288,15 +1290,13 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
 }
 
 /* Returns the slave id! */
-int report_slave_id(modbus_param_t *mb_param, int slave,
-                    uint8_t *data_dest)
+int report_slave_id(modbus_param_t *mb_param, uint8_t *data_dest)
 {
         int ret;
         int query_length;
         uint8_t query[MIN_QUERY_LENGTH];
 
-        query_length = build_query_basis(mb_param, slave, FC_REPORT_SLAVE_ID,
-                                         0, 0, query);
+        query_length = build_query_basis(mb_param, FC_REPORT_SLAVE_ID, 0, 0, query);
 
         /* HACKISH, start_addr and count are not used */
         query_length -= 4;
@@ -1333,7 +1333,7 @@ int report_slave_id(modbus_param_t *mb_param, int slave,
 */
 void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
                      int baud, const char *parity, int data_bit,
-                     int stop_bit)
+                     int stop_bit, int slave)
 {
         memset(mb_param, 0, sizeof(modbus_param_t));
         strcpy(mb_param->device, device);
@@ -1344,6 +1344,7 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
         mb_param->stop_bit = stop_bit;
         mb_param->type_com = RTU;
         mb_param->error_handling = FLUSH_OR_RECONNECT_ON_ERROR;
+        mb_param->slave = slave;
 }
 
 /* Initializes the modbus_param_t structure for TCP.
@@ -1355,13 +1356,14 @@ void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
    to 1024 because it's not necessary to be root to use this port
    number.
 */
-void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port)
+void modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port, int slave)
 {
         memset(mb_param, 0, sizeof(modbus_param_t));
         strncpy(mb_param->ip, ip, sizeof(char)*16);
         mb_param->port = port;
         mb_param->type_com = TCP;
         mb_param->error_handling = FLUSH_OR_RECONNECT_ON_ERROR;
+        mb_param->slave = slave;
 }
 
 /* By default, the error handling mode used is FLUSH_OR_RECONNECT_ON_ERROR.

+ 25 - 22
src/modbus.h

@@ -27,6 +27,7 @@ extern "C" {
 #endif
 
 #define MODBUS_TCP_DEFAULT_PORT   502
+#define MODBUS_BROADCAST_ADDRESS  255
 
 /* Slave index */
 #define HEADER_LENGTH_RTU           1
@@ -135,6 +136,8 @@ typedef enum { FLUSH_OR_RECONNECT_ON_ERROR, NOP_ON_ERROR } error_handling_t;
 
 /* This structure is byte-aligned */
 typedef struct {
+        /* Slave address */
+        int slave;
         /* Descriptor (tty or socket) */
         int fd;
         /* Communication mode: RTU or TCP */
@@ -189,41 +192,39 @@ typedef struct {
 
 /* Reads the boolean status of coils and sets the array elements in
    the destination to TRUE or FALSE */
-int read_coil_status(modbus_param_t *mb_param, int slave,
-                     int start_addr, int nb, uint8_t *dest);
+int read_coil_status(modbus_param_t *mb_param, int start_addr, int nb,
+                     uint8_t *dest);
 
 /* Same as read_coil_status but reads the slaves input table */
-int read_input_status(modbus_param_t *mb_param, int slave,
-                      int start_addr, int nb, uint8_t *dest);
+int read_input_status(modbus_param_t *mb_param, int start_addr, int nb,
+                      uint8_t *dest);
 
 /* Reads the holding registers in a slave and put the data into an
    array */
-int read_holding_registers(modbus_param_t *mb_param, int slave,
-                           int start_addr, int nb, uint16_t *dest);
+int read_holding_registers(modbus_param_t *mb_param, int start_addr, int nb,
+                           uint16_t *dest);
 
 /* Reads the input registers in a slave and put the data into an
    array */
-int read_input_registers(modbus_param_t *mb_param, int slave,
-                         int start_addr, int nb, uint16_t *dest);
+int read_input_registers(modbus_param_t *mb_param, int start_addr, int nb,
+                         uint16_t *dest);
 
 /* Turns ON or OFF a single coil in the slave device */
-int force_single_coil(modbus_param_t *mb_param, int slave,
-                      int coil_addr, int state);
+int force_single_coil(modbus_param_t *mb_param, int coil_addr, int state);
 
 /* Sets a value in one holding register in the slave device */
-int preset_single_register(modbus_param_t *mb_param, int slave,
-                           int reg_addr, int value);
+int preset_single_register(modbus_param_t *mb_param, int reg_addr, int value);
 
 /* Sets/resets the coils in the slave from an array in argument */
-int force_multiple_coils(modbus_param_t *mb_param, int slave,
-                         int start_addr, int nb, const uint8_t *data);
+int force_multiple_coils(modbus_param_t *mb_param, int start_addr, int nb,
+                         const uint8_t *data);
 
 /* Copies the values in the slave from the array given in argument */
-int preset_multiple_registers(modbus_param_t *mb_param, int slave,
-                              int start_addr, int nb, const uint16_t *data);
+int preset_multiple_registers(modbus_param_t *mb_param, int start_addr, int nb,
+                              const uint16_t *data);
 
 /* Returns the slave id! */
-int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *dest);
+int report_slave_id(modbus_param_t *mb_param, uint8_t *dest);
 
 /* Initializes the modbus_param_t structure for RTU.
    - device: "/dev/ttyS0"
@@ -234,18 +235,20 @@ int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *dest);
 */
 void modbus_init_rtu(modbus_param_t *mb_param, const char *device,
                      int baud, const char *parity, int data_bit,
-                     int stop_bit);
+                     int stop_bit, int slave);
 
 /* Initializes the modbus_param_t structure for TCP.
-   - ip : "192.168.0.5"
-   - port : 1099
+   - ip: "192.168.0.5"
+   - port: 1099
+   - slave: 5
 
    Set the port to MODBUS_TCP_DEFAULT_PORT to use the default one
    (502). It's convenient to use a port number greater than or equal
    to 1024 because it's not necessary to be root to use this port
    number.
 */
-void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port);
+void modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port,
+                     int slave);
 
 /* By default, the error handling mode used is RECONNECT_ON_ERROR.
 
@@ -312,7 +315,7 @@ int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
    If an error occurs, this function construct the response
    accordingly.
 */
-void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
+void modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
                          int query_length, modbus_mapping_t *mb_mapping);
 
 

+ 3 - 3
tests/bandwidth-master.c

@@ -53,7 +53,7 @@ int main(void)
         uint32_t rate;
 
         /* TCP */
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         if (modbus_connect(&mb_param) == -1) {
                 printf("ERROR Connection failed\n");
                 exit(1);
@@ -72,7 +72,7 @@ int main(void)
         nb_points = MAX_STATUS;
         start = gettime_ms();
         for (i=0; i<NB_LOOPS; i++) {
-                ret = read_coil_status(&mb_param, SLAVE, 0, nb_points, tab_rp_status);
+                ret = read_coil_status(&mb_param, 0, nb_points, tab_rp_status);
         }
         end = gettime_ms();
         elapsed = end - start;
@@ -105,7 +105,7 @@ int main(void)
         nb_points = MAX_REGISTERS;
         start = gettime_ms();
         for (i=0; i<NB_LOOPS; i++) {
-                ret = read_holding_registers(&mb_param, SLAVE, 0, nb_points, tab_rp_registers);
+                ret = read_holding_registers(&mb_param, 0, nb_points, tab_rp_registers);
         }
         end = gettime_ms();
         elapsed = end - start;

+ 5 - 3
tests/bandwidth-slave-many-up.c

@@ -24,7 +24,9 @@
 
 #include "modbus.h"
 
-#define NB_CONNECTION 5
+#define SLAVE         0x11
+#define NB_CONNECTION    5
+
 int slave_socket;
 modbus_mapping_t mb_mapping;
 
@@ -48,7 +50,7 @@ int main(void)
         /* Maximum file descriptor number */
         int fdmax;
 
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
 
         ret = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
         if (ret == FALSE) {
@@ -109,7 +111,7 @@ int main(void)
 
                                         ret = modbus_slave_receive(&mb_param, master_socket, query, &query_size);
                                         if (ret == 0) {
-                                                modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
+                                                modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
                                         } else {
                                                 /* Connection closed by the client, end of server */
                                                 printf("Connection closed on socket %d\n", master_socket);

+ 4 - 2
tests/bandwidth-slave-one.c

@@ -22,6 +22,8 @@
 
 #include "modbus.h"
 
+#define SLAVE 0x11
+
 int main(void)
 {
         int socket;
@@ -29,7 +31,7 @@ int main(void)
         modbus_mapping_t mb_mapping;
         int ret;
 
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
 
         ret = modbus_mapping_new(&mb_mapping,  MAX_STATUS, 0, MAX_REGISTERS, 0);
         if (ret == FALSE) {
@@ -46,7 +48,7 @@ int main(void)
 
                 ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
                 if (ret == 0) {
-                        modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
+                        modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
                 } else if (ret == CONNECTION_CLOSED) {
                         /* Connection closed by the client, end of server */
                         break;

+ 11 - 12
tests/random-test-master.c

@@ -60,7 +60,7 @@ int main(void)
         /* modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, "none", 8, 1); */
 
         /* TCP */
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_set_debug(&mb_param, TRUE);
         if (modbus_connect(&mb_param) == -1) {
                 printf("ERROR Connection failed\n");
@@ -95,14 +95,14 @@ int main(void)
                         nb = ADDRESS_END - addr;
 
                         /* SINGLE COIL */
-                        ret = force_single_coil(&mb_param, SLAVE, addr, tab_rq_status[0]);
+                        ret = force_single_coil(&mb_param, addr, tab_rq_status[0]);
                         if (ret != 1) {
                                 printf("ERROR force_single_coil (%d)\n", ret);
                                 printf("Slave = %d, address = %d, value = %d\n",
                                        SLAVE, addr, tab_rq_status[0]);
                                 nb_fail++;
                         } else {
-                                ret = read_coil_status(&mb_param, SLAVE, addr, 1, tab_rp_status);
+                                ret = read_coil_status(&mb_param, addr, 1, tab_rp_status);
                                 if (ret != 1 || tab_rq_status[0] != tab_rp_status[0]) {
                                         printf("ERROR read_coil_status single (%d)\n", ret);
                                         printf("Slave = %d, address = %d\n",
@@ -112,14 +112,14 @@ int main(void)
                         }
 
                         /* MULTIPLE COILS */
-                        ret = force_multiple_coils(&mb_param, SLAVE, addr, nb, tab_rq_status);
+                        ret = force_multiple_coils(&mb_param, addr, nb, tab_rq_status);
                         if (ret != nb) {
                                 printf("ERROR force_multiple_coils (%d)\n", ret);
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                        SLAVE, addr, nb);
                                 nb_fail++;
                         } else {
-                                ret = read_coil_status(&mb_param, SLAVE, addr, nb, tab_rp_status);
+                                ret = read_coil_status(&mb_param, addr, nb, tab_rp_status);
                                 if (ret != nb) {
                                         printf("ERROR read_coil_status\n");
                                         printf("Slave = %d, address = %d, nb = %d\n",
@@ -140,15 +140,14 @@ int main(void)
                         }
 
                         /* SINGLE REGISTER */
-                        ret = preset_single_register(&mb_param, SLAVE, addr, tab_rq_registers[0]);
+                        ret = preset_single_register(&mb_param, addr, tab_rq_registers[0]);
                         if (ret != 1) {
                                 printf("ERROR preset_single_register (%d)\n", ret);
                                 printf("Slave = %d, address = %d, value = %d (0x%X)\n",
                                        SLAVE, addr, tab_rq_registers[0], tab_rq_registers[0]);
                                 nb_fail++;
                         } else {
-                                ret = read_holding_registers(&mb_param, SLAVE,
-                                                            addr, 1, tab_rp_registers);
+                                ret = read_holding_registers(&mb_param, addr, 1, tab_rp_registers);
                                 if (ret != 1) {
                                         printf("ERROR read_holding_registers single (%d)\n", ret);
                                         printf("Slave = %d, address = %d\n",
@@ -167,16 +166,16 @@ int main(void)
                         }
 
                         /* MULTIPLE REGISTERS */
-                        ret = preset_multiple_registers(&mb_param, SLAVE,
-                                                        addr, nb, tab_rq_registers);
+                        ret = preset_multiple_registers(&mb_param, addr, nb,
+                                                        tab_rq_registers);
                         if (ret != nb) {
                                 printf("ERROR preset_multiple_registers (%d)\n", ret);
                                 printf("Slave = %d, address = %d, nb = %d\n",
                                                SLAVE, addr, nb);
                                 nb_fail++;
                         } else {
-                                ret = read_holding_registers(&mb_param, SLAVE,
-                                                             addr, nb, tab_rp_registers);
+                                ret = read_holding_registers(&mb_param, addr, nb,
+                                                             tab_rp_registers);
                                 if (ret != nb) {
                                         printf("ERROR read_holding_registers (%d)\n", ret);
                                         printf("Slave = %d, address = %d, nb = %d\n",

+ 4 - 2
tests/random-test-slave.c

@@ -21,6 +21,8 @@
 
 #include "modbus.h"
 
+#define SLAVE 0x11
+
 int main(void)
 {
         int socket;
@@ -28,7 +30,7 @@ int main(void)
         modbus_mapping_t mb_mapping;
         int ret;
 
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         /* modbus_set_debug(&mb_param, TRUE); */
 
         ret = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
@@ -46,7 +48,7 @@ int main(void)
 
                 ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
                 if (ret == 0) {
-                        modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
+                        modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
                 } else if (ret == CONNECTION_CLOSED) {
                         /* Connection closed by the client, end of server */
                         break;

+ 54 - 26
tests/unit-test-master.c

@@ -38,11 +38,12 @@ int main(void)
         int ret;
 
         /* RTU parity : none, even, odd */
-/*      modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, "none", 8, 1); */
+/*      modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, "none", 8, 1, SLAVE); */
 
         /* TCP */
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
 /*        modbus_set_debug(&mb_param, TRUE);*/
+        modbus_set_error_handling(&mb_param, NOP_ON_ERROR);
 
         if (modbus_connect(&mb_param) == -1) {
                 printf("ERROR Connection failed\n");
@@ -69,7 +70,7 @@ int main(void)
         /** COIL STATUS **/
 
         /* Single */
-        ret = force_single_coil(&mb_param, SLAVE, UT_COIL_STATUS_ADDRESS, ON);
+        ret = force_single_coil(&mb_param, UT_COIL_STATUS_ADDRESS, ON);
         printf("1/2 force_single_coil: ");
         if (ret == 1) {
                 printf("OK\n");
@@ -78,7 +79,7 @@ int main(void)
                 goto close;
         }
 
-        ret = read_coil_status(&mb_param, SLAVE, UT_COIL_STATUS_ADDRESS, 1,
+        ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS, 1,
                                tab_rp_status);
         printf("2/2 read_coil_status: ");
         if (ret != 1) {
@@ -99,7 +100,7 @@ int main(void)
 
                 set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
                                     UT_COIL_STATUS_TAB);
-                ret = force_multiple_coils(&mb_param, SLAVE,
+                ret = force_multiple_coils(&mb_param,
                                            UT_COIL_STATUS_ADDRESS,
                                            UT_COIL_STATUS_NB_POINTS,
                                            tab_value);
@@ -112,7 +113,7 @@ int main(void)
                 }
         }
 
-        ret = read_coil_status(&mb_param, SLAVE, UT_COIL_STATUS_ADDRESS,
+        ret = read_coil_status(&mb_param, UT_COIL_STATUS_ADDRESS,
                                UT_COIL_STATUS_NB_POINTS, tab_rp_status);
         printf("2/2 read_coil_status: ");
         if (ret != UT_COIL_STATUS_NB_POINTS) {
@@ -140,7 +141,7 @@ int main(void)
         /* End of multiple coils */
 
         /** INPUT STATUS **/
-        ret = read_input_status(&mb_param, SLAVE, UT_INPUT_STATUS_ADDRESS,
+        ret = read_input_status(&mb_param, UT_INPUT_STATUS_ADDRESS,
                                 UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
         printf("1/1 read_input_status: ");
 
@@ -170,7 +171,7 @@ int main(void)
         /** HOLDING REGISTERS **/
 
         /* Single register */
-        ret = preset_single_register(&mb_param, SLAVE,
+        ret = preset_single_register(&mb_param,
                                      UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
         printf("1/2 preset_single_register: ");
         if (ret == 1) {
@@ -180,7 +181,7 @@ int main(void)
                 goto close;
         }
 
-        ret = read_holding_registers(&mb_param, SLAVE,
+        ret = read_holding_registers(&mb_param,
                                      UT_HOLDING_REGISTERS_ADDRESS,
                                      1, tab_rp_registers);
         printf("2/2 read_holding_registers: ");
@@ -198,7 +199,7 @@ int main(void)
         /* End of single register */
 
         /* Many registers */
-        ret = preset_multiple_registers(&mb_param, SLAVE,
+        ret = preset_multiple_registers(&mb_param,
                                         UT_HOLDING_REGISTERS_ADDRESS,
                                         UT_HOLDING_REGISTERS_NB_POINTS,
                                         UT_HOLDING_REGISTERS_TAB);
@@ -211,7 +212,7 @@ int main(void)
         }
 
         ret = read_holding_registers(&mb_param,
-                                     SLAVE, UT_HOLDING_REGISTERS_ADDRESS,
+                                     UT_HOLDING_REGISTERS_ADDRESS,
                                      UT_HOLDING_REGISTERS_NB_POINTS,
                                      tab_rp_registers);
         printf("2/2 read_holding_registers: ");
@@ -234,7 +235,7 @@ int main(void)
 
         /** INPUT REGISTERS **/
         ret = read_input_registers(&mb_param,
-                                   SLAVE, UT_INPUT_REGISTERS_ADDRESS,
+                                   UT_INPUT_REGISTERS_ADDRESS,
                                    UT_INPUT_REGISTERS_NB_POINTS,
                                    tab_rp_registers);
         printf("1/1 read_input_registers: ");
@@ -259,7 +260,7 @@ int main(void)
         /* The mapping begins at 0 and ending at address + nb_points so
          * the addresses below are not valid. */
 
-        ret = read_coil_status(&mb_param, SLAVE,
+        ret = read_coil_status(&mb_param,
                                UT_COIL_STATUS_ADDRESS,
                                UT_COIL_STATUS_NB_POINTS + 1,
                                tab_rp_status);
@@ -269,7 +270,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_input_status(&mb_param, SLAVE,
+        ret = read_input_status(&mb_param,
                                 UT_INPUT_STATUS_ADDRESS,
                                 UT_INPUT_STATUS_NB_POINTS + 1,
                                 tab_rp_status);
@@ -279,7 +280,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_holding_registers(&mb_param, SLAVE,
+        ret = read_holding_registers(&mb_param,
                                      UT_HOLDING_REGISTERS_ADDRESS,
                                      UT_HOLDING_REGISTERS_NB_POINTS + 1,
                                      tab_rp_registers);
@@ -289,7 +290,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_input_registers(&mb_param, SLAVE,
+        ret = read_input_registers(&mb_param,
                                    UT_INPUT_REGISTERS_ADDRESS,
                                    UT_INPUT_REGISTERS_NB_POINTS + 1,
                                    tab_rp_registers);
@@ -299,7 +300,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = force_single_coil(&mb_param, SLAVE,
+        ret = force_single_coil(&mb_param,
                                 UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
                                 ON);
         printf("* force_single_coil: ");
@@ -309,7 +310,7 @@ int main(void)
                 printf("FAILED\n");
         }
 
-        ret = force_multiple_coils(&mb_param, SLAVE,
+        ret = force_multiple_coils(&mb_param,
                                    UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
                                    UT_COIL_STATUS_NB_POINTS,
                                    tab_rp_status);
@@ -320,7 +321,7 @@ int main(void)
                 printf("FAILED\n");
         }
 
-        ret = preset_multiple_registers(&mb_param, SLAVE,
+        ret = preset_multiple_registers(&mb_param,
                                         UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
                                         UT_HOLDING_REGISTERS_NB_POINTS,
                                         tab_rp_registers);
@@ -335,7 +336,7 @@ int main(void)
         /** TOO MANY DATA **/
         printf("\nTEST TOO MANY DATA ERROR:\n");
 
-        ret = read_coil_status(&mb_param, SLAVE,
+        ret = read_coil_status(&mb_param,
                                UT_COIL_STATUS_ADDRESS,
                                MAX_STATUS + 1,
                                tab_rp_status);
@@ -345,7 +346,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_input_status(&mb_param, SLAVE,
+        ret = read_input_status(&mb_param,
                                 UT_INPUT_STATUS_ADDRESS,
                                 MAX_STATUS + 1,
                                 tab_rp_status);
@@ -355,7 +356,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_holding_registers(&mb_param, SLAVE,
+        ret = read_holding_registers(&mb_param,
                                      UT_HOLDING_REGISTERS_ADDRESS,
                                      MAX_REGISTERS + 1,
                                      tab_rp_registers);
@@ -365,7 +366,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = read_input_registers(&mb_param, SLAVE,
+        ret = read_input_registers(&mb_param,
                                    UT_INPUT_REGISTERS_ADDRESS,
                                    MAX_REGISTERS + 1,
                                    tab_rp_registers);
@@ -375,7 +376,7 @@ int main(void)
         else
                 printf("FAILED\n");
 
-        ret = force_multiple_coils(&mb_param, SLAVE,
+        ret = force_multiple_coils(&mb_param,
                                    UT_COIL_STATUS_ADDRESS,
                                    MAX_STATUS + 1,
                                    tab_rp_status);
@@ -386,7 +387,7 @@ int main(void)
                 printf("FAILED\n");
         }
 
-        ret = preset_multiple_registers(&mb_param, SLAVE,
+        ret = preset_multiple_registers(&mb_param,
                                         UT_HOLDING_REGISTERS_ADDRESS,
                                         MAX_REGISTERS + 1,
                                         tab_rp_registers);
@@ -397,6 +398,33 @@ int main(void)
                 printf("FAILED\n");
         }
 
+        /** SLAVE REPLY **/
+        printf("\nTEST SLAVE REPLY:\n");
+
+        mb_param.slave = 0x12;
+        ret = read_holding_registers(&mb_param,
+                                     UT_HOLDING_REGISTERS_ADDRESS+1,
+                                     UT_HOLDING_REGISTERS_NB_POINTS,
+                                     tab_rp_registers);
+        printf("1/2 No reply from slave %d: ", mb_param.slave);
+        if (ret != UT_HOLDING_REGISTERS_NB_POINTS) {
+                printf("OK\n", ret);
+        } else {
+                printf("FAILED\n");
+        }
+ 
+        mb_param.slave = MODBUS_BROADCAST_ADDRESS;
+        ret = read_holding_registers(&mb_param,
+                                     UT_HOLDING_REGISTERS_ADDRESS,
+                                     UT_HOLDING_REGISTERS_NB_POINTS,
+                                     tab_rp_registers);
+        printf("2/2 Reply after a broadcast query: ");
+        if (ret == UT_HOLDING_REGISTERS_NB_POINTS) {
+                printf("OK\n", ret);
+        } else {
+                printf("FAILED\n");
+        }
+
         /** BAD RESPONSE **/
         printf("\nTEST BAD RESPONSE ERROR:\n");
 
@@ -404,7 +432,7 @@ int main(void)
         uint16_t *tab_rp_registers_bad = (uint16_t *) malloc(
                 UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
         ret = read_holding_registers(&mb_param,
-                                     SLAVE, UT_HOLDING_REGISTERS_ADDRESS,
+                                     UT_HOLDING_REGISTERS_ADDRESS,
                                      UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
                                      tab_rp_registers_bad);
         printf("* read_holding_registers: ");

+ 2 - 2
tests/unit-test-slave.c

@@ -31,7 +31,7 @@ int main(void)
         int ret;
         int i;
 
-        modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
+        modbus_init_tcp(&mb_param, "127.0.0.1", 1502, SLAVE);
         modbus_set_debug(&mb_param, TRUE);
 
         ret = modbus_mapping_new(&mb_mapping,
@@ -75,7 +75,7 @@ int main(void)
                                 query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
                         }
 
-                        modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
+                        modbus_slave_manage(&mb_param, query, query_size, &mb_mapping);
                 } else if (ret == CONNECTION_CLOSED) {
                         /* Connection closed by the client, end of server */
                         break;

+ 2 - 0
tests/unit-test.h

@@ -20,6 +20,8 @@
 
 #include <stdint.h>
 
+#define SLAVE 0x11
+
 const uint16_t UT_COIL_STATUS_ADDRESS = 0x13;
 const uint16_t UT_COIL_STATUS_NB_POINTS = 0x25;
 const uint8_t UT_COIL_STATUS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };