forked from daneos/lutango
initial DeviceProxy read/write implementation
This commit is contained in:
parent
bc20b25c54
commit
d9a4685c1f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build/*
|
||||
lib/*
|
||||
52
Makefile
Normal file
52
Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
VERSION=$(shell git describe --tags --always --dirty)\:$(shell date +'%Y%m%d')
|
||||
|
||||
SRC_DIR := src
|
||||
BUILD_DIR := build
|
||||
OUT_DIR := lib
|
||||
|
||||
ifeq ($(LUA_VERSION),)
|
||||
LUA_VERSION := 5.1
|
||||
endif
|
||||
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX := /usr/local/lib/lua/$(LUA_VERSION)/lutango
|
||||
endif
|
||||
|
||||
LUT_INCLUDE := $(SRC_DIR)
|
||||
|
||||
SRCS := $(shell find . -name '*.cpp')
|
||||
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
||||
SONAME := core.so.$(VERSION)
|
||||
SOLINK := core.so
|
||||
|
||||
CC = g++
|
||||
CXX = $(CC)
|
||||
|
||||
CFLAGS = -shared -fpic -D_REENTRANT -DVERSION=\"$(VERSION)\" -I$(LUT_INCLUDE)
|
||||
CFLAGS += $(shell pkg-config --cflags tango lua$(LUA_VERSION))
|
||||
LDFLAGS = $(shell pkg-config --libs tango lua$(LUA_VERSION))
|
||||
CPPFLAGS += $(CFLAGS)
|
||||
|
||||
dir-guard=@mkdir -p $(@D)
|
||||
|
||||
.PHONY: default clean install
|
||||
|
||||
default: $(OUT_DIR)/$(SONAME)
|
||||
|
||||
$(OUT_DIR)/$(SONAME): $(OBJS)
|
||||
$(dir-guard)
|
||||
$(CXX) $^ $(CPPFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
$(BUILD_DIR)/%.cpp.o: %.cpp
|
||||
$(dir-guard)
|
||||
$(CXX) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
rm -rf lib
|
||||
|
||||
install:
|
||||
install -d $(PREFIX)
|
||||
install -m 644 $(SRC_DIR)/*.lua $(PREFIX)
|
||||
install -s -m 644 $(OUT_DIR)/$(SONAME) $(PREFIX)
|
||||
ln -sf $(PREFIX)/$(SONAME) $(PREFIX)/$(SOLINK)
|
||||
34
src/core/logging/log.cpp
Normal file
34
src/core/logging/log.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "log.h"
|
||||
|
||||
void _log(LogLevel level, const char* fmt, const char* _file, const char* _func, int _line, ...)
|
||||
{
|
||||
if(level <= current_log_level)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, _line);
|
||||
fprintf(stderr, "[%s]@[CORE:%s:%s:%d]: ", LogLevelLabels[level], _file, _func, _line);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void set_log_level(LogLevel level)
|
||||
{
|
||||
current_log_level = level;
|
||||
}
|
||||
|
||||
void lut_lua_register_log(lua_State* L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lut_log);
|
||||
lua_setfield(L, -2, "log");
|
||||
LUT_LOG(INFO, "Registered log table");
|
||||
}
|
||||
|
||||
int lut_log_set_log_level(lua_State* L)
|
||||
{
|
||||
int level = luaL_checknumber(L, 1);
|
||||
set_log_level((LogLevel)level);
|
||||
return 1;
|
||||
}
|
||||
38
src/core/logging/log.h
Normal file
38
src/core/logging/log.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef __LOG_H__
|
||||
# define __LOG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <core/lua.h>
|
||||
|
||||
#define LUT_LOG(level, msg, ...) _log(level, msg, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
|
||||
typedef enum _LogLevel
|
||||
{
|
||||
CRITICAL = 0,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
DEBUG,
|
||||
TRACE
|
||||
} LogLevel;
|
||||
|
||||
static const char* LogLevelLabels[] = {"CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
|
||||
static LogLevel current_log_level = WARNING;
|
||||
|
||||
// C API
|
||||
void _log(LogLevel level, const char* fmt, const char* _file, const char* _func, int _line, ...);
|
||||
void set_log_level(LogLevel level);
|
||||
|
||||
// Lua API
|
||||
void lut_lua_register_log(lua_State* L);
|
||||
int lut_log_set_log_level(lua_State* L);
|
||||
|
||||
static const luaL_reg lut_log[] =
|
||||
{
|
||||
{ "set_log_level", lut_log_set_log_level },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#endif /* __LOG_H__ */
|
||||
16
src/core/lua.h
Normal file
16
src/core/lua.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __LUA_INCLUDES_H__
|
||||
# define __LUA_INCLUDES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LUA_INCLUDES_H__ */
|
||||
7
src/core/lua/object.cpp
Normal file
7
src/core/lua/object.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "object.h"
|
||||
|
||||
void *lut_getobj(lua_State *L, int n)
|
||||
{
|
||||
LUT_LOG(TRACE, "Extracting object from userdata");
|
||||
return *(void**)lua_touserdata(L, n);
|
||||
}
|
||||
9
src/core/lua/object.h
Normal file
9
src/core/lua/object.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __OBJECT_H__
|
||||
# define __OBJECT_H__
|
||||
|
||||
#include <core/lua.h>
|
||||
#include <core/logging/log.h>
|
||||
|
||||
void *lut_getobj(lua_State *L, int n);
|
||||
|
||||
#endif /* __LUT_OBJECT_H__ */
|
||||
25
src/core/lutango_core.cpp
Normal file
25
src/core/lutango_core.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "lutango_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int luaopen_lutango_core(lua_State* L)
|
||||
{
|
||||
LUT_LOG(TRACE, "luTango core open.");
|
||||
LUT_LOG(INFO, "luTango core v%s", VERSION);
|
||||
|
||||
lua_newtable(L);
|
||||
lut_lua_register_log(L);
|
||||
lut_lua_register_sys(L);
|
||||
lut_lua_register_DeviceProxy(L);
|
||||
|
||||
LUT_LOG(TRACE, "Core module table registered.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
26
src/core/lutango_core.h
Normal file
26
src/core/lutango_core.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __LUTANGO_H__
|
||||
# define __LUTANGO_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// #define LUTANGO_CORE "lutango_core"
|
||||
|
||||
#include <core/lua.h>
|
||||
#include <core/logging/log.h>
|
||||
#include <core/sys/sys.h>
|
||||
|
||||
#include <core/tango/DeviceProxy/lut_DeviceProxy.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// core is loaded as "lutango.core"
|
||||
int luaopen_lutango_core(lua_State* L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#endif /* __LUTANGO_H__ */
|
||||
21
src/core/sys/sys.cpp
Normal file
21
src/core/sys/sys.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "sys.h"
|
||||
|
||||
void lut_lua_register_sys(lua_State* L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lut_sys);
|
||||
lua_setfield(L, -2, "sys");
|
||||
LUT_LOG(INFO, "Registered sys table");
|
||||
}
|
||||
|
||||
int lut_sys_version(lua_State* L)
|
||||
{
|
||||
lua_pushstring(L, VERSION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lut_sys_tango_version(lua_State* L)
|
||||
{
|
||||
lua_pushstring(L, Tango::TgLibVers);
|
||||
return 1;
|
||||
}
|
||||
20
src/core/sys/sys.h
Normal file
20
src/core/sys/sys.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __SYS_H__
|
||||
# define __SYS_H__
|
||||
|
||||
#include <core/lua.h>
|
||||
#include <core/tango.h>
|
||||
#include <core/logging/log.h>
|
||||
|
||||
// Lua API
|
||||
void lut_lua_register_sys(lua_State* L);
|
||||
int lut_sys_version(lua_State* L);
|
||||
int lut_sys_tango_version(lua_State* L);
|
||||
|
||||
static const luaL_reg lut_sys[] =
|
||||
{
|
||||
{ "version", lut_sys_version },
|
||||
{ "tango_version", lut_sys_tango_version },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#endif /* __SYS_H__ */
|
||||
6
src/core/tango.h
Normal file
6
src/core/tango.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __TANGO_INCLUDES_H__
|
||||
# define __TANGO_INCLUDES_H__
|
||||
|
||||
#include <tango/tango.h>
|
||||
|
||||
#endif /* __TANGO_INCLUDES_H__ */
|
||||
112
src/core/tango/DeviceProxy/lut_DeviceProxy.cpp
Normal file
112
src/core/tango/DeviceProxy/lut_DeviceProxy.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "lut_DeviceProxy.h"
|
||||
|
||||
// WRAPPER CLASS --------------------------------------------------------------
|
||||
DeviceProxyWrapper::DeviceProxyWrapper(const char* name)
|
||||
{
|
||||
dev = new Tango::DeviceProxy(name);
|
||||
}
|
||||
|
||||
DeviceProxyWrapper::~DeviceProxyWrapper()
|
||||
{
|
||||
delete dev;
|
||||
}
|
||||
|
||||
// TANGO API ------------------------------------------------------------------
|
||||
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());
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
vector<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);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// LUA API --------------------------------------------------------------------
|
||||
void lut_lua_register_DeviceProxy(lua_State* L)
|
||||
{
|
||||
// create table, register funcs and add it as DeviceProxy to lutango's table
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lut_DeviceProxy);
|
||||
lua_setfield(L, -2, "DeviceProxy");
|
||||
|
||||
LUT_LOG(INFO, "Registered DeviceProxy table");
|
||||
}
|
||||
|
||||
int lut_DeviceProxy_create(lua_State* L)
|
||||
{
|
||||
const char* name = luaL_checkstring(L, 1);
|
||||
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:create(%s)", name);
|
||||
|
||||
// push userdata containing the DeviceProxy
|
||||
DeviceProxyWrapper** udata = (DeviceProxyWrapper**)lua_newuserdata(L, sizeof(DeviceProxyWrapper*));
|
||||
*udata = new DeviceProxyWrapper(name);
|
||||
|
||||
// set metatable, that allows userdata proper garbage collection
|
||||
luaL_newmetatable(L, LUT_DEVICEPROXY);
|
||||
luaL_register(L, NULL, lut_DeviceProxy_userdata);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lut_DeviceProxy_destroy(lua_State* L)
|
||||
{
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:destroy()");
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
delete udata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// aka read_attribute
|
||||
int lut_DeviceProxy_index(lua_State* L)
|
||||
{
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
const char* attr_name = luaL_checkstring(L, 2);
|
||||
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:index(%s)", 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();
|
||||
|
||||
extract_and_push(L, attr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// aka write_attribute
|
||||
int lut_DeviceProxy_newindex(lua_State* L)
|
||||
{
|
||||
DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1);
|
||||
const char* attr_name = luaL_checkstring(L, 2);
|
||||
|
||||
LUT_LOG(TRACE, "LUA API DeviceProxy:newindex(%s)", attr_name);
|
||||
|
||||
if(udata->type_map.find(attr_name) == udata->type_map.end())
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
Tango::DeviceAttribute v = pop_and_pack(L, udata->type_map[attr_name], attr_name);
|
||||
udata->dev->write_attribute(v);
|
||||
|
||||
return 1;
|
||||
}
|
||||
54
src/core/tango/DeviceProxy/lut_DeviceProxy.h
Normal file
54
src/core/tango/DeviceProxy/lut_DeviceProxy.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef __LUT_DEVICEPROXY_H__
|
||||
# define __LUT_DEVICEPROXY_H__
|
||||
|
||||
#include <core/tango.h>
|
||||
#include <core/lua.h>
|
||||
|
||||
#include <core/tango/attrtype.h>
|
||||
#include <core/lua/object.h>
|
||||
#include <core/logging/log.h>
|
||||
|
||||
#define LUT_DEVICEPROXY "lut_DeviceProxy"
|
||||
|
||||
// Wrapper class
|
||||
class DeviceProxyWrapper
|
||||
{
|
||||
public:
|
||||
DeviceProxyWrapper(const char* name);
|
||||
~DeviceProxyWrapper();
|
||||
Tango::DeviceProxy* dev;
|
||||
AttrTypeMap type_map;
|
||||
};
|
||||
|
||||
// Tango API
|
||||
int lut_DeviceProxy_status(lua_State* L);
|
||||
int lut_DeviceProxy_get_attribute_list(lua_State* L);
|
||||
|
||||
// Lua API
|
||||
void lut_lua_register_DeviceProxy(lua_State* L);
|
||||
int lut_DeviceProxy_create(lua_State* L);
|
||||
int lut_DeviceProxy_destroy(lua_State* L);
|
||||
int lut_DeviceProxy_index(lua_State* L);
|
||||
int lut_DeviceProxy_newindex(lua_State* L);
|
||||
|
||||
static const luaL_reg lut_DeviceProxy[] =
|
||||
{
|
||||
// Lua API
|
||||
{ "create", lut_DeviceProxy_create },
|
||||
{ "index", lut_DeviceProxy_index },
|
||||
{ "newindex", lut_DeviceProxy_newindex },
|
||||
|
||||
// Tango API
|
||||
{ "status", lut_DeviceProxy_status },
|
||||
{ "get_attribute_list", lut_DeviceProxy_get_attribute_list},
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const luaL_reg lut_DeviceProxy_userdata[] =
|
||||
{
|
||||
{ "__gc", lut_DeviceProxy_destroy },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#endif /* __LUT_DEVICEPROXY_H__ */
|
||||
366
src/core/tango/attrtype.cpp
Normal file
366
src/core/tango/attrtype.cpp
Normal file
@ -0,0 +1,366 @@
|
||||
#include "attrtype.h"
|
||||
|
||||
void extract_and_push(lua_State* L, Tango::DeviceAttribute attr)
|
||||
{
|
||||
switch(attr.get_type())
|
||||
{
|
||||
case 0: // void
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
|
||||
case 1: // bool
|
||||
push_bool(L, attr);
|
||||
break;
|
||||
|
||||
case 2: // short
|
||||
push_number<short>(L, attr);
|
||||
break;
|
||||
|
||||
case 3: // long
|
||||
push_number<long>(L, attr);
|
||||
break;
|
||||
|
||||
case 4: // float
|
||||
push_number<float>(L, attr);
|
||||
break;
|
||||
|
||||
case 5: // double
|
||||
push_number<double>(L, attr);
|
||||
break;
|
||||
|
||||
case 6: // ushort
|
||||
push_number<unsigned short>(L, attr);
|
||||
break;
|
||||
|
||||
case 7: // ulong
|
||||
push_number<unsigned long>(L, attr);
|
||||
break;
|
||||
|
||||
case 8: // string
|
||||
case 9: // char[]
|
||||
case 20: // const string
|
||||
push_string(L, attr);
|
||||
break;
|
||||
|
||||
case 10: // short[]
|
||||
{
|
||||
std::vector<short> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 11: // long[]
|
||||
{
|
||||
std::vector<long> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 12: // float[]
|
||||
{
|
||||
std::vector<float> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 13: // double[]
|
||||
{
|
||||
std::vector<double> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 14: // ushort[]
|
||||
{
|
||||
std::vector<unsigned short> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 15: // ulong[]
|
||||
{
|
||||
std::vector<unsigned long> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 16: // string[]
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
attr >> v;
|
||||
push_string_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 21: // bool[]
|
||||
{
|
||||
std::vector<bool> v;
|
||||
attr >> v;
|
||||
push_bool_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 22: // uchar
|
||||
{
|
||||
unsigned char v;
|
||||
attr >> v;
|
||||
lua_pushstring(L, (const char *)&v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 23: // long64
|
||||
push_number<int64_t>(L, attr);
|
||||
break;
|
||||
|
||||
case 24: // ulong64
|
||||
push_number<uint64_t>(L, attr);
|
||||
break;
|
||||
|
||||
case 25: // long64[]
|
||||
{
|
||||
std::vector<int64_t> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 26: // ulong64[]
|
||||
{
|
||||
std::vector<uint64_t> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 27: // int
|
||||
push_number<int>(L, attr);
|
||||
break;
|
||||
|
||||
case 17: // longstring[] ???
|
||||
case 18: // doublestring[] ???
|
||||
case 19: // DevState
|
||||
case 28: // DevEncoded
|
||||
LUT_LOG(WARNING, "%s: Attribute type not implemented for reading yet: %d", attr.name.c_str(), attr.get_type());
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
|
||||
default:
|
||||
LUT_LOG(ERROR, "%s: Device returned unknown type: %d", attr.name.c_str(), attr.get_type());
|
||||
lua_pushnil(L);
|
||||
//return luaL_error(L, "Device returned type %d, that is unknown or unsupported.", attr.get_type());
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void push_number(lua_State* L, Tango::DeviceAttribute attr)
|
||||
{
|
||||
Tango::AttrDataFormat fmt = attr.get_data_format();
|
||||
if(fmt == Tango::SCALAR)
|
||||
{
|
||||
T v;
|
||||
attr >> v;
|
||||
lua_pushnumber(L, v);
|
||||
}
|
||||
else if(fmt == Tango::SPECTRUM || fmt == Tango::IMAGE)
|
||||
{
|
||||
std::vector<T> v;
|
||||
attr >> v;
|
||||
push_number_table(L, v);
|
||||
}
|
||||
else if(fmt == Tango::IMAGE)
|
||||
{
|
||||
// std::vector<std::vector<T>> v;
|
||||
// //attr >> v;
|
||||
// // push_number_2d(L, v);
|
||||
LUT_LOG(WARNING, "%s: IMAGE data format is not supported yet", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUT_LOG(ERROR, "%s: Invalid data format", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
}
|
||||
|
||||
void push_bool(lua_State* L, Tango::DeviceAttribute attr)
|
||||
{
|
||||
Tango::AttrDataFormat fmt = attr.get_data_format();
|
||||
if(fmt == Tango::SCALAR)
|
||||
{
|
||||
bool v;
|
||||
attr >> v;
|
||||
lua_pushboolean(L, v);
|
||||
}
|
||||
else if(fmt == Tango::SPECTRUM)
|
||||
{
|
||||
std::vector<bool> v;
|
||||
attr >> v;
|
||||
push_bool_table(L, v);
|
||||
}
|
||||
else if(fmt == Tango::IMAGE)
|
||||
{
|
||||
LUT_LOG(WARNING, "%s: IMAGE data format is not supported yet", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUT_LOG(ERROR, "%s: Invalid data format", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void push_string(lua_State* L, Tango::DeviceAttribute attr)
|
||||
{
|
||||
Tango::AttrDataFormat fmt = attr.get_data_format();
|
||||
if(fmt == Tango::SCALAR)
|
||||
{
|
||||
std::string v;
|
||||
attr >> v;
|
||||
lua_pushstring(L, v.c_str());
|
||||
}
|
||||
else if(fmt == Tango::SPECTRUM)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
attr >> v;
|
||||
push_string_table(L, v);
|
||||
}
|
||||
else if(fmt == Tango::IMAGE)
|
||||
{
|
||||
LUT_LOG(WARNING, "%s: IMAGE data format is not supported yet", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUT_LOG(ERROR, "%s: Invalid data format", attr.name.c_str());
|
||||
lua_pushnil(L);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void push_number_table(lua_State* L, std::vector<T> v)
|
||||
{
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < v.size(); i++)
|
||||
{
|
||||
lua_pushnumber(L, v[i]);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
}
|
||||
|
||||
void push_bool_table(lua_State* L, std::vector<bool> v)
|
||||
{
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < v.size(); i++)
|
||||
{
|
||||
lua_pushboolean(L, v[i]);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
}
|
||||
|
||||
void push_string_table(lua_State* L, std::vector<std::string> v)
|
||||
{
|
||||
lua_newtable(L);
|
||||
for(int i = 0; i < v.size(); i++)
|
||||
{
|
||||
lua_pushstring(L, v[i].c_str());
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
}
|
||||
|
||||
Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const char* attr_name)
|
||||
{
|
||||
switch(d.type)
|
||||
{
|
||||
case 0: // void
|
||||
LUT_LOG(ERROR, "%s: Void is not writeable type!", attr_name);
|
||||
break;
|
||||
|
||||
case 1: // bool
|
||||
// Lua 5.1 is missing the luaL_checkboolean function
|
||||
return pack_value(attr_name, (bool)lua_toboolean(L, 3));
|
||||
break;
|
||||
|
||||
case 2: // short
|
||||
return pack_value(attr_name, pop_number<short>(L, 3));
|
||||
break;
|
||||
|
||||
case 3: // long
|
||||
return pack_value(attr_name, pop_number<long>(L, 3));
|
||||
break;
|
||||
|
||||
case 4: // float
|
||||
return pack_value(attr_name, pop_number<float>(L, 3));
|
||||
break;
|
||||
|
||||
case 5: // double
|
||||
return pack_value(attr_name, pop_number<double>(L, 3));
|
||||
break;
|
||||
|
||||
case 6: // ushort
|
||||
return pack_value(attr_name, pop_number<unsigned short>(L, 3));
|
||||
break;
|
||||
|
||||
case 7: // ulong
|
||||
return pack_value(attr_name, pop_number<unsigned long>(L, 3));
|
||||
break;
|
||||
|
||||
case 8: // string
|
||||
case 9: // char[]
|
||||
case 20: // const string
|
||||
return pack_value(attr_name, luaL_checkstring(L, 3));
|
||||
break;
|
||||
|
||||
case 23: // long64
|
||||
return pack_value(attr_name, pop_number<int64_t>(L, 3));
|
||||
break;
|
||||
|
||||
case 24: // ulong64
|
||||
return pack_value(attr_name, pop_number<uint64_t>(L, 3));
|
||||
break;
|
||||
|
||||
case 27: // int
|
||||
return pack_value(attr_name, pop_number<int>(L, 3));
|
||||
break;
|
||||
|
||||
case 10: // short[]
|
||||
case 11: // long[]
|
||||
case 12: // float[]
|
||||
case 13: // double[]
|
||||
case 14: // ushort[]
|
||||
case 15: // ulong[]
|
||||
case 16: // string[]
|
||||
case 17: // longstring[] ???
|
||||
case 18: // doublestring[] ???
|
||||
case 19: // DevState
|
||||
case 21: // bool[]
|
||||
case 22: // uchar
|
||||
case 25: // long64[]
|
||||
case 26: // ulong64[]
|
||||
case 28: // DevEncoded
|
||||
LUT_LOG(WARNING, "%s: Attribute type not implemented for writing yet: %d", attr_name, d.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
LUT_LOG(ERROR, "%s: Attribute reports unknown type: %d", attr_name, d.type);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T pop_number(lua_State* L, int idx)
|
||||
{
|
||||
return luaL_checknumber(L, idx);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Tango::DeviceAttribute pack_value(const char* name, T value)
|
||||
{
|
||||
Tango::DeviceAttribute v(name, value);
|
||||
return v;
|
||||
}
|
||||
42
src/core/tango/attrtype.h
Normal file
42
src/core/tango/attrtype.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __ATTRTYPE_H__
|
||||
# define __ATTRTYPE_H__
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <core/lua.h>
|
||||
#include <core/tango.h>
|
||||
#include <core/logging/log.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
Tango::AttrDataFormat format;
|
||||
} AttrTypeDescription;
|
||||
|
||||
typedef std::map<const char*, AttrTypeDescription> AttrTypeMap;
|
||||
|
||||
// READ ATTRIBUTE -------------------------------------------------------------
|
||||
void extract_and_push(lua_State* L, Tango::DeviceAttribute attr);
|
||||
|
||||
template<class T>
|
||||
void push_number(lua_State* L, Tango::DeviceAttribute attr);
|
||||
void push_bool(lua_State* L, Tango::DeviceAttribute attr);
|
||||
void push_string(lua_State* L, Tango::DeviceAttribute attr);
|
||||
|
||||
template<class T>
|
||||
void push_number_table(lua_State* L, std::vector<T> value);
|
||||
void push_bool_table(lua_State* L, std::vector<bool> value);
|
||||
void push_string_table(lua_State* L, std::vector<std::string> value);
|
||||
|
||||
// WRITE ATTRIBUTE ------------------------------------------------------------
|
||||
Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const char* attr_name);
|
||||
|
||||
template<class T>
|
||||
T pop_number(lua_State* L, int idx);
|
||||
|
||||
template<class T>
|
||||
Tango::DeviceAttribute pack_value(const char* name, T value);
|
||||
|
||||
#endif /* __ATTRTYPE_H__ */
|
||||
14
src/init.lua
Normal file
14
src/init.lua
Normal file
@ -0,0 +1,14 @@
|
||||
local log = require "lutango.lutLog"
|
||||
local core = require "lutango.core"
|
||||
local lutObject = require "lutango.lutObject"
|
||||
|
||||
local lutango = {
|
||||
__prefix = prefix,
|
||||
log = log,
|
||||
sys = core.sys,
|
||||
lutObject = lutObject,
|
||||
DeviceProxy = lutObject("DeviceProxy")
|
||||
}
|
||||
|
||||
log(log.level.TRACE, "luTango module ready")
|
||||
return lutango
|
||||
35
src/lutLog.lua
Normal file
35
src/lutLog.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local core = require "lutango.core"
|
||||
local utils = require "lutango.utils"
|
||||
|
||||
local _log_level = {
|
||||
CRITICAL = 0,
|
||||
ERROR = 1,
|
||||
WARNING = 2,
|
||||
INFO = 3,
|
||||
DEBUG = 4,
|
||||
TRACE = 5
|
||||
}
|
||||
|
||||
local log = {
|
||||
level = _log_level,
|
||||
current_log_level = _log_level.WARNING
|
||||
}
|
||||
|
||||
function log:__call(level, msg)
|
||||
if level <= self.current_log_level then
|
||||
level = utils.get_key_by_value(self.level, level)
|
||||
local caller = debug.getinfo(2)
|
||||
local file = utils.get_file_name(caller.source)
|
||||
local func = caller.name or "<anonymous>"
|
||||
local line = caller.linedefined
|
||||
io.stderr:write("["..level.."]@[API:"..file..":"..func..":"..line.."]: "..msg.."\n")
|
||||
end
|
||||
end
|
||||
|
||||
function log:set_log_level(level)
|
||||
self.current_log_level = level
|
||||
core.log.set_log_level(level)
|
||||
end
|
||||
|
||||
setmetatable(log, log)
|
||||
return log
|
||||
53
src/lutObject.lua
Normal file
53
src/lutObject.lua
Normal file
@ -0,0 +1,53 @@
|
||||
local core = require "lutango.core"
|
||||
local log = require "lutango.lutLog"
|
||||
|
||||
local lutObject = {}
|
||||
|
||||
function create_lutObject(type)
|
||||
log(log.level.TRACE, "New lutObject for "..type)
|
||||
local o = {
|
||||
__type = type
|
||||
}
|
||||
|
||||
setmetatable(o, lutObject)
|
||||
return o
|
||||
end
|
||||
|
||||
function lutObject:__call(...)
|
||||
log(log.level.TRACE, "New "..self.__type.."("..table.concat({...}, ", ")..")")
|
||||
local o = {
|
||||
__type = self.__type
|
||||
}
|
||||
|
||||
if self.__type then
|
||||
o.__obj = core[self.__type].create(...)
|
||||
end
|
||||
|
||||
setmetatable(o, lutObject)
|
||||
return o
|
||||
end
|
||||
|
||||
function lutObject:__index(key)
|
||||
if self.__type then
|
||||
local from_core = core[self.__type][key]
|
||||
if from_core then
|
||||
return function(...)
|
||||
return from_core(self.__obj, ...)
|
||||
end
|
||||
end
|
||||
return core[self.__type].index(self.__obj, key)
|
||||
else return nil end
|
||||
end
|
||||
|
||||
function lutObject:__newindex(key, value)
|
||||
if self.__type then
|
||||
local from_core = core[self.__type][key]
|
||||
if from_core then
|
||||
log(log.level.ERROR, "Cannot write non-attribute: "..key)
|
||||
return nil
|
||||
end
|
||||
core[self.__type].newindex(self.__obj, key, value)
|
||||
else return nil end
|
||||
end
|
||||
|
||||
return create_lutObject
|
||||
15
src/utils.lua
Normal file
15
src/utils.lua
Normal file
@ -0,0 +1,15 @@
|
||||
local utils = {}
|
||||
|
||||
function utils.get_key_by_value(t, value)
|
||||
for k,v in pairs(t) do
|
||||
if v == value then return k end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function utils.get_file_name(path)
|
||||
return path:match("^.+[/\\](.+)$")
|
||||
end
|
||||
|
||||
|
||||
return utils
|
||||
Loading…
x
Reference in New Issue
Block a user