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:
Thu Jun 16 08:38:31 2016 +0000
Parent:
39:083cf93121a9
Child:
41:a50a534a2fbb
Commit message:
Working with a few issues:; - Added RPC AnalogIn, wdt reset when creating new object on PC_0; - Added creating RPC string but not tested yet

Changed in this revision

Formatter.cpp Show annotated file Show diff for this revision Revisions of this file
Formatter.h Show annotated file Show diff for this revision Revisions of this file
HTTPServer.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
RPCCommand.cpp Show annotated file Show diff for this revision Revisions of this file
RPCCommand.h Show annotated file Show diff for this revision Revisions of this file
RPCObjectManager.cpp Show annotated file Show diff for this revision Revisions of this file
RPCObjectManager.h Show annotated file Show diff for this revision Revisions of this file
RPCType.cpp Show annotated file Show diff for this revision Revisions of this file
RPCType.h Show annotated file Show diff for this revision Revisions of this file
RequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
RequestHandler.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rpc-nucleo.lib Show annotated file Show diff for this revision Revisions of this file
mbed-rpc.lib Show diff for this revision Revisions of this file
protocol_rpc.txt Show diff for this revision Revisions of this file
protocol_v2.0.txt Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Formatter.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,187 @@
+#include "Formatter.h"
+#include "mbed.h"
+#include "RPCObjectManager.h"
+#include "EthernetInterface.h"
+
+const char *SIMPLE_HTML_CODE = "\
+<!DOCTYPE html>\
+<html>\
+<head>\
+<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
+<title>TCP Server</title>\
+</head>\
+ <body>";
+
+
+const char* INTERACTIVE_HTML_CODE_1 = "\
+<!DOCTYPE html> \
+<html>\
+<head>\
+<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\
+<title>TCP Server</title>\
+<script type=\"text/javascript\">\
+var ip = \"%s\";\
+function submitCreateForm()\
+{\
+var list = document.getElementById(\"type\");\
+var type = list.options[list.selectedIndex].value;\
+var name = document.getElementById(\"name\").value;\
+if(name === \"\") \
+return;\
+var arg = document.getElementById(\"arg\").value;\
+var url;\
+if(arg === \"\") url = \"http://\" + ip + type + \"new?name=\" + name;\
+else url = \"http://\" + ip + type + \"new?arg=\" + arg + \"&name=\" + name;\
+location.href= url;\
+}\
+function submitCallFuncForm()\
+{\
+var command = document.getElementById(\"command\").value;\
+if(command === \"\") \
+return; \
+var tmp = command.split(\' \');\
+var url = tmp[0];\
+if(tmp.length > 1)\
+url += \"?\";\
+for(var i = 1; i < tmp.length; ++i)\
+{\
+url += \"arg\" + i + \"=\" + tmp[i];\
+if(i+1 < tmp.length)\
+url += \"&\";\
+}\
+location.href = url;\
+}\
+</script>\
+</head> \
+<body>";
+    
+const char* INTERACTIVE_HTML_CODE_2 = "<h3>Create Object :</h3>\
+<form>\
+Type: <select id=\"type\">\
+<option value=\"/DigitalOut/\">DigitalOut</option>\
+<option value=\"/DigitalIn/\">DigitalIn</option>\
+<option value=\"/DigitalInOut/\">DigitalInOut</option>\
+<option value=\"/AnalogIn/\">AnalogIn</option>\
+<option value=\"/PwmOut/\">PwmOut</option>\
+<option value=\"/Timer/\">Timer</option>\
+</select><br>\
+name: <input type=\"text\" id=\"name\"><br>\
+arg(optional): <input type=\"text\" id=\"arg\">\
+<p><input type=\"button\" value=\"Create\" onclick=\"javascript:submitCreateForm();\"></p>\
+</form> \
+ \
+<h3>Call a function :</h3>\
+<p>Enter an RPC command.</p>\
+<form>\
+Command: <input type= \"text\" id=\"command\" maxlength=127><br>\
+<p><input type=\"button\" value=\"Send\" onclick=\"javascript:submitCallFuncForm();\"></p><br>\
+</form>\
+</body> \
+</html>";
+
+static char chunk[1024];
+        
+Formatter::Formatter(int nb):
+currentChunk(0),
+nbChunk(nb)
+{
+}    
+
+char* Formatter::get_page(char *reply)
+{
+    chunk[0] = '\0';
+
+    if(currentChunk < nbChunk)
+    {
+        get_chunk(currentChunk, reply);
+        currentChunk++;
+    }
+    else
+        currentChunk = 0;
+    
+    return chunk;
+}    
+
+void Formatter::get_chunk(const int c, char *reply)
+{
+    strcat(chunk, reply);
+}
+
+SimpleHTMLFormatter::SimpleHTMLFormatter():
+Formatter()
+{
+}
+
+void SimpleHTMLFormatter::get_chunk(const int c, char* reply)
+{
+    strcat(chunk, SIMPLE_HTML_CODE);
+    
+    if(reply != NULL && strlen(reply) != 0)
+    {
+        strcat(chunk, "RPC reply : ");
+        strcat(chunk, reply);
+    }
+        
+    if(!RPCObjectManager::instance().is_empty())
+    {
+        strcat(chunk, "<ul>");
+        for(std::list<char*>::iterator itor = RPCObjectManager::instance().begin();
+            itor != RPCObjectManager::instance().end();
+            ++itor)
+        {
+            strcat(chunk, "<li>");
+            strcat(chunk, *itor);
+            strcat(chunk, "</li>");
+        }
+        strcat(chunk, "</ul>");
+    }
+    
+    strcat(chunk, "</body></html>");
+}
+
+InteractiveHTMLFormatter::InteractiveHTMLFormatter():
+Formatter(3)
+{
+}
+
+void InteractiveHTMLFormatter::get_chunk(const int c, char *reply)
+{
+    if(c == 0)
+        //sprintf(chunk, INTERACTIVE_HTML_CODE_1, EthernetInterface::getIPAddress());
+        sprintf(chunk, INTERACTIVE_HTML_CODE_1, eth.getIPAddress());
+
+    else if(c == 1)
+    {
+        if(reply != NULL && strlen(reply) != 0)
+        {
+            strcat(chunk, "RPC reply : ");
+            strcat(chunk, reply);
+        }
+        if(!RPCObjectManager::instance().is_empty())
+        {
+            strcat(chunk, "<p>Objects created :</p>");
+
+            strcat(chunk, "<ul>");
+            for(std::list<char*>::iterator itor = RPCObjectManager::instance().begin();
+                itor != RPCObjectManager::instance().end();
+                ++itor)
+            {
+                strcat(chunk, "<li>");
+                strcat(chunk, *itor);
+                strcat(chunk, " (<a href=\"http://");
+                //strcat(chunk, EthernetInterface::getIPAddress());
+                strcat(chunk, eth.getIPAddress());
+                strcat(chunk, "/");
+                strcat(chunk, *itor);
+                strcat(chunk, "/delete\">delete</a>)");
+                strcat(chunk, "</li>");
+            }
+            strcat(chunk, "</ul>");
+        }
+        strcat(chunk, " ");
+    }
+    else if(c == 2)
+        strcat(chunk, INTERACTIVE_HTML_CODE_2);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Formatter.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,51 @@
+#ifndef FORMATTER
+#define FORMATTER
+
+#include "EthernetInterface.h"
+
+extern EthernetInterface eth;
+
+class Formatter
+{
+    public :
+        
+        Formatter(int nbChunk = 1);
+        
+        char* get_page(char *reply);
+        
+    protected :
+    
+        virtual void get_chunk(const int c, char *reply);
+        
+    private :
+    
+        int currentChunk;
+        int nbChunk;
+};
+
+class SimpleHTMLFormatter : public Formatter
+{        
+    public :
+    
+        SimpleHTMLFormatter();
+        
+    protected :
+    
+        virtual void get_chunk(const int c, char *reply);
+
+};
+
+class InteractiveHTMLFormatter : public Formatter
+{
+    public :
+    
+        InteractiveHTMLFormatter();
+
+    protected :
+        
+        virtual void get_chunk(const int c, char *reply);
+};
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,120 @@
+#include "HTTPServer.h"
+
+#define INVALID_FORMATTER "No valid formatter specified"
+
+bool cmp(char* a, char* b)
+{
+    return strcmp(a,b) < 0;
+}
+
+HTTPServer::HTTPServer(Formatter *f):
+socket(),
+handlers(&cmp),
+formatter(f),
+reply(),
+command()
+{
+}
+
+HTTPServer::~HTTPServer()
+{
+    for(std::map<char*, RequestHandler*>::iterator itor = handlers.begin();
+        itor != handlers.end();
+        ++itor)
+        delete itor->second;
+    
+    if(formatter)
+        delete formatter;
+}
+
+bool HTTPServer::init(int port)
+{
+    socket.set_blocking(true);
+    if(socket.bind(port))
+    {
+        printf("Could not bind on port %d.\n", port);
+        return false; 
+    }
+    
+    if(socket.listen())
+    {
+        printf("Could not listen %d\n", port);
+        return false;
+    }
+    
+    return true;
+}
+
+void HTTPServer::run()
+{
+    TCPSocketConnection c;
+    while(true)
+    {
+        while(socket.accept(c));
+        c.set_blocking(false, 1000);
+        while(c.is_connected())
+        {
+            char buffer[512];
+            int n = c.receive_all(buffer, sizeof(buffer)-1);
+            if(n == 0)
+            {
+                c.close();
+                break;
+            }
+            else if(n != -1)
+            {
+                printf("Received data\n");
+                buffer[n] = '\0';
+                handle_request(buffer);
+                if(formatter != NULL)
+                {
+                    printf("Sending data...");
+                    char *page = formatter->get_page(reply);
+                    do
+                    {
+                        c.send(page, strlen(page)+1);
+                        page = formatter->get_page(reply);
+                    }while(strlen(page)>0);
+                    printf("done\n");
+                }
+                else
+                    c.send(INVALID_FORMATTER, strlen(INVALID_FORMATTER)+1);
+            }
+            else
+                printf("Error while receiving data\n");
+        }
+    }
+}
+
+void HTTPServer::handle_request(char *buffer)
+{
+    char *request_type = strtok(buffer, " ");
+    char *request = strtok(NULL, " ");
+
+    reply[0] = '\0';
+    if(!strcmp(request, "/"))
+        return;    
+    
+    if(!command.decode(request))
+    {
+        strcat(reply, "Malformed request");
+        return;
+    }
+    
+    std::map<char*, RequestHandler*>::iterator itor = handlers.find(request_type);
+    if(itor == handlers.end())
+    {
+        strcat(reply, "No request handler found for this type of request.");
+        return;
+    }
+    if(itor->second != NULL)
+        itor->second->handle(command, reply);
+    else
+        strcat(reply, "Invalid request handler");
+}
+
+void HTTPServer::add_request_handler(char *name, RequestHandler* handler)
+{
+    handlers[name] = handler;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,39 @@
+#ifndef HTTP_SERVER
+#define HTTP_SERVER
+
+#include <map>
+
+#include "mbed.h"
+#include "mbed_rpc.h"
+#include "RequestHandler.h"
+#include "Formatter.h"
+#include "EthernetInterface.h"
+#include "RPCCommand.h"
+
+
+class HTTPServer
+{
+    public :
+    
+        HTTPServer(Formatter *f = new Formatter());
+        virtual ~HTTPServer();
+        
+        bool init(int port);
+
+        void run();
+        
+        void add_request_handler(char *name, RequestHandler* handler);
+        
+    private :
+
+        void handle_request(char *buffer);
+        
+        TCPSocketServer socket;
+        std::map<char*, RequestHandler*, bool(*)(char*, char*)> handlers;
+        Formatter *formatter;
+        char reply[RPC_MAX_STRING];
+        RPCCommand command;
+};
+
+#endif
+
--- a/README.md	Tue Jun 14 21:25:04 2016 +0000
+++ b/README.md	Thu Jun 16 08:38:31 2016 +0000
@@ -1,102 +1,12 @@
-# Features
-
-Forked of F103_NNIO_RPC rev36:3055e4
-Firmware for NNIO modules based on STM32F103RBT6 and W5500.
-
-- TCP/UDP server for controlling and monitoring using NNIO v2.0 and RPC protocols.
-- UDP server for discovering and configuring.
-
-# Usage
-
-## Set RTC for timed Digital Ouputs
-
-Use TCP client or UDP to send configuration to the module:
-
-Set the current_time variable
-
-```
-/Time/write abcdef
-```
-
-where abcdef is time from 00:00am in seconds.
-
-Run RPC SetTime() function to execute set_current_time() to set current time to the current_time variable
+Forked of RPC over HTTP server
 
-```
-/SetTime/run x
-```
-
-## Set On/Off time for Digital Outputs
-
-```
-/do0OnTime/write abcdef
-/do0OffTime/write abcdef
-```
-
-where abcdef is time in seconds, start from 00:00am. Check it by sending to read
-
-```
-/do0OnTime/read x
-/do0OffTime/read x
-```
-
-
-# Releases
-
-## v2.0.0 (04/06/2016)
-
-New features
+------------------
+Modified but not commit yet:
 
-- RPCVariable
-- RPCFunction
-
-Improvements
-
-- Removed private mbed-rpc
-- Updated to latest mbed-rtos, NTPClient, Watchdog, W5500Interface and mbed.
-
-Bug fixes
-
-- Had to compile from source as eeprom library failed when using the compiled mbed library
-
-## v1.1.1 (07/02/2015)
-
-Improvements
-
-- Updated RPC names
-
-## v1.1 (24/01/2015)
-
-New features
-
-- Process RPC-style command in tcp client, similar to TCP/UDP server.
-
-Improvements
-
-- Control command is able to be processed by both TCP and UDP.
-- Use only one network output buffer for both RPC-style and NNIO protocols.
-- Automatically reset after setting network configuration or setting TCP server for auto update mode.
-- RPC object name is 16 chars max.
-
-
-## v1.0 (06/01/2014)
-
-New features
-
-- RPC command replies as following object_name:reply_value
-
-Improvements
-
-- Modified: clean code in my_eeprom_funcs and main.cpp
-    
-## v0.1 (29/12/2014)
-
-Initial
-
-- Imported F103_NNIO rev27:22f289beceb8
-- process_control_command() with return value. 0 if NNIO protocol or RPC protocol without reply; length of RPC outbut buffer; or -1 if RPC failed.
-- TCP server now checks to return data to client.
-- use device description instead of device config code in Discovery command.
-- working with ConfigurationTool v2.0 and AlarmMonitoring v1.1.
-    
-    
+1. Updated Formatter.c to use eth.getIPAddress()
+2. Added AnalogIn
+  - to HTML code in Formatter.c
+  - to RPCType.c
+  
+Tested working but creating RPC object AnalogIn at PC_0 caused watchdog resets
+-------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCCommand.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,130 @@
+#include "RPCCommand.h"
+#include "mbed.h"
+#include "RPCType.h"
+
+
+RPCCommand::RPCCommand():
+cmd(),
+obj_name(NULL),
+func_name(NULL)
+{
+
+}
+
+bool RPCCommand::decode(char *buffer)
+{
+    if(buffer == NULL)
+        return false;
+    if(buffer[0] != '/')
+        return false;
+    
+    ++buffer;
+    char *tmp = strchr(buffer ,'/');
+
+    if(tmp == NULL)
+        return false;
+    if(tmp == buffer)
+        return false;
+    
+    tmp[0] = '\0';
+    obj_name = buffer;
+    
+    buffer = tmp+1;
+    
+    if(buffer[0] == '\0' || buffer[0] == '?')
+        return false;
+    
+    func_name = buffer;
+    
+    tmp = strchr(buffer, '?');
+    if(tmp != NULL)
+    {
+        if(tmp[1] == '\0')
+            return false;
+        tmp[0] = '\0';
+    }
+    
+    cmd[0] = '\0';
+    strcat(cmd, "/");
+    strcat(cmd, obj_name);
+    strcat(cmd, "/");
+    strcat(cmd, func_name);
+
+    if(tmp == NULL)
+        return true;
+    
+    buffer = tmp+1;
+    do
+    {
+        tmp = strchr(buffer, '&');
+        
+        if(tmp != NULL)
+        {
+            if(tmp[1] == '\0' || buffer == tmp)
+                return false;
+            tmp[0] = '\0';
+        }
+
+        char *sep = strchr(buffer, '=');
+        if(sep == NULL)
+            return false;
+        if(sep == buffer)
+            return false;
+        if(sep[1] == '\0' || sep[1] == '&')
+            return false;
+        
+        strcat(cmd, " ");
+        strcat(cmd, sep+1);
+        
+        if(tmp != NULL)
+            buffer = tmp+1;
+        else
+            buffer = NULL;
+    }while(buffer);
+    
+    return true;
+}
+
+
+
+char* RPCCommand::get_cmd() const
+{
+    return (char*)cmd;
+}
+
+RPC_COMMAND_TYPE RPCCommand::get_type() const
+{
+    if(!strcmp(func_name, "new") && RPCType::instance().is_supported_type(obj_name))
+        return CREATE;
+    
+    RPC* r = RPC::lookup(obj_name);
+    if(r == NULL)
+        return INVALID;
+    
+    if(!strcmp(func_name, "delete"))
+        return DELETE;
+        
+    const struct rpc_method *methods = r->get_rpc_methods();
+    int i = 0;
+    while(methods[i].name != NULL)
+    {
+        if(!strcmp(func_name, methods[i].name))
+        {
+            return FUNCTION_CALL;
+        }
+        ++i;
+    }
+    
+    return INVALID;
+}
+
+char* RPCCommand::get_obj_name() const
+{
+    return obj_name;
+}
+
+char* RPCCommand::get_func_name() const
+{
+    return func_name;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCCommand.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,36 @@
+#ifndef RPCCOMMAND
+#define RPCCOMMAND
+
+#include <list>
+#include "mbed_rpc.h"
+
+enum RPC_COMMAND_TYPE { INVALID, CREATE, DELETE, FUNCTION_CALL };
+
+struct rpc_arg
+{
+    char *name;
+    char *val;
+};
+
+class RPCCommand
+{
+    public :
+    
+        RPCCommand();
+
+        bool decode(char *buffer);
+
+        char* get_cmd() const;
+        RPC_COMMAND_TYPE get_type() const;
+        char* get_obj_name() const;
+        char* get_func_name() const;
+
+    private :
+        
+        char cmd[RPC_MAX_STRING];
+        char* obj_name;
+        char* func_name;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObjectManager.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,68 @@
+#include "RPCObjectManager.h"
+#include "mbed.h"
+
+RPCObjectManager& RPCObjectManager::instance()
+{
+    static RPCObjectManager om;
+    return om;
+}
+
+RPCObjectManager::RPCObjectManager():
+objects()
+{
+}
+
+RPCObjectManager::~RPCObjectManager()
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        delete *itor;
+}
+
+void RPCObjectManager::store_object(char *obj_name)
+{
+    char *obj = new char[strlen(obj_name)+1];
+    strcpy(obj, obj_name);
+    obj[strlen(obj_name)] = '\0';
+    objects.push_back(obj);
+}
+
+void RPCObjectManager::remove_object(char *obj_name)
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        if(!strcmp(obj_name, *itor))
+        {
+            delete *itor;
+            objects.erase(itor);
+            break;
+        }
+}
+
+bool RPCObjectManager::lookup_object(char *obj_name)
+{
+    for(std::list<char*>::iterator itor = objects.begin();
+        itor != objects.end();
+        ++itor)
+        if(!strcmp(obj_name, *itor))
+            return true;
+    return false;
+}
+
+bool RPCObjectManager::is_empty()
+{
+    return objects.empty();
+}
+
+std::list<char*>::iterator RPCObjectManager::begin()
+{
+    return objects.begin();
+}
+
+std::list<char*>::iterator RPCObjectManager::end()
+{
+    return objects.end();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObjectManager.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,29 @@
+#ifndef RPCOBJECTMANAGER
+#define RPCOBJECTMANAGER
+
+#include <list>
+
+class RPCObjectManager
+{
+    public :
+        
+        static RPCObjectManager& instance();
+        
+        void store_object(char *obj_name);
+        void remove_object(char *obj_name);
+        bool lookup_object(char *obj_name);
+        
+        std::list<char*>::iterator begin();
+        std::list<char*>::iterator end();
+
+        bool is_empty();
+        
+    private :
+    
+        RPCObjectManager();
+        ~RPCObjectManager();
+        
+        std::list<char*> objects;
+};
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCType.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,59 @@
+#include "mbed.h"
+#include "mbed_rpc.h"
+#include "RPCType.h"
+
+
+RPCType::RPCType():
+supported_types()
+{
+}
+
+RPCType& RPCType::instance()
+{
+    static RPCType t;
+    return t;
+}
+
+void RPCType::register_types()
+{
+    RPCType &t = instance();
+    
+    RPC::add_rpc_class<RpcDigitalOut>();
+    t.supported_types.push_back("DigitalOut");
+    RPC::add_rpc_class<RpcDigitalIn>();
+    t.supported_types.push_back("DigitalIn");
+    RPC::add_rpc_class<RpcDigitalInOut>();
+    t.supported_types.push_back("DigitalInOut");
+
+    #if DEVICE_ANALOGIN
+    RPC::add_rpc_class<RpcAnalogIn>();
+    t.supported_types.push_back("AnalogIn");
+    #endif
+    #if DEVICE_PWMOUT
+    RPC::add_rpc_class<RpcPwmOut>();
+    t.supported_types.push_back("PwmOut");
+    #endif
+    #if DEVICE_SPI
+    t.supported_types.push_back("SPI");
+    RPC::add_rpc_class<RpcSPI>();
+    #endif
+    #if DEVICE_SERIAL
+    t.supported_types.push_back("Serial");
+    RPC::add_rpc_class<RpcSerial>();
+    #endif
+    RPC::add_rpc_class<RpcTimer>();
+    t.supported_types.push_back("Timer");
+}
+
+bool RPCType::is_supported_type(char *type)
+{
+    for(std::list<char*>::iterator itor = instance().supported_types.begin();
+        itor != instance().supported_types.end();
+        ++itor)
+        if(!strcmp(*itor,type))
+            return true;
+
+    return false;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCType.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,23 @@
+#ifndef RPCTYPE_H
+#define RPCTYPE_H
+
+#include <list>
+
+class RPCType
+{
+    public :
+        
+        static RPCType& instance();
+        
+        void register_types();
+        
+        bool is_supported_type(char *type);
+        
+    private :
+
+        RPCType();
+        std::list<char*> supported_types;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.cpp	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,109 @@
+#include "RequestHandler.h"
+#include "mbed_rpc.h"
+#include "RPCObjectManager.h"
+#include "RPCCommand.h"
+
+const char* INVALID_CMD = "Invalid RPC command";
+const char* DELETE_ERROR = "You must send a DELETE request to remove an object ";
+const char* CREATE_ERROR = "You must send a PUT request to create an object";
+const char* FUNC_CALL_ERROR = "You must send a GET request to call a function";
+
+void GetRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case DELETE:
+            printf("Error: %s\n", DELETE_ERROR);
+            strcat(reply, DELETE_ERROR);
+            break;
+        case FUNCTION_CALL:
+            RPC::call(cmd.get_cmd(), reply);
+            break;
+        case CREATE:
+            printf("Error: %s\n", CREATE_ERROR);
+            strcat(reply, CREATE_ERROR);
+            break;
+        default:
+            printf("Error: %s\n", INVALID_CMD);
+            strcat(reply, INVALID_CMD);
+            break;
+    }
+}
+
+void PutRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case DELETE:
+            printf("Error: %s\n", DELETE_ERROR);
+            strcat(reply, DELETE_ERROR);
+            break;
+        case FUNCTION_CALL:
+            printf("Error: %s\n", FUNC_CALL_ERROR);
+            strcat(reply, FUNC_CALL_ERROR);
+            break;
+        case CREATE:
+            RPC::call(cmd.get_cmd(), reply);
+            if(strlen(reply) > 0)
+            {
+                RPCObjectManager::instance().store_object(reply);
+                strcat(reply, " has been created");
+            }
+            else
+            {
+                printf("Error while creating object\n");
+                strcat(reply, "Error while creating object.");
+            }
+            break;
+        default:
+            printf("Error: %s\n", INVALID_CMD);
+            strcat(reply, INVALID_CMD);
+            break;
+    }
+}
+
+void DeleteRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case CREATE:
+            printf("Error: %s\n", CREATE_ERROR);
+            strcat(reply, CREATE_ERROR);
+            break;
+        case FUNCTION_CALL:
+            printf("Error: %s\n", FUNC_CALL_ERROR);
+            strcat(reply, FUNC_CALL_ERROR);
+            break;
+        case DELETE:
+            RPC::call(cmd.get_cmd(), reply);
+            RPCObjectManager::instance().remove_object(cmd.get_obj_name());
+            strcat(reply, "Deleted object ");
+            strcat(reply, cmd.get_obj_name());
+            break;
+        default:
+            printf("Error: %s\n", INVALID_CMD);
+            strcat(reply, INVALID_CMD);
+            break;
+    }
+}
+
+void ComplexRequestHandler::handle(const RPCCommand& cmd, char *reply)
+{
+    switch(cmd.get_type())
+    {
+        case CREATE :
+            putHandler.handle(cmd, reply);
+            break;
+        case DELETE :
+            deleteHandler.handle(cmd, reply);
+            break;
+        case FUNCTION_CALL :
+            getHandler.handle(cmd, reply);
+            break;
+        default :
+            printf("Error: %s\n", INVALID_CMD);
+            strcat(reply, INVALID_CMD);
+            break;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.h	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,51 @@
+#ifndef REQUEST_HANDLER
+#define REQUEST_HANDLER
+
+#include "RPCCommand.h"
+
+class RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply) = 0;
+};
+
+class GetRequestHandler : public RequestHandler
+{
+    public :
+    
+        virtual void handle(const RPCCommand& cmd, char* reply);
+};
+
+class PutRequestHandler : public RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply);
+
+};
+
+
+class DeleteRequestHandler : public RequestHandler
+{
+    public :
+            
+        virtual void handle(const RPCCommand& cmd, char* reply);
+
+};
+
+class ComplexRequestHandler : public RequestHandler
+{
+    public :
+        
+        virtual void handle(const RPCCommand& cmd, char* reply);
+        
+    private :
+        
+        GetRequestHandler getHandler;
+        PutRequestHandler putHandler;
+        DeleteRequestHandler deleteHandler;
+};
+
+#endif
+
--- 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rpc-nucleo.lib	Thu Jun 16 08:38:31 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/olympux/code/mbed-rpc-nucleo/#e65ed29fd4d1
--- a/mbed-rpc.lib	Tue Jun 14 21:25:04 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://developer.mbed.org/users/olympux/code/mbed-rpc-nucleo/#e6a835c40639
--- a/protocol_rpc.txt	Tue Jun 14 21:25:04 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-NNIO module can be controlled through TCP/UDP using RPC commands.
-
-
-1. Connections
-  + UDP port: 11000
-  + TCP port: 10000 (NNIO module is TCP server)
-
-2. Digital inputs
-  + Digital inputs: di0 - di7
-  + Commands: /di0/read x
-    
-3. Digital outputs
-  + Digital outputs: do0 - do7
-  + Commands:
-    /do0/read x
-    /do0/write 1
-
-3. Analog inputs
-  + Analog inputs: ai0 - ai1
-  + Commands:
-    /ai0/read x: returns a value between 0 to 1
-    /ai0/read_u16 x: returns a value between 0 to 0xFFFF
-
-4. PWM outputs:
-  + PWM outputs: pwm0 - pwm1
-  + Commands:
-    /pwm/period 0.5: Set the PWM period, specified in seconds (float), keeping the duty cycle the same.
-    /pwm/period_ms 500: Set the PWM period, specified in milli-seconds (int), keeping the duty cycle the same.
-    /pwm/pulsewidth 1: Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
-    /pwm/pulsewidth_ms 1000: Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
-    /pwm/read x: Return the current output duty-cycle setting, measured as a percentage (float).
-    /pwm/write 0.6: Set the ouput duty-cycle, specified as a percentage (float).
-
-5. Timers:
-  + Timer: timer1
-  + Commands:
-    /tmr1/start x
-    /tmr1/stop x
-    /tmr1/reset x
-    /tmr1/read x: returns float, between 0 to 1.
-    /tmr1/read_ms
-    /tmr1/read_us
-
-6. UARTs:
-  + Uart: uart
-  + Commands:
-    /uart/baud 9600
-    /uart/putc 60: send ASCII code, '<'
-    /uart/getc x: return ASCII code
-    /uart/puts helloworld: print helloworld to serial port
-    
-7. RPCVariable
-  + Declare normal variables and associate them with RPCVariable, e.g. int wheels, float speed, char banner
-  + Commands:
-    /speed/write 34.5
-    /speed/read x
-    /wheels/write 64
-    /wheels/read x
-    /banner/write c
-    /banner/read x
-    
-8. RPCFunction
-  + Declare a function and associate it with RPCFunction
-  + Commands:
-    /func_name/run x
\ No newline at end of file
--- a/protocol_v2.0.txt	Tue Jun 14 21:25:04 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-CONFIGURATION SECTION (UDP)
-A configuration command always starts with "NNCF"
-1. DISCOVERY Command
-    + UDP broadcast: 192.168.0.255 to port 11000
-    + Send: NNCFDS
-    + Receive: NNCF (4-bytes) MAC-address (6-bytes) IP-address
-1a. Query Command: IP, subnet, gateway, mac
-    + Send: NNCFIP (enter configuration mode), NNCFSN, NNCFGW, NNCFMC
-
-2. TCP SERVER PORT Command
-    + Send: NNCFTP
-    + Receive: 10000
-
-3. UDP SERVER PORT Command
-    + Send: NNCFUP
-    + Receive: 11000
-
-4. Set time using NTP Command    
-    + Send NNCFTM
-    + Receive:
-      DIS: if NTP is disabled
-      ERR: if cannot update time
-      Successful: Fri Sep 26 20:28:01 2014 {0A}
-      
-5. Set new network configuration
-    + Send: 19 bytes in total, NNCF + 15-byte
-      NNCF         4-byte IP address    4-byte subnet    4-byte gateway   3-byte MAC
-      4E 4E 43 46    C0 A8 00 78         FF FF FF 00       C0 A8 00 01     00 00 01
-
-6. Set TCP server info (only when the device is as a TCP client)
-    + Send: 12 bytes in total, NNIO + 8 bytes
-      NNCF         1-byte auto flag        1-byte time period (s)      4-byte IP       2-byte port (LSB MSB)
-      4E 4E 43 46  'Y' or others            05 (5s)                   C0 A8 00 09       E0 2E (0x2EE0 = 12000)
-
-NOTE:
-1. Both TCP client and server are working. Can be enabled/disabled using u16enable_tcp_client/server flags in eeprom (not in use now).
-2. UDP server is always working.
-
-
-INTERFACING SECTION (TCP)
-4. Receiving Protocol: 58-bytes in total
-Ex in hex
-ID: 4E 4E 49 4F
-OP: 4F 4F 4F 4F 51
-IP: C0 A8 00 78
-DO: 48 48 48 48 48 48 48 48
-AO: 80 00 80 00 (no DAC)
-UART: 32-byte
-CR: 0D
-    
-    + Field ID (4-bytes) = NNIO
-    + Field OP (5-bytes): output control enable flag
-      Byte 1: Digital output
-      Byte 2: Analog output 0
-      Byte 3: Analog output 1
-      Byte 4: UART output
-      Byte 5: Command (Q: query status)
-      'O': enable controlling output
-      Others: disable controlling output
-      If Command is 'Q', device will update its outputs if needed and send its status including new outputs
-    + Field IP (4-bytes): device IP address
-    + Field DO[n] (8-bytes): digital output values
-      'H': output set to high
-      'L': output set to low
-    + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
-      no DAC
-    + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
-      no DAC
-    + UART output (32-bytes): max 32 bytes, stop string by NULL
-    + End char: CR
-    
-5. Sending Protocol: 39-bytes in total
-    + Field ID (4-bytes) = NNIO
-    + Field MAC (6-bytes)
-    + Field IP (4-bytes)
-    + Field DI[n]: 8-bit digital input values
-      'H' if input is HIGH
-      'L' if input is LOW
-    + Field DO[n]: 8-bit digital output values
-      'H' if output is HIGH
-      'L' if output is LOW
-    + Field AI_0 (2-bytes): analog 16-bit input value, normalised, channel 0
-      1st byte = LSB, 2nd byte = MSB
-    + Field AI_1 (2-bytes): analog 16-bit input value, normalised, channel 1
-      1st byte = LSB, 2nd byte = MSB
-    + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
-      no DAC, fixed
-    + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
-      no DAC, fixed
-    + End char: CR
-    
-6 Commands:
-    + QUERY STATUS ('Q')
\ No newline at end of file