各ピンへのread/writeを提供するサーバサンプル

Dependencies:   NySNICInterface mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
komoritan
Date:
Tue Feb 10 12:15:47 2015 +0000
Commit message:
Fixed

Changed in this revision

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
NySNICInterface.lib Show annotated file Show diff for this revision Revisions of this file
RPCObject.cpp Show annotated file Show diff for this revision Revisions of this file
RPCObject.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-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
parse_pins.cpp Show annotated file Show diff for this revision Revisions of this file
parse_pins.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.cpp	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,145 @@
+#include "HTTPServer.h"
+#include "mbed.h"
+
+
+bool cmp(char* a, char* b)
+{
+    return strcmp(a,b) < 0;
+}
+
+
+HTTPServer::HTTPServer():
+handlers(&cmp),
+reply()
+{
+}
+
+
+HTTPServer::~HTTPServer()
+{
+}
+
+
+bool HTTPServer::init(int port)
+{    
+    DigitalOut led4(LED4);
+    
+    socketserver.set_blocking(true);
+    if(socketserver.bind(port))
+    {
+        printf("Could not bind on port %d.\n", port);
+        return false; 
+    }
+    
+    if(socketserver.listen())
+    {
+        printf("Could not listen %d.\n", port);
+        return false;
+    }
+    
+    led4 = 1;  // server is ready
+    
+    return true;
+}
+
+
+void HTTPServer::run()
+{
+    char buffer[1024];
+    TCPSocketConnection c;
+    
+    while(true)
+    {
+        while(socketserver.accept(&c));
+        c.set_blocking(false, 1000);
+        
+        while(c.is_connected())
+        {
+            int n = c.receive(buffer, sizeof(buffer)-1);
+            if(n == 0)
+            {
+                c.close();
+                break;
+            }
+            else if(n != -1)
+            {
+                buffer[n] = '\0';
+                printf("Received data -- %s --. \r\n", buffer);
+                handle_request(buffer);
+                create_response(buffer);
+                printf("Sending data -- %s --. \r\n", buffer);
+                c.send_all(buffer, strlen(buffer));
+                printf("done. \r\n");
+                c.close();
+                break;
+            }
+            else {
+                printf("Error while receiving data. \r\n");
+                c.close();
+                break;
+            }
+        }
+    }
+}
+
+
+void HTTPServer::handle_request(char *buffer)
+{
+    char* request_type = strtok(buffer, " ");
+    char* request = strtok(NULL, " ");
+
+    reply[0] = '\0';
+    response_code = HTTP_404_NOTFOUND;
+
+    if(!object.decode(request, reply)){
+        return;
+    }
+
+    std::map<char*, RequestHandler*>::iterator itor = handlers.find(request_type);
+    if(itor == handlers.end())
+    {
+        printf("No request handler found for this type of request.\r\n");
+        return;
+    }
+    if(itor->second != NULL)
+        response_code = itor->second->handle(object, reply);
+    else
+        printf("Invalid request handler\r\n");
+}
+
+
+void HTTPServer::create_response(char *buffer)
+{
+    char content_length[30] = "";
+    buffer[0] = '\0';
+    
+    /* HTTP Status Code */
+    strcat(buffer, "HTTP/1.1 ");    
+    switch(response_code){
+    case HTTP_200_OK:
+        strcat(buffer, "200 OK\r\n");
+        break;
+    case HTTP_404_NOTFOUND:
+        strcat(buffer, "404 Not Found\r\n");
+        break;
+    default:
+        strcat(buffer, "500 Internal Server Error\r\n");
+        break;  
+    }
+    
+    /* add header */
+    strcat(buffer, "Access-Control-Allow-Origin: *\r\n");
+    sprintf(content_length, "Content-Length: %d\r\n", strlen(reply));
+    strncat(buffer, content_length, strlen(content_length));
+    strcat(buffer, "Content-Type: text/plain\r\n\r\n"); 
+    
+    /* add content */
+    strcat(buffer, reply);
+}
+
+
+void HTTPServer::add_request_handler(char *name, RequestHandler* handler)
+{
+    handlers[name] = handler;
+    printf("%s request hander.\r\n", name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.h	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,42 @@
+#ifndef HTTP_SERVER
+#define HTTP_SERVER
+
+#include <map>
+#include "mbed.h"
+#include "SNIC_WifiInterface.h"
+#include "TCPSocketServer.h"
+#include "TCPSocketConnection.h"
+#include "RequestHandler.h"
+#include "RPCObject.h"
+
+#define HTTP_REPLY_MAX_STRING 1024
+
+enum
+{
+    HTTP_200_OK         = 200,
+    HTTP_400_BADREQUEST = 400,
+    HTTP_404_NOTFOUND   = 404
+};
+
+
+class HTTPServer
+{
+    public :
+        HTTPServer();
+        virtual ~HTTPServer();
+        bool init(int port);
+        void run();
+        void add_request_handler(char *name, RequestHandler* handler);
+        
+    private :
+        void handle_request(char* buffer);
+        void create_response(char* buffer);
+        TCPSocketServer socketserver;
+        std::map<char*, RequestHandler*, bool(*)(char*, char*)> handlers;
+        RPCObject object;
+        char reply[HTTP_REPLY_MAX_STRING];
+        int response_code;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NySNICInterface.lib	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/KDDI-Fx0-hackathon/code/NySNICInterface/#680ab480d0e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObject.cpp	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,87 @@
+#include "RPCObject.h"
+#include "parse_pins.h"
+#include "mbed.h"
+#include "HTTPServer.h"
+
+
+RPCObject::RPCObject()
+{
+}
+
+
+int RPCObject::decode(char* request, char* reply)
+{
+   char* clz = strtok(request+1,"/");
+   char* pin = strtok(NULL, "/");
+   char* val = strtok(NULL, "/");   
+
+    if(!strcmp(clz, "DigitalIn")){
+        type = RPC_PIN_DIGITAL_IN;
+        printf(" type is DigitalIn. \r\n");
+    } else if(!strcmp(clz, "DigitalOut")){
+        type = RPC_PIN_DIGITAL_OUT;
+        printf(" type is DigitalOut. \r\n");
+    } else if(!strcmp(clz, "DigitalInOut")){
+        type = RPC_PIN_DIGITAL_INOUT;
+        printf(" type is DigitalInOut. \r\n");
+    } else {
+        type = RPC_PIN_UNKNOWN;
+        printf("Unsupported type name: %s. \r\n", clz);
+        sprintf(reply, "Unsupported type name: %s. \r\n", clz);
+        return HTTP_400_BADREQUEST;
+    }
+   
+    pin_name = parse_pins(pin);
+    if(pin_name == NC){
+        printf("Unsupported pin name: %s. \n", pin);
+        sprintf(reply, "Unsupported pin name: %s. \r\n", pin);
+        return HTTP_400_BADREQUEST;
+    }
+    
+    if(!val || val[0] == '\0'){
+        value = -1;
+    }
+    else if(!strcmp(val, "delete")){
+        value = -2;
+    }    
+    else {
+        value = (val[0] - '0') ? 1 : 0;
+    }
+    
+    return 0;
+}
+
+
+bool RPCObject::create_pin_object(char* reply) 
+{
+    RPCClass* pinobj;
+    
+    if(pinObjects.find(pin_name) != pinObjects.end()){
+        printf("The pin already exists.\r\n");
+        strcat(reply, "The pin already exists. ");
+        return false;
+    }
+    
+    switch(type){
+    case RPC_PIN_DIGITAL_IN:
+        printf("DigitalIn.\r\n");
+        pinobj = new RPCDigitalIn(pin_name);
+        break; 
+    case RPC_PIN_DIGITAL_OUT:
+        printf("DigitalOut.\r\n");
+        pinobj = new RPCDigitalOut(pin_name);
+        break;
+    case RPC_PIN_DIGITAL_INOUT:
+        printf("DigitalInOut.\r\n");
+        pinobj = new RPCDigitalInOut(pin_name);
+        break;
+    default:
+        printf(" Unsupported type.\r\n");
+        strcat(reply, "Unsupported type. ");
+        return false;
+    }
+    
+    pinObjects[pin_name] = pinobj;   
+    
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPCObject.h	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,79 @@
+#ifndef RPCOBJECT
+#define RPCOBJECT
+
+#include <map>
+#include "mbed.h"
+
+enum RPC_PIN_TYPE {
+    RPC_PIN_DIGITAL_IN,
+    RPC_PIN_DIGITAL_OUT,
+    RPC_PIN_DIGITAL_INOUT,
+    RPC_PIN_UNKNOWN
+};
+
+struct rpc_arg
+{
+    char *name;
+    char *val;
+};
+
+class RPCClass
+{
+    public :
+        virtual int read()= 0;
+        virtual void write(int value) = 0;
+};
+
+class RPCDigitalIn : public RPCClass
+{
+    public :
+        RPCDigitalIn(PinName pin) :i(pin){}
+        virtual int read(void){return i.read();}
+        virtual void write(int value){}
+       
+    private :
+        DigitalIn i;
+};
+
+class RPCDigitalOut : public RPCClass
+{
+     public :  
+        RPCDigitalOut(PinName pin) :o(pin){}
+        virtual int read(void){return o.read();}
+        virtual void write(int value){o.write(value);}
+    
+    private :
+        DigitalOut o;
+};
+
+class RPCDigitalInOut : public RPCClass
+{
+     public :  
+        RPCDigitalInOut(PinName pin) :o(pin){}
+        virtual int read(void){return o.read();}
+        virtual void write(int value){o.write(value);}
+    
+    private :
+        DigitalInOut o;
+};
+
+class RPCObject
+{
+    public :
+        RPCObject();
+        int decode(char *request, char* reply);
+        
+        RPC_PIN_TYPE get_type() const { return type; }
+        PinName get_pin_name() const { return pin_name; }
+        int get_value() const { return value; }
+        bool create_pin_object(char* reply);
+        std::map<PinName, RPCClass*> pinObjects;
+        
+    private :
+        RPC_PIN_TYPE type;
+        char obj_name[20];
+        PinName pin_name;
+        int value;
+};
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.cpp	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,86 @@
+#include "mbed.h"
+#include "RequestHandler.h"
+#include "RPCObject.h"
+#include "HTTPServer.h"
+
+
+int GetRequestHandler::handle(RPCObject& cmd, char* reply)
+{
+    int value;
+    std::map<PinName, RPCClass*>::iterator itor;
+    
+    printf("handling GET request.\r\n");
+    itor = cmd.pinObjects.find(cmd.get_pin_name());
+    if(itor == cmd.pinObjects.end()){
+        printf("The pin is not created.\r\n");
+        return HTTP_404_NOTFOUND;
+    }
+    value = itor->second->read();
+    
+    reply[0] = '0' + value;
+    reply[1] = '\0';
+    
+    return HTTP_200_OK;
+}
+
+
+int  PostRequestHandler::handle(RPCObject& cmd, char* reply)
+{
+    int value = cmd.get_value();
+    std::map<PinName, RPCClass*>::iterator itor;
+    
+    printf("handling POST request.\r\n");
+    switch(value){
+    case 0:
+    case 1:
+         //update
+        printf("now updating the object to %d.\r\n", value);
+        itor = cmd.pinObjects.find(cmd.get_pin_name());
+        if(itor == cmd.pinObjects.end()){
+            printf("The pin is not created.\r\n");
+            return HTTP_404_NOTFOUND;
+        }
+        itor->second->write(value);
+        break;
+    case -1:
+        //create
+        printf("now createing the object.\r\n");
+        if(!cmd.create_pin_object(reply)){
+            return -1;
+        }
+        break;
+    case -2:
+        // delete
+        itor = cmd.pinObjects.find(cmd.get_pin_name());
+        if(itor == cmd.pinObjects.end()){
+            printf("The pin is not created.\r\n");
+            return HTTP_404_NOTFOUND;
+        }
+        delete itor->second;
+        cmd.pinObjects.erase(cmd.pinObjects.find(cmd.get_pin_name()));
+        break;
+    default:
+        return -1;
+    }
+    
+    return HTTP_200_OK;
+}
+
+
+int DeleteRequestHandler::handle(RPCObject& cmd, char* reply)
+{   
+    std::map<PinName, RPCClass*>::iterator itor;
+    
+    printf("handling DELETE request.\r\n");
+    itor = cmd.pinObjects.find(cmd.get_pin_name());
+    if(itor == cmd.pinObjects.end()){
+        printf("The pin is not created.\r\n");
+        return HTTP_404_NOTFOUND;
+    }
+    delete itor->second;
+    cmd.pinObjects.erase(cmd.pinObjects.find(cmd.get_pin_name()));
+    
+    return HTTP_200_OK;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RequestHandler.h	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,45 @@
+#ifndef REQUEST_HANDLER
+#define REQUEST_HANDLER
+
+#include "RPCObject.h"
+
+
+
+class RequestHandler
+{
+    public :
+        
+        virtual int handle(RPCObject& cmd, char* reply) = 0;
+        
+    protected :
+};
+
+class GetRequestHandler : public RequestHandler
+{
+    public :
+    
+        virtual int handle(RPCObject& cmd, char* reply);
+        
+};
+
+class PostRequestHandler : public RequestHandler
+{
+    public :
+        
+        virtual int handle(RPCObject& cmd, char* reply);
+
+};
+
+
+class DeleteRequestHandler : public RequestHandler
+{
+    public :
+            
+        virtual int handle(RPCObject& cmd, char* reply);
+
+};
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,83 @@
+#include "mbed.h"
+#include "SNIC_WifiInterface.h"
+#include "HTTPServer.h"
+
+/**
+ * Wifi AP parameter
+ */
+
+/* Set this */ 
+#define WIFI_SSID           ""
+#define WIFI_SECUTIRY_KEY   ""
+//#define WIFI_SECURITY_TYPE  e_SEC_OPEN
+//#define WIFI_SECURITY_TYPE  e_SEC_WEP
+//#define WIFI_SECURITY_TYPE  e_SEC_WPA_TKIP
+#define WIFI_SECURITY_TYPE  e_SEC_WPA2_AES
+//#define WIFI_SECURITY_TYPE  e_SEC_WPA2_MIXED
+//#define WIFI_SECURITY_TYPE  e_SEC_WPA_AES
+
+
+#define IP_ADDRESS      "192.168.0.44"
+#define NET_MASK        "255.255.255.0"
+#define DEFAULT_GATEWAY "192.168.0.1"
+#define PORT_NUMBER     80
+
+
+Serial pc(USBTX, USBRX);    // This is required when defined "_DEBUG"
+/** Wi-Fi SNIC UART Interface*/
+C_SNIC_WifiInterface     mSNICwifi( p13, p14, p12, p11, p20 );
+
+
+
+
+void wifi_connect()
+{
+    // Initialize Wi-Fi interface
+    if(mSNICwifi.init()!=0){
+        printf("Wi-Fi initial failed\r\n");
+        mbed_die();
+    }
+    wait(0.5);
+    
+    if(mSNICwifi.disconnect()!= 0 )
+    {
+        printf("on the disconnect state\r\n");
+        mbed_die();
+    } 
+    wait(0.3);
+
+    // Connect to AP
+    if(mSNICwifi.connect( WIFI_SSID,strlen(WIFI_SSID), 
+                          WIFI_SECURITY_TYPE, 
+                          WIFI_SECUTIRY_KEY, 
+                          strlen(WIFI_SECUTIRY_KEY))!=0)
+    {
+        printf("Connect AP is failed\r\n");
+        mbed_die();
+    }
+    wait(0.5);
+    
+    int retIp = mSNICwifi.setIPConfig(false, IP_ADDRESS, NET_MASK, DEFAULT_GATEWAY);
+}
+
+
+int main()
+{
+    // for debug
+    pc.baud( 115200 );
+
+    wifi_connect();
+    
+    HTTPServer srv;
+    
+    pc.printf("server init.\r\n");
+    srv.init(PORT_NUMBER);
+    
+    srv.add_request_handler("GET",    new GetRequestHandler());
+    srv.add_request_handler("DELETE", new DeleteRequestHandler());
+    srv.add_request_handler("POST",   new PostRequestHandler());
+    
+    wait(1);
+    pc.printf("server running.\r\n");
+    srv.run();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#5dfe422a963d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/0b3ab51c8877
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parse_pins.cpp	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,80 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "port_api.h"
+
+namespace mbed {
+
+PinName parse_pins(const char *str) {
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088)
+    static const PinName pin_names[] = {p5, p6, p7, p8, p9, p10, p11, p12, p13, p14
+                                , p15, p16, p17, p18, p19, p20, p21, p22, p23
+                                , p24, p25, p26, p27, p28, p29, p30};
+#endif
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) || defined(TARGET_LPC812) || defined(TARGET_LPC4088)
+    if (str[0] == 'P') {              // Pn_n
+        uint32_t port = str[1] - '0';
+        uint32_t pin  = str[3] - '0'; // Pn_n
+        uint32_t pin2 = str[4] - '0'; // Pn_nn
+        if (pin2 <= 9) {
+            pin = pin * 10 + pin2;
+        }
+        return port_pin((PortName)port, pin);
+
+#elif defined(TARGET_KL25Z)
+        if (str[0] == 'P' && str[1] == 'T') {   // PTx_n
+            uint32_t port = str[2] - 'A';
+            uint32_t pin  = str[3] - '0'; // PTxn
+            uint32_t pin2 = str[4] - '0'; // PTxnn
+
+            if (pin2 <= 9) {
+                pin = pin * 10 + pin2;
+            }
+            return port_pin((PortName)port, pin);
+#endif
+
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC2368) || defined(TARGET_LPC4088)
+    } else if (str[0] == 'p') {       // pn
+        uint32_t pin  = str[1] - '0'; // pn
+        uint32_t pin2 = str[2] - '0'; // pnn
+        if (pin2 <= 9) {
+            pin = pin * 10 + pin2;
+        }
+        if (pin < 5 || pin > 30) {
+            return NC;
+        }
+        return pin_names[pin - 5];
+#endif
+
+    } else if (str[0] == 'L') {  // LEDn
+        switch (str[3]) {
+            case '1' : return LED1;
+            case '2' : return LED2;
+            case '3' : return LED3;
+            case '4' : return LED4;
+        }
+
+    } else if (str[0] == 'U') {  // USB?X
+        switch (str[3]) {
+            case 'T' : return USBTX;
+            case 'R' : return USBRX;
+        }
+    }
+
+    return NC;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parse_pins.h	Tue Feb 10 12:15:47 2015 +0000
@@ -0,0 +1,27 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBED_PINMAP_H
+#define MBED_PINMAP_H
+
+#include "PinNames.h"
+
+namespace mbed {
+
+PinName parse_pins(const char *str);
+
+}
+
+#endif