diff --git a/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp b/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp index 50b52b8..064783b 100644 --- a/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp +++ b/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp @@ -21,9 +21,9 @@ DeviceProxyWrapper::DeviceProxyWrapper(const char* name) Tango::CommandInfoList* cmdlist = dev->command_list_query(); for(int i = 0; i < attrlist->size(); i++) - attr_cache[(*attrlist)[i].name] = (*attrlist)[i]; + attr_info[(*attrlist)[i].name] = (*attrlist)[i]; for(int i = 0; i < cmdlist->size(); i++) - cmd_cache[(*cmdlist)[i].cmd_name] = (*cmdlist)[i]; + cmd_info[(*cmdlist)[i].cmd_name] = (*cmdlist)[i]; delete attrlist; delete cmdlist; @@ -34,26 +34,6 @@ DeviceProxyWrapper::~DeviceProxyWrapper() delete dev; } -int DeviceProxyWrapper::attr_type(const char* name) -{ - return attr_cache[name].data_type; -} - -Tango::AttrDataFormat DeviceProxyWrapper::attr_format(const char* name) -{ - return attr_cache[name].data_format; -} - -int DeviceProxyWrapper::cmd_in_type(const char* name) -{ - return cmd_cache[name].in_type; -} - -int DeviceProxyWrapper::cmd_out_type(const char* name) -{ - return cmd_cache[name].out_type; -} - // COMMAND WRAPPER ------------------------------------------------------------ int __cmd_wrapper(lua_State* L) { @@ -64,13 +44,12 @@ int __cmd_wrapper(lua_State* L) LUT_LOG(TRACE, "Running command wrapper %s", full_name.c_str()); + int in_type = udata->cmd_info[cmd_name].in_type; + int out_type = udata->cmd_info[cmd_name].out_type; + LUT_LOG(TRACE, "Command: %s in:%d out:%d", full_name.c_str(), in_type, out_type); + try { - int in_type = udata->cmd_in_type(cmd_name); - int out_type = udata->cmd_out_type(cmd_name); - - LUT_LOG(TRACE, "Command: %s in:%d out:%d", full_name.c_str(), in_type, out_type); - Tango::DeviceData in = lut_toTangoType(L, 1, in_type); Tango::DeviceData out = udata->dev->command_inout(cmd_name, in); lut_fromTangoType(L, out, out_type); @@ -125,6 +104,41 @@ int lut_DeviceProxy_get_attribute_list(lua_State* L) return 1; } +int lut_DeviceProxy_get_attribute_config(lua_State* L) +{ + LUT_LOG(TRACE, "TANGO API DeviceProxy:get_attribute_config()"); + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); + const char* name = luaL_checkstring(L, 3); // arg[2] is Lua "self" + std::string dev_name = udata->dev->dev_name(); + std::string full_name = build_name(dev_name, name); + + if(udata->attr_info.find(name) == udata->attr_info.end()) + { + LUT_LOG(ERROR, "Attribute %s not found!", full_name.c_str()); + lua_pushnil(L); + } + else + lut_AttributeInfo(L, udata->attr_info[name]); + + return 1; +} + +int lut_DeviceProxy_attribute_list_query(lua_State* L) +{ + LUT_LOG(TRACE, "TANGO API DeviceProxy:attribute_list_query()"); + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); + + lua_newtable(L); + int top = lua_gettop(L); + for(AttrInfoMap::iterator i = udata->attr_info.begin(); i != udata->attr_info.end(); i++) + { + lut_AttributeInfo(L, i->second); + lua_setfield(L, top, i->first.c_str()); + } + + return 1; +} + int lut_DeviceProxy_get_command_list(lua_State* L) { LUT_LOG(TRACE, "TANGO API DeviceProxy:get_command_list()"); @@ -150,6 +164,41 @@ int lut_DeviceProxy_get_command_list(lua_State* L) return 1; } +int lut_DeviceProxy_get_command_config(lua_State* L) +{ + LUT_LOG(TRACE, "TANGO API DeviceProxy:get_command_config()"); + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); + const char* name = luaL_checkstring(L, 3); // arg[2] is Lua "self" + std::string dev_name = udata->dev->dev_name(); + std::string full_name = build_name(dev_name, name); + + if(udata->cmd_info.find(name) == udata->cmd_info.end()) + { + LUT_LOG(ERROR, "Command %s not found!", full_name.c_str()); + lua_pushnil(L); + } + else + lut_CommandInfo(L, udata->cmd_info[name]); + + return 1; +} + +int lut_DeviceProxy_command_list_query(lua_State* L) +{ + LUT_LOG(TRACE, "TANGO API DeviceProxy:command_list_query()"); + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); + + lua_newtable(L); + int top = lua_gettop(L); + for(CmdInfoMap::iterator i = udata->cmd_info.begin(); i != udata->cmd_info.end(); i++) + { + lut_CommandInfo(L, i->second); + lua_setfield(L, top, i->first.c_str()); + } + + return 1; +} + // LUA API -------------------------------------------------------------------- void lut_lua_register_DeviceProxy(lua_State* L) { @@ -204,33 +253,35 @@ int lut_DeviceProxy_index(lua_State* L) LUT_LOG(TRACE, "LUA API DeviceProxy(%s):index(%s)", dev_name.c_str(), name); - try + if(udata->cmd_info.find(name) != udata->cmd_info.end()) { - std::vector* cmdlist = udata->dev->get_command_list(); - - if(std::count(cmdlist->begin(), cmdlist->end(), name)) + // index is a command, push wrapper closure + // commands are supposed to be called, to allow this + // command "read" returns a function closure + lua_pushlightuserdata(L, udata); + lua_pushstring(L, name); + lua_pushcclosure(L, __cmd_wrapper, 2); + } + else if(udata->attr_info.find(name) != udata->attr_info.end()) + { + // index is an attribute + try { - // index is a command, push wrapper closure - // commands are supposed to be called, to allow this - // command "read" returns a function closure - lua_pushlightuserdata(L, udata); - lua_pushstring(L, name); - lua_pushcclosure(L, __cmd_wrapper, 2); - } - else - { - // index is an attribute LUT_LOG(TRACE, "Reading attribute %s", full_name.c_str()); Tango::DeviceAttribute attr = udata->dev->read_attribute(name); lut_fromTangoType(L, attr, attr.get_type(), attr.get_data_format()); } - delete cmdlist; + catch(Tango::DevFailed e) + { + lut_DevFailed(L, e, full_name.c_str()); + } } - catch(Tango::DevFailed e) + else { - lut_DevFailed(L, e, full_name.c_str()); + LUT_LOG(ERROR, "%s is neither command nor attribute!", full_name.c_str()); + lua_pushnil(L); } - + return 1; } @@ -244,24 +295,20 @@ int lut_DeviceProxy_newindex(lua_State* L) LUT_LOG(TRACE, "LUA API DeviceProxy(%s):newindex(%s)", dev_name.c_str(), attr_name); - try + if(udata->attr_info.find(attr_name) == udata->attr_info.end()) + LUT_LOG(ERROR, "Not an attribute: %s!", full_name.c_str()); + else { - std::vector* attrlist = udata->dev->get_attribute_list(); - - if(!std::count(attrlist->begin(), attrlist->end(), attr_name)) + try { - // name is not an attribute - LUT_LOG(ERROR, "Not an attribute: %s", full_name.c_str()); - return 0; + Tango::DeviceAttribute v = lut_toTangoType(L, 3, udata->attr_info[attr_name].data_type, udata->attr_info[attr_name].data_format); + v.set_name(attr_name); + udata->dev->write_attribute(v); + } + catch(Tango::DevFailed e) + { + lut_DevFailed(L, e, full_name.c_str()); } - - Tango::DeviceAttribute v = lut_toTangoType(L, 3, udata->attr_type(attr_name), udata->attr_format(attr_name)); - v.set_name(attr_name); - udata->dev->write_attribute(v); - } - catch(Tango::DevFailed e) - { - lut_DevFailed(L, e, full_name.c_str()); } return 0; diff --git a/src/core/tango/DeviceProxy/lut_DeviceProxy.h b/src/core/tango/DeviceProxy/lut_DeviceProxy.h index 19eebd2..f424c32 100644 --- a/src/core/tango/DeviceProxy/lut_DeviceProxy.h +++ b/src/core/tango/DeviceProxy/lut_DeviceProxy.h @@ -26,6 +26,7 @@ #include #include +#include #include #define LUT_DEVICEPROXY "lut_DeviceProxy" @@ -35,18 +36,11 @@ class DeviceProxyWrapper { public: Tango::DeviceProxy* dev; + AttrInfoMap attr_info; + CmdInfoMap cmd_info; DeviceProxyWrapper(const char* name); ~DeviceProxyWrapper(); - - int attr_type(const char* name); - Tango::AttrDataFormat attr_format(const char* name); - int cmd_in_type(const char* name); - int cmd_out_type(const char* name); - - private: - AttrInfoMap attr_cache; - CmdInfoMap cmd_cache; }; // Command wrapper @@ -55,7 +49,11 @@ int __cmd_wrapper(lua_State* L); // Tango API int lut_DeviceProxy_status(lua_State* L); int lut_DeviceProxy_get_attribute_list(lua_State* L); +int lut_DeviceProxy_get_attribute_config(lua_State* L); +int lut_DeviceProxy_attribute_list_query(lua_State* L); int lut_DeviceProxy_get_command_list(lua_State* L); +int lut_DeviceProxy_get_command_config(lua_State* L); +int lut_DeviceProxy_command_list_query(lua_State* L); // Lua API void lut_lua_register_DeviceProxy(lua_State* L); @@ -74,7 +72,11 @@ static const luaL_Reg lut_DeviceProxy[] = // Tango API { "status", lut_DeviceProxy_status }, { "get_attribute_list", lut_DeviceProxy_get_attribute_list }, + { "get_attribute_config", lut_DeviceProxy_get_attribute_config }, + { "attribute_list_query", lut_DeviceProxy_attribute_list_query }, { "get_command_list", lut_DeviceProxy_get_command_list }, + { "get_command_config", lut_DeviceProxy_get_command_config }, + { "command_list_query", lut_DeviceProxy_command_list_query }, { NULL, NULL } }; diff --git a/tests/_print_kv.lua b/tests/_print_kv.lua new file mode 100644 index 0000000..c97c842 --- /dev/null +++ b/tests/_print_kv.lua @@ -0,0 +1,27 @@ +------------------------------------------------------------------------------- +-- +-- luTango - Lua binding for Tango +-- +-- Copyright (C) 2023 Grzegorz Kowalski +-- See LICENSE for legal information +-- +-- file: _print_kv.lua +-- +-- Nested table printing utility +-- +------------------------------------------------------------------------------- + +local function print_kv(k, v, prefix) + prefix = prefix or "" + print(prefix..tostring(k)..": "..tostring(v)) + if type(v) == "table" then + for kk,vv in ipairs(v) do + print_kv(kk, vv, prefix.."\t") + end + for kk,vv in pairs(v) do + print_kv(kk, vv, prefix.."\t") + end + end +end + +return print_kv diff --git a/tests/attributeproxy.lua b/tests/attributeproxy.lua index 12ed98d..2c2c791 100644 --- a/tests/attributeproxy.lua +++ b/tests/attributeproxy.lua @@ -12,21 +12,9 @@ ------------------------------------------------------------------------------- local lut = require "lutango" +local print_kv = require "_print_kv" lut.log:set_log_level(lut.log.level.WARNING) -local function print_kv(k, v, prefix) - prefix = prefix or "" - print(prefix..k..": "..tostring(v)) - if type(v) == "table" then - for kk,vv in ipairs(v) do - print_kv(kk, vv, prefix.."\t") - end - for kk,vv in pairs(v) do - print_kv(kk, vv, prefix.."\t") - end - end -end - local ap = lut.AttributeProxy("sys/tg_test/1/ampli") print("Reading state and status") diff --git a/tests/dp_info.lua b/tests/dp_info.lua new file mode 100644 index 0000000..84de739 --- /dev/null +++ b/tests/dp_info.lua @@ -0,0 +1,49 @@ +------------------------------------------------------------------------------- +-- +-- luTango - Lua binding for Tango +-- +-- Copyright (C) 2023 Grzegorz Kowalski +-- See LICENSE for legal information +-- +-- file: dp_info.lua +-- +-- Test script for attribute and command info +-- +------------------------------------------------------------------------------- + +local lut = require "lutango" +local print_kv = require "_print_kv" +lut.log:set_log_level(lut.log.level.WARNING) + +local dp = lut.DeviceProxy(arg[1] or "sys/tg_test/1") + +print("Get full lists:") +local ai_list = dp:attribute_list_query() +for k,v in pairs(ai_list) do + print_kv(k, v) +end + +local ci_list = dp:command_list_query() +for k,v in pairs(ci_list) do + print_kv(k, v) +end + +print("\nGet single attr:") +local ai = dp:get_attribute_config("double_spectrum_ro") +for k,v in pairs(ai) do + print_kv(k, v) +end + +print("\nGet single command:") +local ci = dp:get_command_config("DevLong64") +for k,v in pairs(ci) do + print_kv(k, v) +end + +print("\nGet non-existent attr:") +local non_ai = dp:get_attribute_config("non_existent_attr") +print(tostring(non_ai)) + +print("\nGet non-existent command:") +local non_ci = dp:get_command_config("NonExistentCommand") +print(tostring(non_ci)) diff --git a/tests/read_attrs.lua b/tests/read_attrs.lua index defdc56..7a65ab4 100644 --- a/tests/read_attrs.lua +++ b/tests/read_attrs.lua @@ -30,3 +30,7 @@ for _,v in ipairs(attrlist) do end print() end + +print("\nReading non existent attribute") +local ne = dp.non_existent_attr +print(tostring(ne)) diff --git a/tests/run_cmds.lua b/tests/run_cmds.lua index d9baba0..0e91af2 100644 --- a/tests/run_cmds.lua +++ b/tests/run_cmds.lua @@ -74,3 +74,7 @@ run_array_cmd("DevVarStringArray", {"hello", "world", "from", "Lua"}) run_array_cmd("DevVarULong64Array", {11111111111, 22222222222, 33333333333}) run_array_cmd("DevVarULongArray", {11111111111, 22222222222, 33333333333}) run_array_cmd("DevVarUShortArray", {1111, 2222, 3333}) + +print("\nRunning non-existent command:") +local ok, ret = pcall(dp.NonExistentCmd) +print("ok="..tostring(ok).." ret="..tostring(ret))