Webserver only w/o any other functions, single thread. Running on STM32F013+W5500

Dependencies:   NTPClient W5500Interface Watchdog device_configuration eeprom_flash mbed-rpc-nucleo mbed-rtos mbed

Fork of F103-Serial-to-Ethernet by Chau Vo

Files at this revision

API Documentation at this revision

Comitter:
olympux
Date:
Sat Jan 24 20:49:24 2015 +0000
Parent:
30:15e23257e786
Child:
32:db2e8ea06ee1
Commit message:
Process both RPC and NNIO control commands with UDP and TCP

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
readme.txt Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Sun Jan 11 13:53:53 2015 +0000
+++ b/main.cpp	Sat Jan 24 20:49:24 2015 +0000
@@ -14,20 +14,20 @@
 #include "Watchdog.h"
 
 
-//Debug is disabled by default
+/** Debug option
+ *
+ */
 #if 1
 //Enable debug
 #include <cstdio>
-#define DBG(x, ...) std::printf("[main : DBG]"x"\r\n", ##__VA_ARGS__); 
-#define WARN(x, ...) std::printf("[main : WARN]"x"\r\n", ##__VA_ARGS__); 
-#define ERR(x, ...) std::printf("[main : ERR]"x"\r\n", ##__VA_ARGS__); 
-
+#define DBG(x, ...) std::printf("[main : DBG]"x"\r\n", ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[main : WARN]"x"\r\n", ##__VA_ARGS__);
+#define ERR(x, ...) std::printf("[main : ERR]"x"\r\n", ##__VA_ARGS__);
 #else
 //Disable debug
-#define DBG(x, ...) 
+#define DBG(x, ...)
 #define WARN(x, ...)
-#define ERR(x, ...) 
-
+#define ERR(x, ...)
 #endif
 
 
@@ -49,18 +49,18 @@
                                      0x5212, // UDP server port, not used
                                      0x8888, // 1st run? 0xA5A5 = configured
                                      0x6212, 0x6313, 0x6414, // MAC
-                                     
+
                                      // this section is for the TCP server that this device connects to in TCP client mode
                                      0x7212, 0x7313, // 0xA5A5 = auto transmit status, time period
                                      0x8212, 0x8313,0x8414, 0x8515, // TCP server IP address
                                      0x9212, // TCP server port
-                                     
+
                                      // this section is for selecting protocol, not used
                                      0xA212, // 0xA5A5 = enable TCP server
                                      0xA313, // 0xA5A5 = eanble TCP client
                                      0xA414  // 0xA5A5 = enable UDP server
-                                     };
-                                     
+                                    };
+
 
 /*
 * Network configuration
@@ -110,11 +110,9 @@
 uint16_t u16enable_tcp_client, u16enable_tcp_server;// flags for enabling TCP client or TCP server
 
 #define NET_BUF_LEN         256
-#define RPC_BUF_LEN         256
 char tcp_receiving_buffer[NET_BUF_LEN];
-char tcp_sending_buffer[NET_BUF_LEN]; // socket buffer
 char udp_receiving_buffer[NET_BUF_LEN];
-char rpc_outbuf[RPC_BUF_LEN]; // rpc output buffer
+char network_output_buffer[NET_BUF_LEN]; // output buffer for TCP/UDP control command
 
 
 /*
@@ -251,10 +249,11 @@
 /*
 * Threads
 */
-// Timer thread for auto update
-void auto_update_timer_thread(void const* args) {
+// Timer thread for auto update in TCP client function
+void auto_update_timer_thread(void const* args)
+{
     bool update_flag = true;
-    
+
     Thread::wait(500);
     while(true) {
         auto_update_queue.put(&update_flag);
@@ -264,7 +263,8 @@
 
 
 // WDT reset
-void wdt_reset_thread(void const* args) {
+void wdt_reset_thread(void const* args)
+{
     while (true)
         wdt.Service();
 }
@@ -273,31 +273,32 @@
 int main()
 {
     int n, ret;
-    
+
     Thread::wait(500); // turn on delay
-        
+
     /*
     * Configure
     */
     uart.baud(115200);
     DBG("\r\nStarting...");
-    
+
+    // check watchdog
     if (wdt.WatchdogCausedReset())
         DBG("Watchdog caused reset.");
     wdt.Configure(4);
-    
+
     /*
     * FLASH
     */
     load_eeprom_network();
     load_eeprom_tcpserver();
-    
+
     /*
     * UI threads
     */
     Thread t2(auto_update_timer_thread);
     Thread t3(wdt_reset_thread);
-    
+
     /*
     * Ethernet
     */
@@ -306,13 +307,13 @@
         ERR("Ethernet initialisation failed. App halted.");
         while (true) {};
     }
-    
+
     Thread::wait(2000); // TCP/UDP stack delay
 
-/*
-* UDP server
-* TCP server/client
-*/
+    /*
+    * UDP server
+    * TCP server/client
+    */
 #ifdef UDP_SERVER
     ret = udp_server.bind(udp_server_local_port);
     DBG("UDP server started (sock.bind = %d)...", ret);
@@ -329,7 +330,7 @@
 #ifdef TCP_CLIENT
 
 #endif
-    
+
     /*
     * Network loop processor
     */
@@ -341,21 +342,20 @@
                 ret = tcp_sock.connect(str_server_ip_addr, u16tcp_server_port); // timeout is default in connect() in W5500.h
                 if (ret > -1) {
                     DBG("Successfully connected to %s on port %d", str_server_ip_addr, u16tcp_server_port);
-                }
-                else {
+                } else {
                     ERR("Unable to connect to %s on port %d", str_server_ip_addr, u16tcp_server_port);
                 }
             }
-                
+
             // transmit data if connected
             if (tcp_sock.is_connected()) {
                 osEvent evt = auto_update_queue.get(1); // timeout after 1ms
                 if (evt.status == osEventMessage) {
                     DBG("Updating...");
-                    update_sending_frame(tcp_sending_buffer);
-                    tcp_sock.send_all(tcp_sending_buffer, SENDING_PROTOCOL_LENGTH);
+                    update_sending_frame(network_output_buffer);
+                    tcp_sock.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
                 }
-                
+
                 // check to receive or timeout
                 tcp_sock.set_blocking(false, TCP_CLIENT_RECEIVE_TIMEOUT);
                 n = tcp_sock.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer));
@@ -374,26 +374,37 @@
         if (1) {
             // wait for client within timeout
             ret = tcp_server.accept(tcp_client);
-            
+
             // tcp client connected
             if (ret > -1) {
                 DBG("Connection from: %s", tcp_client.get_address());
-                
+
                 // loop waiting and receiving data within timeout
                 tcp_client.set_blocking(false, TCP_SERVER_RECEIVE_TIMEOUT); // Timeout after x seconds
-                while (true) {
+                while (tcp_client.is_connected()) {
                     n = tcp_client.receive(tcp_receiving_buffer, sizeof(tcp_receiving_buffer));
                     if (n <= 0) break;
-                    
+
                     // got some data, process it
                     tcp_receiving_buffer[n] = '\0'; // for debugging purpose
                     DBG("TCP server received: %s", tcp_receiving_buffer);
                     n = process_control_command(tcp_receiving_buffer, n);
-                    // send rpc reply back to client, NNIO protocol always returns 0
+                    // send reply back to client, NNIO protocol always returns 0
+                    // RPC-style protocol
                     if (n > 0) {
-                        rpc_outbuf[n] = '\0';
-                        tcp_client.send_all(rpc_outbuf, strlen(rpc_outbuf));
-                    }
+                        network_output_buffer[n] = '\0';
+                        tcp_client.send_all(network_output_buffer, strlen(network_output_buffer));
+                    } // RPC-style protocol
+                    else if (n == 0) {
+                        // then, check query status command and sending protocol if required
+                        if (tcp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
+                            DBG("Requested to send device status through TCP");
+                            // sending protocol
+                            update_sending_frame(network_output_buffer);
+                            tcp_client.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
+                            DBG("Sent");
+                        }
+                    } // NNIO protocol
                 } // end loop if no data received within timeout
             } // if client connected
             tcp_client.close();
@@ -402,9 +413,9 @@
 
 #ifdef UDP_SERVER // configuration and control, both NNIO and RPC-style
         bool discovery_mode_flag, config_mode_flag;
-        
+
         n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
-        
+
         // check to see if it is a query command
         // if yes, is it a discovery command or an ip query to enter config mode
         discovery_mode_flag = false;
@@ -421,11 +432,10 @@
             DBG("Entered configuration mode...");
             DBG("!!! RESET when finished");
         } // NNCFIP
-        
+
         // if received NNCFIP, enter config mode
         if (config_mode_flag) {
-            while (n > 0)
-            {
+            while (n > 0) {
                 // got some data, test it
                 DBG("UDP received (%s) from (%s:%d)", udp_receiving_buffer, ep_udp_client.get_address(), ep_udp_client.get_port());
                 process_config_command(udp_receiving_buffer, n);
@@ -438,9 +448,20 @@
         else if ((n > 0) && (!discovery_mode_flag)) {
             n = process_control_command(udp_receiving_buffer, n);
             // send rpc reply back to client, NNIO protocol always returns 0
+            // RPC-style protocol
             if (n > 0) {
-                rpc_outbuf[n] = '\0';
-                udp_server.sendTo(ep_udp_client, rpc_outbuf, strlen(rpc_outbuf));
+                network_output_buffer[n] = '\0';
+                udp_server.sendTo(ep_udp_client, network_output_buffer, strlen(network_output_buffer));
+            } // RPC-style protocol
+            else if (n == 0) {
+                // then, check query status command and sending protocol if required
+                if (udp_receiving_buffer[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
+                    DBG("Requested to send device status through UDP");
+                    // sending protocol
+                    update_sending_frame(network_output_buffer);
+                    udp_server.sendTo(ep_udp_client, network_output_buffer, SENDING_PROTOCOL_LENGTH);
+                    DBG("Sent");
+                }
             }
         }
 #endif
@@ -454,13 +475,13 @@
 void process_config_command(char* received_buffer, int len)
 {
     DBG("Processing configuration command");
-    
+
     // a configuration command always starts with NN
     if ((received_buffer[0] == 'N') && (received_buffer[1] == 'N') &&
-        (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) {
+            (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) {
         switch (len) {
-            // length = 6, a QUERY command (discovery command, TCP port, or UDP port)
-            // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM
+                // length = 6, a QUERY command (discovery command, TCP port, or UDP port)
+                // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM
             case QUERY_NETWORK_CONFIG_CMD_LENGTH: {
                 if (strstr(received_buffer, QUERY_IP_CMD) != NULL) {
                     udp_server.sendTo(ep_udp_client, eth.getIPAddress(), strlen(eth.getIPAddress()));
@@ -564,10 +585,10 @@
     char* received_frame;
     bool rpc_style;
     int pos;
-    char inbuf[RPC_BUF_LEN];
-    
+    char inbuf[NET_BUF_LEN];
+
     DBG("Processing control command");
-    
+
     /*
      * This section is for RPC-style command
      */
@@ -580,14 +601,13 @@
     if ((len > 0) && (inbuf[0] == '/')) {
         char obj_name[32];
         bool result;
-        
+
         rpc_style = true;
         // find RPC object name
         for (int i = 1; i < strlen(inbuf); i++) {
             if (inbuf[i] != '/') {
                 obj_name[i-1] = inbuf[i];
-            }
-            else {
+            } else {
                 obj_name[i-1] = '\0';
                 break;
             }
@@ -596,24 +616,23 @@
         /*
          * execute RPC command, return reply length and reply in rpc_outbuf
          */
-        result = RPC::call(inbuf, rpc_outbuf);
+        result = RPC::call(inbuf, network_output_buffer);
         if (result) {
             // re-arrange output buffer as following: object_name:output_value
-            strcpy(inbuf, rpc_outbuf); // use inbuf as temp
-            strcpy(rpc_outbuf, obj_name); // rpc object name
-            strcat(rpc_outbuf, ":");
-            strcat(rpc_outbuf, inbuf); // concat rpc reply
-            strcat(rpc_outbuf, "\r\n"); // CR-LF
-            int j = strlen(rpc_outbuf);
-            DBG("Reply of rpc command on \"%s\" (%d bytes): %s", obj_name, j, rpc_outbuf);
+            strcpy(inbuf, network_output_buffer); // use inbuf as temp
+            strcpy(network_output_buffer, obj_name); // rpc object name
+            strcat(network_output_buffer, ":");
+            strcat(network_output_buffer, inbuf); // concat rpc reply
+            strcat(network_output_buffer, "\r\n"); // CR-LF
+            int j = strlen(network_output_buffer);
+            DBG("Reply of rpc command on \"%s\" (%d bytes): %s", obj_name, j, network_output_buffer);
             return j; // return length of rpc_outbuf
-        }
-        else {
+        } else {
             ERR("Failed: %s", inbuf);
             return -1;
         }
     }
-    
+
     /*
      * This section below is  for NNIO protocol
      */
@@ -627,13 +646,13 @@
         }
         pos = id - received_buffer;
         DBG("Found a frame at %d", pos);
-        
+
         // extract this frame
         received_frame = &received_buffer[pos];
         // calculate the rest
         received_buffer = &received_buffer[pos + RECEIVING_PROTOCOL_LENGTH];
         len -= RECEIVING_PROTOCOL_LENGTH;
-        
+
         // process this received frame
         // firstly, update outputs if required
         // digital outputs
@@ -662,17 +681,8 @@
             str_uart[32] = '\0';
             uart.printf("%s\r\n", str_uart);
         }
-                            
-        // then, check query status command and sending protocol if required
-        if (received_frame[RECEIVING_PROTOCOL_COMMAND_POS] == QUERY_STATUS_COMMAND) {
-            DBG("Requested to send device status through TCP");
-            // sending protocol
-            update_sending_frame(tcp_sending_buffer);
-            tcp_client.send_all(tcp_sending_buffer, SENDING_PROTOCOL_LENGTH);
-            DBG("Sent");
-        }
     }
-    
+
     DBG("Successfully processed.");
     return 0;
 }
@@ -681,11 +691,12 @@
 /*
 * W5500 Ethernet init
 */
-int ethernet_init(void) {
+int ethernet_init(void)
+{
     int dhcp_ret, ret;
-    
+
     DBG("Initialising ethernet...");
-    
+
     // if not configured, try dhcp
     dhcp_ret = -1;
     if (configured_ip != DEFAULT_ENABLE_FLAG_VALUE) {
@@ -694,7 +705,7 @@
         if (dhcp_ret == 0)
             dhcp_ret = eth.connect();
     }
-    
+
     if (dhcp_ret != 0) {
         DBG("No DHCP, load static IP configuration");
         ret = eth.init(u8mac, str_ip_addr, str_ip_subnet, str_ip_gateway); // static
@@ -719,7 +730,7 @@
         ERR("Error eth.connect() - ret = %d", ret);
         return -1;
     }
-    
+
     return 0;
 }
 
@@ -727,9 +738,10 @@
 /*
 * Update digital outputs according to receiving protocol
 */
-void update_digital_outputs(char* buf) {
+void update_digital_outputs(char* buf)
+{
     DBG("Digital outputs: %s", buf);
-    
+
     dout0 = (buf[0] == DIGITAL_HIGH)? 1 : 0;
     dout1 = (buf[1] == DIGITAL_HIGH)? 1 : 0;
     dout2 = (buf[2] == DIGITAL_HIGH)? 1 : 0;
@@ -743,11 +755,12 @@
 /*
 * Prepare a frame for sending protocol, which includes status of I/Os
 */
-void update_sending_frame(char* buf) {
+void update_sending_frame(char* buf)
+{
     memcpy(&buf[SENDING_PROTOCOL_ID_POS], DEVICE_CONTROL_CODE, 4); // device id
     memcpy(&buf[SENDING_PROTOCOL_MAC_POS], &u8mac, 6);
     memcpy(&buf[SENDING_PROTOCOL_IP_POS], &u8ip_addr, 4);
-    
+
     buf[SENDING_PROTOCOL_DI_POS+0] = (din0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DI_POS+1] = (din1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DI_POS+2] = (din2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
@@ -756,7 +769,7 @@
     buf[SENDING_PROTOCOL_DI_POS+5] = (din5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DI_POS+6] = (din6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DI_POS+7] = (din7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    
+
     buf[SENDING_PROTOCOL_DO_POS+0] = (dout0 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DO_POS+1] = (dout1 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DO_POS+2] = (dout2 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
@@ -765,7 +778,7 @@
     buf[SENDING_PROTOCOL_DO_POS+5] = (dout5 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DO_POS+6] = (dout6 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
     buf[SENDING_PROTOCOL_DO_POS+7] = (dout7 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    
+
     uint16_t val = ain0.read_u16(); // 16-bits normalised
     memcpy(&buf[SENDING_PROTOCOL_AI0_POS], &val, 2); // LSB MSB
     val = ain1.read_u16(); // 16-bits normalised
--- a/readme.txt	Sun Jan 11 13:53:53 2015 +0000
+++ b/readme.txt	Sat Jan 24 20:49:24 2015 +0000
@@ -12,4 +12,8 @@
     
 v1.0 (06/01/2014)
     + Added: RPC command replies as following object_name:reply_value
-    + Modified: clean code in my_eeprom_funcs and main.cpp
\ No newline at end of file
+    + Modified: clean code in my_eeprom_funcs and main.cpp
+    
+v1.1 (24/01/2015)
+    + Modified: control command is able to be processed by both TCP and UDP.
+      Only one network output buffer is used for RPC-style and NNIO protocols.
\ No newline at end of file