mbedからGluinサーバへ接続するライブラリです

Dependents:   Servo_DxDevice

Revision:
0:735163979ecf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DxClient.cpp	Sat Feb 14 00:28:40 2015 +0000
@@ -0,0 +1,957 @@
+#include "DxClient.h"
+#include "picojson.h"
+
+#if 1
+#define DXDBG(x, ...) printf("[DxClient : DBG]"x"\r\n", ##__VA_ARGS__); 
+#define DXWARN(x, ...) printf("[DxClient : WARN]"x"\r\n", ##__VA_ARGS__); 
+#define DXERR(x, ...) printf("[DxClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+#else
+#define DXDBG(x, ...) 
+#define DXWARN(x, ...)
+#define DXERR(x, ...) 
+#endif
+
+#define DXINFO(x, ...) printf("[DxClient : INFO]"x"\r\n", ##__VA_ARGS__); 
+
+void generate_randomid( char* out, int len )
+{
+    int i;
+    static char* words = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!#$%&()=<>?-_[]{}";
+    for (i=0;i<len-1;i++) {
+        out[i] = words[ rand()%strlen(words) ];
+    }
+    out[len-1] = 0;
+}
+
+DxClient::DxClient(char * url, char* deviceid, float seed) 
+{
+    m_ws.set_server( url );   
+    strcpy( m_deviceid, deviceid );
+    
+    memset( m_user, 0, sizeof(m_user));
+    memset( m_pass, 0, sizeof(m_pass));
+    memset( m_dev_name, 0, sizeof(m_dev_name));
+    memset( m_dev_description, 0, sizeof(m_dev_description));
+    
+    m_func_get_request = NULL;
+    m_func_set_request = NULL;
+    
+    DXDBG("random seed is %f", seed );
+    srand(seed);
+}
+
+
+void DxClient::set_user(char* user, char *pass)
+{
+    //  set auth user and password
+    strncpy( m_user, user, sizeof(m_user) );
+    strncpy( m_pass, pass, sizeof(m_pass) );
+}
+
+void DxClient::set_device_description(char* desc)
+{
+    strncpy( m_dev_description, desc, sizeof(m_dev_description) );
+}
+void DxClient::set_device_name(char* name)
+{
+    strncpy( m_dev_name, name, sizeof(m_dev_name) );
+}
+
+
+bool DxClient::connect()
+{
+    bool res;
+    res = m_ws.connect();
+    if (res) {
+        DXDBG("Connected to server by Websocket");
+        // send user_auth_request
+        res = dx_user_auth_request();
+        if (res) {
+            DXDBG("...Authorized");
+        } else {
+            DXDBG("...Login failed");
+        }
+    } else {
+        DXDBG("Failed to server by Websocket");
+    }
+    return res;
+}
+
+bool DxClient::close()
+{
+    return m_ws.close();
+}
+
+// ==============================================
+//  Send user_auth_request to server
+//  if user is authorized correctly, clinet gets 200 OK response
+//  this request must be sent before any other requset
+// ==============================================
+bool DxClient::dx_user_auth_request()
+{
+    DXDBG("Call dx_user_auth_request");
+    
+    int  i, len;
+    bool res;
+    
+    char message[MAX_MESSAGELEN];
+    char mesid[MAX_MESSAGEIDLEN];
+    generate_randomid( mesid, sizeof(mesid) );
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"user-auth-request\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"username\":\"%s\"," \
+                    "\"password\":\"%s\"" \
+                    "}",
+                    mesid,
+                    m_user,
+                    m_pass
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "USER_AUTH: message is over MAX LEN");
+        return false;
+    }
+    DXDBG("send: %s", message);
+
+    m_ws.send(message);
+
+    // clear the buffer and wait a sec...
+    memset( message, 0, sizeof(message));
+    for (i=0, res=false;i<10;i++) {
+        wait(0.5f);
+        if (m_ws.read(message)) {
+            DXDBG("Get Message: %s\n", message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                
+                // check auth response
+                if (root["type"].is<std::string>()) {
+                    if (strcmp(root["type"].get<std::string>().c_str(), "user-auth-response")) {
+                        DXDBG("USER_AUTH: Not user_auth_response\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("USER_AUTH: there is no type\n");
+                    break;
+                }
+                if (root["message-id"].is<std::string>()) {
+                    if (strcmp(root["message-id"].get<std::string>().c_str(), mesid)) {
+                        DXDBG("USER_AUTH: Not correct response message-id\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("USER_AUTH: there is no message-id\n");
+                    break;
+                }
+                if (root["status"].is<std::string>()) {
+                    if (strcmp(root["status"].get<std::string>().c_str(), "200 OK")) {
+                        DXDBG("USER_AUTH: status error\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("USER_AUTH: there is no status\n");
+                    break;
+                }
+
+                DXDBG("USER_AUTH: user auth is success\n");
+                res = true;
+            } else {
+                DXDBG("USER_AUTH: JSON parse Error\n");
+            }
+            break;        
+        }
+    }
+    return res;
+}
+
+char* dx_type_to_string( dx_prop_type type, char* buf)
+{
+    char *res = buf;
+    switch( type ) {
+        case DX_STRING:
+            sprintf( res, "string" );
+            break;
+        case DX_INTEGER:
+            sprintf( res, "integer" );
+            break;
+        case DX_FLOAT:
+            sprintf( res, "float" );
+            break;
+        case DX_BOOLEAN:
+            sprintf( res, "boolean" );
+            break;
+        default:
+            sprintf( res, "unknown" );
+            break;
+    }
+    return res;
+}
+char* dx_direction_to_string( dx_prop_direction dic, char* buf)
+{
+    char *res = buf;
+    switch( dic ) {
+        case DX_UPONLY:
+            sprintf( res, "uponly" );
+            break;
+        case DX_DOWNONLY:
+            sprintf( res, "downonly" );
+            break;
+        case DX_UPDOWN:
+            sprintf( res, "updown" );
+            break;
+        default:
+            sprintf( res, "unknown" );
+            break;
+    }
+    return res;
+}
+char* dx_mode_to_string( dx_prop_mode mode, char* buf)
+{
+    char *res = buf;
+    switch( mode ) {
+        case DX_READONLY:
+            sprintf( res, "readonly" );
+            break;
+        case DX_WRITEONLY:
+            sprintf( res, "writeonly" );
+            break;
+        case DX_READWRITE:
+            sprintf( res, "readwrite" );
+            break;
+        default:
+            sprintf( res, "unknown" );
+            break;
+    }
+    return res;
+}
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::register_device( dx_props *props )
+{
+    DXDBG("Call register_device");
+    
+    bool res;
+    int len;
+
+    char message[MAX_MESSAGELEN];
+    char mesid[MAX_MESSAGEIDLEN];
+    generate_randomid( mesid, sizeof(mesid) );
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"device-register-request\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"name\":\"%s\"," \
+                    "\"description\":\"%s\"," \
+                    "\"props\":{",
+                    m_deviceid,
+                    mesid,
+                    m_dev_name,
+                    m_dev_description
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "REGISTER_DEVICE: message is over  MAX LEN");
+        return false;
+    }
+                    
+    int i;
+    for (i=0;i<props->numofprops;i++) {
+        char s_prop[MAX_PROPLEN];
+        char s_type[16];
+        char s_direction[16];
+        char s_mode[16];
+        
+        char s_val[MAX_PROPSVALLEN];
+        switch( props->props[i].type ){
+            case DX_STRING:
+                sprintf( s_val, "\"%s\"", props->props[i].s_val );
+                break;
+            case DX_INTEGER:
+                sprintf( s_val, "%d", (int)(props->props[i].f_val) );
+                break;
+            case DX_FLOAT:
+                sprintf( s_val, "%f", props->props[i].f_val );
+                break;
+            case DX_BOOLEAN:
+                sprintf( s_val, "%s", props->props[i].b_val?"true":"false" );
+                break;
+        }
+        
+        len = snprintf( s_prop, sizeof(s_prop), "\"%s\": {" \
+                            "\"value\":%s," \
+                            "\"type\":\"%s\"," \
+                            "\"direction\":\"%s\"," \
+                            "\"mode\":\"%s\"" \
+                            "}",
+                            props->props[i].name,
+                            s_val,
+                            dx_type_to_string( props->props[i].type, s_type ),
+                            dx_direction_to_string( props->props[i].direction, s_direction ),
+                            dx_mode_to_string( props->props[i].mode, s_mode )
+                            );
+        if (len >= sizeof(s_prop)-1) {
+            DXDBG( "REGISTER_DEVICE: prop is over  MAX LEN");
+            return false;
+        }
+        if (len + strlen(message) >= sizeof(message)-1) {
+            DXDBG( "REGISTER_DEVICE: message is over  MAX LEN");
+            return false;
+        }
+        strcat( message, s_prop );
+        
+        if (i+1 < props->numofprops) {
+            if (1 + strlen(message) >= sizeof(message)-1) {
+                DXDBG( "REGISTER_DEVICE: message is over  MAX LEN");
+                return false;
+            }
+            strncat( message, ",", sizeof(message) );
+        }
+    }
+
+    if (2 + strlen(message) >= sizeof(message)-1) {
+        DXDBG( "REGISTER_DEVICE: message is over  MAX LEN");
+        return false;
+    }
+    strcat( message, "}}" );
+
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+    
+    // clear the buffer and wait a sec...
+    memset( message, 0, sizeof(message));
+    for (i=0, res=false;i<10;i++) {
+        wait(0.5f);
+        if (m_ws.read(message)) {
+            DXDBG("Get Message(%d): %s", strlen(message), message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                // check auth response
+                if (root["type"].is<std::string>()) {
+                    if (strcmp(root["type"].get<std::string>().c_str(), "device-register-response")) {
+                        DXDBG("REGISTER_DEVICE: Not device_register_response");
+                        break;
+                    }
+                } else {
+                    DXDBG("REGISTER_DEVICE: there is no type");
+                    break;
+                }
+                if (root["message-id"].is<std::string>()) {
+                    if (strcmp(root["message-id"].get<std::string>().c_str(), mesid)) {
+                        DXDBG("REGISTER_DEVICE: Not correct response message-id");
+                        break;
+                    }
+                } else {
+                    DXDBG("REGISTER_DEVICE: there is no message-id");
+                    break;
+                }
+                if (root["status"].is<std::string>()) {
+                    if (strcmp(root["status"].get<std::string>().c_str(), "200 OK")) {
+                        DXDBG("REGISTER_DEVICE: status error");
+                        break;
+                    }
+                } else {
+                    DXDBG("REGISTER_DEVICE: there is no status");
+                    break;
+                }
+                DXDBG("REGISTER_DEVICE: device register is success");
+                res = true;
+            } else {
+                DXDBG("REGISTER_DEVICE: Parse Error");
+            }
+            break;
+        }
+    }
+
+    return res;
+}
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::deregister_device()
+{
+    int len;
+    
+    char message[MAX_MESSAGELEN];
+    char mesid[MAX_MESSAGEIDLEN];
+
+    generate_randomid( mesid, sizeof(mesid) );
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"device-deregister-request\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"" \
+                    "}",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "DEREGISTER_DEVICE: message is over  MAX LEN");
+        return false;
+    }
+
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+
+    // clear the buffer and wait a sec...
+    bool res;
+    int i;
+    memset( message, 0, sizeof(message));
+    for (i=0, res=false;i<10;i++) {
+        wait(0.5f);
+        if (m_ws.read(message)) {
+            DXDBG("Get Message(%d): %s", strlen(message), message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                // check auth response
+                if (root["type"].is<std::string>()) {
+                    if (strcmp(root["type"].get<std::string>().c_str(), "device-deregister-response")) {
+                        DXDBG("DEREGISTER_DEVICE: Not device_deregister_response");
+                        break;
+                    }
+                } else {
+                    DXDBG("DEREGISTER_DEVICE: there is no type");
+                    break;
+                }
+                if (root["message-id"].is<std::string>()) {
+                    if (strcmp(root["message-id"].get<std::string>().c_str(), mesid)) {
+                        DXDBG("DEREGISTER_DEVICE: Not correct response message-id");
+                        break;
+                    }
+                } else {
+                    DXDBG("REGISTER_DEVICE: there is no message-id");
+                    break;
+                }
+                if (root["status"].is<std::string>()) {
+                    if (strcmp(root["status"].get<std::string>().c_str(), "200 OK")) {
+                        DXDBG("DEREGISTER_DEVICE: status error");
+                        break;
+                    }
+                } else {
+                    DXDBG("DEREGISTER_DEVICE: there is no status");
+                    break;
+                }
+                DXDBG("DEREGISTER_DEVICE: device deregister is success");
+                res = true;
+            } else {
+                DXDBG("DEREGISTER_DEVICE: Parse Error");
+            }
+            break;
+        }
+    }
+                    
+    return res;
+}
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::update_device( dx_props *props )
+{
+    int len;
+    
+    char message[MAX_MESSAGELEN];
+    char mesid[MAX_MESSAGEIDLEN];
+
+    generate_randomid( mesid, sizeof(mesid) );
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"device-update-request\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"props\":{",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "UPDATE_DEVICE: message is over  MAX LEN");
+        return false;
+    }
+
+    int i;                    
+    for (i=0;i<props->numofprops;i++) {
+        char s_prop[MAX_PROPLEN];
+        char s_val[MAX_PROPSVALLEN];
+        switch( props->props[i].type ){
+            case DX_STRING:
+                sprintf( s_val, "\"%s\"", props->props[i].s_val );
+                break;
+            case DX_INTEGER:
+                sprintf( s_val, "%d", (int)(props->props[i].f_val) );
+                break;
+            case DX_FLOAT:
+                sprintf( s_val, "%f", props->props[i].f_val );
+                break;
+            case DX_BOOLEAN:
+                sprintf( s_val, "%s", props->props[i].b_val?"true":"false" );
+                break;
+        }
+        
+        len = snprintf( s_prop, sizeof(s_prop), "\"%s\": {" \
+                            "\"value\":%s" \
+                            "}",
+                            props->props[i].name,
+                            s_val
+                            );
+        if (len >= sizeof(s_prop)-1) {
+            DXDBG( "UPDATE_DEVICE: prop is over  MAX LEN");
+            return false;
+        }
+        if (len + strlen(message) >= sizeof(message)-1) {
+            DXDBG( "UPDATE_DEVICE: message is over  MAX LEN");
+            return false;
+        }
+        strcat( message, s_prop );
+        
+        if (i+1 < props->numofprops) {
+            if (1 + strlen(message) >= sizeof(message)-1) {
+                DXDBG( "UPDATE_DEVICE: message is over  MAX LEN");
+                return false;
+            }
+            strncat( message, ",", sizeof(message) );
+        }
+    }
+
+    if (2 + strlen(message) >= sizeof(message)-1) {
+        DXDBG( "UPDATE_DEVICE: message is over  MAX LEN");
+        return false;
+    }
+    strcat( message, "}}" );
+
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+
+    bool res=true;
+/*    
+    // clear the buffer and wait a sec...
+    memset( message, 0, sizeof(message));
+    for (i=0, res=false;i<10;i++) {
+        wait(0.5f);
+        if (m_ws.read(message)) {
+            DXDBG("Get Message(%d): %s", strlen(message), message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                // check auth response
+                if (root["type"].is<std::string>()) {
+                    if (strcmp(root["type"].get<std::string>().c_str(), "device-update-response")) {
+                        DXDBG("UPDATE_DEVICE: Not device_update_response");
+                        break;
+                    }
+                } else {
+                    DXDBG("UPDATE_DEVICE: there is no type");
+                    break;
+                }
+                if (root["message-id"].is<std::string>()) {
+                    if (strcmp(root["message-id"].get<std::string>().c_str(), mesid)) {
+                        DXDBG("UPDATE_DEVICE: Not correct response message-id");
+                        break;
+                    }
+                } else {
+                    DXDBG("UPDATE_DEVICE: there is no message-id");
+                    break;
+                }
+                if (root["status"].is<std::string>()) {
+                    if (strcmp(root["status"].get<std::string>().c_str(), "200 OK")) {
+                        DXDBG("UPDATE_DEVICE: status error");
+                        break;
+                    }
+                } else {
+                    DXDBG("UPDATE_DEVICE: there is no status");
+                    break;
+                }
+                DXDBG("UPDATE_DEVICE: device update is success");
+                res = true;
+            } else {
+                DXDBG("UPDATE_DEVICE: Parse Error");
+            }
+            break;
+        }
+    }
+
+*/
+    return res;
+}
+
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::keepalive_device()
+{
+    DXDBG("Call keepalive_device");
+    
+    int  len;
+    
+    char message[MAX_MESSAGELEN];
+    char mesid[MAX_MESSAGEIDLEN];
+    generate_randomid( mesid, sizeof(mesid) );
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"keep-alive-request\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"" \
+                    "}",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "KEEPALIVE_DEVICE: message is over MAX LEN");
+        return false;
+    }
+    DXDBG("send: %s", message);
+
+    m_ws.send(message);
+
+    bool res=true;
+/*
+    int i;
+    // clear the buffer and wait a sec...
+    memset( message, 0, sizeof(message));
+    for (i=0, res=true;i<10;i++) {
+        wait(0.5f);
+        if (m_ws.read(message)) {
+            DXDBG("Get Message: %s\n", message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                
+                // check auth response
+                if (root["type"].is<std::string>()) {
+                    if (strcmp(root["type"].get<std::string>().c_str(), "keep-alive-response")) {
+                        DXDBG("KEEPALIVE_DEVICE: Not keep-alive-response\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("KEEPALIVE_DEVICE: there is no type\n");
+                    break;
+                }
+                if (root["message-id"].is<std::string>()) {
+                    if (strcmp(root["message-id"].get<std::string>().c_str(), mesid)) {
+                        DXDBG("KEEPALIVE_DEVICE: Not correct response message-id\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("KEEPALIVE_DEVICE: there is no message-id\n");
+                    break;
+                }
+                if (root["status"].is<std::string>()) {
+                    if (strcmp(root["status"].get<std::string>().c_str(), "200 OK")) {
+                        DXDBG("KEEPALIVE_DEVICE: status error\n");
+                        break;
+                    }
+                } else {
+                    DXDBG("KEEPALIVE_DEVICE: there is no status\n");
+                    break;
+                }
+
+                DXDBG("KEEPALIVE_DEVICE: keep alive is success\n");
+                res = true;
+            } else {
+                DXDBG("KEEPALIVE_DEVICE: JSON parse Error\n");
+            }
+            break;        
+        }
+    }
+*/
+    return res;
+}
+
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::handle_messages()
+{
+    bool res = true;
+    
+    char message[MAX_MESSAGELEN];
+
+    
+    // clear the buffer and wait a sec...
+    while(1) {
+        memset( message, 0, sizeof(message));
+        if (m_ws.read(message)) {
+            DXDBG("Get Message(%d): %s", strlen(message), message);
+            picojson::value v;
+            std::string err;
+            picojson::parse(v, (const char *)message, (const char *)(message + strlen(message)), &err);
+
+            if (err.empty())
+            {
+                picojson::object& root = v.get<picojson::object>();
+                // check auth response
+                if (root["message-id"].is<std::string>()) {
+                    // no check message-d
+                } else {
+                    DXDBG("HANDLE_MESSAGE: there is no message-id");
+                    continue;
+                }
+                if (root["device-id"].is<std::string>()) {
+                    if (strcmp(root["device-id"].get<std::string>().c_str(), m_deviceid)) {
+                        DXDBG("HANDLE_MESSAGE: different device-id");
+                        continue;
+                    }
+                } else {
+                    DXDBG("HANDLE_MESSAGE: there is no device-id");
+                    continue;
+                }
+                
+                if (root["type"].is<std::string>()) {
+                    if (!strcmp(root["type"].get<std::string>().c_str(), "device-get-request")
+                        || !strcmp(root["type"].get<std::string>().c_str(), "device-set-request")) {
+                        DXDBG("HANDLE_MESSAGE: recv %s", root["type"].get<std::string>().c_str());
+
+//                        if ( 1) {
+                        if(root["props"].is<picojson::object>() ){
+//                            picojson::object& props_root = root;
+                            picojson::object& props_root = root["props"].get<picojson::object>();
+
+                            dx_props ps;
+                            ps.numofprops = props_root.size();
+                            DXDBG("HANDLE_MESSAGE: prop size: %d", ps.numofprops);
+
+                            ps.props = (dx_prop*)malloc( sizeof(dx_prop) * ps.numofprops );
+                            if (ps.props == NULL) {
+                                DXDBG("HANDLE_MESSAGE: No memory");
+                                continue;
+                            }
+                            memset( ps.props, 0, sizeof(dx_prop) * ps.numofprops );
+
+                            dx_prop *pr = ps.props;
+                            for (picojson::object::const_iterator it = props_root.begin(); it != props_root.end(); it++,pr++) {
+                                if (props_root[it->first].is<picojson::object>()) {
+                                    picojson::object& prop = props_root[it->first].get<picojson::object>();
+                                    
+                                    if (prop["value"].is<std::string>()) { // test only
+                                        snprintf( pr->s_val, sizeof(pr->s_val), "%s", prop["value"].get<std::string>().c_str() );
+                                    }
+                                    else if (prop["value"].is<double>()) { // integer or float
+                                        pr->f_val = prop["value"].get<double>();
+                                        if ( (int)(pr->f_val) ) {
+                                            pr->b_val = true;
+                                        } else {
+                                            pr->b_val = false;
+                                        }
+                                    }
+                                    else if (prop["value"].is<bool>()) { // integer or float
+                                        pr->b_val = prop["value"].get<bool>();
+                                        if(pr->b_val){
+                                            pr->f_val = 1;
+                                        } else {
+                                            pr->f_val = 0;
+                                        }
+                                    }
+                                }
+                                snprintf( pr->name, sizeof(pr->name), "%s", it->first.c_str() );
+                                DXDBG("HANDLE_MESSAGE: prop name: %s", pr->name);
+                            }
+                            
+                            if (m_func_get_request && !strcmp(root["type"].get<std::string>().c_str(), "device-get-request")) {
+                                if((*m_func_get_request)( &ps )) {
+                                    dx_device_get_response(&ps, root["message-id"].get<std::string>().c_str());
+                                } else {
+                                    dx_error_response(root["message-id"].get<std::string>().c_str());
+                                }
+                            }
+                            if (m_func_set_request && !strcmp(root["type"].get<std::string>().c_str(), "device-set-request")) {
+                                if((*m_func_set_request)( &ps )) {
+                                    dx_device_set_response(&ps, root["message-id"].get<std::string>().c_str());
+                                } else {
+                                    dx_error_response(root["message-id"].get<std::string>().c_str());
+                                }
+                            }
+                            free(ps.props);
+                            continue;
+                        } else {
+                            DXDBG("HANDLE_MESSAGE: no props in request");
+                        }
+                        // send error message
+                        dx_error_response(root["message-id"].get<std::string>().c_str());
+                    }
+                    else if (!strcmp(root["type"].get<std::string>().c_str(), "device-update-response")) {
+                        DXDBG("HANDLE_MESSAGE: recv device-update-response");
+                    }
+                    else if (!strcmp(root["type"].get<std::string>().c_str(), "keep-alive-response")) {
+                        DXDBG("HANDLE_MESSAGE: recv keep-alive-response");
+
+                    }
+                    else {
+                        DXDBG("HANDLE_MESSAGE: Unknown message type");
+                    }
+                } else {
+                    DXDBG("HANDLE_MESSAGE: there is no type");
+                }
+            } else {
+                DXDBG("HANDLE_MESSAGE: Parse Error");
+            }
+        } else {
+            break; // no more message
+        }
+    }
+
+    return res;
+}
+
+
+bool DxClient::dx_error_response( const char* mesid)
+{
+    DXDBG("Call dx_error_response");
+    
+    int  len;
+    char message[MAX_MESSAGELEN];
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"status\":\"400 Bad Request\"" \
+                    "}",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "ERROR_RESPONSE: message is over MAX LEN");
+        return false;
+    }
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+    
+    return true;
+}
+
+
+void DxClient::set_get_requset_handler(REQUEST_HANDLER handler)
+{
+    m_func_get_request = handler;
+}
+void DxClient::set_set_requset_handler(REQUEST_HANDLER handler)
+{
+    m_func_set_request = handler;
+}
+
+
+// ==============================================
+//
+// ==============================================
+bool DxClient::dx_device_get_response( dx_props *props, const char* mesid )
+{
+    DXDBG("Call dx_device_get_response");
+
+    int len;
+    char message[MAX_MESSAGELEN];
+
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"device-get-response\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"props\":{",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "DEVICE_GET: message is over  MAX LEN");
+        return false;
+    }
+
+    int i;                    
+    for (i=0;i<props->numofprops;i++) {
+        char s_prop[MAX_PROPLEN];
+        char s_val[MAX_PROPSVALLEN];
+        switch( props->props[i].type ){
+            case DX_STRING:
+                sprintf( s_val, "\"%s\"", props->props[i].s_val );
+                break;
+            case DX_INTEGER:
+                sprintf( s_val, "%d", (int)(props->props[i].f_val) );
+                break;
+            case DX_FLOAT:
+                sprintf( s_val, "%f", props->props[i].f_val );
+                break;
+            case DX_BOOLEAN:
+                sprintf( s_val, "%s", props->props[i].b_val?"true":"false" );
+                break;
+        }
+        
+        len = snprintf( s_prop, sizeof(s_prop), "\"%s\": {" \
+                            "\"value\":%s" \
+                            "}",
+                            props->props[i].name,
+                            s_val
+                            );
+        if (len >= sizeof(s_prop)-1) {
+            DXDBG( "DEVICE_GET: prop is over  MAX LEN");
+            return false;
+        }
+        if (len + strlen(message) >= sizeof(message)-1) {
+            DXDBG( "DEVICE_GET: message is over  MAX LEN");
+            return false;
+        }
+        strcat( message, s_prop );
+        
+        if (i+1 < props->numofprops) {
+            if (1 + strlen(message) >= sizeof(message)-1) {
+                DXDBG( "DEVICE_GET: message is over  MAX LEN");
+                return false;
+            }
+            strncat( message, ",", sizeof(message) );
+        }
+    }
+
+    if (2 + strlen(message) >= sizeof(message)-1) {
+        DXDBG( "DEVICE_GET: message is over  MAX LEN");
+        return false;
+    }
+    strcat( message, "}}" );
+
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+    
+    return true;
+}
+
+bool DxClient::dx_device_set_response( dx_props *props, const char* mesid )
+{
+    DXDBG("Call dx_device_set_response");
+    
+    int  len;
+    char message[MAX_MESSAGELEN];
+    len = snprintf(message, sizeof(message), "{" \
+                    "\"type\":\"device-set-response\"," \
+                    "\"device-id\":\"%s\"," \
+                    "\"message-id\":\"%s\"," \
+                    "\"status\":\"200 OK\"" \
+                    "}",
+                    m_deviceid,
+                    mesid
+                    );
+    if (len >= sizeof(message)-1) {
+        DXDBG( "ERROR_RESPONSE: message is over MAX LEN");
+        return false;
+    }
+    DXDBG("send: %s", message);
+    m_ws.send(message);
+    
+    return true;
+}