Chau Vo / Mbed 2 deprecated F103-Web-Server

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

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

Revision:
40:c966abbe2d62
Parent:
39:083cf93121a9
Child:
41:a50a534a2fbb
diff -r 083cf93121a9 -r c966abbe2d62 main.cpp
--- a/main.cpp	Tue Jun 14 21:25:04 2016 +0000
+++ b/main.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -13,6 +13,14 @@
 #include "my_eeprom_funcs.h"
 #include "Watchdog.h"
 
+#include "RPCCommand.h"
+#include "HTTPServer.h"
+#include "Formatter.h"
+#include "RequestHandler.h"
+#include "RPCType.h"
+
+#define SERVER_PORT 80
+
 
 /** Debug option
  *
@@ -37,6 +45,7 @@
 // Ethernet
 SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
 EthernetInterface eth(&spi, PA_4, PC_9); // spi, cs, reset
+int ethernet_init(void);
 
 /*
 * EEPROM section
@@ -63,33 +72,6 @@
 
 
 /*
-* Network configuration
-*/
-#define TCP_SERVER
-#define TCP_CLIENT
-#define UDP_SERVER
-//#define UDP_CLIENT
-#define NTP
-
-#define TCP_SERVER_WAIT_CLIENT_TIMEOUT     200 // timeout for local tcp server wait for a remote client
-#define TCP_SERVER_RECEIVE_TIMEOUT         2000 // timeout for local tcp server wait to receive from remote client
-#define TCP_CLIENT_RECEIVE_TIMEOUT         200 // timeout for local tcp client try to connect remote server
-#define UDP_SERVER_RECEIVE_TIMEOUT         100 // timeout for checking config command
-
-
-// TCP server function
-TCPSocketServer tcp_server;
-TCPSocketConnection tcp_client;
-// TCP client function
-TCPSocketConnection tcp_sock;
-// UDP server
-UDPSocket udp_server;
-Endpoint ep_udp_client;
-// NTP
-NTPClient ntp;
-
-
-/*
 * Variables for network configuration, TCP server
 */
 uint8_t u8mac[6], u8ip_addr[4];// keep mac and ip address in 8-bits
@@ -109,191 +91,21 @@
 uint16_t u16tcp_server_port; // directly loaded from eeprom
 uint16_t u16enable_tcp_client, u16enable_tcp_server;// flags for enabling TCP client or TCP server
 
-#define NET_BUF_LEN         256
-char tcp_receiving_buffer[NET_BUF_LEN];
-char udp_receiving_buffer[NET_BUF_LEN];
-char network_output_buffer[NET_BUF_LEN]; // output buffer for TCP/UDP control command
 
-
-/*
- * RPC Protocol
- * Use the RPC enabled wrapped class  - see RpcClasses.h for more info
- */
-// DigitalIn
-RpcDigitalIn di0(PB_14, "di0");
-RpcDigitalIn di1(PB_12, "di1");
-RpcDigitalIn di2(PB_10, "di2");
-RpcDigitalIn di3(PB_1, "di3");
-RpcDigitalIn di4(PB_15, "di4");
-RpcDigitalIn di5(PB_13, "di5");
-RpcDigitalIn di6(PB_11, "di6");
-RpcDigitalIn di7(PB_2, "di7");
-DigitalIn din0(PB_14);
-DigitalIn din1(PB_12);
-DigitalIn din2(PB_10);
-DigitalIn din3(PB_1);
-DigitalIn din4(PB_15);
-DigitalIn din5(PB_13);
-DigitalIn din6(PB_11);
-DigitalIn din7(PB_2);
-// DigitalOut
-RpcDigitalOut do0(PB_3, "do0");
-RpcDigitalOut do1(PB_5, "do1");
-RpcDigitalOut do2(PB_7, "do2");
-RpcDigitalOut do3(PB_9, "do3");
-RpcDigitalOut do4(PD_2, "do4");
-RpcDigitalOut do5(PB_4, "do5");
-RpcDigitalOut do6(PB_6, "do6");
-RpcDigitalOut do7(PB_8, "do7");
-DigitalOut dout0(PB_3);
-DigitalOut dout1(PB_5);
-DigitalOut dout2(PB_7);
-DigitalOut dout3(PB_9);
-DigitalOut dout4(PD_2);
-DigitalOut dout5(PB_4);
-DigitalOut dout6(PB_6);
-DigitalOut dout7(PB_8);
-// AnalogIn
-RpcAnalogIn adc10(PC_0, "ai0"); // adc10
-RpcAnalogIn adc11(PC_1, "ai1"); // adc11
-AnalogIn ain0(PC_0);
-AnalogIn ain1(PC_1);
-// AnalogOut, PWM
-RpcPwmOut pwm11(PA_8, "pwm0"); // pwm11
-RpcPwmOut pwm21(PA_15, "pwm1"); // pwm21
 // Serial
-RpcSerial usart2(USBTX, USBRX, "uart"); // usart2
 Serial uart(USBTX,USBRX);
-// Timer
-RpcTimer timer1("tmr1");
 // Watchdog
 Watchdog wdt;
 
-
-// Some variable types that can be modified through RPC.
-//int wheelsOn;
-//char lcdBannerMessage;
-//float speed;
-int current_time;
-int do0OnTime, do0OffTime;
-int do1OnTime, do1OffTime;
- 
-//RPCVariable<int> rpcLights(&wheelsOn, "wheels");
-//RPCVariable<char> rpcBanner(&lcdBannerMessage, "banner");
-//RPCVariable<float> rpcSpeed(&speed, "speed");
-RPCVariable<int> rpcCurrentTime(&current_time, "Time");
-RPCVariable<int> rpcdo0OnTime(&do0OnTime, "do0OnTime");
-RPCVariable<int> rpcdo0OffTime(&do0OffTime, "do0OffTime");
-RPCVariable<int> rpcdo1OnTime(&do0OnTime, "do1OnTime");
-RPCVariable<int> rpcdo1OffTime(&do0OffTime, "do1OffTime");
-
-// RPC function definitions
-// Create a function of the required format
-void set_current_time(Arguments* args, Reply* rep);
-void set_current_time(Arguments* args, Reply* rep){
-    time_t ct = (time_t)current_time; // convert
-    struct tm *st = localtime(&ct);
-    
-    set_time(ct); // set time
-    
-    DBG("Set current time to: %s", ctime(&ct));
-    DBG("Time only: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec);
-}
-// Attach it to an RPC object
-RPCFunction rpcSetCurrentTime(&set_current_time, "SetTime");
-
-/*
- * NNIO Protocol
- */
-// Commands
-#define DEVICE_DESCRIPTION                  "NNIO"
-#define DEVICE_CONFIG_CODE                  "NNCF"
-#define DEVICE_CONTROL_CODE                 "NNIO"
-
-#define RECEIVING_PROTOCOL_LENGTH           58
-#define SENDING_PROTOCOL_LENGTH             39
-#define QUERY_NETWORK_CONFIG_CMD_LENGTH     6
-#define SET_NETWORK_CONFIG_CMD_LENGTH       19
-#define UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH   12
-
-#define QUERY_DISCOVERY_CMD                 "NNCFDS"
-#define QUERY_IP_CMD                        "NNCFIP"
-#define QUERY_SUBNET_CMD                    "NNCFSN"
-#define QUERY_GATEWAY_CMD                   "NNCFGW"
-#define QUERY_MAC_CMD                       "NNCFMC"
-#define QUERY_UDP_PORT_CMD                  "NNCFUP"
-#define QUERY_TCP_PORT_CMD                  "NNCFTP"
-#define QUERY_UPDATE_TIME_CMD               "NNCFTM"
-#define RECEIVING_PROTOCOL_ENABLE_OUTPUT    'O'
-#define QUERY_STATUS_COMMAND                'Q'
-#define DIGITAL_HIGH                        'H'
-#define DIGITAL_LOW                         'L'
-
-
-// Positions
-#define RECEIVING_PROTOCOL_ID_POS           0
-#define RECEIVING_PROTOCOL_OP_POS           4
-#define RECEIVING_PROTOCOL_EN_DO_POS        RECEIVING_PROTOCOL_OP_POS + 0
-#define RECEIVING_PROTOCOL_EN_A0O_POS       RECEIVING_PROTOCOL_OP_POS + 1
-#define RECEIVING_PROTOCOL_EN_A1O_POS       RECEIVING_PROTOCOL_OP_POS + 2
-#define RECEIVING_PROTOCOL_EN_UART_POS      RECEIVING_PROTOCOL_OP_POS + 3
-#define RECEIVING_PROTOCOL_COMMAND_POS      RECEIVING_PROTOCOL_OP_POS + 4
-
-#define RECEIVING_PROTOCOL_IP_POS           9
-#define RECEIVING_PROTOCOL_DO_POS           13
-#define RECEIVING_PROTOCOL_A0O_POS          21
-#define RECEIVING_PROTOCOL_A01_POS          23
-#define RECEIVING_PROTOCOL_UART_POS         25
-
-
-#define SENDING_PROTOCOL_ID_POS             0
-#define SENDING_PROTOCOL_MAC_POS            4
-#define SENDING_PROTOCOL_IP_POS             10
-#define SENDING_PROTOCOL_DI_POS             14
-#define SENDING_PROTOCOL_DO_POS             22
-#define SENDING_PROTOCOL_AI0_POS            30
-#define SENDING_PROTOCOL_AI1_POS            32
-#define SENDING_PROTOCOL_AO0_POS            34
-#define SENDING_PROTOCOL_AO1_POS            36
-#define SENDING_PROTOCOL_CR_POS             38
-
-
-/*
-* RTOS
-*/
-struct message_t {
-    int len;
-    char *msg;
-};
-Queue<message_t, 16> uart_queue;
-Queue<bool, 1> auto_update_queue;
-
-
-
-// Prototypes
-int ethernet_init(void);
-int process_control_command(char* received_buffer, int len);
-void process_config_command(char* received_buffer, int len);
-void update_digital_outputs(char* buf);
-void update_sending_frame(char* buf);
+float speed;
+RPCVariable<float> rpcSpeed(&speed, "speed");
+char stripaddr[20];
+RPCVariable<char*> rpcIPAddress(stripaddr, "ipaddr");
 
 
 /*
 * Threads
 */
-// 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);
-        Thread::wait(1000*transmit_time_period); // Thread::wait() in ms
-    }
-}
-
-
 // WDT reset
 void wdt_reset_thread(void const* args)
 {
@@ -301,104 +113,21 @@
         wdt.Service();
 }
 
-// Timer thread to check on/off time
-void digital_outputs_timer_thread(void const* args)
+
+HTTPServer create_simple_server()
+{    
+    HTTPServer srv;
+    srv.add_request_handler("DELETE", new DeleteRequestHandler());
+    srv.add_request_handler("GET", new GetRequestHandler());
+    srv.add_request_handler("PUT", new PutRequestHandler());
+    return srv;
+}
+
+HTTPServer create_interactive_server()
 {
-    Thread::wait(700);
-    
-    while(true) {
-        // read current time
-        time_t seconds = time(NULL);
-        struct tm *st = localtime(&seconds);
-        int current_time_in_seconds = 3600*(st->tm_hour) + 60*(st->tm_min) + st->tm_sec;
-        DBG("Current time: %d:%d:%d", st->tm_hour, st->tm_min, st->tm_sec);
-        
-        // check do0
-        if (do0OnTime < do0OffTime) {
-            if ((current_time_in_seconds >= do0OnTime) && (current_time_in_seconds < do0OffTime)){
-                if (dout0 == 0) {
-                    dout0 = 1;
-                    DBG("do0 ON");
-                }
-                else {
-                    DBG("do0 ON'ed");
-                }
-            }
-            else {
-                if (dout0 == 1) {
-                    dout0 = 0;
-                    DBG("do0 OFF'ed");
-                }
-                else {
-                    DBG("do0 OFF");
-                }
-            }
-        }
-        else {
-            if ((current_time_in_seconds >= do0OffTime) && ((current_time_in_seconds < do0OnTime))) {
-                if (dout0 == 1) {
-                    dout0 = 0;
-                    DBG("do0 OFF");
-                }
-                else {
-                    DBG("do0 OFF'ed");
-                }
-            }
-            else {
-                if (dout0 == 0) {
-                    dout0 = 1;
-                    DBG("do0 ON");
-                }
-                else {
-                    DBG("do0 ON'ed");
-                }
-            }
-        }
-        
-        // check do1
-        if (do1OnTime < do1OffTime) {
-            if ((current_time_in_seconds >= do1OnTime) && (current_time_in_seconds < do1OffTime)){
-                if (dout1 == 0) {
-                    dout1 = 1;
-                    DBG("do1 ON");
-                }
-                else {
-                    DBG("do1 ON'ed");
-                }
-            }
-            else {
-                if (dout1 == 1) {
-                    dout1 = 0;
-                    DBG("do1 OFF");
-                }
-                else {
-                    DBG("do1 OFF'ed");
-                }
-            }
-        }
-        else {
-            if ((current_time_in_seconds >= do1OffTime) && ((current_time_in_seconds < do1OnTime))) {
-                if (dout1 == 1) {
-                    dout1 = 0;
-                    DBG("do1 OFF");
-                }
-                else {
-                    DBG("do1 OFF'ed");
-                }
-            }
-            else {
-                if (dout1 == 0) {
-                    dout1 = 1;
-                    DBG("do1 ON");
-                }
-                else {
-                    DBG("do1 ON'ed");
-                }
-            }
-        }
-        // wait 1s
-        Thread::wait(10000); // Thread::wait() in ms
-    }
+    HTTPServer srv(new InteractiveHTMLFormatter());
+    srv.add_request_handler("GET", new ComplexRequestHandler());
+    return srv;
 }
 
 // Main code
@@ -428,9 +157,10 @@
     /*
     * UI threads
     */
-    Thread t2(auto_update_timer_thread);
     Thread t3(wdt_reset_thread);
-    Thread t4(digital_outputs_timer_thread);
+    
+    // rpc
+    RPCType::instance().register_types();
 
     /*
     * Ethernet
@@ -442,400 +172,23 @@
     }
 
     Thread::wait(2000); // TCP/UDP stack delay
-
-    /*
-    * UDP server
-    * TCP server/client
-    */
-#ifdef UDP_SERVER
-    ret = udp_server.bind(udp_server_local_port);
-    DBG("UDP server started (sock.bind = %d)...", ret);
-    udp_server.set_blocking(false, UDP_SERVER_RECEIVE_TIMEOUT);
-#endif
-
-#ifdef TCP_SERVER
-    tcp_server.bind(tcp_server_local_port);
-    tcp_server.listen();
-    DBG("TCP server started...");
-    tcp_server.set_blocking(false, TCP_SERVER_WAIT_CLIENT_TIMEOUT);
-#endif
-
-#ifdef TCP_CLIENT
-
-#endif
-
-    /*
-    * Network loop processor
-    */
-    while (true) {
-#ifdef TCP_CLIENT // auto update device status to a remote TCP server
-        if (auto_transmit_flag == DEFAULT_ENABLE_FLAG_VALUE) {
-            // connect to TCP server if required
-            if (!tcp_sock.is_connected()) {
-                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 {
-                    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(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));
-                if (n > 0) {
-                    // got some data, test it
-                    DBG("TCP client received %d bytes: %s", n, tcp_receiving_buffer);
-                    n = process_control_command(tcp_receiving_buffer, n);
-                    // send reply back to client, NNIO protocol always returns 0
-                    // RPC-style protocol
-                    if (n > 0) {
-                        network_output_buffer[n] = '\0';
-                        tcp_sock.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_sock.send_all(network_output_buffer, SENDING_PROTOCOL_LENGTH);
-                            DBG("Sent");
-                        }
-                    } // NNIO protocol
-                }
-            }
-        } // if tcp client enabled && auto transmit
-#endif
-
-
-#ifdef TCP_SERVER // control and monitor from a remote TCP client, both NNIO and RPC-style
-        // no tcp client connected{
-        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 (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 reply back to client, NNIO protocol always returns 0
-                    // RPC-style protocol
-                    if (n > 0) {
-                        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();
-        } // if tcp server enabled && no client connected
-#endif
-
-#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;
-        config_mode_flag = false;
-        if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_DISCOVERY_CMD) != NULL)) {
-            discovery_mode_flag = true;
-            DBG("Received discovery command");
-            char str[50];
-            sprintf(str, "%s%s%s", DEVICE_DESCRIPTION, eth.getMACAddress(), eth.getIPAddress());
-            udp_server.sendTo(ep_udp_client, str, strlen(str));
-        } // NNCFDS
-        else if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_IP_CMD) != NULL)) {
-            config_mode_flag = true;
-            DBG("Entered configuration mode...");
-            DBG("!!! RESET when finished");
-        } // NNCFIP
+    
+    // Test parsing ip address string
+    char* ipaddr = "192.168.0.121";
+    int b[4];
+    sscanf(ipaddr, "%d.%d.%d.%d", &b[0], &b[1], &b[2], &b[3]);
+    DBG("%d.%d.%d.%d",b[0],b[1],b[2],b[3]);
 
-        // if received NNCFIP, enter config mode
-        if (config_mode_flag) {
-            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);
-                // wait to receive new config command
-                udp_server.set_blocking(true);
-                n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
-            } // while (n > 0), config loop
-        } // if (config_mode_flag)
-        // process control packages sent using UDP
-        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) {
-                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");
-                }
-            } // NNIO protocol
-        }
-#endif
-    } // network processor
-}
-
-
-/*
- * Process NNCF commands
- */
-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')) {
-        switch (len) {
-                // 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()));
-                } // NNCFIP
-                else if (strstr(received_buffer, QUERY_SUBNET_CMD) != NULL) {
-                    udp_server.sendTo(ep_udp_client, eth.getNetworkMask(), strlen(eth.getNetworkMask()));
-                } // NNCFSN
-                else if (strstr(received_buffer, QUERY_GATEWAY_CMD) != NULL) {
-                    udp_server.sendTo(ep_udp_client, eth.getGateway(), strlen(eth.getGateway()));
-                } // NNCFGW
-                else if (strstr(received_buffer, QUERY_MAC_CMD) != NULL) {
-                    udp_server.sendTo(ep_udp_client, eth.getMACAddress(), strlen(eth.getMACAddress()));
-                } // NNCFMC
-                // ask for TCP server port
-                else if (strstr(received_buffer, QUERY_TCP_PORT_CMD) != NULL) {
-                    char port[5];
-                    sprintf(port, "%5d", tcp_server_local_port);
-                    udp_server.sendTo(ep_udp_client, port, strlen(port));
-                } // NNCFTP
-                // ask for UDP server port
-                else if (strstr(received_buffer, QUERY_UDP_PORT_CMD) != NULL) {
-                    char port[5];
-                    sprintf(port, "%5d", udp_server_local_port);
-                    udp_server.sendTo(ep_udp_client, port, strlen(port));
-                } // NNCFUP
-                else if (strstr(received_buffer, QUERY_UPDATE_TIME_CMD) != NULL) {
-#ifdef NTP
-                    char str_time[50];
-
-                    DBG("Trying to update time...");
-                    if (ntp.setTime("0.pool.ntp.org") == 0) {
-                        DBG("Set time successfully");
-                        time_t ctTime;
-                        ctTime = time(NULL);
+    // create rpc http server
+    HTTPServer srv = create_interactive_server();
 
-                        DBG("Time is set to (UTC): %s", ctime(&ctTime));
-                        sprintf(str_time, "%s", ctime(&ctTime));
-                        udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
-                    } else {
-                        WARN("Error");
-                        sprintf(str_time, "ERR");
-                        udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
-                    }
-#else
-                    WARN("NTP disabled");
-                    sprintf(str_time, "DIS");
-                    udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
-#endif
-                } // NNCFTM
-                break;
-            }
-            // length = 19, SET NETWORK CONFIGURATION
-            // Format: 4E 4E 43 46      C0 A8 00 78        FF FF FF 00            C0 A8 00 01      00 00 01
-            //        (NNCF;            IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1)
-            case SET_NETWORK_CONFIG_CMD_LENGTH: {
-                // check device id
-                char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
-                if (id == NULL)
-                    break;
-                else if ((id - received_buffer) > 0)
-                    break;
-
-                DBG("Received user configuration");
-                write_eeprom_network(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char, 15-bytes
-                NVIC_SystemReset();
-                break;
-            }
-            // length = 12, SET TCP SERVER CONFIGURATION
-            // auto update & its time period, TCP server configuration (IP & port)
-            // Format: 4E 4E 43 46   'Y'     01   C0 A8 00 09   E0 2E (LSB MSB)
-            //         NNCF          Auto    1s   192.168.0.9   12000
-            case UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH: {
-                char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
-                if (id == NULL)
-                    break;
-                else if ((id - received_buffer) > 0)
-                    break;
-
-                DBG("Received TCP server configuration");
-                write_eeprom_tcpserver(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char
-                NVIC_SystemReset();
-                break;
-            }
-            default:
-                break;
-        } // switch (n), check configuration command length
-    } // if starts with NNCF, a config command
-    else { // if not a configuration command
-    }
-}
-
-/*
- * Procedure to process receiving protocol, which includes command to control outputs.
- * Support both NNIO and RPC-style commands.
- * RPC always starts with '/'.
- * Return:
- *      0 if NNIO protocol;
- *      length of rpc output buffer if rpc;
- *      -1 if rpc failed
- */
-int process_control_command(char* received_buffer, int len)
-{
-    char* received_frame;
-    bool rpc_style;
-    int pos;
-    char inbuf[NET_BUF_LEN];
-
-    DBG("Processing control command");
-
-    /*
-     * This section is for RPC-style command
-     */
-    // check if it is a RPC-style command
-    rpc_style = false;
-    strncpy(inbuf, received_buffer, len);
-    inbuf[len] = '\r'; // use inbuf for RPC protocol
-    inbuf[len+1] = '\n';
-    inbuf[len+2] = '\0'; // add CR-LF
-    if ((len > 0) && (inbuf[0] == '/')) {
-        char obj_name[16];
-        bool ok;
-
-        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 {
-                obj_name[i-1] = '\0';
-                break;
-            }
-        }
-        DBG("Rpc command = %s", inbuf);
-        /*
-         * execute RPC command, return reply length and reply in rpc_outbuf
-         */
-        ok = RPC::call(inbuf, network_output_buffer);
-        if (ok) {
-            // re-arrange output buffer as following: object_name:output_value
-            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 {
-            ERR("Failed: %s", inbuf);
-            return -1;
-        }
+    if(!srv.init(SERVER_PORT))
+    {
+        eth.disconnect();
+        return -1;
     }
 
-    /*
-     * This section below is  for NNIO protocol
-     */
-    while ((!rpc_style) && (len >= RECEIVING_PROTOCOL_LENGTH)) {
-        // find device ID
-        DBG("Checking device ID...");
-        char* id = strstr(received_buffer, DEVICE_CONTROL_CODE);
-        if (id == NULL) {
-            DBG("No device ID found");
-            break;
-        }
-        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
-        if (received_frame[RECEIVING_PROTOCOL_EN_DO_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
-            DBG("Update digital outputs");
-            char str_dout[9];
-            memcpy(str_dout, &received_frame[RECEIVING_PROTOCOL_DO_POS], 8);
-            str_dout[8] = '\0';
-            update_digital_outputs(str_dout);
-        }
-        // analog output 0
-        if (received_frame[RECEIVING_PROTOCOL_EN_A0O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
-            DBG("Update analog output 0");
-            //TODO Update analog output
-        }
-        // analog output 1
-        if (received_buffer[RECEIVING_PROTOCOL_EN_A1O_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
-            DBG("Update analog output 1");
-            //TODO Update analog output
-        }
-        // UART
-        if (received_frame[RECEIVING_PROTOCOL_EN_UART_POS] == RECEIVING_PROTOCOL_ENABLE_OUTPUT) {
-            DBG("UART data: ");
-            char str_uart[33];
-            memcpy(str_uart, &received_frame[RECEIVING_PROTOCOL_UART_POS], 32);
-            str_uart[32] = '\0';
-            uart.printf("%s\r\n", str_uart);
-        }
-    }
-
-    DBG("Successfully processed.");
-    return 0;
+    srv.run();
 }
 
 
@@ -885,59 +238,3 @@
     return 0;
 }
 
-
-/*
-* Update digital outputs according to receiving protocol
-*/
-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;
-    dout3 = (buf[3] == DIGITAL_HIGH)? 1 : 0;
-    dout4 = (buf[4] == DIGITAL_HIGH)? 1 : 0;
-    dout5 = (buf[5] == DIGITAL_HIGH)? 1 : 0;
-    dout6 = (buf[6] == DIGITAL_HIGH)? 1 : 0;
-    dout7 = (buf[7] == DIGITAL_HIGH)? 1 : 0;
-}
-
-/*
-* Prepare a frame for sending protocol, which includes status of I/Os
-*/
-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;
-    buf[SENDING_PROTOCOL_DI_POS+3] = (din3 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    buf[SENDING_PROTOCOL_DI_POS+4] = (din4 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    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;
-    buf[SENDING_PROTOCOL_DO_POS+3] = (dout3 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    buf[SENDING_PROTOCOL_DO_POS+4] = (dout4 == 1) ? DIGITAL_HIGH : DIGITAL_LOW;
-    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
-    memcpy(&buf[SENDING_PROTOCOL_AI1_POS], &val, 2); // LSB MSB
-    val = 0x1234;
-    memcpy(&buf[SENDING_PROTOCOL_AO0_POS], &val, 2); // LSB MSB
-    val = 0x5678;
-    memcpy(&buf[SENDING_PROTOCOL_AO1_POS], &val, 2); // LSB MSB
-    buf[SENDING_PROTOCOL_CR_POS] = 0x0D;
-    buf[SENDING_PROTOCOL_CR_POS+1] = '\0';
-}
\ No newline at end of file