modbus_client.c
Go to the documentation of this file.
1 /**
2  * @file modbus_client.c
3  * @brief Modbus/TCP client
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL MODBUS_TRACE_LEVEL
31 
32 //Dependencies
33 #include "modbus/modbus_client.h"
36 #include "debug.h"
37 
38 //Check TCP/IP stack configuration
39 #if (MODBUS_CLIENT_SUPPORT == ENABLED)
40 
41 
42 /**
43  * @brief Initialize Modbus/TCP client context
44  * @param[in] context Pointer to the Modbus/TCP client context
45  * @return Error code
46  **/
47 
49 {
50  //Make sure the Modbus/TCP client context is valid
51  if(context == NULL)
53 
54  //Clear Modbus/TCP client context
55  memset(context, 0, sizeof(ModbusClientContext));
56 
57  //Initialize Modbus/TCP client state
59 
60  //Default timeout
62  //Default unit identifier
63  context->unitId = MODBUS_DEFAULT_UNIT_ID;
64 
65  //The transaction identifier is used to uniquely identify the matching
66  //requests and responses
67  context->transactionId = (uint16_t) netGetRand();
68 
69  //Successful initialization
70  return NO_ERROR;
71 }
72 
73 
74 /**
75  * @brief Set timeout value for blocking operations
76  * @param[in] context Pointer to the Modbus/TCP client context
77  * @param[in] timeout Timeout value, in milliseconds
78  * @return Error code
79  **/
80 
82 {
83  //Make sure the Modbus/TCP client context is valid
84  if(context == NULL)
86 
87  //Save timeout value
88  context->timeout = timeout;
89 
90  //Successful processing
91  return NO_ERROR;
92 }
93 
94 
95 /**
96  * @brief Set unit identifier
97  * @param[in] context Pointer to the Modbus/TCP client context
98  * @param[in] unitId Identifier of the remote slave
99  * @return Error code
100  **/
101 
103 {
104  //Make sure the Modbus/TCP client context is valid
105  if(context == NULL)
107 
108  //Save unit identifier
109  context->unitId = unitId;
110 
111  //Successful processing
112  return NO_ERROR;
113 }
114 
115 
116 /**
117  * @brief Bind the Modbus/TCP client to a particular network interface
118  * @param[in] context Pointer to the Modbus/TCP client context
119  * @param[in] interface Network interface to be used
120  * @return Error code
121  **/
122 
124  NetInterface *interface)
125 {
126  //Make sure the Modbus/TCP client context is valid
127  if(context == NULL)
129 
130  //Explicitly associate the Modbus/TCP client with the specified interface
131  context->interface = interface;
132 
133  //Successful processing
134  return NO_ERROR;
135 }
136 
137 
138 /**
139  * @brief Establish connection with the Modbus/TCP server
140  * @param[in] context Pointer to the Modbus/TCP client context
141  * @param[in] serverIpAddr IP address of the server to connect to
142  * @param[in] serverPort TCP port number that will be used
143  * @return Error code
144  **/
145 
147  const IpAddr *serverIpAddr, uint16_t serverPort)
148 {
149  error_t error;
150 
151  //Check parameters
152  if(context == NULL || serverIpAddr == NULL)
154 
155  //Initialize status code
156  error = NO_ERROR;
157 
158  //Establish connection with the Modbus/TCP server
159  while(!error)
160  {
161  //Check current state
163  {
164  //Open a TCP socket
166 
167  //Valid socket?
168  if(context->socket != NULL)
169  {
170  //Associate the socket with the relevant interface
171  error = socketBindToInterface(context->socket, context->interface);
172 
173  //Check status code
174  if(!error)
175  {
176  //Set timeout
177  error = socketSetTimeout(context->socket, context->timeout);
178  }
179 
180  //Check status code
181  if(!error)
182  {
183  //Save current time
184  context->timestamp = osGetSystemTime();
185  //Update Modbus/TCP client state
187  }
188  }
189  else
190  {
191  //Report an error
192  error = ERROR_OPEN_FAILED;
193  }
194  }
195  else if(context->state == MODBUS_CLIENT_STATE_CONNECTING)
196  {
197  //Establish TCP connection
198  error = socketConnect(context->socket, serverIpAddr, serverPort);
199 
200  //Check status code
201  if(error == NO_ERROR)
202  {
203  //Update Modbus/TCP client state
205  }
206  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
207  {
208 #if (NET_RTOS_SUPPORT == DISABLED)
209  systime_t time;
210 
211  //Get current time
212  time = osGetSystemTime();
213 
214  //Check whether the timeout has elapsed
215  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
216  {
217  //Report a timeout error
218  error = ERROR_TIMEOUT;
219  }
220  else
221  {
222  //The operation would block
223  error = ERROR_WOULD_BLOCK;
224  }
225 #else
226  //Report a timeout error
227  error = ERROR_TIMEOUT;
228 #endif
229  }
230  else
231  {
232  //A communication error has occured
233  }
234  }
235  else if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
236  {
237  //The Modbus/TCP client is connected
238  break;
239  }
240  else
241  {
242  //Invalid state
243  error = ERROR_WRONG_STATE;
244  }
245  }
246 
247  //Failed to establish connection with the Modbus/TCP server?
248  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
249  {
250  //Clean up side effects
251  if(context->socket != NULL)
252  {
253  socketClose(context->socket);
254  context->socket = NULL;
255  }
256 
257  //Update Modbus/TCP client state
259  }
260 
261  //Return status code
262  return error;
263 }
264 
265 
266 /**
267  * @brief Read coils
268  *
269  * This function code is used to read from 1 to 2000 contiguous status of
270  * coils in a remote device. The request specifies the starting address and
271  * the number of coils
272  *
273  * @param[in] context Pointer to the Modbus/TCP client context
274  * @param[in] address Address of the first coil
275  * @param[in] quantity Number of coils
276  * @param[out] value Value of the discrete outputs
277  * @return Error code
278  **/
279 
281  uint16_t address, uint_t quantity, uint8_t *value)
282 {
283  error_t error;
284 
285  //Check parameters
286  if(context == NULL || value == NULL)
288 
289  //The number of coils must be in range 1 to 2000
290  if(quantity < 1 || quantity > 2000)
292 
293  //Initialize status code
294  error = NO_ERROR;
295 
296  //Perform Modbus request/response transaction
297  while(!error)
298  {
299  //Check current state
300  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
301  {
302  //Format request
303  error = modbusClientFormatReadCoilsReq(context, address,
304  quantity);
305  }
306  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
308  {
309  //Send Modbus request and wait for a matching response
310  error = modbusClientTransaction(context);
311  }
312  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
313  {
314  //Parse response
315  error = modbusClientParseReadCoilsResp(context, quantity,
316  value);
317 
318  //The Modbus transaction is complete
320  break;
321  }
322  else
323  {
324  //Invalid state
325  error = ERROR_NOT_CONNECTED;
326  }
327  }
328 
329  //Return status code
330  return error;
331 }
332 
333 
334 /**
335  * @brief Read discrete inputs
336  *
337  * This function code is used to read from 1 to 2000 contiguous status of
338  * discrete inputs in a remote device. The request specifies the starting
339  * address and the number of inputs
340  *
341  * @param[in] context Pointer to the Modbus/TCP client context
342  * @param[in] address Address of the first input
343  * @param[in] quantity Number of inputs
344  * @param[out] value Value of the discrete inputs
345  * @return Error code
346  **/
347 
349  uint8_t address, uint_t quantity, uint8_t *value)
350 {
351  error_t error;
352 
353  //Check parameters
354  if(context == NULL || value == NULL)
356 
357  //The number of discrete inputs must be in range 1 to 2000
358  if(quantity < 1 || quantity > 2000)
360 
361  //Initialize status code
362  error = NO_ERROR;
363 
364  //Perform Modbus request/response transaction
365  while(!error)
366  {
367  //Check current state
368  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
369  {
370  //Format request
372  quantity);
373  }
374  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
376  {
377  //Send Modbus request and wait for a matching response
378  error = modbusClientTransaction(context);
379  }
380  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
381  {
382  //Parse response
383  error = modbusClientParseReadDiscreteInputsResp(context, quantity,
384  value);
385 
386  //The Modbus transaction is complete
388  break;
389  }
390  else
391  {
392  //Invalid state
393  error = ERROR_NOT_CONNECTED;
394  }
395  }
396 
397  //Return status code
398  return error;
399 }
400 
401 
402 /**
403  * @brief Read holding registers
404  *
405  * This function code is used to read the contents of a contiguous block of
406  * holding registers in a remote device. The request specifies the starting
407  * register address and the number of registers
408  *
409  * @param[in] context Pointer to the Modbus/TCP client context
410  * @param[in] address Starting register address
411  * @param[in] quantity Number of registers
412  * @param[out] value Value of the holding registers
413  * @return Error code
414  **/
415 
417  uint16_t address, uint_t quantity, uint16_t *value)
418 {
419  error_t error;
420 
421  //Check parameters
422  if(context == NULL || value == NULL)
424 
425  //The number of registers must be in range 1 to 125
426  if(quantity < 1 || quantity > 125)
428 
429  //Initialize status code
430  error = NO_ERROR;
431 
432  //Perform Modbus request/response transaction
433  while(!error)
434  {
435  //Check current state
436  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
437  {
438  //Format request
440  quantity);
441  }
442  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
444  {
445  //Send Modbus request and wait for a matching response
446  error = modbusClientTransaction(context);
447  }
448  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
449  {
450  //Parse response
451  error = modbusClientParseReadHoldingRegsResp(context, quantity,
452  value);
453 
454  //The Modbus transaction is complete
456  break;
457  }
458  else
459  {
460  //Invalid state
461  error = ERROR_NOT_CONNECTED;
462  }
463  }
464 
465  //Return status code
466  return error;
467 }
468 
469 
470 /**
471  * @brief Read input registers
472  *
473  * This function code is used to read from 1 to 125 contiguous input registers
474  * in a remote device. The request specifies the starting register address and
475  * the number of registers
476  *
477  * @param[in] context Pointer to the Modbus/TCP client context
478  * @param[in] address Starting register address
479  * @param[in] quantity Number of registers
480  * @param[out] value Value of the input registers
481  * @return Error code
482  **/
483 
485  uint16_t address, uint_t quantity, uint16_t *value)
486 {
487  error_t error;
488 
489  //Check parameters
490  if(context == NULL || value == NULL)
492 
493  //The number of registers must be in range 1 to 125
494  if(quantity < 1 || quantity > 125)
496 
497  //Initialize status code
498  error = NO_ERROR;
499 
500  //Perform Modbus request/response transaction
501  while(!error)
502  {
503  //Check current state
504  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
505  {
506  //Format request
508  quantity);
509  }
510  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
512  {
513  //Send Modbus request and wait for a matching response
514  error = modbusClientTransaction(context);
515  }
516  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
517  {
518  //Parse response
519  error = modbusClientParseReadInputRegsResp(context, quantity,
520  value);
521 
522  //The Modbus transaction is complete
524  break;
525  }
526  else
527  {
528  //Invalid state
529  error = ERROR_NOT_CONNECTED;
530  }
531  }
532 
533  //Return status code
534  return error;
535 }
536 
537 
538 /**
539  * @brief Write single coil
540  *
541  * This function code is used to write a single output to either ON or OFF in
542  * a remote device. The request specifies the address of the coil to be forced
543  * and the requested ON/OFF state
544  *
545  * @param[in] context Pointer to the Modbus/TCP client context
546  * @param[in] address Address of the coil to be forced
547  * @param[in] value Value of the discrete output
548  * @return Error code
549  **/
550 
552  uint16_t address, bool_t value)
553 {
554  error_t error;
555 
556  //Make sure the Modbus/TCP client context is valid
557  if(context == NULL)
559 
560  //Initialize status code
561  error = NO_ERROR;
562 
563  //Perform Modbus request/response transaction
564  while(!error)
565  {
566  //Check current state
567  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
568  {
569  //Format request
571  }
572  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
574  {
575  //Send Modbus request and wait for a matching response
576  error = modbusClientTransaction(context);
577  }
578  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
579  {
580  //Parse response
582 
583  //The Modbus transaction is complete
585  break;
586  }
587  else
588  {
589  //Invalid state
590  error = ERROR_NOT_CONNECTED;
591  }
592  }
593 
594  //Return status code
595  return error;
596 }
597 
598 
599 /**
600  * @brief Write single register
601  *
602  * This function code is used to write a single holding register in a remote
603  * device. The request specifies the address of the register to be written and
604  * the register value
605  *
606  * @param[in] context Pointer to the Modbus/TCP client context
607  * @param[in] address Address of the register to be written
608  * @param[in] value Register value
609  * @return Error code
610  **/
611 
613  uint16_t address, uint16_t value)
614 {
615  error_t error;
616 
617  //Make sure the Modbus/TCP client context is valid
618  if(context == NULL)
620 
621  //Initialize status code
622  error = NO_ERROR;
623 
624  //Perform Modbus request/response transaction
625  while(!error)
626  {
627  //Check current state
628  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
629  {
630  //Format request
632  }
633  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
635  {
636  //Send Modbus request and wait for a matching response
637  error = modbusClientTransaction(context);
638  }
639  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
640  {
641  //Parse response
643 
644  //The Modbus transaction is complete
646  break;
647  }
648  else
649  {
650  //Invalid state
651  error = ERROR_NOT_CONNECTED;
652  }
653  }
654 
655  //Return status code
656  return error;
657 }
658 
659 
660 /**
661  * @brief Write multiple coils
662  *
663  * This function code is used to force each coil in a sequence of coils to
664  * either ON or OFF in a remote device. The request specifies the starting
665  * address, the number of outputs and the requested ON/OFF states
666  *
667  * @param[in] context Pointer to the Modbus/TCP client context
668  * @param[in] address Address of the first coil to be forced
669  * @param[in] quantity Number of coils
670  * @param[in] value Value of the discrete outputs
671  * @return Error code
672  **/
673 
675  uint16_t address, uint_t quantity, const uint8_t *value)
676 {
677  error_t error;
678 
679  //Check parameters
680  if(context == NULL || value == NULL)
682 
683  //The number of coils must be in range 1 to 1968
684  if(quantity < 1 || quantity > 1968)
686 
687  //Initialize status code
688  error = NO_ERROR;
689 
690  //Perform Modbus request/response transaction
691  while(!error)
692  {
693  //Check current state
694  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
695  {
696  //Format request
698  quantity, value);
699  }
700  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
702  {
703  //Send Modbus request and wait for a matching response
704  error = modbusClientTransaction(context);
705  }
706  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
707  {
708  //Parse response
710  quantity);
711 
712  //The Modbus transaction is complete
714  break;
715  }
716  else
717  {
718  //Invalid state
719  error = ERROR_NOT_CONNECTED;
720  }
721  }
722 
723  //Return status code
724  return error;
725 }
726 
727 
728 /**
729  * @brief Write multiple registers
730  *
731  * This function code is used to write a block of contiguous registers (1 to
732  * 123 registers) in a remote device. The request specifies the starting
733  * address, the number of registers and the requested written values
734  *
735  * @param[in] context Pointer to the Modbus/TCP client context
736  * @param[in] address Starting register address
737  * @param[in] quantity Number of registers
738  * @param[in] value Value of the holding registers
739  * @return Error code
740  **/
741 
743  uint16_t address, uint_t quantity, const uint16_t *value)
744 {
745  error_t error;
746 
747  //Check parameters
748  if(context == NULL || value == NULL)
750 
751  //The number of registers must be in range 1 to 123
752  if(quantity < 1 || quantity > 123)
754 
755  //Initialize status code
756  error = NO_ERROR;
757 
758  //Perform Modbus request/response transaction
759  while(!error)
760  {
761  //Check current state
762  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
763  {
764  //Format request
766  quantity, value);
767  }
768  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
770  {
771  //Send Modbus request and wait for a matching response
772  error = modbusClientTransaction(context);
773  }
774  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
775  {
776  //Parse response
778  quantity);
779 
780  //The Modbus transaction is complete
782  break;
783  }
784  else
785  {
786  //Invalid state
787  error = ERROR_NOT_CONNECTED;
788  }
789  }
790 
791  //Return status code
792  return error;
793 }
794 
795 
796 /**
797  * @brief Apply AND/OR bitmask to a register
798  *
799  * This function code is used to modify the contents of a specified holding
800  * register using a combination of an AND mask, an OR mask, and the register's
801  * current contents. The function can be used to set or clear individual bits
802  * in the register
803  *
804  * @param[in] context Pointer to the Modbus/TCP client context
805  * @param[in] address Address of the holding register
806  * @param[in] andMask AND bitmask
807  * @param[in] orMask OR bitmask
808  * @return Error code
809  **/
810 
812  uint16_t address, uint16_t andMask, uint16_t orMask)
813 {
814  error_t error;
815 
816  //Make sure the Modbus/TCP client context is valid
817  if(context == NULL)
819 
820  //Initialize status code
821  error = NO_ERROR;
822 
823  //Perform Modbus request/response transaction
824  while(!error)
825  {
826  //Check current state
827  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
828  {
829  //Format request
831  andMask, orMask);
832  }
833  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
835  {
836  //Send Modbus request and wait for a matching response
837  error = modbusClientTransaction(context);
838  }
839  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
840  {
841  //Parse response
843  andMask, orMask);
844 
845  //The Modbus transaction is complete
847  break;
848  }
849  else
850  {
851  //Invalid state
852  error = ERROR_NOT_CONNECTED;
853  }
854  }
855 
856  //Return status code
857  return error;
858 }
859 
860 
861 /**
862  * @brief Read/write multiple registers
863  *
864  * This function code performs a combination of one read operation and one
865  * write operation in a single Modbus transaction. The write operation is
866  * performed before the read
867  *
868  * @param[in] context Pointer to the Modbus/TCP client context
869  * @param[in] readAddress Address of the first holding registers to be read
870  * @param[in] readQuantity Number of holding registers to be read
871  * @param[out] readValue Value of the holding registers (read operation)
872  * @param[in] writeAddress Address of the first holding registers to be written
873  * @param[in] writeQuantity Number of holding registers to be written
874  * @param[in] writeValue Value of the holding registers (write operation)
875  * @return Error code
876  **/
877 
879  uint16_t readAddress, uint16_t readQuantity, uint16_t *readValue,
880  uint16_t writeAddress, uint16_t writeQuantity, const uint16_t *writeValue)
881 {
882  error_t error;
883 
884  //Check parameters
885  if(context == NULL || readValue == NULL || writeValue == NULL)
887 
888  //The number of registers to be read must be in range 1 to 125
889  if(readQuantity < 1 || readQuantity > 125)
891 
892  //The number of registers to be written must be in range 1 to 121
893  if(writeQuantity < 1 || writeQuantity > 121)
895 
896  //Initialize status code
897  error = NO_ERROR;
898 
899  //Perform Modbus request/response transaction
900  while(!error)
901  {
902  //Check current state
903  if(context->state == MODBUS_CLIENT_STATE_CONNECTED)
904  {
905  //Format request
907  readAddress, readQuantity, writeAddress, writeQuantity, writeValue);
908  }
909  else if(context->state == MODBUS_CLIENT_STATE_SENDING ||
911  {
912  //Send Modbus request and wait for a matching response
913  error = modbusClientTransaction(context);
914  }
915  else if(context->state == MODBUS_CLIENT_STATE_COMPLETE)
916  {
917  //Parse response
919  readQuantity, readValue);
920 
921  //The Modbus transaction is complete
923  break;
924  }
925  else
926  {
927  //Invalid state
928  error = ERROR_NOT_CONNECTED;
929  }
930  }
931 
932  //Return status code
933  return error;
934 }
935 
936 
937 /**
938  * @brief Retrieve exception code
939  * @param[in] context Pointer to the Modbus/TCP client context
940  * @param[out] exceptionCode Exception code
941  * @return Error code
942  **/
943 
946 {
947  //Check parameters
948  if(context == NULL || exceptionCode == NULL)
950 
951  //Retrieve exception code
952  *exceptionCode = context->exceptionCode;
953 
954  //Successful processing
955  return NO_ERROR;
956 }
957 
958 
959 /**
960  * @brief Disconnect from the Modbus/TCP server
961  * @param[in] context Pointer to the Modbus/TCP client context
962  * @return Error code
963  **/
964 
966 {
967  //Make sure the Modbus/TCP client context is valid
968  if(context == NULL)
970 
971  //Valid socket handle?
972  if(context->socket != NULL)
973  {
974  //Close TCP socket
975  socketClose(context->socket);
976  context->socket = NULL;
977  }
978 
979  //The Modbus/TCP client is disconnected
981 
982  //Successful processing
983  return NO_ERROR;
984 }
985 
986 
987 /**
988  * @brief Release Modbus/TCP client context
989  * @param[in] context Pointer to the Modbus/TCP client context
990  **/
991 
993 {
994  //Make sure the Modbus/TCP client context is valid
995  if(context != NULL)
996  {
997  //Valid socket handle?
998  if(context->socket != NULL)
999  {
1000  //Close TCP socket
1001  socketClose(context->socket);
1002  }
1003 
1004  //Clear Modbus/TCP client context
1005  memset(context, 0, sizeof(ModbusClientContext));
1006  }
1007 }
1008 
1009 #endif
Modbus PDU formatting and parsing.
ModbusExceptionCode exceptionCode
Exception code.
Definition: modbus_client.h:90
error_t modbusClientGetExceptionCode(ModbusClientContext *context, ModbusExceptionCode *exceptionCode)
Retrieve exception code.
error_t modbusClientWriteSingleCoil(ModbusClientContext *context, uint16_t address, bool_t value)
Write single coil.
uint32_t systime_t
Definition: compiler_port.h:44
void modbusClientDeinit(ModbusClientContext *context)
Release Modbus/TCP client context.
#define MODBUS_CLIENT_DEFAULT_TIMEOUT
Definition: modbus_client.h:45
error_t modbusClientFormatReadHoldingRegsReq(ModbusClientContext *context, uint16_t address, uint_t quantity)
Format Read Holding Registers request.
error_t modbusClientBindToInterface(ModbusClientContext *context, NetInterface *interface)
Bind the Modbus/TCP client to a particular network interface.
#define timeCompare(t1, t2)
Definition: os_port.h:40
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
error_t modbusClientParseWriteSingleCoilResp(ModbusClientContext *context, uint16_t address, bool_t value)
Parse Write Single Coil response.
error_t modbusClientFormatReadCoilsReq(ModbusClientContext *context, uint16_t address, uint_t quantity)
Format Read Coils request.
Helper functions for Modbus/TCP client.
Debugging facilities.
systime_t timestamp
Timestamp to manage timeout.
Definition: modbus_client.h:83
error_t modbusClientFormatWriteSingleCoilReq(ModbusClientContext *context, uint16_t address, bool_t value)
Format Write Single Coil request.
error_t modbusClientReadDiscreteInputs(ModbusClientContext *context, uint8_t address, uint_t quantity, uint8_t *value)
Read discrete inputs.
Invalid parameter.
Definition: error.h:45
error_t modbusClientParseWriteMultipleRegsResp(ModbusClientContext *context, uint16_t address, uint_t quantity)
Parse Write Multiple Registers response.
uint16_t orMask
error_t modbusClientFormatWriteMultipleRegsReq(ModbusClientContext *context, uint16_t address, uint_t quantity, const uint16_t *value)
Format Write Multiple Registers request.
error_t modbusClientReadInputRegs(ModbusClientContext *context, uint16_t address, uint_t quantity, uint16_t *value)
Read input registers.
IP network address.
Definition: ip.h:57
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:797
error_t modbusClientParseReadHoldingRegsResp(ModbusClientContext *context, uint_t quantity, uint16_t *value)
Parse Read Holding Registers response.
error_t modbusClientFormatReadWriteMultipleRegsReq(ModbusClientContext *context, uint16_t readAddress, uint16_t readQuantity, uint16_t writeAddress, uint16_t writeQuantity, const uint16_t *writeValue)
Format Read/Write Multiple Registers request.
uint8_t unitId
error_t modbusClientParseWriteMultipleCoilsResp(ModbusClientContext *context, uint16_t address, uint_t quantity)
Parse Write Multiple Coils response.
error_t modbusClientParseReadDiscreteInputsResp(ModbusClientContext *context, uint_t quantity, uint8_t *value)
Parse Discrete Inputs response.
error_t modbusClientReadCoils(ModbusClientContext *context, uint16_t address, uint_t quantity, uint8_t *value)
Read coils.
error_t modbusClientFormatMaskWriteRegReq(ModbusClientContext *context, uint16_t address, uint16_t andMask, uint16_t orMask)
Format Mask Write Register request.
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:216
error_t modbusClientInit(ModbusClientContext *context)
Initialize Modbus/TCP client context.
Definition: modbus_client.c:48
NetInterface * interface
Underlying network interface.
Definition: modbus_client.h:78
uint32_t netGetRand(void)
Get a random value.
Definition: net.c:1523
ModbusExceptionCode
Modbus exception codes.
Definition: modbus_common.h:97
error_t modbusClientFormatReadInputRegsReq(ModbusClientContext *context, uint16_t address, uint_t quantity)
Format Read Input Registers request.
error_t modbusClientMaskWriteReg(ModbusClientContext *context, uint16_t address, uint16_t andMask, uint16_t orMask)
Apply AND/OR bitmask to a register.
ModbusClientState state
Modbus/TCP client state.
Definition: modbus_client.h:77
error_t modbusClientParseReadInputRegsResp(ModbusClientContext *context, uint_t quantity, uint16_t *value)
Parse Read Input Registers response.
error_t modbusClientFormatWriteSingleRegReq(ModbusClientContext *context, uint16_t address, uint16_t value)
Format Write Single Register request.
uint8_t unitId
Identifier of the remote slave.
Definition: modbus_client.h:79
error_t modbusClientSetTimeout(ModbusClientContext *context, systime_t timeout)
Set timeout value for blocking operations.
Definition: modbus_client.c:81
error_t modbusClientFormatReadDiscreteInputsReq(ModbusClientContext *context, uint16_t address, uint_t quantity)
Format Read Discrete Inputs request.
error_t modbusClientParseWriteSingleRegResp(ModbusClientContext *context, uint16_t address, uint16_t value)
Parse Write Single Register response.
Success.
Definition: error.h:42
Ipv6Addr address
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:357
systime_t timeout
Timeout value.
Definition: modbus_client.h:82
Modbus/TCP client context.
Definition: modbus_client.h:75
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:92
error_t modbusClientWriteMultipleCoils(ModbusClientContext *context, uint16_t address, uint_t quantity, const uint8_t *value)
Write multiple coils.
error_t modbusClientWriteMultipleRegs(ModbusClientContext *context, uint16_t address, uint_t quantity, const uint16_t *value)
Write multiple registers.
error_t modbusClientFormatWriteMultipleCoilsReq(ModbusClientContext *context, uint16_t address, uint_t quantity, const uint8_t *value)
Format Write Multiple Coils request.
#define NetInterface
Definition: net.h:34
Modbus/TCP client.
uint8_t value[]
Definition: dtls_misc.h:141
Socket * socket
Underlying TCP socket.
Definition: modbus_client.h:81
error_t modbusClientParseReadCoilsResp(ModbusClientContext *context, uint_t quantity, uint8_t *value)
Parse Read Coils response.
error_t modbusClientParseReadWriteMultipleRegsResp(ModbusClientContext *context, uint_t readQuantity, uint16_t *readValue)
Parse Read/Write Multiple Registers response.
uint8_t exceptionCode
error_t modbusClientReadWriteMultipleRegs(ModbusClientContext *context, uint16_t readAddress, uint16_t readQuantity, uint16_t *readValue, uint16_t writeAddress, uint16_t writeQuantity, const uint16_t *writeValue)
Read/write multiple registers.
error_t modbusClientSetUnitId(ModbusClientContext *context, uint8_t unitId)
Set unit identifier.
uint16_t andMask
uint16_t transactionId
Modbus transaction identifier.
Definition: modbus_client.h:80
error_t modbusClientReadHoldingRegs(ModbusClientContext *context, uint16_t address, uint_t quantity, uint16_t *value)
Read holding registers.
error_t modbusClientTransaction(ModbusClientContext *context)
Perform Modbus transaction.
#define MODBUS_DEFAULT_UNIT_ID
Definition: modbus_common.h:40
error_t modbusClientConnect(ModbusClientContext *context, const IpAddr *serverIpAddr, uint16_t serverPort)
Establish connection with the Modbus/TCP server.
int bool_t
Definition: compiler_port.h:47
error_t modbusClientWriteSingleReg(ModbusClientContext *context, uint16_t address, uint16_t value)
Write single register.
error_t socketBindToInterface(Socket *socket, NetInterface *interface)
Bind a socket to a particular network interface.
Definition: socket.c:309
error_t modbusClientParseMaskWriteRegResp(ModbusClientContext *context, uint16_t address, uint16_t andMask, uint16_t orMask)
Parse Mask Write Register response.
error_t modbusClientDisconnect(ModbusClientContext *context)
Disconnect from the Modbus/TCP server.