From f73a09c9aa16fd9a8c43f7602032bbca5efb8170 Mon Sep 17 00:00:00 2001 From: Ake Hedman Date: Thu, 1 Feb 2018 22:50:00 +0100 Subject: [PATCH] Lua script callbacks in place --- src/common/lua/LuaXML_lib.c | 2 + src/common/mongoose.c | 54 +- src/vscp/common/devicethread.cpp | 8 +- src/vscp/common/duktape_vscp_func.cpp | 2 + src/vscp/common/lua_vscp_func.cpp | 553 +++++++++++---- src/vscp/common/lua_vscp_func.h | 31 +- src/vscp/common/lua_vscp_wrkthread.cpp | 12 +- src/vscp/common/remotevariable.cpp | 177 +++-- src/vscp/common/remotevariable.h | 19 +- src/vscp/common/version.h | 4 +- src/vscp/common/vscp.h | 8 +- src/vscp/common/vscphelper.cpp | 154 ++++- src/vscp/common/vscphelper.h | 15 +- src/vscp/common/vscpremotetcpif.cpp | 2 +- src/vscp/common/vscpremotetcpif.h | 4 +- tests/dm/lua/dm-enteries.xml | 908 +++++++++++++++++++++++++ 16 files changed, 1677 insertions(+), 276 deletions(-) diff --git a/src/common/lua/LuaXML_lib.c b/src/common/lua/LuaXML_lib.c index 435dd57d1..ca4bea397 100644 --- a/src/common/lua/LuaXML_lib.c +++ b/src/common/lua/LuaXML_lib.c @@ -1,6 +1,8 @@ /** LuaXML License +https://github.com/LuaDist/luaxml + LuaXml is licensed under the terms of the MIT license reproduced below, the same as Lua itself. This means that LuaXml is free software and can be used for both academic and commercial purposes at absolutely no cost. diff --git a/src/common/mongoose.c b/src/common/mongoose.c index f80b4daf3..957623529 100644 --- a/src/common/mongoose.c +++ b/src/common/mongoose.c @@ -13,7 +13,7 @@ /* Amalgamated: #include "common/mg_mem.h" */ #ifndef MBUF_REALLOC -#define MBUF_REALLOC MG_REALLOC +#define MBUF_REALLOC MG_REALLOC #endif #ifndef MBUF_FREE @@ -2834,7 +2834,6 @@ void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, } else { /* Drop on the floor. */ MG_FREE(buf); - nc->iface->vtable->recved(nc, len); } } @@ -3451,8 +3450,11 @@ void mg_socket_if_connect_udp(struct mg_connection *nc) { } if (nc->flags & MG_F_ENABLE_BROADCAST) { int optval = 1; - setsockopt(nc->sock, SOL_SOCKET, SO_BROADCAST, (const char *) &optval, - sizeof(optval)); + if (setsockopt(nc->sock, SOL_SOCKET, SO_BROADCAST, (const char *) &optval, + sizeof(optval)) < 0) { + nc->err = mg_get_errno() ? mg_get_errno() : 1; + return; + } } nc->err = 0; } @@ -3914,10 +3916,16 @@ time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms) { /* A hack to make sure all our file descriptos fit into FD_SETSIZE. */ if (nc->sock >= (sock_t) FD_SETSIZE && try_dup) { int new_sock = dup(nc->sock); - if (new_sock >= 0 && new_sock < (sock_t) FD_SETSIZE) { - closesocket(nc->sock); - DBG(("new sock %d -> %d", nc->sock, new_sock)); - nc->sock = new_sock; + if (new_sock >= 0) { + if (new_sock < (sock_t) FD_SETSIZE) { + closesocket(nc->sock); + DBG(("new sock %d -> %d", nc->sock, new_sock)); + nc->sock = new_sock; + } else { + closesocket(new_sock); + DBG(("new sock is still larger than FD_SETSIZE, disregard")); + try_dup = 0; + } } else { try_dup = 0; } @@ -8459,9 +8467,11 @@ size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, size_t *data_len) { static const char cd[] = "Content-Disposition: "; size_t hl, bl, n, ll, pos, cdl = sizeof(cd) - 1; + int shl; if (buf == NULL || buf_len <= 0) return 0; - if ((hl = mg_http_get_request_len(buf, buf_len)) <= 0) return 0; + if ((shl = mg_http_get_request_len(buf, buf_len)) <= 0) return 0; + hl = shl; if (buf[0] != '-' || buf[1] != '-' || buf[2] == '\n') return 0; /* Get boundary length */ @@ -8835,6 +8845,7 @@ static void mg_prepare_cgi_environment(struct mg_connection *nc, char *p; size_t i; char buf[100]; + size_t path_info_len = path_info != NULL ? path_info->len : 0; blk->len = blk->nvars = 0; blk->nc = nc; @@ -8866,7 +8877,7 @@ static void mg_prepare_cgi_environment(struct mg_connection *nc, mg_conn_addr_to_str(nc, buf, sizeof(buf), MG_SOCK_STRINGIFY_PORT); mg_addenv(blk, "SERVER_PORT=%s", buf); - s = hm->uri.p + hm->uri.len - path_info->len - 1; + s = hm->uri.p + hm->uri.len - path_info_len - 1; if (*s == '/') { const char *base_name = strrchr(prog, DIRSEP); mg_addenv(blk, "SCRIPT_NAME=%.*s/%s", (int) (s - hm->uri.p), hm->uri.p, @@ -10849,8 +10860,7 @@ static void mg_mqtt_broker_handle_connect(struct mg_mqtt_broker *brk, /* TODO(mkm): check header (magic and version) */ mg_mqtt_session_init(brk, s, nc); - s->user_data = nc->user_data; - nc->user_data = s; + nc->priv_2 = s; mg_mqtt_add_session(s); mg_mqtt_connack(nc, MG_EV_MQTT_CONNACK_ACCEPTED); @@ -10858,7 +10868,7 @@ static void mg_mqtt_broker_handle_connect(struct mg_mqtt_broker *brk, static void mg_mqtt_broker_handle_subscribe(struct mg_connection *nc, struct mg_mqtt_message *msg) { - struct mg_mqtt_session *ss = (struct mg_mqtt_session *) nc->user_data; + struct mg_mqtt_session *ss = (struct mg_mqtt_session *) nc->priv_2; uint8_t qoss[MG_MQTT_MAX_SESSION_SUBSCRIPTIONS]; size_t num_subs = 0; struct mg_str topic; @@ -10936,18 +10946,18 @@ void mg_mqtt_broker(struct mg_connection *nc, int ev, void *data) { struct mg_mqtt_broker *brk; if (nc->listener) { - brk = (struct mg_mqtt_broker *) nc->listener->user_data; + brk = (struct mg_mqtt_broker *) nc->listener->priv_2; } else { - brk = (struct mg_mqtt_broker *) nc->user_data; + brk = (struct mg_mqtt_broker *) nc->priv_2; } switch (ev) { case MG_EV_ACCEPT: if (nc->proto_data == NULL) mg_set_protocol_mqtt(nc); - nc->user_data = NULL; /* Clear up the inherited pointer to broker */ + nc->priv_2 = NULL; /* Clear up the inherited pointer to broker */ break; case MG_EV_MQTT_CONNECT: - if (nc->user_data == NULL) { + if (nc->priv_2 == NULL) { mg_mqtt_broker_handle_connect(brk, nc); } else { /* Repeated CONNECT */ @@ -10955,7 +10965,7 @@ void mg_mqtt_broker(struct mg_connection *nc, int ev, void *data) { } break; case MG_EV_MQTT_SUBSCRIBE: - if (nc->user_data != NULL) { + if (nc->priv_2 != NULL) { mg_mqtt_broker_handle_subscribe(nc, msg); } else { /* Subscribe before CONNECT */ @@ -10963,7 +10973,7 @@ void mg_mqtt_broker(struct mg_connection *nc, int ev, void *data) { } break; case MG_EV_MQTT_PUBLISH: - if (nc->user_data != NULL) { + if (nc->priv_2 != NULL) { mg_mqtt_broker_handle_publish(brk, msg); } else { /* Publish before CONNECT */ @@ -10971,8 +10981,8 @@ void mg_mqtt_broker(struct mg_connection *nc, int ev, void *data) { } break; case MG_EV_CLOSE: - if (nc->listener && nc->user_data != NULL) { - mg_mqtt_close_session((struct mg_mqtt_session *) nc->user_data); + if (nc->listener && nc->priv_2 != NULL) { + mg_mqtt_close_session((struct mg_mqtt_session *) nc->priv_2); } break; } @@ -11690,6 +11700,8 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query, } strncpy(req->name, name, sizeof(req->name)); + req->name[sizeof(req->name) - 1] = '\0'; + req->query = query; req->callback = cb; req->data = data; diff --git a/src/vscp/common/devicethread.cpp b/src/vscp/common/devicethread.cpp index f10e95ae6..d894b403b 100644 --- a/src/vscp/common/devicethread.cpp +++ b/src/vscp/common/devicethread.cpp @@ -353,7 +353,7 @@ void *deviceThread::Entry() // * * * * Blocking version * * * * if ( m_pCtrlObject->m_debugFlags1 & VSCP_DEBUG1_DRIVER ) { - m_pCtrlObject->logMsg(_("[Device tread] Level I Blocking version.")); + m_pCtrlObject->logMsg(_("[Device tread] Level I blocking version.")); } ///////////////////////////////////////////////////////////////////////////// @@ -379,7 +379,7 @@ void *deviceThread::Entry() } if ( m_pCtrlObject->m_debugFlags1 & VSCP_DEBUG1_DRIVER ) { - m_pCtrlObject->logMsg(_("[Device tread] Level I Write thread started.")); + m_pCtrlObject->logMsg(_("[Device tread] Level I write thread started.")); } ///////////////////////////////////////////////////////////////////////////// @@ -405,7 +405,7 @@ void *deviceThread::Entry() } if ( m_pCtrlObject->m_debugFlags1 & VSCP_DEBUG1_DRIVER ) { - m_pCtrlObject->logMsg(_("[Device tread] Level I Receive thread started.")); + m_pCtrlObject->logMsg(_("[Device tread] Level I receive thread started.")); } // Just sit and wait until the end of the world as we know it... @@ -414,7 +414,7 @@ void *deviceThread::Entry() } if ( m_pCtrlObject->m_debugFlags1 & VSCP_DEBUG1_DRIVER ) { - m_pCtrlObject->logMsg(_("[Device tread] Level I Work loop ended.")); + m_pCtrlObject->logMsg(_("[Device tread] Level I work loop ended.")); } m_preceiveThread->m_bQuit = true; diff --git a/src/vscp/common/duktape_vscp_func.cpp b/src/vscp/common/duktape_vscp_func.cpp index 35e08143d..7a82a9403 100644 --- a/src/vscp/common/duktape_vscp_func.cpp +++ b/src/vscp/common/duktape_vscp_func.cpp @@ -653,6 +653,7 @@ duk_ret_t js_vscp_sendEvent( duk_context *ctx ) duk_push_boolean(ctx,0); // return code false return JAVASCRIPT_OK; } + duk_pop_n(ctx, 1); // Send the event @@ -662,6 +663,7 @@ duk_ret_t js_vscp_sendEvent( duk_context *ctx ) return JAVASCRIPT_OK; } + pEvent->pdata = NULL; vscp_convertVSCPfromEx( pEvent, &ex ); duk_push_global_object(ctx); /* -> stack: [ global ] */ diff --git a/src/vscp/common/lua_vscp_func.cpp b/src/vscp/common/lua_vscp_func.cpp index 224586c25..50b51f881 100644 --- a/src/vscp/common/lua_vscp_func.cpp +++ b/src/vscp/common/lua_vscp_func.cpp @@ -315,6 +315,42 @@ int lua_vscp_base64_decode( struct lua_State *L ) } +/////////////////////////////////////////////////////////////////////////////// +// lua_vscp_escapexml +// +// result = escapexml(string) +// +// TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + +int lua_vscp_escapexml( struct lua_State *L ) +{ + int nArgs = lua_gettop( L ); + + if ( 0 == nArgs ) { + return luaL_error( L, "vscp.escapexml: Wrong number of arguments: " + "vscp.escapexml( string-to-escape ) "); + } + + // String to escape + if ( !lua_isstring( L, 1 ) ) { + return luaL_error( L, "vscp.readvariable: Argument error, string expected: " + "vscp.readvariable( \"name\"[,format] ) "); + } + + size_t len; + const char *pstr = lua_tolstring ( L, 1, &len ); + + if ( !len ) { + lua_pushnil( L ); + return 1; + } + + // TODO + + return 1; +} + + /////////////////////////////////////////////////////////////////////////////// // lua_vscp_readVariable // @@ -404,19 +440,46 @@ int lua_vscp_readVariable( struct lua_State *L ) } // Get only value else if ( 3 == format ) { - // Get the variable value un encoded - wxString strVal; - strVal = variable.getValue(); - lua_pushlstring( L, (const char *)strVal.mbc_str(), - strVal.Length() ); + // Get the variable value + wxString strval = variable.getValue(); + if ( variable.isNumerical() ) { + if ( VSCP_DAEMON_VARIABLE_CODE_INTEGER == variable.getType() ) { + int val = atoi( strval ); + lua_pushinteger( L, val ); + } + else if ( VSCP_DAEMON_VARIABLE_CODE_LONG == variable.getType() ) { + long val = atol( strval ); + lua_pushnumber( L, val ); + } + else if ( VSCP_DAEMON_VARIABLE_CODE_DOUBLE == variable.getType() ) { + double val; + strval.ToDouble( &val ); + lua_pushnumber( L, val ); + } + } + else { + if ( VSCP_DAEMON_VARIABLE_CODE_BOOLEAN == variable.getType() ) { + lua_pushboolean( L, variable.isTrue() ); + } + else { + + // Decode if needed + if ( variable.isValueBase64Encoded() ) { + vscp_base64_wxdecode( strval ); + } + + lua_pushlstring( L, (const char *)strval.mbc_str(), + strval.Length() ); + } + } } // Get only note else if ( 4 == format ) { // Get the variable value un encoded - wxString strVal; - strVal = variable.getValue(); - lua_pushlstring( L, (const char *)strVal.mbc_str(), - strVal.Length() ); + wxString strval = variable.getValue(); + vscp_base64_wxdecode( strval ); + lua_pushlstring( L, (const char *)strval.mbc_str(), + strval.Length() ); } else { return luaL_error( L, "vscp.readvariable: Format must be 0=string, " @@ -428,15 +491,13 @@ int lua_vscp_readVariable( struct lua_State *L ) /////////////////////////////////////////////////////////////////////////////// -// js_vscp_writeVariable +// lua_vscp_writeVariable // -// writeVariable( value[, format]) +// writeVariable( value[,format]) // // format = 0 - string // format = 1 - XML // format = 2 - JSON -// format = 3 - Value -// format = 4 . Note // int lua_vscp_writeVariable( struct lua_State *L ) @@ -477,14 +538,7 @@ int lua_vscp_writeVariable( struct lua_State *L ) format = (int)lua_tointeger( L, 2 ); } - - // Get Base64 flags - if ( nArgs >= 3 ) { - if ( lua_isboolean( L, 3 ) ) { - bBase64 = lua_toboolean( L, 3 ) ? true : false; - } - } - + if ( 0 == format ) { // Set variable from string if ( !variable.setVariableFromString( varValue ) ) { @@ -506,19 +560,12 @@ int lua_vscp_writeVariable( struct lua_State *L ) " from JSON object."); } } - else if ( 3 == format ) { - // Set variable value - variable.setValue( varValue, bBase64 ); - } - else if ( 4 == format ) { - // Set variable note - variable.setNote( varValue, bBase64 ); - } else { return luaL_error( L, "vscp.writevariable: Format must be 0=string, " - "1=XML, 2=JSON, 0=value, 3=note"); + "1=XML, 2=JSON"); } + // Update or add variable if not defined if ( !gpobj->m_variables.add( variable ) ) { return luaL_error( L, "vscp.writevariable: Failed to update/add variable!"); } @@ -530,21 +577,24 @@ int lua_vscp_writeVariable( struct lua_State *L ) /////////////////////////////////////////////////////////////////////////////// // lua_vscp_writeVariableValue // -// writeVariableValue( varname, value, bBase64) +// writeVariableValue( varname, value[, bBase64]) // // int lua_vscp_writeVariableValue( struct lua_State *L ) { + size_t len; + const char *pstr; + bool bBase64 = false; wxString varName; wxString varValue; CVSCPVariable variable; int nArgs = lua_gettop( L ); - if ( nArgs < 3 ) { + if ( nArgs < 2 ) { return luaL_error( L, "vscp.writeVariableValue: Wrong number of arguments: " - "vscp.writeVariableValue( varname, varvalue, bBase64 ) "); + "vscp.writeVariableValue( varname, varvalue[, bBase64] ) "); } // variable name @@ -553,36 +603,101 @@ int lua_vscp_writeVariableValue( struct lua_State *L ) "vscp.writeVariableValue( varname, varvalue, bBase64 ) "); } - size_t len; - const char *pstr = lua_tolstring ( L, 1, &len ); + pstr = lua_tolstring ( L, 1, &len ); varName = wxString::FromUTF8( pstr, len ); - - // variable value - if ( !lua_isstring( L, 2 ) ) { - return luaL_error( L, "vscp.writeVariableValue: Argument error, string expected: " - "vscp.writeVariableValue( varname, varvalue, bBase64 ) "); - } - - pstr = lua_tolstring ( L, 2, &len ); - varValue = wxString::FromUTF8( pstr, len ); - - - // variable base64 flag - bool bBase64 = false; - if ( !lua_isboolean( L, 3 ) ) { - return luaL_error( L, "vscp.writeVariableValue: Argument error, boolean expected: " - "vscp.writeVariableValue( varname, varvalue, bBase64 ) "); - } - - bBase64 = lua_toboolean ( L, 3 ); - if ( !gpobj->m_variables.find( varName, variable ) ) { return luaL_error( L, "vscp.writeVariableValue: No variable with that " "name found!"); } - - variable.setValue( varValue, bBase64 ); + + // variable value + if ( variable.isNumerical() ) { + + if ( VSCP_DAEMON_VARIABLE_CODE_INTEGER == variable.getType() ) { + + int val; + if ( lua_isnumber( L, 2 ) ) { + val = lua_tointeger( L, 2 ); + variable.setValue( val ); + } + else if ( lua_isstring( L, 2 ) ) { + pstr = lua_tolstring ( L, 2, &len ); + val = atoi( pstr ); + variable.setValue( val ); + } + else { + return luaL_error( L, "vscp.writeVariableValue: Value has " + "wrong format !"); + } + + } + else if ( VSCP_DAEMON_VARIABLE_CODE_LONG == variable.getType() ) { + + long val; + if ( lua_isnumber( L, 2 ) ) { + val = lua_tonumber( L, 2 ); + variable.setValue( val ); + } + else if ( lua_isstring( L, 2 ) ) { + pstr = lua_tolstring ( L, 2, &len ); + val = atol( pstr ); + variable.setValue( val ); + } + + else { + return luaL_error( L, "vscp.writeVariableValue: Value has " + "wrong format !"); + } + + } + else if ( VSCP_DAEMON_VARIABLE_CODE_DOUBLE == variable.getType() ) { + + double val; + if ( lua_isnumber( L, 2 ) ) { + val = lua_tonumber( L, 2 ); + variable.setValue( val ); + } + else if ( lua_isstring( L, 2 ) ) { + val = lua_tonumber( L, 2 ); + variable.setValue( val ); + } + + else { + return luaL_error( L, "vscp.writeVariableValue: Value has " + "wrong format !"); + } + + } + + } + else { + + if ( VSCP_DAEMON_VARIABLE_CODE_BOOLEAN == variable.getType() ) { + bool bVal; + if ( lua_isboolean( L, 2 ) ) { + variable.setValue( lua_toboolean( L, 2 ) ? true : false ); + } + else { + return luaL_error( L, "vscp.writeVariableValue: Value has " + "wrong format !"); + } + variable.setValue( bVal ); + } + else { + // This is a string type value + + // variable base64 flag + if ( nArgs < 3 ) { + bBase64 = lua_toboolean ( L, 3 ); + } + + pstr = lua_tolstring ( L, 1, &len ); + wxString str = wxString::FromUTF8( pstr, len ); + variable.setValue( str, bBase64 ); + } + + } if ( !gpobj->m_variables.update( variable ) ) { return luaL_error( L, "vscp.writeVariableValue: Failed to update variable value!"); @@ -691,6 +806,185 @@ int lua_vscp_deleteVariable( struct lua_State *L ) } +/////////////////////////////////////////////////////////////////////////////// +// lua_vscp_isVariableBase64Encoded +// +// isVariableBase64(name) +// +// + +int lua_vscp_isVariableBase64Encoded( struct lua_State *L ) +{ + size_t len; + bool bBase64 = false; + wxString varName; + CVSCPVariable variable; + + int nArgs = lua_gettop( L ); + + if ( 0 == nArgs ) { + return luaL_error( L, "vscp.isVariableBase64: Wrong number of arguments: " + "vscp.isVariableBase64( name ) "); + } + + if ( nArgs >= 1 ) { + + // variable name + if ( !lua_isstring( L, 1 ) ) { + return luaL_error( L, "vscp.isVariableBase64: Argument error, string expected: " + "vscp.isVariableBase64( name ) "); + } + + const char *pstr = lua_tolstring ( L, 1, &len ); + varName = wxString::FromUTF8( pstr, len ); + + } + + if ( !gpobj->m_variables.find( varName, variable ) ) { + return luaL_error( L, "vscp.isVariableBase64: No variable with that " + "name found!"); + } + + lua_pushboolean( L, variable.isValueBase64Encoded() ); + + return 1; +} + + +/////////////////////////////////////////////////////////////////////////////// +// lua_vscp_isVariablePersistent +// +// isVariablePersistent(name) +// +// + +int lua_vscp_isVariablePersistent( struct lua_State *L ) +{ + size_t len; + bool bBase64 = false; + wxString varName; + CVSCPVariable variable; + + int nArgs = lua_gettop( L ); + + if ( 0 == nArgs ) { + return luaL_error( L, "vscp.isVariablePersistent: Wrong number of arguments: " + "vscp.isVariablePersistent( name ) "); + } + + if ( nArgs >= 1 ) { + + // variable name + if ( !lua_isstring( L, 1 ) ) { + return luaL_error( L, "vscp.isVariablePersistent: Argument error, string expected: " + "vscp.isVariablePersistent( name ) "); + } + + const char *pstr = lua_tolstring ( L, 1, &len ); + varName = wxString::FromUTF8( pstr, len ); + + } + + if ( !gpobj->m_variables.find( varName, variable ) ) { + return luaL_error( L, "vscp.isVariablePersistent: No variable with that " + "name found!"); + } + + lua_pushboolean( L, variable.isPersistent() ); + + return 1; +} + + +/////////////////////////////////////////////////////////////////////////////// +// lua_vscp_isVariableNumerical +// +// isVariableNumerical(name) +// +// + +int lua_vscp_isVariableNumerical( struct lua_State *L ) +{ + size_t len; + bool bBase64 = false; + wxString varName; + CVSCPVariable variable; + + int nArgs = lua_gettop( L ); + + if ( 0 == nArgs ) { + return luaL_error( L, "vscp.isVariableNumerical: Wrong number of arguments: " + "vscp.isVariableNumerical( name ) "); + } + + if ( nArgs >= 1 ) { + + // variable name + if ( !lua_isstring( L, 1 ) ) { + return luaL_error( L, "vscp.isVariableNumerical: Argument error, string expected: " + "vscp.isVariableNumerical( name ) "); + } + + const char *pstr = lua_tolstring ( L, 1, &len ); + varName = wxString::FromUTF8( pstr, len ); + + } + + if ( !gpobj->m_variables.find( varName, variable ) ) { + return luaL_error( L, "vscp.isVariableNumerical: No variable with that " + "name found!"); + } + + lua_pushboolean( L, variable.isNumerical() ); + + return 1; +} + + +/////////////////////////////////////////////////////////////////////////////// +// lua_vscp_isStockVariable +// +// isStockVariable(name) +// +// + +int lua_vscp_isStockVariable( struct lua_State *L ) +{ + size_t len; + bool bBase64 = false; + wxString varName; + CVSCPVariable variable; + + int nArgs = lua_gettop( L ); + + if ( 0 == nArgs ) { + return luaL_error( L, "vscp.isStockVariable: Wrong number of arguments: " + "vscp.isStockVariable( name ) "); + } + + if ( nArgs >= 1 ) { + + // variable name + if ( !lua_isstring( L, 1 ) ) { + return luaL_error( L, "vscp.isStockVariable: Argument error, string expected: " + "vscp.isStockVariable( name ) "); + } + + const char *pstr = lua_tolstring ( L, 1, &len ); + varName = wxString::FromUTF8( pstr, len ); + + } + + if ( !gpobj->m_variables.find( varName, variable ) ) { + return luaL_error( L, "vscp.isStockVariable: No variable with that " + "name found!"); + } + + lua_pushboolean( L, variable.isStockVariable() ); + + return 1; +} + /////////////////////////////////////////////////////////////////////////////// // lua_vscp_sendEvent // @@ -700,17 +994,6 @@ int lua_vscp_deleteVariable( struct lua_State *L ) // format = 1 - XML format. // format = 2 - JSON format. // -// { -// "time": "2017-01-13T10:16:02", -// "head": 2, -// "timestamp":50817, -// "obid"; 123, -// "class": 10, -// "type": 8, -// "guid": "00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:02", -// "data": [1,2,3,4,5,6,7], -// } -// int lua_vscp_sendEvent( struct lua_State *L ) { @@ -726,6 +1009,13 @@ int lua_vscp_sendEvent( struct lua_State *L ) lua_gettable (L, LUA_REGISTRYINDEX ); pClientItem = (CClientItem *)lua_touserdata( L, -1 ); + nArgs = lua_gettop( L ); + + // Remove client item from stack + lua_pop( L, 1 ); + + nArgs = lua_gettop( L ); + if ( NULL == pClientItem ) { return luaL_error( L, "vscp.sendEvent: VSCP server client not found."); } @@ -756,17 +1046,20 @@ int lua_vscp_sendEvent( struct lua_State *L ) format = (int)lua_tointeger( L, 2 ); } + // String if ( 0 == format ) { if ( !vscp_setVscpEventExFromString( &ex, strEvent ) ) { return luaL_error( L, "vscp.sendEvent: Failed to get VSCP event from string!"); } } + // XML else if ( 1 == format ) { if ( !vscp_convertXMLToEventEx( strEvent, &ex ) ) { return luaL_error( L, "vscp.sendEvent: Failed to get " "VSCP event from XML!"); } } + // JSON else if ( 2 == format ) { if ( !vscp_convertJSONToEventEx( strEvent, &ex ) ) { return luaL_error( L, "vscp.sendEvent: Failed to get " @@ -774,17 +1067,20 @@ int lua_vscp_sendEvent( struct lua_State *L ) } } - vscpEvent *pEvent; + vscpEvent *pEvent = new vscpEvent; + if ( NULL == pEvent ) { + return luaL_error( L, "vscp.sendEvent: Failed to " + "allocate VSCP event!"); + } + pEvent->pdata = NULL; vscp_convertVSCPfromEx( pEvent, &ex ); if ( !gpobj->sendEvent( pClientItem, pEvent ) ) { // Failed to send event - vscp_deleteVSCPevent( pEvent ); + vscp_deleteVSCPevent_v2( &pEvent ); return luaL_error( L, "vscp.sendEvent: Failed to send event!"); } - vscp_deleteVSCPevent( pEvent ); - return 1; } @@ -792,6 +1088,8 @@ int lua_vscp_sendEvent( struct lua_State *L ) /////////////////////////////////////////////////////////////////////////////// // lua_vscp_getEvent // +// receiveevent([format]) +// int lua_vscp_getEvent( struct lua_State *L ) { @@ -802,6 +1100,14 @@ int lua_vscp_getEvent( struct lua_State *L ) int nArgs = lua_gettop( L ); + // Get format - if given + if ( 0 != nArgs ) { + + if ( !lua_isnumber( L, 1 ) ) { + format = (int)lua_tointeger( L, 1 ); + } + } + // Get the client item lua_pushlstring( L, "vscp_clientitem", 15 ); lua_gettable (L, LUA_REGISTRYINDEX ); @@ -811,10 +1117,7 @@ int lua_vscp_getEvent( struct lua_State *L ) return luaL_error( L, "vscp.getEvent: VSCP server client not found."); } - if ( 0 == nArgs ) { - return luaL_error( L, "vscp.getEvent: Wrong number of arguments: " - "vscp.getEvent( format ) "); - } + try_again: @@ -834,69 +1137,58 @@ int lua_vscp_getEvent( struct lua_State *L ) pClientItem->m_clientInputQueue.DeleteNode( nodeClient ); pClientItem->m_mutexClientInputQueue.Unlock(); - if ( NULL != pEvent ) { - - if ( vscp_doLevel2Filter( pEvent, &pClientItem->m_filterVSCP ) ) { + if ( NULL == pEvent ) { + return luaL_error( L, "vscp.getEvent: Allocation error when " + "getting event from client!"); + } - // Write it out - wxString strResult; - switch ( format ) { - case 0: // String - if ( !vscp_writeVscpEventToString( pEvent, strResult ) ) { - return luaL_error( L, - "vscp.getEvent: Failed to " - "convert event to string form."); - } - break; + if ( vscp_doLevel2Filter( pEvent, &pClientItem->m_filterVSCP ) ) { + + // Write it out + wxString strResult; + switch ( format ) { + case 0: // String + if ( !vscp_writeVscpEventToString( pEvent, strResult ) ) { + return luaL_error( L, + "vscp.getEvent: Failed to " + "convert event to string form."); + } + break; - case 1: // XML - if ( !vscp_convertEventToXML( pEvent, strResult ) ) { - return luaL_error( L, - "vscp.getEvent: Failed to " - "convert event to XML form."); - } - break; + case 1: // XML + if ( !vscp_convertEventToXML( pEvent, strResult ) ) { + return luaL_error( L, + "vscp.getEvent: Failed to " + "convert event to XML form."); + } + break; - case 2: // JSON - if ( !vscp_convertEventToJSON( pEvent, strResult ) ) { - return luaL_error( L, - "vscp.getEvent: Failed to " - "convert event to JSON form."); - } - break; - } - - // Event is not needed anymore - vscp_deleteVSCPevent( pEvent ); - - lua_pushlstring( L, - (const char *)strResult.mbc_str(), - strResult.Length() ); - - // All OK return event - return 1; - + case 2: // JSON + if ( !vscp_convertEventToJSON( pEvent, strResult ) ) { + return luaL_error( L, + "vscp.getEvent: Failed to " + "convert event to JSON form."); + } + break; } - else { - - // Filtered out - vscp_deleteVSCPevent( pEvent ); - goto try_again; - } - - // Remove the event + // Event is not needed anymore vscp_deleteVSCPevent( pEvent ); + + lua_pushlstring( L, + (const char *)strResult.mbc_str(), + strResult.Length() ); + + // All OK return event + return 1; } // Valid pEvent pointer - else { - // NULL event - lua_pushnil( L ); // return code failure - return 1; - } + } // events available + // No events available + lua_pushnil( L ); return 1; } @@ -904,6 +1196,7 @@ int lua_vscp_getEvent( struct lua_State *L ) /////////////////////////////////////////////////////////////////////////////// // lua_vscp_getCountEvent // +// cnt = vscp.countevents() // int lua_vscp_getCountEvent( struct lua_State *L ) @@ -999,7 +1292,7 @@ int lua_vscp_setFilter( struct lua_State *L ) switch ( format ) { case 0: - if ( !vscp_readFilterFromString( &filter, strFilter ) ) { + if ( !vscp_readFilterMaskFromString( &filter, strFilter ) ) { luaL_error( L, "vscp.setFilter: Failed to read filter!"); } break; @@ -1295,7 +1588,7 @@ int lua_send_Measurement( struct lua_State *L ) /////////////////////////////////////////////////////////////////////////////// // lua_is_Measurement // -// event,format +// result = ismeasurement(event,format) // // format = 0 - String format. // format = 1 - XML format. diff --git a/src/vscp/common/lua_vscp_func.h b/src/vscp/common/lua_vscp_func.h index fdec69346..f73347b8e 100644 --- a/src/vscp/common/lua_vscp_func.h +++ b/src/vscp/common/lua_vscp_func.h @@ -102,30 +102,43 @@ int lua_vscp_readVariable( struct lua_State *L ); * * vscp.readvariable( "name"[, format ] ) * - * Lua Parameter 1: Variable name + * Lua Parameter 1: variable * Lua Parameter 2: Optional format - * Lua: Return: True if variable got updated/added. + * Lua: Return: 1 on success. * - * @param v7 Pointer to v7 object. - * @param res Pointer to JSON object or NULL if variable was not found. - * @return v7 error code. */ int lua_vscp_writeVariable( struct lua_State *L ); +/*! + * Write remote variable value + * + * Lua Parameter 1: variable name + * Lua Parameter 2: variable value + * Lua Parameter 3: OPTIONAL Flag for BASE64 coding of value. + * Lua: Return: 1 on success. + * + */ +int lua_vscp_writeVariableValue( struct lua_State *L ); + /*! * Delete VSCP variable * * Lua Parameter 0: ClientItem * Lua Parameter 1: Name of variable - * Lua: Return: True if variable got deleted. + * Lua: Return: 1 on success. * - * @param v7 Pointer to v7 object. - * @param res Pointer to JSON object or NULL if variable was not found. - * @return v7 error code. */ int lua_vscp_deleteVariable( struct lua_State *L ); +int lua_vscp_isVariableBase64Encoded( struct lua_State *L ) ; + +int lua_vscp_isVariablePersistent( struct lua_State *L ); + +int lua_vscp_isVariableNumerical( struct lua_State *L ); + +int lua_vscp_isStockVariable( struct lua_State *L ); + /*! * Send VSCP event on the local client queue * diff --git a/src/vscp/common/lua_vscp_wrkthread.cpp b/src/vscp/common/lua_vscp_wrkthread.cpp index dc73de0fc..f3b562a0d 100644 --- a/src/vscp/common/lua_vscp_wrkthread.cpp +++ b/src/vscp/common/lua_vscp_wrkthread.cpp @@ -200,11 +200,17 @@ void *actionThread_Lua::Entry() web_reg_function( L, "readvariable", lua_vscp_readVariable ); web_reg_function( L, "writevariable", lua_vscp_writeVariable ); + web_reg_function( L, "writevariablevalue", lua_vscp_writeVariableValue ); web_reg_function( L, "deletevariable", lua_vscp_deleteVariable ); + + web_reg_function( L, "isVariableBase64Encoded", lua_vscp_isVariableBase64Encoded ); + web_reg_function( L, "isVariablePersistent", lua_vscp_isVariablePersistent ); + web_reg_function( L, "isVariableNumerical", lua_vscp_isVariableNumerical ); + web_reg_function( L, "isStockVariable", lua_vscp_isStockVariable ); web_reg_function( L, "sendevent", lua_vscp_sendEvent ); - web_reg_function( L, "getevent", lua_vscp_getEvent ); - web_reg_function( L, "getcountevent", lua_vscp_getCountEvent ); + web_reg_function( L, "receiveevent", lua_vscp_getEvent ); + web_reg_function( L, "countevent", lua_vscp_getCountEvent ); web_reg_function( L, "setfilter", lua_vscp_setFilter ); web_reg_function( L, "ismeasurement", lua_is_Measurement ); @@ -302,7 +308,7 @@ void *actionThread_Lua::Entry() (const char *)m_wxstrScript.mbc_str() ); gpobj->logMsg( strError, DAEMON_LOGMSG_NORMAL, DAEMON_LOGTYPE_DM ); - return NULL; + return NULL; } // The script file is loaded, now call it diff --git a/src/vscp/common/remotevariable.cpp b/src/vscp/common/remotevariable.cpp index a6acc7545..374e58e55 100644 --- a/src/vscp/common/remotevariable.cpp +++ b/src/vscp/common/remotevariable.cpp @@ -196,9 +196,10 @@ uint16_t CVSCPVariable::getVariableTypeFromString( const wxString& strVariableTy wxString str = strVariableType; long val; - if ( str.IsNumber() ) { - str.ToLong( &val, 10 ); - type = val; + if ( str.IsNumber() || + str.StartsWith(_("0x")) || + str.StartsWith(_("0X")) ) { + type = vscp_readStringValue( str ); } else { str.Trim(); @@ -585,7 +586,7 @@ bool CVSCPVariable::setFromJSON( wxString &strVariable ) } if (j.find("user") != j.end()) { - m_userid = j.at("userid").get(); + m_userid = j.at("user").get(); } if (j.find("accessrights") != j.end()) { @@ -597,12 +598,54 @@ bool CVSCPVariable::setFromJSON( wxString &strVariable ) } if (j.find("value") != j.end()) { - m_strValue = j.at("value").get(); + + wxString str; + + if ( isNumerical() ) { + + if ( VSCP_DAEMON_VARIABLE_CODE_INTEGER == getType() ) { + int val = j.at("value").get(); + setValue( val ); + } + else if ( VSCP_DAEMON_VARIABLE_CODE_LONG == getType() ) { + long val = j.at("value").get(); + setValue( val ); + } + else if ( VSCP_DAEMON_VARIABLE_CODE_DOUBLE == getType() ) { + double val = j.at("value").get(); + setValue( val ); + } + + } + else { + + if ( VSCP_DAEMON_VARIABLE_CODE_BOOLEAN == getType() ) { + bool bVal = j.at("value").get(); + setValue( bVal ); + } + else { + str = j.at("value").get(); + setValue( str, false ); + } + + } + } + + if (j.find("valuebase64") != j.end()) { + wxString str = j.at("valuebase64").get(); + setValue( str, true ); } if (j.find("note") != j.end()) { - m_note = j.at("note").get(); + wxString str = j.at("note").get(); + setNote( str, false ); + } + + if (j.find("notebase64") != j.end()) { + wxString str = j.at("notebase64").get(); + setNote( str, true ); } + } catch ( ... ) { gpobj->logMsg( _("Remote variable, setFromJSON: " @@ -655,15 +698,29 @@ bool CVSCPVariable::setFromXML( wxString &strVariable ) // Mark last changed as now setLastChangedToNow(); - + + // name + wxstr = doc.GetRoot()->GetAttribute( _("name") ); + if ( wxEmptyString != wxstr ) { + wxstr.MakeUpper(); + wxstr.Trim(); + wxstr.Trim( false ); + if ( wxstr.Length() ) { + setName( wxstr ); + } + } + // type wxstr = doc.GetRoot()->GetAttribute( _("type") ); if ( wxEmptyString != wxstr ) { setType( getVariableTypeFromString( wxstr ) ); } + else { + setType( VSCP_DAEMON_VARIABLE_CODE_STRING ); // String is default + } // persistence - wxstr = doc.GetRoot()->GetAttribute( _("persistent") ); + wxstr = doc.GetRoot()->GetAttribute( _("persistence") ); if ( wxEmptyString != wxstr ) { wxstr.MakeUpper(); if ( wxNOT_FOUND != wxstr.Find( _("TRUE") ) ) { @@ -681,6 +738,9 @@ bool CVSCPVariable::setFromXML( wxString &strVariable ) setOwnerID( lval ); } } + else { + setOwnerID( 0 ); + } // access-rights wxstr = doc.GetRoot()->GetAttribute( _("access-rights") ); @@ -688,31 +748,27 @@ bool CVSCPVariable::setFromXML( wxString &strVariable ) lval = vscp_readStringValue( wxstr ); setAccessRights( lval ); } - - // name - wxstr = doc.GetRoot()->GetAttribute( _("name") ); - if ( wxEmptyString != wxstr ) { - wxstr.MakeUpper(); - wxstr.Trim(); - wxstr.Trim( false ); - if ( wxstr.Length() ) { - setName( wxstr ); - } + else { + setAccessRights( 0x744 ); } // value wxstr = doc.GetRoot()->GetAttribute( _("value") ); if ( wxEmptyString != wxstr ) { - setValueFromString( getType(), - wxstr, - CVSCPVariable::isValueBase64Encoded( getType() ) ); + setValue( wxstr, false ); } + + // value-base64 Should always be coded + wxstr = doc.GetRoot()->GetAttribute( _("value-base64") ); + setValue( wxstr, true ); // note wxstr = doc.GetRoot()->GetAttribute( _("note"), _("") ); - if ( wxEmptyString != wxstr ) { - setNote( wxstr, true ); - } + setNote( wxstr, false ); + + // note-base64 Should always be coded + wxstr = doc.GetRoot()->GetAttribute( _("note-base64"), _("") ); + setNote( wxstr, true ); return true; } @@ -1105,7 +1161,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool case VSCP_DAEMON_VARIABLE_CODE_STRING: // Should we do a BASE64 conversion - if ( bBase64 ) { + if ( bBase64 ) { // TODO m_strValue = _(""); char *pbuf = new char[ wxBase64EncodedSize( strlen( strValue.mbc_str() ) ) + 1 ]; if ( NULL == pbuf ) return false; @@ -1113,7 +1169,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool wxBase64Encode( pbuf, wxBase64EncodedSize( strlen( strValue.mbc_str() ) ), (const char *)strValue.mbc_str(), - strlen( strValue.mbc_str() ) ); + strlen( strValue.mbc_str() ) ); if ( wxCONV_FAILED == len ) { delete [] pbuf; return false; @@ -1198,7 +1254,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1228,7 +1284,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1250,7 +1306,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1272,7 +1328,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1294,7 +1350,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1316,7 +1372,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1338,7 +1394,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1360,7 +1416,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1382,7 +1438,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1404,7 +1460,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1426,7 +1482,7 @@ bool CVSCPVariable::setValueFromString( int type, const wxString& strValue, bool // Should we do a BASE64 conversion if ( bBase64 ) { m_strValue = _(""); - char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; + char *pbuf = new char[ wxBase64EncodedSize( strValue.Length() ) ]; // TODO if ( NULL == pbuf ) return false; size_t len = wxBase64Encode( pbuf, wxBase64EncodedSize( strValue.Length() ), @@ -1476,8 +1532,8 @@ bool CVSCPVariable::getNote( wxString& strNote, bool bBase64 ) // bool CVSCPVariable::setVariableFromString( const wxString& strVariable, - bool bBase64, - const wxString& strUser ) + bool bBase64, + const wxString& strUser ) { wxString strRights; // User rights for variable bool bPersistent = false; // Persistence of variable @@ -1502,11 +1558,18 @@ bool CVSCPVariable::setVariableFromString( const wxString& strVariable, if ( tkz.HasMoreTokens() ) { wxString str = tkz.GetNextToken(); str.Trim(); - if ( str.Length() ) { - m_type = getVariableTypeFromString( str ); + if ( str.IsNumber() || + str.StartsWith(_("0x") ) || + str.StartsWith(_("0X") ) ) { + m_type = vscp_readStringValue( str ); } else { - m_type = getVariableTypeFromString( _("STRING") ); + if ( str.Length() ) { + m_type = getVariableTypeFromString( str ); + } + else { + m_type = getVariableTypeFromString( _("STRING") ); + } } } else { @@ -1585,15 +1648,8 @@ bool CVSCPVariable::setVariableFromString( const wxString& strVariable, wxString value = tkz.GetNextToken(); value.Trim(); - // If the string starts with "Base64" it should be encoded - if ( value.Upper().StartsWith( "BASE64:" ) ) { - value = value.Right( value.Length() - 7 ); - value.Trim(); - bBase64 = true; - } - if ( value.Length() ) { - setValueFromString( m_type, value, bBase64 ); + setValueFromString( m_type, value ); } else { // If no value given use RESET value @@ -1612,13 +1668,10 @@ bool CVSCPVariable::setVariableFromString( const wxString& strVariable, wxString note = tkz.GetNextToken(); // If the string starts with "Base64" it should be encoded - if ( note.Upper().StartsWith( "BASE64:" ) ) { - note = note.Right( note.Length() - 7 ); - note.Trim(); - bBase64 = true; - } + wxString str = note; + vscp_decodeBase64IfNeeded( str, note ); - setNote( note, bBase64 ); + setNote( note ); } @@ -1633,7 +1686,7 @@ bool CVSCPVariable::setVariableFromString( const wxString& strVariable, void CVSCPVariable::setValue( wxString value, bool bBase64 ) { if ( bBase64 ) { - m_strValue = wxBase64Encode( value, value.Length() ); + m_strValue = wxBase64Encode( value, value.Length() ); // // TODO } else { m_strValue = value; @@ -1648,7 +1701,7 @@ void CVSCPVariable::setNote( const wxString& strNote, bool bBase64 ) { wxString wxstr = strNote; if ( bBase64 ) { - wxstr = wxBase64Encode( strNote, strNote.Length() ); + wxstr = wxBase64Encode( strNote, strNote.Length() ); // TODO } m_note = wxstr; @@ -6773,7 +6826,7 @@ bool CVariableStorage::putStockVariable( CVSCPVariable& var, // can be used wxstr = var.getValue(); - size_t len = wxBase64Decode( NULL, 0, wxstr ); + size_t len = wxBase64Decode( NULL, 0, wxstr ); // TODO if ( 0 == len ) return false; uint8_t *pbuf = new uint8_t[len]; if ( NULL == pbuf ) return false; @@ -6791,7 +6844,7 @@ bool CVariableStorage::putStockVariable( CVSCPVariable& var, wxstr = var.getValue(); const char *p = wxstr.mbc_str(); - size_t len = wxBase64Decode( NULL, 0, wxstr ); + size_t len = wxBase64Decode( NULL, 0, wxstr ); // TODO if ( 0 == len ) return false; uint8_t *pbuf = new uint8_t[len]; if ( NULL == pbuf ) return false; @@ -6815,7 +6868,7 @@ bool CVariableStorage::putStockVariable( CVSCPVariable& var, // write wxstr = var.getValue(); - size_t len = wxBase64Decode( NULL, 0, wxstr ); + size_t len = wxBase64Decode( NULL, 0, wxstr ); // TODO if ( 0 == len ) return false; uint8_t *pbuf = new uint8_t[len]; if ( NULL == pbuf ) return false; @@ -7656,7 +7709,7 @@ bool CVariableStorage::loadFromXML( const wxString& path ) else if (subchild->GetName() == _("note-base64")) { wxstr = subchild->GetNodeContent(); - size_t len = wxBase64Decode( NULL, 0, wxstr ); + size_t len = wxBase64Decode( NULL, 0, wxstr ); // TODO if ( 0 == len ) return false; uint8_t *pbuf = new uint8_t[len]; if ( NULL == pbuf ) return false; diff --git a/src/vscp/common/remotevariable.h b/src/vscp/common/remotevariable.h index 822fb92ad..dd2ef1b29 100644 --- a/src/vscp/common/remotevariable.h +++ b/src/vscp/common/remotevariable.h @@ -115,16 +115,15 @@ class wxFFileOutputStream; "}" -#define VARIABLE_XML_TEMPLATE "\n"\ - "'%s'\n"\ - "%hu\n"\ - "%lu\n"\ - "%lu\n"\ - "%s\n"\ - "%s\n"\ - "%s\n"\ - "%s\n"\ -"" +#define VARIABLE_XML_TEMPLATE "" /* diff --git a/src/vscp/common/version.h b/src/vscp/common/version.h index a40ee09e2..ae45f36c1 100644 --- a/src/vscp/common/version.h +++ b/src/vscp/common/version.h @@ -35,9 +35,9 @@ #define VSCPD_MAJOR_VERSION 12 #define VSCPD_MINOR_VERSION 29 #define VSCPD_RELEASE_VERSION 2 -#define VSCPD_BUILD_VERSION 49 +#define VSCPD_BUILD_VERSION 51 -#define VSCPD_DISPLAY_VERSION "12.29.2.49 Magnesium (Development version)" +#define VSCPD_DISPLAY_VERSION "12.29.2.51 Magnesium (Development version)" #define VSCPD_COPYRIGHT "Copyright (C) 2000-2018, Grodans Paradis AB, http://www.paradiseofthefrog.com" #define VSCPD_COPYRIGHT_HTML "Copyright (C) 2000-2018, Paradise of the Frog, http://www.paradiseofthefrog.com" diff --git a/src/vscp/common/vscp.h b/src/vscp/common/vscp.h index 02760bb54..b188be0de 100644 --- a/src/vscp/common/vscp.h +++ b/src/vscp/common/vscp.h @@ -639,21 +639,21 @@ note: This is a note
"

" -#define VSCP_XML_FILTER_TEMPLATE "" #define VSCP_JSON_FILTER_TEMPLATE "{\n"\ - "\"mask_head\": %d,\n"\ + "\"mask_priority\": %d,\n"\ "\"mask_class\": %d,\n"\ "\"mask_type\": %d,\n"\ "\"mask_guid\": \"%s\",\n"\ - "\"filter_head\": %d,\n"\ + "\"filter_priority\": %d,\n"\ "\"filter_class\": %d,\n"\ "\"filter_type\": %d,\n"\ "\"filter_guid\": \"%s\",\n"\ diff --git a/src/vscp/common/vscphelper.cpp b/src/vscp/common/vscphelper.cpp index 29c2c5af4..3bd614d9a 100644 --- a/src/vscp/common/vscphelper.cpp +++ b/src/vscp/common/vscphelper.cpp @@ -466,14 +466,14 @@ bool vscp_getISOTimeString( char *buf, size_t buf_len, time_t *t ) /////////////////////////////////////////////////////////////////////////////// // vscp_toXMLEscape // -// Escape invalid XML characters for insert in XML file. +// Escape "invalid" XML characters for insert in XML file. // Note: Must be room in original buffer for result // -void vscp_toXMLEscape( char *temp_str ) +bool vscp_XML_Escape( const char *src, char *dst, size_t dst_len ) { - const char cEscapeChars[6]={'&','\'','\"','>','<','\0'}; - const char * const pEscapedSeqTable[] = + const char escapeCharTbl[ 6 ] = {'&','\'','\"','>','<','\0'}; + const char * const escapeSeqTbl[] = { "&", "'", @@ -484,33 +484,41 @@ void vscp_toXMLEscape( char *temp_str ) unsigned int i, j, k; unsigned int nRef = 0; - unsigned int nEscapeCharsLen = strlen( cEscapeChars ); - unsigned int str_len = strlen( temp_str ); + unsigned int nEscapeChars = strlen( escapeCharTbl ); + unsigned int str_len = strlen( src ); int nShifts = 0; - for ( i=0; i 0 ) { + if ( ( nShifts = strlen( escapeTable[ nRef ] ) - 1 ) > 0 ) { memmove( temp_str + i + nShifts, temp_str + i, str_len - i + nShifts ); for ( j=i, k=0; j<=i+nShifts, k<=nShifts; j++,k++ ) { - temp_str[ j ] = pEscapedSeqTable[ nRef ][ k ]; + temp_str[ j ] = escapeTable[ nRef ][ k ]; } str_len += nShifts; } } } - } + }*/ - temp_str[ str_len ] = '\0'; + dst[ str_len ] = '\0'; + + return true; } /////////////////////////////////////////////////////////////////////////////// @@ -3041,6 +3049,7 @@ bool vscp_convertJSONToEventEx( wxString& strJSON, vscpEventEx *pEventEx ) wxString dtStr = j.at("datetime").get(); wxDateTime dt; dt.ParseISOCombined( dtStr ); + vscp_setEventExDateTime( pEventEx, dt ); } @@ -3459,6 +3468,11 @@ bool vscp_setEventExDateTime( vscpEventEx *pEventEx, wxDateTime& dt ) { if ( NULL == pEventEx ) return false; + // If invalid date set to current + if ( !dt.IsValid() ) { + dt = wxDateTime::UNow(); + } + pEventEx->year = dt.GetYear(); pEventEx->month = dt.GetMonth() + 1; pEventEx->day = dt.GetDay(); @@ -3651,7 +3665,7 @@ bool vscp_readFilterFromString( vscpEventFilter *pFilter, // Get filter priority if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); - pFilter->filter_priority = vscp_readStringValue(strTok); + pFilter->filter_priority = vscp_readStringValue( strTok ); } else { return true; @@ -3660,7 +3674,7 @@ bool vscp_readFilterFromString( vscpEventFilter *pFilter, // Get filter class if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); - pFilter->filter_class = vscp_readStringValue(strTok); + pFilter->filter_class = vscp_readStringValue( strTok ); } else { return true; @@ -3669,7 +3683,7 @@ bool vscp_readFilterFromString( vscpEventFilter *pFilter, // Get filter type if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); - pFilter->filter_type = vscp_readStringValue(strTok); + pFilter->filter_type = vscp_readStringValue( strTok ); } else { return true; @@ -3726,7 +3740,7 @@ bool vscp_readMaskFromString(vscpEventFilter *pFilter, const wxString& strMask) wxStringTokenizer tkz( strMask, _(",")); - // Get filter priority + // Get mask priority if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); pFilter->mask_priority = vscp_readStringValue(strTok); @@ -3735,7 +3749,7 @@ bool vscp_readMaskFromString(vscpEventFilter *pFilter, const wxString& strMask) return true; } - // Get filter class + // Get mask class if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); pFilter->mask_class = vscp_readStringValue(strTok); @@ -3744,7 +3758,7 @@ bool vscp_readMaskFromString(vscpEventFilter *pFilter, const wxString& strMask) return true; } - // Get filter type + // Get mask type if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); pFilter->mask_type = vscp_readStringValue(strTok); @@ -3753,7 +3767,7 @@ bool vscp_readMaskFromString(vscpEventFilter *pFilter, const wxString& strMask) return true; } - // Get filter GUID + // Get mask GUID if (tkz.HasMoreTokens()) { strTok = tkz.GetNextToken(); vscp_getGuidFromStringToArray(pFilter->mask_GUID, @@ -3786,6 +3800,94 @@ bool vscp_writeMaskToString( const vscpEventFilter *pFilter, return true; } +////////////////////////////////////////////////////////////////////////////// +// vscp_readFilterMaskFromString +// + +bool vscp_readFilterMaskFromString( vscpEventFilter *pFilter, + const wxString& strFilterMask ) +{ + wxString strTok; + + // Check pointer + if (NULL == pFilter) return false; + + // Clear filter and mask + vscp_clearVSCPFilter( pFilter ); + + wxStringTokenizer tkz(strFilterMask, _(",")); + + // Get filter priority + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->filter_priority = vscp_readStringValue( strTok ); + } + else { + return true; + } + + // Get filter class + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->filter_class = vscp_readStringValue( strTok ); + } + else { + return true; + } + + // Get filter type + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->filter_type = vscp_readStringValue( strTok ); + } + else { + return true; + } + + // Get filter GUID + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + vscp_getGuidFromStringToArray(pFilter->filter_GUID, + strTok); + } + + // Get mask priority + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->mask_priority = vscp_readStringValue(strTok); + } + else { + return true; + } + + // Get mask class + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->mask_class = vscp_readStringValue(strTok); + } + else { + return true; + } + + // Get mask type + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + pFilter->mask_type = vscp_readStringValue(strTok); + } + else { + return true; + } + + // Get mask GUID + if (tkz.HasMoreTokens()) { + strTok = tkz.GetNextToken(); + vscp_getGuidFromStringToArray(pFilter->mask_GUID, + strTok); + } + + return true; +} + ////////////////////////////////////////////////////////////////////////////// // vscp_readFilterMaskFromXML // @@ -3910,7 +4012,7 @@ bool vscp_readFilterMaskFromJSON( vscpEventFilter *pFilter, const wxString& strF // mask priority if (j.find("mask_priority") != j.end()) { - pFilter->filter_priority = j.at("mask_priority").get(); + pFilter->mask_priority = j.at("mask_priority").get(); } // mask_class @@ -4486,9 +4588,9 @@ bool vscp_setVscpEventFromString(vscpEvent *pEvent, const wxString& strEvent) wxStringTokenizer tkz(str, _(",")); // Get head - if (tkz.HasMoreTokens()) { + if ( tkz.HasMoreTokens() ) { str = tkz.GetNextToken(); - pEvent->head = vscp_readStringValue(str); + pEvent->head = vscp_readStringValue( str ); } else { return false; @@ -4514,9 +4616,9 @@ bool vscp_setVscpEventFromString(vscpEvent *pEvent, const wxString& strEvent) } // Get OBID - Kept here to be compatible with receive - if (tkz.HasMoreTokens()) { + if ( tkz.HasMoreTokens() ) { str = tkz.GetNextToken(); - pEvent->obid = vscp_readStringValue(str); + pEvent->obid = vscp_readStringValue( str ); } else { return false; @@ -4611,7 +4713,7 @@ bool vscp_setVscpEventExFromString( vscpEventEx *pEventEx, vscpEvent event; // Parse the string data - rv = vscp_setVscpEventFromString(&event, strEvent); + rv = vscp_setVscpEventFromString( &event, strEvent ); vscp_convertVSCPtoEx(pEventEx, &event); // Remove possible data diff --git a/src/vscp/common/vscphelper.h b/src/vscp/common/vscphelper.h index 01a4d81c6..28f65cfb3 100644 --- a/src/vscp/common/vscphelper.h +++ b/src/vscp/common/vscphelper.h @@ -205,7 +205,7 @@ extern "C" { /*! Get ISO GMT datetime */ - bool vscp_getISOTimeString( char *buf, size_t buf_len, time_t *t ); + bool vscp_getISOTimeString( char *buf, size_t buf_len, time_t *t ); /*! @@ -214,7 +214,7 @@ extern "C" { * @param Buffer holding input string. Buffer size must be large enough to * hold expanded result. */ - void vscp_toXMLEscape( char *temp_str ); + bool vscp_XML_Escape( const char *src, char *dst, size_t dst_len ); /*! @@ -1040,6 +1040,17 @@ extern "C" { bool vscp_writeMaskToString( const vscpEventFilter *pFilter, wxString& strFilter); + /*! + * Read both filter and mask from string + * + * @param pFilter Pointer to VSCP filter structure which will receive filter + * mask data. + * @param strFilter Filter and mask in comma separated list + * @return true on success, false on failure. + */ + bool vscp_readFilterMaskFromString( vscpEventFilter *pFilter, + const wxString& strFilterMask); + /*! * Read filter from XML coded string * diff --git a/src/vscp/common/vscpremotetcpif.cpp b/src/vscp/common/vscpremotetcpif.cpp index 8818937d4..5825cf01d 100644 --- a/src/vscp/common/vscpremotetcpif.cpp +++ b/src/vscp/common/vscpremotetcpif.cpp @@ -524,7 +524,7 @@ int VscpRemoteTcpIf::doCmdOpen( const wxString& strHostname, int rv; if ( wxSEMA_NO_ERROR != - ( rv = m_semConnected.WaitTimeout( 10/*3000*/ * (m_responseTimeOut + 1 ) ) ) ) { + ( rv = m_semConnected.WaitTimeout( 10 * (m_responseTimeOut + 1 ) ) ) ) { m_pClientTcpIpWorkerThread->m_bRun = false; #ifdef DEBUG_LIB_VSCP_HELPER wxString wxlog = wxString::Format(_("Connection failed: Code=%d - "), rv); diff --git a/src/vscp/common/vscpremotetcpif.h b/src/vscp/common/vscpremotetcpif.h index 871d62f4f..0c1b133ae 100644 --- a/src/vscp/common/vscpremotetcpif.h +++ b/src/vscp/common/vscpremotetcpif.h @@ -57,7 +57,7 @@ Default response timeout for communication with the tcp/ip interface of the daemon in seconds */ -#define TCPIP_DEFAULT_RESPONSE_TIMEOUT 1000 +#define TCPIP_DEFAULT_RESPONSE_TIMEOUT 2000 #define TCPIP_DEFAULT_AFTER_COMMAND_SLEEP 0 @@ -71,7 +71,7 @@ @def TCPIP_DLL_VERSION Pseudo version string */ -#define TCPIP_DLL_VERSION 0x0000000B +#define TCPIP_DLL_VERSION 0x0000000C /*! @def TCPIP_VENDOR_STRING Pseudo vendor string diff --git a/tests/dm/lua/dm-enteries.xml b/tests/dm/lua/dm-enteries.xml index 74dd89e6c..622b0001a 100644 --- a/tests/dm/lua/dm-enteries.xml +++ b/tests/dm/lua/dm-enteries.xml @@ -177,3 +177,911 @@ -------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + Create string variable from XML string + + + + + + + 0x100 + +local str + +-- Create two string variables +vscp.writevariable('aaaaaaaaaa;0x01;false;0;0x777;VGhpcyBpcyBhIHRlc3QgdmFyaWFibGU=;VGhpcyBpcyBhIG5vdGU=') +vscp.writevariable('bbbbbbbbbb;0x01;false;0;0x777;BASE64:This is a test;BASE64:Supertest') + +-- Create variable from XML +str = '<variable \ + name="cccccccccccccccccc" \ + type="1" \ + user="0"\ + access-rights="0x777" \ + persistence="false" \ + value="This is a test" \ + note="test" />' +vscp.writevariable(str,1) + +-- Create floating point variable +vscp.writevariable('ddddddd;flot;false;0;0x777;3.14;BASE64:Important constant') + + + + + + * + * + * + * + + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + Create string variable from JSON string + + + + + + + 0x100 + +local str + +-- Create string variable from JSON +str = '{ \ + "name": "test_json", \ + "type": 1, \ + "user": 0, \ + "accessrights": 1920, \ + "persistence": false, \ + "value": "This is a JSON test", \ + "note": "Just a comment"\ +}' +vscp.print( "JSON str = ", str ) + +vscp.writevariable(str,2) + + + + + + * + * + * + * + + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Create ineteger variable from JSON string + + + + + + + 0x100 + +local str + +-- Create integer variable from JSON +str = '{ \ + "name": "testint", \ + "type": 3, \ + "user": 0, \ + "accessrights": 1920, \ + "persistence": false, \ + "value": 1000, \ + "note": "This is an integer with intial value set to 1000"\ +}' +vscp.print( "JSON str = ", str ) + +vscp.writevariable(str,2) + + + + * + * + * + * + + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Create string variable from string + + + + + + + 0x100 + +local str + +-- Create integer variable from JSON +str = '{ \ + "name": "testint", \ + "type": 3, \ + "user": 0, \ + "accessrights": 1920, \ + "persistence": false, \ + "value": 1000, \ + "note": "This is an integer with intial value set to 1000"\ +}' +vscp.print( "JSON str = ", str ) + +vscp.writevariable(str,2) + + + + * + * + * + * + + + + + + + + + Add one to integer variable + + + + + + + 0x100 + +local val + +-- Read integer value +val = vscp.readvariable("testint",3) +vscp.print("value =", val ) +val = val + 1; +vscp.writevariable("testint",3,val) + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send VSCP event from string + + + + + + + 0x100 + +local strevent + +-- Create string event +strevent = "0,10,6,,,,,0x8A,0x81,0,0xca" + +vscp.sendevent(strevent) +vscp.log("Event sent from Lua script.") + + + + * + * + * + * + + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send VSCP event from XML string + + + + + + + 0x100 + +local strevent + +-- Create string event +strevent = '<event \ + head="0" \ + obid="0" \ + timestamp="0" \ + class="10" \ + type="6" \ + guid="-" \ + data="0x8A,0x81,0,0xca" />' + +vscp.sendevent(strevent,1) +vscp.log("XML event successfully sent from Lua script.") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send VSCP event from JSON string + + + + + + + 0x100 + +local strevent + +-- Create string event +strevent = '{ \ + "head": 0, \ + "obid": 0, \ + "datetime": "20161102T190032", \ + "timestamp": 0, \ + "class": 10, \ + "type": 6, \ + "guid": "-", \ + "data": [138,129,0,202] \ +}' + +vscp.sendevent(strevent,2) +vscp.log("JSON event successfully sent from Lua script.") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send VSCP event from JSON string + + + + + + + 0x100 + +local event +local bQuit = false + +vscp.log("Waiting for VSCP event") + +-- Keep looking until event is available +while not bQuit do + + -- Fetch event from client queue + event = vscp.receiveevent() + + if event then + + vscp.log("VSCP event received. Event = " .. event ) + bQuit = true + + else + vscp.sleep( 500 ) + end +end + +vscp.log("Done!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Check client queue for number of events waiting + + + + + + + 0x100 + +local cnt + +for i=0,10 do + cnt = vscp.countevent() + vscp.log("Count = " .. cnt ) + vscp.sleep( 1000 ) +end + +vscp.log("Done!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Set filter from string + + + + + + + 0x100 + +local filter + +filter="0,10,0,-,0,0xffff,0,-" +vscp.setfilter( filter ) +vscp.log("Done!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Set filter from XML + + + + + + + 0x100 + +local filter + +filter='<filter mask_priority="0"\ + mask_class="65535"\ + mask_type="0"\ + mask_guid="-"\ + filter_priority="0"\ + filter_class="10"\ + filter_type="0"\ + filter_guid="-" />' +vscp.setfilter( filter, 1 ) +vscp.log("Done!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Set filter from JSON + + + + + + + 0x100 + +-- Allow only CLASS1.MEASUREMENT events, from all, +-- with all priorities +local filter = '{\ + "mask_priority": 0,\ + "mask_class": 65535,\ + "mask_type": 0,\ + "mask_guid": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",\ + "filter_priority": 0,\ + "filter_class": 10,\ + "filter_type": 0,\ + "filter_guid": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"\ +}' + +-- Set the filter +vscp.setfilter( filter,2 ) +vscp_log("Filter set successfully!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send measurement (Level I, Temp) + + + + + + + 0x100 + +-- Send a measurement +-- Level 1, temperature, floating point value + + +-- Send the measurement +vscp.sendmeasurement( 1, false, 123.5, "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00", 6, 1 ) +vscp.log("Sent measurement event successfully!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Send measurement (Level II, Force) + + + + + + + 0x100 + +-- Send a measurement +-- Level II, force, string + + +-- Send the meaurement +vscp.sendmeasurement( 2, true, 0.678956 , "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00", 11, 0 ) +vscp.log("Sent measurement event successfully!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + Check if event is a measurement + + + + + + + 0x100 + + +vscp.log("Sent measurement event successfully!\n") + + + + * + * + * + * + + + + + + + +-------------------------------------------------------------------------------------------------------------------------- + + +==== Example ==== + + +// The JSON text CLASS1.MEASUREMENTL, Type= Temperature,6 sensorindex=0, unit=1 (Celsius) +// 45.464 degrees Celsius +var eventTxt = "{ 'class': 10, 'type': 6, 'data': [0x48,0x34,0x35,0x2E,0x34,0x36,0x34] }"; + +// Make the JSON object +var event = JSON.parse( eventTxt ); + +if ( null != ( value = vscp_getMeasurementValue( event ) ) ) { + vscp_log("Measurement event sent successfully! value = " + value.toString() + "\n"); +} +else { + vscp_log("This is not a measurement event!\n"); +} + + +----------------------------------------- + + +==== Example ==== + +Will output Unit = 1. + + +// The JSON text CLASS1.MEASUREMENTL, Type= Temperature,6 sensorindex=1, unit=1 (Celsius) +// 45.464 degrees Celsius +var eventTxt = "{ 'class': 10, 'type': 6, 'data': [0x49,0x34,0x35,0x2E,0x34,0x36,0x34] }"; + +// Make the JSON object +var event = JSON.parse( eventTxt ); + +vscp_log("Unit = " + vscp_getMeasurementUnit( event ).toString() + "\n"); + + + +------------------------------------------ + +==== Example ==== + +Will output sensorindex = 1. + + +// The JSON text CLASS1.MEASUREMENTL, Type= Temperature,6 sensorindex=1, unit=1 (Celsius) +// 45.464 degrees Celsius +var eventTxt = "{ \"class\": 10, \"type\": 6, \"data\": [0x49,0x34,0x35,0x2E,0x34,0x36,0x34] }"; + +// Make the JSON object +var event = JSON.parse( eventTxt ); + +vscp_log("Sensor index = " + vscp_getMeasurementSensorIndex( event ).toString() + "\n"); + + + +-------------------------------------------- + + +==== Example ==== + +Will output Zone = 0. + + +// The JSON text CLASS1.MEASUREMENTL, Type= Temperature,6 sensorindex=1, unit=1 (Celsius) +// 45.464 degrees Celsius +var eventTxt = "{ \"class\": 10, \"type\": 6, \"data\": [0x49,0x34,0x35,0x2E,0x34,0x36,0x34] }"; + +// Make the JSON object +var event = JSON.parse( eventTxt ); + +vscp_log("Zone = " + vscp.getmeasurementzone( event ).toString() + "\n"); + + + +--------------------------------------------- + + +==== Example ==== + +Will output Subzone = 0. + + +// The JSON text CLASS1.MEASUREMENTL, Type= Temperature,6 sensorindex=1, unit=1 (Celsius) +// 45.464 degrees Celsius +var eventTxt = "{ \"class\": 10, \"type\": 6, \"data\": [0x49,0x34,0x35,0x2E,0x34,0x36,0x34] }"; + +// Make the JSON object +var event = JSON.parse( eventTxt ); + +vscp_log("Subzone = " + vscp_getMeasurementSubZone( event ).toString() + "\n"); + + + + + + +