/ src / hal / user_comps / mb2hal / mb2hal.h
mb2hal.h
  1  #include <stdlib.h>
  2  #include <signal.h>
  3  #include <sys/time.h>
  4  #include <string.h>
  5  #include <unistd.h>
  6  #include <pthread.h>
  7  
  8  #include "rtapi.h"
  9  #ifdef RTAPI
 10  #include "rtapi_app.h"
 11  #endif
 12  #include "rtapi_string.h"
 13  #include "rtapi_errno.h"
 14  #include "hal.h"
 15  #include "inifile.h"
 16  
 17  #include <modbus.h>
 18  
 19  #define MB2HAL_MAX_LINKS            32
 20  #define MB2HAL_MAX_DEVICE_LENGTH    32
 21  #define MB2HAL_DEFAULT_TCP_PORT    502
 22  #define MB2HAL_DEFAULT_MB_RESPONSE_TIMEOUT_MS 500
 23  #define MB2HAL_DEFAULT_MB_BYTE_TIMEOUT_MS     500
 24  #define MB2HAL_DEFAULT_TCP_PORT    502
 25  #define MB2HAL_MAX_FNCT02_ELEMENTS 100
 26  #define MB2HAL_MAX_FNCT03_ELEMENTS 100
 27  #define MB2HAL_MAX_FNCT04_ELEMENTS 100
 28  #define MB2HAL_MAX_FNCT05_ELEMENTS 100
 29  #define MB2HAL_MAX_FNCT06_ELEMENTS 1
 30  #define MB2HAL_MAX_FNCT15_ELEMENTS 100
 31  #define MB2HAL_MAX_FNCT16_ELEMENTS 100
 32  
 33  #ifdef MODULE_VERBOSE
 34  MODULE_VERBOSE(emc2, "component:mb2hal:Userspace HAL component to communicate with one or more Modbus devices");
 35  MODULE_VERBOSE(emc2, "license:LGPL");
 36  MODULE_LICENSE("LGPL");
 37  #endif
 38  
 39  typedef enum { linkRTU,
 40                 linkTCP
 41               } link_type_t;
 42  
 43  typedef enum { mbtxERR,
 44                 mbtx_02_READ_DISCRETE_INPUTS,
 45                 mbtx_03_READ_HOLDING_REGISTERS,
 46                 mbtx_04_READ_INPUT_REGISTERS,
 47                 mbtx_06_WRITE_SINGLE_REGISTER,
 48                 mbtx_15_WRITE_MULTIPLE_COILS,
 49                 mbtx_16_WRITE_MULTIPLE_REGISTERS,
 50                 mbtxMAX
 51               } mb_tx_fnct; //modbus transaction code
 52  typedef enum { debugSILENT, debugERR, debugOK, debugDEBUG, debugMAX
 53               } DEBUG_TYPE; //message levels
 54  typedef enum { retOK, retOKwithWarning, retERR
 55               } retCode; //funtions return codes
 56  
 57  #define ERR(debug, fmt, args...) if(debug >= debugERR) {fprintf(stderr, "%s %s ERR: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}
 58  #define OK(debug, fmt, args...) if(debug >= debugOK) {fprintf(stdout, "%s %s OK: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}
 59  #define DBG(debug, fmt, args...) if(debug >= debugDEBUG) {fprintf(stdout, "%s %s DEBUG: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}
 60  
 61  //Modbus transaction structure (mb_tx_t)
 62  //Store each transaction defined in INI config file
 63  //Plus HAL and run time parameters for each transaction
 64  typedef struct {
 65      //cfg_* are link params only for INI config reading purpose
 66      //then we use the parameters of mb_link_t
 67      link_type_t cfg_link_type; //RTU (serial) or TCP
 68      char cfg_link_type_str[10]; //str version of lp_link_type
 69      char cfg_serial_device[MB2HAL_MAX_DEVICE_LENGTH]; //device: example "/dev/ttyS0"
 70      int  cfg_serial_baud;      //bauds
 71      char cfg_serial_parity[5]; //parity: "even", "odd", "none"
 72      int  cfg_serial_data_bit;  //data bit
 73      int  cfg_serial_stop_bit;  //stop bit
 74      int  cfg_serial_delay_ms;  //delay between tx in serial lines
 75      char cfg_tcp_ip[17];       //tcp address
 76      int  cfg_tcp_port;         //tcp port number
 77      //mb_* are Modbus transaction protocol related params
 78      int        mb_tx_slave_id; //MB device id
 79      mb_tx_fnct mb_tx_fnct;     //MB function code id
 80      char       mb_tx_fnct_name[64]; //str version of mb_tx_fnct
 81      int        mb_tx_1st_addr; //MB first register
 82      int        mb_tx_nelem;    //MB n registers
 83      char **    mb_tx_names;    //MB register pin names. NULL if no names are specified
 84      int        mb_response_timeout_ms; //MB response timeout
 85      int        mb_byte_timeout_ms;     //MB byte timeout
 86      //cfg_* are others INI config params
 87      double cfg_update_rate;    //tx update rate
 88      int    cfg_debug;          //tx debug level (program, may be also protocol)
 89      //Modbus protocol debug
 90      int  protocol_debug;       //Flag debug Modbus protocol
 91      //internal processing values
 92      int mb_tx_num;         //each tx know it's own number
 93      int mb_link_num;       //each tx know it's own link
 94      //internal processing values
 95      double time_increment; //wait time between tx
 96      double next_time;      //next time for this tx
 97      double last_time_ok;   //last OK tx time
 98      //HAL related params
 99      char hal_tx_name[HAL_NAME_LEN + 1];
100      hal_float_t **float_value;
101      hal_s32_t **int_value;
102      //hal_float_t *scale;  //not yet implemented
103      //hal_float_t *offset; //not yet implemented
104      hal_bit_t **bit;
105      hal_u32_t **num_errors;     //num of acummulated errors (0=last tx OK)
106  } mb_tx_t;
107  
108  //Modbus link structure (mb_link_t)
109  //Group common transaction's links in one unique link
110  //Store each run time Modbus link parameters here
111  typedef struct {
112      //lp_* are real link params for real time use
113      link_type_t lp_link_type; //RTU (serial) or TCP
114      char lp_type_com_str[10]; //str version of lp_type_com
115      char lp_serial_device[MB2HAL_MAX_DEVICE_LENGTH]; //device: example "/dev/ttyS0"
116      int  lp_serial_baud;      //bauds
117      char lp_serial_parity;    //parity: 'E', 'O', 'N'
118      //NOTE in mb_tx is "even", "odd", "none"
119      int  lp_serial_data_bit;  //data bit
120      int  lp_serial_stop_bit;  //stop bit
121      int  lp_serial_delay_ms;  //delay between tx in serial lines
122      char lp_tcp_ip[17];       //tcp address
123      int  lp_tcp_port;         //tcp port number
124      //run time processing values
125      int mb_link_num;       //corresponding number of this link/thread
126      modbus_t *modbus;
127      pthread_t thrd;
128  } mb_link_t;
129  
130  //Structure of global data (gbl_t)
131  //Reduce functions parameters using this common global structure.
132  typedef struct {
133      //INI config file
134      FILE *ini_file_ptr;
135      char *ini_file_path;
136      //INI config, common section
137      int    init_dbg;
138      double slowdown;
139      //HAL related
140      int   hal_mod_id;
141      char *hal_mod_name;
142      //mb_tx
143      mb_tx_t *mb_tx;
144      int tot_mb_tx;
145      //mb_links
146      mb_link_t *mb_links;
147      int   tot_mb_links;
148      //others
149      const char *mb_tx_fncts[mbtxMAX];
150      int quit_flag;
151  } gbl_t;
152  
153  extern gbl_t gbl;
154  
155  //mb2hal.c
156  void *link_loop_and_logic(void *thrd_link_num);
157  retCode is_this_tx_ready(const int this_mb_link_num, const int this_mb_tx_num, int *ret_available);
158  retCode get_tx_connection(const int mb_tx_num, int *ret_connected);
159  void set_init_gbl_params();
160  double get_time();
161  void quit_signal(int signal);
162  void quit_cleanup(void);
163  
164  //mb2hal_init.c
165  retCode parse_main_args(int argc, char **argv);
166  retCode parse_ini_file();
167  retCode parse_common_section();
168  retCode parse_transaction_section(const int mb_tx_num);
169  retCode parse_tcp_subsection(const char *section, const int mb_tx_num);
170  retCode parse_serial_subsection(const char *section, const int mb_tx_num);
171  retCode check_int_in(int n_args, const int int_value, ...);
172  retCode check_str_in(int n_args, const char *str_value, ...);
173  retCode init_mb_links();
174  retCode init_mb_tx();
175  
176  //mb2hal_hal.c
177  retCode create_HAL_pins();
178  retCode create_each_mb_tx_hal_pins(mb_tx_t *mb_tx);
179  
180  //mb2hal_modbus.c
181  retCode fnct_15_write_multiple_coils(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
182  retCode fnct_02_read_discrete_inputs(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
183  retCode fnct_04_read_input_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
184  retCode fnct_03_read_holding_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
185  retCode fnct_06_write_single_register(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
186  retCode fnct_16_write_multiple_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);