forked from daneos/lutango
add error handling
This commit is contained in:
parent
a93c8292f1
commit
69143b963b
55
src/core/tango/DevFailed/lut_DevFailed.cpp
Normal file
55
src/core/tango/DevFailed/lut_DevFailed.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "lut_DevFailed.h"
|
||||
|
||||
int lut_DevFailed(lua_State* L, Tango::DevFailed e, const char* source)
|
||||
{
|
||||
int nerr = e.errors.length();
|
||||
lua_createtable(L, nerr, 1);
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_pushstring(L, source);
|
||||
lua_setfield(L, -2, "source");
|
||||
|
||||
for(int i = 0; i < nerr; i++)
|
||||
{
|
||||
lua_pushnumber(L, i+1);
|
||||
lua_createtable(L, 0, 4);
|
||||
|
||||
lua_pushstring(L, severity_str(e.errors[i].severity));
|
||||
lua_setfield(L, -2, "severity");
|
||||
|
||||
lua_pushstring(L, e.errors[i].reason);
|
||||
lua_setfield(L, -2, "reason");
|
||||
|
||||
lua_pushstring(L, e.errors[i].desc);
|
||||
lua_setfield(L, -2, "desc");
|
||||
|
||||
lua_pushstring(L, e.errors[i].origin);
|
||||
lua_setfield(L, -2, "origin");
|
||||
|
||||
lua_settable(L, top);
|
||||
}
|
||||
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
const char* severity_str(Tango::ErrSeverity s)
|
||||
{
|
||||
switch(s)
|
||||
{
|
||||
case Tango::WARN:
|
||||
return "WARNING";
|
||||
break;
|
||||
|
||||
case Tango::ERR:
|
||||
return "ERROR";
|
||||
break;
|
||||
|
||||
case Tango::PANIC:
|
||||
return "PANIC";
|
||||
break;
|
||||
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
10
src/core/tango/DevFailed/lut_DevFailed.h
Normal file
10
src/core/tango/DevFailed/lut_DevFailed.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __LUT_DEVFAILED_H__
|
||||
# define __LUT_DEVFAILED_H__
|
||||
|
||||
#include <core/tango.h>
|
||||
#include <core/lua.h>
|
||||
|
||||
int lut_DevFailed(lua_State* L, Tango::DevFailed e, const char* source);
|
||||
const char* severity_str(Tango::ErrSeverity s);
|
||||
|
||||
#endif /* __LUT_DEVFAILED_H__ */
|
||||
@ -15,22 +15,32 @@ DeviceProxyWrapper::~DeviceProxyWrapper()
|
||||
int cmd_wrapper(lua_State* L)
|
||||
{
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lua_touserdata(L, lua_upvalueindex(1));
|
||||
const char* name = lua_tostring(L, lua_upvalueindex(2));
|
||||
LUT_LOG(TRACE, "Running command wrapper %s/%s()", udata->dev->name().c_str(), name);
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
const char* cmd_name = lua_tostring(L, lua_upvalueindex(2));
|
||||
std::string full_name = build_name(dev_name, cmd_name, true);
|
||||
|
||||
if(udata->cmd_info.find(name) == udata->cmd_info.end())
|
||||
LUT_LOG(TRACE, "Running command wrapper %s", full_name.c_str());
|
||||
|
||||
try
|
||||
{
|
||||
LUT_LOG(TRACE, "Command info for %s doesn't exist, fetching first", name);
|
||||
udata->cmd_info[name] = udata->dev->get_command_config(name);
|
||||
if(udata->cmd_info.find(cmd_name) == udata->cmd_info.end())
|
||||
{
|
||||
LUT_LOG(TRACE, "Command info for %s doesn't exist, fetching first", full_name.c_str());
|
||||
udata->cmd_info[cmd_name] = udata->dev->get_command_config(cmd_name);
|
||||
}
|
||||
long in_type = udata->cmd_info[cmd_name].in_type;
|
||||
long 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);
|
||||
|
||||
Tango::DeviceData in = pack_cmd_data(L, 1, in_type);
|
||||
Tango::DeviceData out = udata->dev->command_inout(cmd_name, in);
|
||||
unpack_cmd_data(L, out, out_type);
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
lut_DevFailed(L, e, full_name.c_str());
|
||||
}
|
||||
long in_type = udata->cmd_info[name].in_type;
|
||||
long out_type = udata->cmd_info[name].out_type;
|
||||
|
||||
LUT_LOG(TRACE, "Command: %s in:%d out:%d", name, in_type, out_type);
|
||||
|
||||
Tango::DeviceData in = pack_cmd_data(L, 1, in_type);
|
||||
Tango::DeviceData out = udata->dev->command_inout(name, in);
|
||||
unpack_cmd_data(L, out, out_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -39,7 +49,17 @@ int lut_DeviceProxy_status(lua_State* L)
|
||||
{
|
||||
LUT_LOG(TRACE, "TANGO API DeviceProxy:status()");
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
lua_pushstring(L, udata->dev->status().c_str());
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
|
||||
try
|
||||
{
|
||||
lua_pushstring(L, udata->dev->status().c_str());
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
lut_DevFailed(L, e, dev_name.c_str());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -47,14 +67,23 @@ int lut_DeviceProxy_get_attribute_list(lua_State* L)
|
||||
{
|
||||
LUT_LOG(TRACE, "TANGO API DeviceProxy:get_attribute_list()");
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
std::vector<std::string>* attrlist = udata->dev->get_attribute_list();
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < attrlist->size(); i++)
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
|
||||
try
|
||||
{
|
||||
lua_pushstring(L, (*attrlist)[i].c_str());
|
||||
lua_rawseti(L, -2, i+1);
|
||||
std::vector<std::string>* attrlist = udata->dev->get_attribute_list();
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < attrlist->size(); i++)
|
||||
{
|
||||
lua_pushstring(L, (*attrlist)[i].c_str());
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
delete attrlist;
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
lut_DevFailed(L, e, dev_name.c_str());
|
||||
}
|
||||
delete attrlist;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -62,14 +91,24 @@ int lut_DeviceProxy_get_command_list(lua_State* L)
|
||||
{
|
||||
LUT_LOG(TRACE, "TANGO API DeviceProxy:get_command_list()");
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
std::vector<std::string>* cmdlist = udata->dev->get_command_list();
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < cmdlist->size(); i++)
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
|
||||
try
|
||||
{
|
||||
lua_pushstring(L, (*cmdlist)[i].c_str());
|
||||
lua_rawseti(L, -2, i+1);
|
||||
std::vector<std::string>* cmdlist = udata->dev->get_command_list();
|
||||
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < cmdlist->size(); i++)
|
||||
{
|
||||
lua_pushstring(L, (*cmdlist)[i].c_str());
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
delete cmdlist;
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
lut_DevFailed(L, e, dev_name.c_str());
|
||||
}
|
||||
delete cmdlist;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -92,7 +131,14 @@ int lut_DeviceProxy_create(lua_State* L)
|
||||
|
||||
// push userdata containing the DeviceProxy
|
||||
DeviceProxyWrapper** udata = (DeviceProxyWrapper**)lua_newuserdata(L, sizeof(DeviceProxyWrapper*));
|
||||
*udata = new DeviceProxyWrapper(name);
|
||||
try
|
||||
{
|
||||
*udata = new DeviceProxyWrapper(name);
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
lut_DevFailed(L, e, name);
|
||||
}
|
||||
|
||||
// set metatable, that allows userdata proper garbage collection
|
||||
luaL_newmetatable(L, LUT_DEVICEPROXY);
|
||||
@ -115,29 +161,40 @@ int lut_DeviceProxy_index(lua_State* L)
|
||||
{
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
const char* name = luaL_checkstring(L, 2);
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
std::string full_name = build_name(dev_name, name);
|
||||
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:index(%s)", name);
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy(%s):index(%s)", dev_name.c_str(), name);
|
||||
|
||||
std::vector<std::string>* cmdlist = udata->dev->get_command_list();
|
||||
if(std::count(cmdlist->begin(), cmdlist->end(), name))
|
||||
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);
|
||||
std::vector<std::string>* 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
|
||||
{
|
||||
// index is an attribute
|
||||
LUT_LOG(TRACE, "Reading attribute %s", full_name.c_str());
|
||||
Tango::DeviceAttribute attr = udata->dev->read_attribute(name);
|
||||
udata->type_map[name].type = attr.get_type();
|
||||
udata->type_map[name].format = attr.get_data_format();
|
||||
unpack_attr_data(L, attr);
|
||||
}
|
||||
delete cmdlist;
|
||||
}
|
||||
else
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
// index is an attribute
|
||||
LUT_LOG(TRACE, "Reading attribute %s", name);
|
||||
Tango::DeviceAttribute attr = udata->dev->read_attribute(name);
|
||||
udata->type_map[name].type = attr.get_type();
|
||||
udata->type_map[name].format = attr.get_data_format();
|
||||
unpack_attr_data(L, attr);
|
||||
lut_DevFailed(L, e, full_name.c_str());
|
||||
}
|
||||
delete cmdlist;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -146,28 +203,38 @@ int lut_DeviceProxy_newindex(lua_State* L)
|
||||
{
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
const char* attr_name = luaL_checkstring(L, 2);
|
||||
std::string dev_name = udata->dev->dev_name();
|
||||
std::string full_name = build_name(dev_name, attr_name);
|
||||
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:newindex(%s)", attr_name);
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy(%s):newindex(%s)", dev_name.c_str(), attr_name);
|
||||
|
||||
std::vector<std::string>* 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", attr_name);
|
||||
return 0;
|
||||
}
|
||||
std::vector<std::string>* attrlist = udata->dev->get_attribute_list();
|
||||
|
||||
if(udata->type_map.find(attr_name) == udata->type_map.end())
|
||||
if(!std::count(attrlist->begin(), attrlist->end(), attr_name))
|
||||
{
|
||||
// name is not an attribute
|
||||
LUT_LOG(ERROR, "Not an attribute: %s", full_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(udata->type_map.find(attr_name) == udata->type_map.end())
|
||||
{
|
||||
// no cached type mapping
|
||||
LUT_LOG(TRACE, "Type mapping for attribute %s doesn't exist, reading first", full_name.c_str());
|
||||
Tango::DeviceAttribute attr = udata->dev->read_attribute(attr_name);
|
||||
udata->type_map[attr_name].type = attr.get_type();
|
||||
udata->type_map[attr_name].format = attr.get_data_format();
|
||||
}
|
||||
|
||||
Tango::DeviceAttribute v = pack_attr_data(L, 3, udata->type_map[attr_name], attr_name);
|
||||
udata->dev->write_attribute(v);
|
||||
}
|
||||
catch(Tango::DevFailed e)
|
||||
{
|
||||
// no cached type mapping
|
||||
LUT_LOG(TRACE, "Type mapping for attribute %s doesn't exist, reading first", attr_name);
|
||||
Tango::DeviceAttribute attr = udata->dev->read_attribute(attr_name);
|
||||
udata->type_map[attr_name].type = attr.get_type();
|
||||
udata->type_map[attr_name].format = attr.get_data_format();
|
||||
lut_DevFailed(L, e, full_name.c_str());
|
||||
}
|
||||
|
||||
Tango::DeviceAttribute v = pack_attr_data(L, 3, udata->type_map[attr_name], attr_name);
|
||||
udata->dev->write_attribute(v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6,12 +6,14 @@
|
||||
|
||||
#include <core/tango.h>
|
||||
#include <core/lua.h>
|
||||
#include <core/utils.h>
|
||||
|
||||
#include <core/lua/object.h>
|
||||
#include <core/logging/log.h>
|
||||
|
||||
#include <core/tango/attrdata.h>
|
||||
#include <core/tango/cmddata.h>
|
||||
#include <core/tango/DevFailed/lut_DevFailed.h>
|
||||
|
||||
#define LUT_DEVICEPROXY "lut_DeviceProxy"
|
||||
|
||||
|
||||
10
src/core/utils.cpp
Normal file
10
src/core/utils.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "utils.h"
|
||||
|
||||
std::string build_name(std::string dev_name, std::string name, bool cmd)
|
||||
{
|
||||
std::string r(dev_name);
|
||||
r += "/";
|
||||
r += name;
|
||||
if(cmd) r += "()";
|
||||
return r;
|
||||
}
|
||||
8
src/core/utils.h
Normal file
8
src/core/utils.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __UTILS_H__
|
||||
# define __UTILS_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string build_name(std::string dev_name, std::string name, bool cmd=false);
|
||||
|
||||
#endif /* __UTILS_H__ */
|
||||
@ -1,5 +1,6 @@
|
||||
local core = require "lutango.core"
|
||||
local log = require "lutango.lutLog"
|
||||
local try = require "lutango.try"
|
||||
|
||||
local lutObject = {}
|
||||
|
||||
@ -20,7 +21,7 @@ function lutObject:__call(...)
|
||||
}
|
||||
|
||||
if self.__type then
|
||||
o.__obj = core[self.__type].create(...)
|
||||
o.__obj = try(core[self.__type].create, ...)
|
||||
end
|
||||
|
||||
setmetatable(o, lutObject)
|
||||
@ -32,10 +33,10 @@ function lutObject:__index(key)
|
||||
local from_core = core[self.__type][key]
|
||||
if from_core then
|
||||
return function(...)
|
||||
return from_core(self.__obj, ...)
|
||||
return try(from_core, self.__obj, ...)
|
||||
end
|
||||
end
|
||||
return core[self.__type].index(self.__obj, key)
|
||||
return try(core[self.__type].index, self.__obj, key)
|
||||
else return nil end
|
||||
end
|
||||
|
||||
@ -46,7 +47,7 @@ function lutObject:__newindex(key, value)
|
||||
log(log.level.ERROR, "Cannot write non-attribute: "..key)
|
||||
return nil
|
||||
end
|
||||
core[self.__type].newindex(self.__obj, key, value)
|
||||
try(core[self.__type].newindex, self.__obj, key, value)
|
||||
else return nil end
|
||||
end
|
||||
|
||||
|
||||
24
src/try.lua
Normal file
24
src/try.lua
Normal file
@ -0,0 +1,24 @@
|
||||
local log = require "lutango.lutLog"
|
||||
|
||||
local function default_handler(e)
|
||||
io.stderr:write("\n=================================== EXCEPTION ===================================\n")
|
||||
io.stderr:write("Tango Error Stack:\t"..e.source.."\n")
|
||||
for i,v in ipairs(e) do
|
||||
io.stderr:write("\t"..i..":\n")
|
||||
io.stderr:write("\t\t"..v.severity.."\t\t"..v.reason.."\n")
|
||||
io.stderr:write("\t\t"..v.desc.."\n")
|
||||
io.stderr:write("\t\t"..v.origin.."\n\n")
|
||||
end
|
||||
io.stderr:write(debug.traceback("", 6))
|
||||
io.stderr:write("\n=================================================================================\n\n")
|
||||
end
|
||||
|
||||
local function try(...)
|
||||
local f = arg[1]
|
||||
table.remove(arg, 1)
|
||||
|
||||
local ok, ret = xpcall(function() return f(unpack(arg)) end, default_handler)
|
||||
return ret
|
||||
end
|
||||
|
||||
return try
|
||||
@ -1,6 +1,9 @@
|
||||
local lut = require "lutango"
|
||||
lut.log:set_log_level(lut.log.level.TRACE)
|
||||
|
||||
print("Attempting to access non-existent device")
|
||||
local invalid = lut.DeviceProxy("non/existent/device")
|
||||
|
||||
local dp = lut.DeviceProxy(arg[1] or "sys/tg_test/1")
|
||||
|
||||
print("Attempting to write core function")
|
||||
|
||||
@ -6,18 +6,14 @@ local dp = lut.DeviceProxy(arg[1] or "sys/tg_test/1")
|
||||
local attrlist = dp:get_attribute_list()
|
||||
|
||||
for _,v in ipairs(attrlist) do
|
||||
if v ~= "no_value" and v ~= "throw_exception" then
|
||||
local r = dp[v]
|
||||
io.write(v.." = "..tostring(r))
|
||||
if type(r) == "table" then
|
||||
io.write(": {")
|
||||
for _,i in ipairs(r) do
|
||||
io.write(tostring(i)..", ")
|
||||
end
|
||||
io.write("}")
|
||||
local r = dp[v]
|
||||
io.write(v.." = "..tostring(r))
|
||||
if type(r) == "table" then
|
||||
io.write(": {")
|
||||
for _,i in ipairs(r) do
|
||||
io.write(tostring(i)..", ")
|
||||
end
|
||||
print()
|
||||
else
|
||||
print("-- Can't handle that yet: "..v)
|
||||
io.write("}")
|
||||
end
|
||||
print()
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user