瀏覽代碼

The transaction identifier used in response is now conform to the
MODBUS Messaging on TCP/IP Implementation Guide V1.0b.

The transaction identifier is used to associate the future response
with the request. So, at a time, on a TCP connection, this identifier
must be unique. There are several manners to use the transaction
identifier:
- For example, it can be used as a simple "TCP sequence number" with a
counter which is incremented at each request.
- It can also be judiciously used as a smart index or pointer to
identify a transaction context in order to memorize the current
remote server and the pending MODBUS request.

Stéphane Raimbault 17 年之前
父節點
當前提交
788cbf0b09
共有 1 個文件被更改,包括 38 次插入27 次删除
  1. 38 27
      modbus/modbus.c

+ 38 - 27
modbus/modbus.c

@@ -208,6 +208,13 @@ static int build_query_basis_tcp(int slave, int function,
                                  int start_addr, int count,
                                  uint8_t *query)
 {
+
+        /* Extract from MODBUS Messaging on TCP/IP Implementation
+           Guide V1.0b (page 23/46):
+           The transaction identifier is used to associate the future
+           response with the request. So, at a time, on a TCP
+           connection, this identifier must be unique.
+        */
         static uint16_t t_id = 0;
 
         /* Transaction ID */
@@ -256,15 +263,12 @@ static int build_response_basis_rtu(int slave, int function, uint8_t *response)
 }
 
 /* Builds a TCP response header */
-static int build_response_basis_tcp(int slave, int function, uint8_t *response)
+static int build_response_basis_tcp(int slave, int function, uint8_t *response, int t_id)
 {
-        static uint16_t t_id = 0;
-
-        /* Transaction ID */
-        if (t_id < USHRT_MAX)
-                t_id++;
-        else
-                t_id = 0;
+        /* Extract from MODBUS Messaging on TCP/IP Implementation
+           Guide V1.0b (page 23/46):
+           The transaction identifier is used to associate the future
+           response with the request. */
         response[0] = t_id >> 8;
         response[1] = t_id & 0x00ff;
 
@@ -281,12 +285,12 @@ static int build_response_basis_tcp(int slave, int function, uint8_t *response)
 }
 
 static int build_response_basis(modbus_param_t *mb_param, int slave, 
-                                int function, uint8_t *response)
+                                int function, uint8_t *response, int t_id)
 {
         if (mb_param->type_com == RTU)
                 return build_response_basis_rtu(slave, function, response);
         else
-                return build_response_basis_tcp(slave, function, response);
+                return build_response_basis_tcp(slave, function, response, t_id);
 }
 
 /* Sets the length of TCP message in the message (query and response) */
@@ -696,12 +700,13 @@ static int response_io_status(int address, int count,
 /* Build the exception response */
 static int response_exception(modbus_param_t *mb_param, int slave,
                               int function, int exception_code,
-                              uint8_t *response)
+                              uint8_t *response, int t_id)
 {
         int response_length;
 
         response_length = build_response_basis(mb_param, slave,
-                                               function + 0x80, response);
+                                               function + 0x80, response,
+                                               t_id);
         /* Positive exception code */
         response[response_length++] = -exception_code;
 
@@ -722,6 +727,12 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
         uint16_t address = (query[offset+2] << 8) + query[offset+3];
         uint8_t response[MAX_MESSAGE_LENGTH];
         int resp_length = 0;
+        int t_id;
+
+        if (mb_param->type_com == TCP)
+                t_id = (query[0] << 8) + query[1];
+        else
+                t_id = 0;
 
         switch (function) {
         case FC_READ_COIL_STATUS: {
@@ -731,9 +742,9 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in read_coil_status\n",
                                address + count); 
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);  
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);  
                 } else {
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         response[resp_length++] = (count / 8) + ((count % 8) ? 1 : 0);
                         resp_length = response_io_status(address, count,
                                                          mb_mapping->tab_coil_status,
@@ -749,9 +760,9 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in read_input_status\n",
                                address + count); 
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);
                 } else {
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         response[resp_length++] = (count / 8) + ((count % 8) ? 1 : 0);
                         resp_length = response_io_status(address, count,
                                                          mb_mapping->tab_input_status,
@@ -766,11 +777,11 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in read_holding_registers\n",
                                address + count); 
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);
                 } else {
                         int i;
                         
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         response[resp_length++] = count << 1;
                         for (i = address; i < address + count; i++) {
                                 response[resp_length++] = mb_mapping->tab_holding_registers[i] >> 8;
@@ -787,11 +798,11 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in read_input_registers\n",
                                address + count);
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);
                 } else {
                         int i;
 
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         response[resp_length++] = count << 1;
                         for (i = address; i < address + count; i++) {
                                 response[resp_length++] = mb_mapping->tab_input_registers[i] >> 8;
@@ -804,7 +815,7 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                 if (address >= mb_mapping->nb_coil_status) {
                         printf("Illegal data address %0X in force_singe_coil\n", address); 
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);  
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);  
                 } else {
                         int data = (query[offset+4] << 8) + query[offset+5];
                         
@@ -819,7 +830,7 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                                 printf("Illegal data value %0X in force_single_coil request at address %0X\n",
                                        data, address);
                                 resp_length = response_exception(mb_param, slave, function,
-                                                                 ILLEGAL_DATA_VALUE, response);
+                                                                 ILLEGAL_DATA_VALUE, response, t_id);
                         }
                 }
                 break;          
@@ -827,7 +838,7 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                 if (address >= mb_mapping->nb_holding_registers) {
                         printf("Illegal data address %0X in preset_holding_register\n", address); 
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);  
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);  
                 } else {
                         int data = (query[offset+4] << 8) + query[offset+5];
                         
@@ -843,9 +854,9 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in force_multiple_coils\n",
                                address + count);
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);
                 } else {
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         /* 4 to copy the coil address (2) and the quantity of coils */
                         memcpy(response + resp_length, query + resp_length, 4);
                         resp_length += 4;
@@ -859,9 +870,9 @@ void manage_query(modbus_param_t *mb_param, uint8_t *query,
                         printf("Illegal data address %0X in preset_multiple_registers\n",
                                address + count);
                         resp_length = response_exception(mb_param, slave, function,
-                                                         ILLEGAL_DATA_ADDRESS, response);
+                                                         ILLEGAL_DATA_ADDRESS, response, t_id);
                 } else {
-                        resp_length = build_response_basis(mb_param, slave, function, response);
+                        resp_length = build_response_basis(mb_param, slave, function, response, t_id);
                         /* 4 to copy the address (2) and the no. of registers */
                         memcpy(response + resp_length, query + resp_length, 4);
                         resp_length += 4;