add AttributeProxy support

This commit is contained in:
Grzegorz Kowalski 2023-02-05 13:42:37 +01:00
parent 152734b329
commit 361e3abead
9 changed files with 245 additions and 11 deletions

View File

@ -1,4 +1,4 @@
# luTango - Lua binding for Tango
luTango is a module providing access to [Tango Control System](https://www.tango-controls.org/) with Lua.
In it's current state, a basic subset of client API is available (DeviceProxy), although not all Tango types are supported.
In it's current state, a basic subset of client API is available (DeviceProxy, AttributeProxy), although not all Tango types are supported.

View File

@ -14,6 +14,7 @@ int luaopen_lutango_core(lua_State* L)
lut_lua_register_log(L);
lut_lua_register_sys(L);
lut_lua_register_DeviceProxy(L);
lut_lua_register_AttributeProxy(L);
LUT_LOG(TRACE, "Core module table registered.");

View File

@ -7,6 +7,7 @@
#include <core/sys/sys.h>
#include <core/tango/DeviceProxy/lut_DeviceProxy.h>
#include <core/tango/AttributeProxy/lut_AttributeProxy.h>
#ifdef __cplusplus
extern "C"

View File

@ -0,0 +1,141 @@
#include "lut_AttributeProxy.h"
// WRAPPER CLASS --------------------------------------------------------------
AttributeProxyWrapper::AttributeProxyWrapper(const char* name)
: type_cached(false)
{
attr = new Tango::AttributeProxy(name);
}
AttributeProxyWrapper::~AttributeProxyWrapper()
{
delete attr;
}
Tango::DeviceAttribute read_attr(AttributeProxyWrapper* udata)
{
Tango::DeviceAttribute attr_data = udata->attr->read();
udata->type_desc.type = attr_data.get_type();
udata->type_desc.format = attr_data.get_data_format();
udata->type_cached = true;
return attr_data;
}
// TANGO API ------------------------------------------------------------------
int lut_AttributeProxy_state(lua_State* L)
{
LUT_LOG(TRACE, "TANGO API AttributeProxy:state()");
AttributeProxyWrapper* udata = (AttributeProxyWrapper*)lut_getobj(L, 1);
std::string attr_name = udata->attr->name();
try
{
lut_DevState(L, udata->attr->state());
}
catch(Tango::DevFailed e)
{
lut_DevFailed(L, e, attr_name.c_str());
}
return 1;
}
int lut_AttributeProxy_status(lua_State* L)
{
LUT_LOG(TRACE, "TANGO API AttributeProxy:status()");
AttributeProxyWrapper* udata = (AttributeProxyWrapper*)lut_getobj(L, 1);
std::string attr_name = udata->attr->name();
try
{
lua_pushstring(L, udata->attr->status().c_str());
}
catch(Tango::DevFailed e)
{
lut_DevFailed(L, e, attr_name.c_str());
}
return 1;
}
// LUA API --------------------------------------------------------------------
void lut_lua_register_AttributeProxy(lua_State* L)
{
// create table, register funcs and add it as AttributeProxy to lutango's table
lua_newtable(L);
luaL_register(L, NULL, lut_AttributeProxy);
lua_setfield(L, -2, "AttributeProxy");
LUT_LOG(INFO, "Registered AttributeProxy table");
}
int lut_AttributeProxy_create(lua_State* L)
{
const char* name = luaL_checkstring(L, 1);
LUT_LOG(TRACE, "LUA API AttributeProxy:create(%s)", name);
// push userdata containing the DeviceProxy
AttributeProxyWrapper** udata = (AttributeProxyWrapper**)lua_newuserdata(L, sizeof(AttributeProxyWrapper*));
try
{
*udata = new AttributeProxyWrapper(name);
}
catch(Tango::DevFailed e)
{
lut_DevFailed(L, e, name);
}
// set metatable, that allows userdata proper garbage collection
luaL_newmetatable(L, LUT_ATTRIBUTEPROXY);
luaL_register(L, NULL, lut_AttributeProxy_userdata);
lua_setmetatable(L, -2);
return 1;
}
int lut_AttributeProxy_destroy(lua_State* L)
{
LUT_LOG(TRACE, "LUA API AttributeProxy:destroy()");
AttributeProxyWrapper* udata = (AttributeProxyWrapper*)lut_getobj(L, 1);
delete udata;
return 0;
}
// aka read / write
int lut_AttributeProxy_call(lua_State* L)
{
AttributeProxyWrapper* udata = (AttributeProxyWrapper*)lut_getobj(L, 1);
std::string attr_name = udata->attr->name();
LUT_LOG(TRACE, "LUA API AttributeProxy(%s):call(...)", attr_name.c_str());
try
{
if(lua_isnoneornil(L, 2))
{
// called without arguments - read attribute
LUT_LOG(TRACE, "Reading attribute %s", attr_name.c_str());
unpack_attr_data(L, read_attr(udata));
return 1;
}
else
{
if(!udata->type_cached)
{
// no cached type mapping
LUT_LOG(TRACE, "Type mapping for attribute %s doesn't exist, reading first", attr_name.c_str());
read_attr(udata);
}
Tango::DeviceAttribute v = pack_attr_data(L, 2, udata->type_desc, attr_name.c_str());
udata->attr->write(v);
return 0;
}
}
catch(Tango::DevFailed e)
{
lut_DevFailed(L, e, attr_name.c_str());
}
return 0;
}

View File

@ -0,0 +1,62 @@
#ifndef __LUT_ATTRIBUTEPROXY_H__
# define __LUT_ATTRIBUTEPROXY_H__
#include <string>
#include <vector>
#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/DevState/lut_DevState.h>
#include <core/tango/DevFailed/lut_DevFailed.h>
#define LUT_ATTRIBUTEPROXY "lut_AttributeProxy"
// Wrapper class
class AttributeProxyWrapper
{
public:
AttributeProxyWrapper(const char* name);
~AttributeProxyWrapper();
Tango::AttributeProxy* attr;
AttrTypeDescription type_desc;
bool type_cached;
};
Tango::DeviceAttribute read_attr(AttributeProxyWrapper* udata);
// Tango API
int lut_AttributeProxy_state(lua_State* L);
int lut_AttributeProxy_status(lua_State* L);
// Lua API
void lut_lua_register_AttributeProxy(lua_State* L);
int lut_AttributeProxy_create(lua_State* L);
int lut_AttributeProxy_destroy(lua_State* L);
int lut_AttributeProxy_call(lua_State* L);
static const luaL_reg lut_AttributeProxy[] =
{
// Lua API
{ "create", lut_AttributeProxy_create },
{ "call", lut_AttributeProxy_call },
// Tango API
{ "status", lut_AttributeProxy_status },
{ "state", lut_AttributeProxy_state },
{ NULL, NULL }
};
static const luaL_reg lut_AttributeProxy_userdata[] =
{
{ "__gc", lut_AttributeProxy_destroy },
{ NULL, NULL }
};
#endif /* __LUT_ATTRIBUTEPROXY_H__ */

View File

@ -7,7 +7,7 @@ void lut_DevState(lua_State* L, Tango::DevState state)
load_lua_lib(L, LUTANGO);
lua_getglobal(L, LUTANGO);
lua_getfield(L, 1, "DevState");
lua_getfield(L, -2, "DevState");
lua_pushnumber(L, (int)state);
lua_call(L, 1, 1);

View File

@ -9,6 +9,7 @@ local lutango = {
sys = core.sys,
lutObject = lutObject,
DeviceProxy = lutObject("DeviceProxy"),
AttributeProxy = lutObject("AttributeProxy"),
DevState = require "lutango.lutDevState"
}

View File

@ -7,6 +7,7 @@ local lutObject = {}
function create_lutObject(type)
log(log.level.TRACE, "New lutObject for "..type)
local o = {
__is_instance = false,
__type = type
}
@ -15,17 +16,26 @@ function create_lutObject(type)
end
function lutObject:__call(...)
log(log.level.TRACE, "New "..self.__type.."("..table.concat({...}, ", ")..")")
local o = {
__type = self.__type
}
if self.__is_instance then
if self.__type then
return try(core[self.__type].call, self.__obj, ...)
else
return nil
end
else
log(log.level.TRACE, "New "..self.__type.."("..table.concat({...}, ", ")..")")
local o = {
__is_instance = true,
__type = self.__type
}
if self.__type then
o.__obj = try(core[self.__type].create, ...)
if self.__type then
o.__obj = try(core[self.__type].create, ...)
end
setmetatable(o, lutObject)
return o
end
setmetatable(o, lutObject)
return o
end
function lutObject:__index(key)

18
tests/attributeproxy.lua Normal file
View File

@ -0,0 +1,18 @@
local lut = require "lutango"
lut.log:set_log_level(lut.log.level.WARNING)
local ap = lut.AttributeProxy("sys/tg_test/1/ampli")
print("Reading state and status")
print("State = "..tostring(ap:state()))
print("Status = "..ap:status())
print("Reading attribute")
local v = ap()
print("ampli = "..v)
print("Writing attribute")
ap(v+1)
print("Reading again")
print("ampli = "..ap())