modbus/mb_runtime.h
branchsvghmi
changeset 2982 1627d552f181
parent 2655 d2b2ee04bfa1
child 2683 5d8a4deacfe1
child 2713 680ea4684209
--- a/modbus/mb_runtime.h	Thu Jun 18 10:42:08 2020 +0200
+++ b/modbus/mb_runtime.h	Thu Jun 18 11:00:26 2020 +0200
@@ -30,6 +30,10 @@
 
 #define DEF_REQ_SEND_RETRIES 0
 
+
+#define MODBUS_PARAM_STRING_SIZE 64
+
+
   // Used by the Modbus server node
 #define MEM_AREA_SIZE 65536
 typedef struct{
@@ -39,8 +43,48 @@
 	    u16		rw_words[MEM_AREA_SIZE];
 	} server_mem_t;
 
+
+/*
+ * Beremiz has a program to run on the PLC (Beremiz_service.py)
+ * to handle downloading of compiled programs, start/stop of PLC, etc.
+ * (see runtime/PLCObject.py for start/stop, loading, ...)
+ * 
+ * This service also includes a web server to access PLC state (start/stop)
+ * and to change some basic confiuration parameters.
+ * (see runtime/NevowServer.py for the web server)
+ * 
+ * The web server allows for extensions, where additional configuration
+ * parameters may be changed on the running/downloaded PLC.
+ * Modbus plugin also comes with an extension to the web server, through
+ * which the basic Modbus plugin configuration parameters may be changed
+ *
+ * This means that most values in the server_node_t and client_node_t
+ * may be changed after the co,piled code (.so file) is loaded into 
+ * memory, and before the code starts executing.
+ * Since the we will also want to change the host and port (TCP) and the
+ * serial device (RTU) at this time, it is best if we allocate memory for
+ * these strings that may be overwritten by the web server (i.e., do not use
+ * const strings) in the server_node_t and client_node_t structures.
+ *
+ * The following structure members
+ *    - node_addr_t.addr.tcp.host
+ *    - node_addr_t.addr.tcp.service  (i.e. the port)
+ *    - node_addr_t.addr.rtu.device
+ * are all char *, and do not allocate memory for the strings.
+ * 
+ * We therefore include two generic char arrays, str1 and str2,
+ * that will store the above strings, and the C code will initiliaze
+ * the node_addre_t.addr string pointers to these strings.
+ * i.e., either addr.rtu.device will point to str1,
+ *          or
+ *        addr.tcp.host and addr.tcp.service 
+ *        will point to str1 and str2 respectively
+ */
 typedef struct{
 	    const char *location;
+        const char *config_name;
+              char  str1[MODBUS_PARAM_STRING_SIZE];
+              char  str2[MODBUS_PARAM_STRING_SIZE]; 
 	    u8		slave_id;
 	    node_addr_t	node_address;
 	    int		mb_nd;      // modbus library node used for this server 
@@ -53,12 +97,36 @@
   // Used by the Modbus client node
 typedef struct{
 	    const char *location;
+        const char *config_name;
+              char  str1[MODBUS_PARAM_STRING_SIZE];
+              char  str2[MODBUS_PARAM_STRING_SIZE]; 
 	    node_addr_t	node_address;
-	    int		mb_nd;
+	    int		mb_nd;      // modbus library node used for this client
 	    int		init_state; // store how far along the client's initialization has progressed
-	    u64		comm_period;
+	    u64		comm_period;// period to use when periodically sending requests to remote server
 	    int		prev_error; // error code of the last printed error message (0 when no error) 
-	    pthread_t	thread_id;  // thread handling all communication with this client
+	    pthread_t   thread_id;  // thread handling all communication for this client node
+	    timer_t      timer_id;  // timer used to periodically activate this client node's thread
+	    pthread_mutex_t mutex;  // mutex to be used with the following condition variable
+        pthread_cond_t  condv;  // used to signal the client thread when to start new modbus transactions
+        int       execute_req;  /* used, in association with condition variable,  
+                                 *   to signal when to send the modbus request to the server
+                                 * Note that we cannot simply rely on the condition variable to signal
+                                 *   when to activate the client thread, as the call to 
+                                 *   pthread_cond_wait() may return without having been signaled!
+                                 *   From the manual:
+                                 *      Spurious  wakeups  from  the
+                                 *      pthread_cond_timedwait() or pthread_cond_wait()  functions  may  occur.
+                                 *      Since  the  return from pthread_cond_timedwait() or pthread_cond_wait()
+                                 *      does not imply anything about the value of this predicate,  the  predi-
+                                 *      cate should be re-evaluated upon such return.
+                                 */
+        int      periodic_act;  /* (boolen) flag will be set when the client node's thread was activated 
+                                 * (by signaling the above condition variable) by the periodic timer.
+                                 * Note that this same thread may also be activated (condition variable is signaled)
+                                 * by other sources, such as when the user program requests that a specific 
+                                 * client MB transation be executed (flag_exec_req in client_request_t)
+                                 */
 	} client_node_t;
 
 
@@ -82,11 +150,37 @@
 	    u8		error_code; // modbus error code (if any) of current request
 	    int		prev_error; // error code of the last printed error message (0 when no error) 
 	    struct timespec resp_timeout;
+	    u8		write_on_change; // boolean flag. If true => execute MB request when data to send changes
 	      // buffer used to store located PLC variables
 	    u16		plcv_buffer[REQ_BUF_SIZE];
 	      // buffer used to store data coming from / going to server
 	    u16		coms_buffer[REQ_BUF_SIZE]; 
 	    pthread_mutex_t coms_buf_mutex; // mutex to access coms_buffer[]
+          /* boolean flag that will be mapped onto a (BOOL) located variable 
+           * (u16 because IEC 61131-3 BOOL are mapped onto u16 in C code! )
+           *    -> allow PLC program to request when to start the MB transaction
+           *    -> will be reset once the MB transaction has completed
+           */
+        u16     flag_exec_req;  
+          /* flag that works in conjunction with flag_exec_req
+           * (does not really need to be u16 as it is not mapped onto a located variable. )
+           *    -> used by internal logic to indicate that the client thread 
+           *       that will be executing the MB transaction
+           *       requested by flag exec_req has already been activated.
+           *    -> will be reset once the MB transaction has completed
+           */
+        u16     flag_exec_started;  
+          /* flag that will be mapped onto a (WORD) located variable 
+           * (u16 because the flag is a word! )
+           *    -> MSByte will store the result of the last executed MB transaction
+           *         1 -> error accessing IP network, or serial interface
+           *         2 -> reply received from server was an invalid frame
+           *         3 -> server did not reply before timeout expired
+           *         4 -> server returned a valid error frame
+           *    -> if the MSByte is 4, the LSByte will store the MB error code returned by the server
+           *    -> will be reset (set to 0) once this MB transaction has completed sucesfully
+           */
+        u16     flag_exec_status;  
 	} client_request_t;