From 889eedd7ac8c77fcb0e2ad530a380e2029bc325d Mon Sep 17 00:00:00 2001
From: Claudio Scafuri <claudio.scafuri@elettra.eu>
Date: Tue, 31 Mar 2020 15:38:51 +0200
Subject: [PATCH] first import from CVS repo elettra/server/RPC2TangoBridge
 release_06

---
 .gitignore                      |  19 ++
 BridgeAttr.cpp                  | 162 +++++++++
 BridgeAttr.h                    |  86 +++++
 BridgeAttribute.h               |  42 +++
 CHANGELOG                       |   9 +
 ClassFactory.cpp                |  47 +++
 Makefile                        | 193 +++++++++++
 README.md                       |  34 +-
 RPC2TangoBridge.cpp             | 564 ++++++++++++++++++++++++++++++++
 RPC2TangoBridge.h               | 271 +++++++++++++++
 RPC2TangoBridgeClass.cpp        | 501 ++++++++++++++++++++++++++++
 RPC2TangoBridgeClass.h          | 161 +++++++++
 RPC2TangoBridgeStateMachine.cpp | 116 +++++++
 RPC2TangoBridgeThread.cpp       |  32 ++
 RPC2TangoBridgeThread.h         |  28 ++
 RPCHandleSet.cpp                | 124 +++++++
 RPCHandleSet.h                  |  43 +++
 RpcHandle.cpp                   | 159 +++++++++
 RpcHandle.h                     |  64 ++++
 RpcReadHandle.cpp               | 464 ++++++++++++++++++++++++++
 RpcReadHandle.h                 |  37 +++
 RpcWriteHandle.cpp              | 274 ++++++++++++++++
 RpcWriteHandle.h                |  43 +++
 attribute_converter.cpp         | 290 ++++++++++++++++
 attribute_converter.h           |  53 +++
 etc/fixsipformat.py             |  28 ++
 main.cpp                        |  71 ++++
 read_dynamic_attribute.cpp      | 311 ++++++++++++++++++
 write_dynamic_attribute.cpp     | 105 ++++++
 29 files changed, 4330 insertions(+), 1 deletion(-)
 create mode 100644 .gitignore
 create mode 100644 BridgeAttr.cpp
 create mode 100644 BridgeAttr.h
 create mode 100644 BridgeAttribute.h
 create mode 100644 CHANGELOG
 create mode 100644 ClassFactory.cpp
 create mode 100644 Makefile
 create mode 100644 RPC2TangoBridge.cpp
 create mode 100644 RPC2TangoBridge.h
 create mode 100644 RPC2TangoBridgeClass.cpp
 create mode 100644 RPC2TangoBridgeClass.h
 create mode 100644 RPC2TangoBridgeStateMachine.cpp
 create mode 100644 RPC2TangoBridgeThread.cpp
 create mode 100644 RPC2TangoBridgeThread.h
 create mode 100644 RPCHandleSet.cpp
 create mode 100644 RPCHandleSet.h
 create mode 100644 RpcHandle.cpp
 create mode 100644 RpcHandle.h
 create mode 100644 RpcReadHandle.cpp
 create mode 100644 RpcReadHandle.h
 create mode 100644 RpcWriteHandle.cpp
 create mode 100644 RpcWriteHandle.h
 create mode 100644 attribute_converter.cpp
 create mode 100644 attribute_converter.h
 create mode 100644 etc/fixsipformat.py
 create mode 100644 main.cpp
 create mode 100644 read_dynamic_attribute.cpp
 create mode 100644 write_dynamic_attribute.cpp

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f768f79
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+.pydevproject
+.project
+.cproject
+.settings
+obj
+bin
+core*
+*~
+*.pyc
+*.so
+*.so*
+.pylintrc
+.metadata
+.idea
+.cvsignore
+.nse_depinfo
+software
+oldsrc
+CVS
diff --git a/BridgeAttr.cpp b/BridgeAttr.cpp
new file mode 100644
index 0000000..b83cd02
--- /dev/null
+++ b/BridgeAttr.cpp
@@ -0,0 +1,162 @@
+#include <BridgeAttr.h>
+#include <RPCHandleSet.h>
+
+namespace RPC2TangoBridge_ns
+{
+
+BridgeAttr::BridgeAttr(const char *name, long data_type,Tango::AttrWriteType w_type) :
+                        Attr(name, data_type, w_type) 
+{
+	wrpch = NULL;
+	rpch = RPCHandleSet::instance()->handleFromList(name);
+	if(!rpch)
+	{
+		rpch = new RPCHandle(name);
+		if(rpch && rpch->connected())
+		{
+			RPCHandleSet::instance()->addHandle(rpch);
+			//printf("\e[1;32m*\e[0m connected to host \"%s\" port %d for attribute \"%s\"", rpch->host().c_str(), rpch->port(), name);
+		}
+		else if(rpch){
+			//printf("\e[1;31m* \e[0merror creating RPC handle for \"%s\": \e[1;4;31mmessage\e[0m: \"%s\"\n", name, rpch->lastRpcError().c_str());
+		}
+	}
+	else{
+		//printf("\e[1;32m* \e[0mread handle for  attribute \"%s\" was already created (host \"%s\":%d\n", name, rpch->host().c_str(), rpch->port());
+	}
+	if(rpch && rpch->connected())
+		d_connected = true;
+	else
+		d_connected = false;
+	if(rpch)
+	{
+		rpch->_refcnt++;
+		rrpch = new RPCReadHandle(rpch);
+	}
+}
+
+/* read write attribute */
+BridgeAttr::BridgeAttr(const char *name, const char *wname, long data_type,Tango::AttrWriteType w_type) :
+                        Attr(name, data_type, w_type) 
+{
+	rpch = RPCHandleSet::instance()->handleFromList(name);
+	if(!rpch)
+	{
+		rpch = new RPCHandle(name);
+		if(rpch && rpch->connected())
+			RPCHandleSet::instance()->addHandle(rpch);
+		else if(rpch){
+			//printf("\e[1;31m* \e[0merror creating RPC handle for \"%s\": \e[1;4;31mmessage\e[0m: \"%s\"\n", 
+					//name, rpch->lastRpcError().c_str());
+		}
+	}
+	else{
+		//printf("\e[1;32m* \e[0mread handle for  attribute \"%s\" was already created (host \"%s\":%d\n", name, rpch->host().c_str(), rpch->port());
+	}
+	
+	if(rpch && rpch->connected())
+		d_connected = true;
+	else
+		d_connected = false;
+	if(rpch)
+	{
+		rpch->_refcnt++;
+		rrpch = new RPCReadHandle(rpch);
+		wrpch = new RPCWriteHandle(rpch);
+	}
+	d_writeName = string(wname);
+}
+
+
+SpectrumBridgeAttr::SpectrumBridgeAttr(const char *name,long data_type,Tango::AttrWriteType w_type, long max_x)
+	: SpectrumAttr(name, data_type, w_type, max_x)
+{
+	rpch = RPCHandleSet::instance()->handleFromList(name);
+	if(!rpch)
+	{
+		rpch = new RPCHandle(name);
+		if(rpch && rpch->connected())
+			RPCHandleSet::instance()->addHandle(rpch);
+		else if(rpch){
+			//printf("\e[1;31m* \e[0merror creating RPC handle for SPECTRUM \"%s\": \e[1;4;31mmessage\e[0m: \"%s\"\n", name, rpch->lastRpcError().c_str());
+		}
+	}
+	else{
+		//printf("\e[1;32m* \e[0mread handle for spectrum attribute \"%s\" was already created (host \"%s\":%d\n", name, rpch->host().c_str(), rpch->port());
+	}
+	if(rpch && rpch->connected())
+		d_connected = true;
+	else
+		d_connected = false;
+	if(rpch)
+	{
+		rpch->_refcnt++;
+		rrpch =new  RPCReadHandle(rpch);
+	}
+}
+
+std::string BridgeAttr::host()
+{
+	if(rpch && rpch->connected())
+		return rpch->host();
+	return string("unconnected");
+}
+
+unsigned short BridgeAttr::port()
+{
+	if(rpch && rpch->connected())
+		return rpch->port();
+	return 0;
+}
+
+string SpectrumBridgeAttr::host()
+{
+	if(rpch && rpch->connected())
+		return rpch->host();
+	return string("unconnected");
+}
+
+unsigned short SpectrumBridgeAttr::port()
+{
+	if(rpch && rpch->connected())
+		return rpch->port();
+	return 0;
+}
+
+
+/* destructors: called by delete_device() */
+SpectrumBridgeAttr::~SpectrumBridgeAttr()
+{
+	if(rpch)
+		rpch->_refcnt--;
+	if(rpch && !rpch->_refcnt)
+	{
+		//printf("\e[1;32m x\e[0m deleting rpc handle linked to spectrum attribute \"%s\"\n", get_name().c_str());
+		RPCHandleSet::instance()->removeHandle(rpch);
+		delete rpch;
+	}
+	else{
+		//printf("\e[1;35m *\e[0m rpc handle linked to \"%s\"  still referenced by %d attributes, not freeing\n", get_name().c_str(), rpch->_refcnt);
+	}
+}
+
+BridgeAttr::~BridgeAttr()
+{
+	if(rpch)
+		rpch->_refcnt--;
+	if(rpch && !rpch->_refcnt)
+	{
+		//printf("\e[1;32m x\e[0m deleting rpc handle linked to scalar attribute \"%s\"\n", get_name().c_str());
+		RPCHandleSet::instance()->removeHandle(rpch);
+		delete rpch;
+	}
+	else{
+		//printf("\e[1;35m *\e[0m rpc handle linked to \"%s\"  still referenced by %d attributes, not freeing\n", get_name().c_str(), rpch->_refcnt);
+	}
+}
+
+} /* namespace ends */
+
+
+
+
diff --git a/BridgeAttr.h b/BridgeAttr.h
new file mode 100644
index 0000000..8a7e6bf
--- /dev/null
+++ b/BridgeAttr.h
@@ -0,0 +1,86 @@
+#ifndef _BRIDGE_ATTR_H
+#define _BRIDGE_ATTR_H
+
+#include <tango.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <RPC2TangoBridge.h>
+#include <RpcReadHandle.h>
+#include <RpcWriteHandle.h>
+
+using namespace Tango;
+
+namespace RPC2TangoBridge_ns
+{
+
+class BridgeAttr : public Tango::Attr
+{
+	public:
+		/** Constructor for Tango::READ attributes (read only )
+		 */
+		BridgeAttr(const char *name,long data_type,Tango::AttrWriteType w_type);
+		
+		/** Constructor for Tango::READ_WRITE attributes (scalar only). Wants a writeName as parameter, 
+		 * that indicates the RPC call to execute when writing attribute.
+		 */
+		BridgeAttr(const char *name, const char* writeName, long data_type,Tango::AttrWriteType w_type);
+
+		~BridgeAttr() ;
+		virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
+			{(static_cast<RPC2TangoBridge *>(dev))->read_BridgeAttr(att);}
+		virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att)
+			{(static_cast<RPC2TangoBridge *>(dev))->write_BridgeAttr(att);}
+		virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
+			{return (static_cast<RPC2TangoBridge *>(dev))->is_BridgeAttr_allowed(ty);}
+
+		RPCHandle *rpcHandle() { return rpch; }
+		
+		std::string host();
+		unsigned short port();
+		
+		bool connected() { return d_connected; }
+		
+		void setRpcWriteHandle(RPCWriteHandle *h) { wrpch = h; }
+		RPCWriteHandle *rpcWriteHandle() { return wrpch; }
+		
+		RPCReadHandle *rpcReadHandle() { return rrpch; }
+		
+		string writeName() { return d_writeName; }
+
+	private:
+		RPCHandle *rpch;
+		RPCWriteHandle *wrpch;
+		RPCReadHandle *rrpch;
+		std::string d_writeName;
+		bool d_connected;
+};
+
+class SpectrumBridgeAttr : public Tango::SpectrumAttr
+{
+	public:
+		SpectrumBridgeAttr(const char *name,long data_type,Tango::AttrWriteType w_type, long max_x);
+		~SpectrumBridgeAttr();
+
+		 virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
+                        {(static_cast<RPC2TangoBridge *>(dev))->read_BridgeAttr(att);}
+                virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
+                        {return (static_cast<RPC2TangoBridge *>(dev))->is_BridgeAttr_allowed(ty);}
+
+		RPCHandle *rpcHandle() { return rpch; }
+		RPCReadHandle *rpcReadHandle() { return rrpch; }
+		bool connected() { return d_connected; }
+			
+		string host();
+		unsigned short port();
+		
+        private:
+                RPCHandle *rpch;
+		RPCWriteHandle *wrpch;
+		RPCReadHandle *rrpch;
+		bool d_connected;
+};
+
+
+} /* namespace RPC2TangoBridge_ns */
+#endif
+
diff --git a/BridgeAttribute.h b/BridgeAttribute.h
new file mode 100644
index 0000000..2451217
--- /dev/null
+++ b/BridgeAttribute.h
@@ -0,0 +1,42 @@
+#ifndef _BRIDGE_ATTR_H
+#define _BRIDGE_ATTR_H
+
+#include <tango.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <RPC2TangoBridge.h>
+
+using namespace Tango;
+
+class BridgeAttr : public Tango::Attr
+{
+	public:
+		BridgeAttr(const char *name,long data_type,Tango::AttrWriteType w_type) :
+			Attr(name, data_type, w_type) {};
+		BridgeAttr(const char *name,long data_type,Tango::AttrWriteType w_type, string host, 
+				unsigned short port) :
+			Attr(name, data_type, w_type), rpchost(host), rpcport(port), rpcname(string(name)) {};
+
+		~BridgeAttr() {};
+		virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
+			{(static_cast<RPC2TangoBridge *>(dev))->read_AlarmAttribute(att);}
+		virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
+			{return (static_cast<RPC2TangoBridge *>(dev))->is_AlarmAttribute_allowed(ty);}
+
+		string rpcHost() {return rpchost; }
+		unsigned short rpcPort() { return rpcport; }
+		string rpcName() { return rpcname; }
+		bool rpcConnected() { return connected; }
+
+	private:
+		string rpchost;
+		string rpcname;
+		unsigned short rpcport;
+		bool connected;
+};
+
+
+
+
+#endif
+
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..68d32ab
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,9 @@
+2012/03/12 - release_02
+- rimossi tutti i printf, in attesa di usare DEBUG_STREAM
+- compilato con tango 7.2.6
+
+2012/11/30 relase_03
+- risolto ticket 928: must free sequences aftre reading
+
+2013/03/06 release_04
+- compilato con tango-8.0.5
diff --git a/ClassFactory.cpp b/ClassFactory.cpp
new file mode 100644
index 0000000..3587dcb
--- /dev/null
+++ b/ClassFactory.cpp
@@ -0,0 +1,47 @@
+static const char *RcsId = "$Header: /home/cvsadm/cvsroot/elettra/server/RPC2TangoBridge/ClassFactory.cpp,v 1.1.1.1 2008-04-28 09:13:16 giacomo Exp $";
+//+=============================================================================
+//
+// file :        ClassFactory.cpp
+//
+// description : C++ source for the class_factory method of the DServer
+//               device class. This method is responsible to create
+//               all class singletin for a device server. It is called
+//               at device server startup
+//
+// project :     TANGO Device Server
+//
+// $Author: giacomo $
+//
+// $Revision: 1.1.1.1 $
+//
+// $Log: ClassFactory.cpp,v $
+// Revision 1.1.1.1  2008-04-28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :    European Synchrotron Radiation Facility
+//               BP 220, Grenoble 38043
+//               FRANCE
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+
+#include <tango.h>
+#include <RPC2TangoBridgeClass.h>
+
+/**
+ *	Create RPC2TangoBridgeClass singleton and store it in DServer object.
+ */
+
+void Tango::DServer::class_factory()
+{
+
+	add_class(RPC2TangoBridge_ns::RPC2TangoBridgeClass::init("RPC2TangoBridge"));
+
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d513ada
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,193 @@
+#=============================================================================
+#
+# file :        Makefile
+#
+# description : Include for the RPC2TangoBridge class.
+#
+# project :     Makefile to generate a Tango server
+#
+# $Author: claudio $
+#
+# $Revision: 1.8 $
+#
+#
+# copyleft :    European Synchrotron Radiation Facility
+#               BP 220, Grenoble 38043
+#               FRANCE
+#
+#=============================================================================
+#  		This file is generated by POGO
+#	(Program Obviously used to Generate tango Object)
+#
+#         (c) - Software Engineering Group - ESRF
+#=============================================================================
+#
+
+CLASS      = RPC2TangoBridge
+MAJOR_VERS = 1
+MINOR_VERS = 1
+RELEASE    = Release_$(MAJOR_VERS)_$(MINOR_VERS)
+
+#-----------------------------------------
+#	Set default home directories
+#-----------------------------------------
+
+TANGO_HOME   =  /usr/local/tango-9.2.5a
+OMNI_HOME = /usr/local/omniorb-4.2.1
+ZMQ_HOME = //usr/local/zeromq-4.0.7
+CPP_SERVERS  =  $(TANGO_HOME)/cppserver
+
+
+
+#ifdef no_debug
+	DEBUG = -O2
+#else
+#	DEBUG = -g
+#endif
+
+CC = c++
+CC_SHLIB = $(CC)  -fPIC
+AR = ar
+
+AR_SL = $(CC) -fPIC -shared 
+SL_EXT = so
+VERS_OPT = -Wl,-soname,
+
+INCLUDE_DIRS =  -I$(TANGO_HOME)/include/tango \
+					 -I$(OMNI_HOME)/include \
+					 -I$(ZMQ_HOME)/include \
+					 -I.	\
+                -I$(CPP_SERVERS)/include -I/runtime/elettra/include
+
+SERVER_DIR  = ./rpcserver
+OBJS_DIR    = obj
+LIB_DIRS    = -L $(TANGO_HOME)/lib -L $(OMNI_HOME)/lib -L$(ZMQ_HOME)/lib -L/runtime/elettra/lib
+
+TARGET_LIB = $(CPP_SERVERS)/lib/libtgclasses.a
+
+
+#-----------------------------------------
+#	Set  CXXFLAGS and LFLAGS
+#-----------------------------------------
+
+
+CXXFLAGS =  -std=c++0x $(DEBUG) -D_REENTRANT $(INCLUDE_DIRS)
+LFLAGS =  $(DEBUG) $(LIB_DIRS)  		\
+				-ltango		\
+				-llog4tango	\
+				-lomniORB4 	\
+				-lomniDynamic4	\
+				-lomnithread	\
+				-lCOS4		\
+				-lzmq		\
+				-ldl -lpthread -llpc -lnc \
+				-lRpcResolver -llpcresolve
+
+
+
+
+#-----------------------------------------
+#	Set  dependences
+#-----------------------------------------
+
+DEPENDPATH += $(SERVER_DIR)
+
+SVC_OBJS = $(OBJS_DIR)/main.o	\
+		$(OBJS_DIR)/ClassFactory.o	\
+		$(OBJS_DIR)/$(CLASS)Class.o	\
+		$(OBJS_DIR)/$(CLASS)StateMachine.o	\
+		$(OBJS_DIR)/$(CLASS).o \
+		$(OBJS_DIR)/RPC2TangoBridgeThread.o	\
+		$(OBJS_DIR)/BridgeAttr.o	\
+		$(OBJS_DIR)/RpcHandle.o	$(OBJS_DIR)/RpcWriteHandle.o	\
+		$(OBJS_DIR)/read_dynamic_attribute.o	\
+		$(OBJS_DIR)/write_dynamic_attribute.o	\
+		$(OBJS_DIR)/attribute_converter.o \
+		$(OBJS_DIR)/RPCHandleSet.o \
+		$(OBJS_DIR)/RpcReadHandle.o
+
+SHLIB_OBJS = 	$(OBJS_DIR)/RPC2TangoBridgeThread.so.o \
+		$(OBJS_DIR)/$(CLASS)Class.so.o	\
+		$(OBJS_DIR)/$(CLASS)StateMachine.so.o	\
+		$(OBJS_DIR)/$(CLASS).so.o
+
+
+SVC_INC = $(CLASS)Class.h \
+		RPC2TangoBridgeThread.h \
+		BridgeAttr.h \
+		RpcHandle.h \
+		RpcWriteHandle.h \
+		attribute_converter.h \
+		RPCHandleSet.h \
+		RpcReadHandle.h \
+		$(CLASS).h
+
+
+$(OBJS_DIR)/%.o: %.cpp $(SVC_INC)
+	$(CC) $(CXXFLAGS) -c $< -o $(OBJS_DIR)/$*.o
+			
+$(OBJS_DIR)/%.so.o: %.cpp $(SVC_INC)
+	$(CC_SHLIB) $(CXXFLAGS) -c $< -o $(OBJS_DIR)/$*.so.o
+
+
+#-----------------------------------------
+#	 Make Entry
+#-----------------------------------------
+all: $(CLASS)
+	
+$(CLASS):	make_obj_dir make_bin_dir $(SVC_OBJS)
+	$(CC) $(SVC_OBJS) -o $(CLASS) $(LFLAGS)
+	@mv $(CLASS) bin/$(CLASS)
+
+shlib:	make_obj_dir make_shlib_dir $(SHLIB_OBJS)
+	$(AR_SL) -o \
+		shlib/$(CLASS).$(SL_EXT).$(MAJOR_VERS).$(MINOR_VERS) \
+		$(VERS_OPT)shlib/$(CLASS).$(SL_EXT).$(MAJOR_VERS) \
+		$(SHLIB_OBJS) $(LFLAGS)
+	@rm -f shlib/$(CLASS).$(SL_EXT)
+	@cd  shlib; \
+		ln -s $(CLASS).$(SL_EXT).$(MAJOR_VERS).$(MINOR_VERS) $(CLASS).$(SL_EXT)
+
+clean:
+	rm -f $(OBJS_DIR)/*.o  \
+	$(OBJS_DIR)/*.so.o \
+	bin/$(CLASS) \
+	core
+
+make_obj_dir:
+	@mkdir -p obj
+
+make_bin_dir:
+	@mkdir -p bin
+
+make_shlib_dir:
+	@mkdir -p shlib
+	
+#-----------------------------------------
+#	 Install binary file
+#-----------------------------------------
+install:
+	cp bin/$(CLASS)  $(TANGO_HOME)/bin
+
+#-----------------------------------------
+#	 Update class library and header files
+#	recompile without debug mode.
+#-----------------------------------------
+lib: clean
+	@make no_debug=1
+	cp *.h $(CPP_SERVERS)/include
+	ar ruv $(TARGET_LIB)/$(CLASS).o
+	ar ruv $(TARGET_LIB)/$(CLASS)Class.o
+	ar ruv $(TARGET_LIB)/$(CLASS)StateMachine.o
+	ident  $(TARGET_LIB)/* | grep $(CLASS)
+
+#----------------------------------------------------
+#	Tag the CVS module corresponding to this class
+#----------------------------------------------------
+tag:
+	@cvstag "$(CLASS)-$(RELEASE)"
+	@make   $(CLASS)
+	@make show_tag
+
+show_tag:
+	@cvstag -d 
diff --git a/README.md b/README.md
index 7c554bd..8d1c368 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,33 @@
-# rpc2tango-bridge
\ No newline at end of file
+## Project
+
+ rpc2tango-bridge
+
+## Description
+
+configurable bridge from Tango to legacy Elettra rpc control system protocol
+
+## Dependencies
+
+leagacy Elettra rpc libraries and services
+
+
+## Installation & deployment
+
+Follow standard C++ Tango device server installation guidelines
+
+## History
+
+2020-03-31 imported from CVS repo elettra/server/RPC2TangoBridge release_06
+
+## Credits
+
+developed by Giacomo Strangolino
+
+Elettra-Sincrotrone Trieste S.C.p.A. di interesse nazionale
+Strada Statale 14 - km 163,5 in AREA Science Park
+34149 Basovizza, Trieste ITALY
+
+## License
+
+GPL 3
+
diff --git a/RPC2TangoBridge.cpp b/RPC2TangoBridge.cpp
new file mode 100644
index 0000000..861222a
--- /dev/null
+++ b/RPC2TangoBridge.cpp
@@ -0,0 +1,564 @@
+static const char *RcsId = "$Header: /home/cvsadm/cvsroot/elettra/server/RPC2TangoBridge/RPC2TangoBridge.cpp,v 1.6 2017-03-28 09:39:02 claudio Exp $";
+//+=============================================================================
+//
+// file :         RPC2TangoBridge.cpp
+//
+// description :  C++ source for the RPC2TangoBridge and its commands. 
+//                The class is derived from Device. It represents the
+//                CORBA servant object which will be accessed from the
+//                network. All commands which can be executed on the
+//                RPC2TangoBridge are implemented in this file.
+//
+// project :      TANGO Device Server
+//
+// $Author: claudio $
+//
+// $Revision: 1.6 $
+//
+// $Log: RPC2TangoBridge.cpp,v $
+// Revision 1.6  2017-03-28 09:39:02  claudio
+// ticket 2413: tango-9
+//
+// Revision 1.5  2012-08-09 13:04:39  claudio
+// tango 4 impl
+//
+// Revision 1.4  2012-03-12 11:31:06  claudio
+// tango-7.2.6
+// rimossi "printf" ridondanti
+//
+// Revision 1.3  2009/08/19 07:37:57  giacomo
+// Correzioni al bridge e allineamento set point a read point in ogni
+// read attribute (per gli attributi RW).
+//
+// Revision 1.2  2009/02/26 08:15:45  giacomo
+// Versione di RPC2TangoBridge con supporto ad attributi SCALARI READ WRITE.
+// La parte WRITE va specificata nelle device properties separata da : dalla
+// parte rpc read.
+//
+// Revision 1.1.1.1  2008/04/28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :     European Synchrotron Radiation Facility
+//                BP 220, Grenoble 38043
+//                FRANCE
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+
+
+//===================================================================
+//
+//	The following table gives the correspondance
+//	between commands and method's name.
+//
+//  Command's name       |  Method's name
+//	----------------------------------------
+//  State                |  dev_state()
+//  Status               |  dev_status()
+//  RPCDataForAttribute  |  rpcdata_for_attribute()
+//  Standby              |  standby()
+//  On                   |  on()
+//
+//===================================================================
+
+
+#include <tango.h>
+#include <RPC2TangoBridge.h>
+#include <RPC2TangoBridgeClass.h>
+#include <RPC2TangoBridgeThread.h>
+#include <BridgeAttr.h>
+#include <RpcHandle.h>
+#include <RPCHandleSet.h>
+#include <attribute_converter.h>
+#include <errno.h>
+
+
+using namespace Tango;
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::RPC2TangoBridge(string &s)
+// 
+// description : 	constructor for simulated RPC2TangoBridge
+//
+// in : - cl : Pointer to the DeviceClass object
+//      - s : Device name 
+//
+//-----------------------------------------------------------------------------
+RPC2TangoBridge::RPC2TangoBridge(Tango::DeviceClass *cl,string &s)
+:TANGO_BASE_CLASS(cl,s.c_str())
+{
+	init_device();
+}
+
+RPC2TangoBridge::RPC2TangoBridge(Tango::DeviceClass *cl,const char *s)
+:TANGO_BASE_CLASS(cl,s)
+{
+	init_device();
+}
+
+RPC2TangoBridge::RPC2TangoBridge(Tango::DeviceClass *cl,const char *s,const char *d)
+:TANGO_BASE_CLASS(cl,s,d)
+{
+	init_device();
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::delete_device()
+// 
+// description : 	will be called at device destruction or at init command.
+//
+//-----------------------------------------------------------------------------
+
+void RPC2TangoBridge::delete_device()
+{
+	//	Delete device's allocated object
+	int cnt = 0, handlecnt = 0;
+	int totatt;
+	set_state(Tango::CLOSE);
+	set_status("deallocating attributes and freeing resources");
+
+	//printf("\e[1;32m*\e[0m freeing RPC resources and deleting dynamic attributes...\n");
+
+	totatt = namesMap.size() + spectrumNamesMap.size();
+
+	map<string, BridgeAttr* >::iterator mapiter;
+	/* NOTE: tango: device.c if  an attribute already exists, the new attribute is deleted!
+	 * So: remove all attributes in delete device.
+	 */
+	for(mapiter = namesMap.begin(); mapiter != namesMap.end(); mapiter++)
+	{
+		//printf("\e[1;32mx\e[0m removing scalar dynamic attribute \"%s\"\n", (*mapiter).second->get_name().c_str());
+		try{
+			remove_attribute((*mapiter).second, true);
+		}
+		catch(Tango::DevFailed &e)
+		{
+			//printf("\e[1;31m*\e[0m error removing attribute: \"%s\"", (*mapiter).second->get_name().c_str());
+			Tango::Except::print_exception(e);
+		}
+	}
+ 	namesMap.erase(namesMap.begin(), namesMap.end());
+	
+	map<string, SpectrumBridgeAttr* >::iterator spmapiter;
+	for(spmapiter = spectrumNamesMap.begin(); spmapiter != spectrumNamesMap.end(); spmapiter++)
+	{
+		//printf("\e[1;32mx\e[0m removing spectrum dynamic attribute \"%s\"\n", (*spmapiter).second->get_name().c_str());
+		try{
+			remove_attribute((*spmapiter).second, true);	
+		}
+		catch(Tango::DevFailed &e)
+		{
+			//printf("\e[1;31m* \e[0merror removing attribute: \"%s\"", (*mapiter).second->get_name().c_str());
+			Tango::Except::print_exception(e);
+		}
+	}
+	spectrumNamesMap.erase(spectrumNamesMap.begin(), spectrumNamesMap.end());
+	
+	/* do not clear() RPCHandleSet here: if we restart device the order of  attribute re-creation and destruction would 
+	 * make the server crash. Indeed, the reference count of the handle would be 0 and so freed in an unappropriate 
+	 * instant. On the other hand, if the server is restarted, we do not exit and the set remains alive and initialized.
+	*/
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::init_device()
+// 
+// description : 	will be called at device initialization.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridge::init_device()
+{
+	set_state(Tango::INIT);
+	INFO_STREAM << "RPC2TangoBridge::RPC2TangoBridge() create device " << device_name << endl;
+
+	// Initialise variables to default values
+	//--------------------------------------------
+	set_state(Tango::INIT);
+	set_status("Reading device properties");
+	get_device_property();
+
+	/* Now let's allocate the dynamic attributes whose name 
+	 * is taken from the configuration file.
+	 */
+	set_status("Allocating dynamic attributes");
+
+	AllocateAttributes();
+	set_state(Tango::ON);
+	set_status("ON");
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::get_device_property()
+// 
+// description : 	Read the device properties from database.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridge::get_device_property()
+{
+	//	Initialize your default values here (if not done with  POGO).
+	//------------------------------------------------------------------
+
+	//	Read device properties from database.(Automatic code generation)
+	//------------------------------------------------------------------
+	Tango::DbData	dev_prop;
+	dev_prop.push_back(Tango::DbDatum("Rpc_items"));
+
+	//	Call database and extract values
+	//--------------------------------------------
+	if (Tango::Util::instance()->_UseDb==true)
+		get_db_device()->get_property(dev_prop);
+	Tango::DbDatum	def_prop, cl_prop;
+	RPC2TangoBridgeClass	*ds_class =
+		(static_cast<RPC2TangoBridgeClass *>(get_device_class()));
+	int	i = -1;
+
+	//	Try to initialize Rpc_items from class property
+	cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+	if (cl_prop.is_empty()==false)	cl_prop  >>  rpc_items;
+	//	Try to initialize Rpc_items from default device value
+	def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+	if (def_prop.is_empty()==false)	def_prop  >>  rpc_items;
+	//	And try to extract Rpc_items value from database
+	if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  rpc_items;
+
+
+
+	//	End of Automatic code generation
+	//------------------------------------------------------------------
+	DEBUG_STREAM << rpc_items.size() << "rpc items " <<  endl;
+
+}
+
+/* NOTE: careful: add_attribute deletes an attribute with the same name if it was 
+ * already created!
+ */
+void RPC2TangoBridge::AllocateAttributes()
+{
+	int i = 0, totatt = 0, j;
+	char rpcentity[MAXLEN];
+
+	UserDefaultAttrProp default_att_prop;
+	
+// 	printf("\e[1;32m* \e[0mCreating dynamic attributes...\n");
+// 	printf("\e[1;33m*\e[0m If you want to remove an attribute from the\n"
+// 		"\e[1;33m*\e[0m list in the \e[1;4;37mdevice properties\e[0m, remember\n"
+// 		"\e[1;33m*\e[0m first to \e[1;4;37mdisable polling\e[0m and to restore\n"
+// 		"\e[1;33m*\e[0m any modified attribute property to its default.\n"
+// 		"\e[1;33m*\e[0m Otherwise you will not be able to start this server\n"
+// 		"\e[1;33m*\e[0m until references to no more existing attributes remain\n"
+// 		"\e[1;33m*\e[0m on the \e[1;4;37mtango database\e[0m.\n\n");
+
+	/* rpc_items is a vector of strings, got from init_device and loaded
+	 * from the DeviceProperties.
+	 */
+// 	totatt = rpc_items.size();
+// 
+// 	if(totatt == 0)
+// 	{
+// // 		printf("\e[1;31mNo RPC entities specified as device properties\n\e[0m");
+// // 		printf("\e[1;32mhint\e[0m: Define some entries and restart the device server\n\n");
+// 		//exit(EXIT_SUCCESS);
+// 	}
+
+	for(i = 0; i < rpc_items.size(); i++)
+	{
+// 		printf("\n- rpc_items %d:\"%s\"\n", i, rpc_items[i].c_str());
+		memset(rpcentity, 0, MAXLEN);
+		strncpy(rpcentity, rpc_items[i].c_str(), MAXLEN - 1);
+// 		print_progress(totatt, i);
+
+		bool force_is_spectrum = force_spectrum(rpcentity);
+		map<string, BridgeAttr*> ::iterator scalarMapIter = namesMap.find(string(rpcentity));
+		map<string, SpectrumBridgeAttr*> ::iterator spectrumMapIter = spectrumNamesMap.find(string(rpcentity));
+		if( scalarMapIter != namesMap.end() || spectrumMapIter != spectrumNamesMap.end() )
+		{
+			/* WARNING: do not add_attribute() two times with the same NAME! */
+			//printf("\e[1;31m* \e[0mthe element \"\e[1;31m%s\e[0m\" is duplicated: not adding it again\n", rpcentity);
+		}
+		else
+		{
+			try
+			{
+				AttributeConverter tangoAttr(rpcentity);
+				if(tangoAttr.isSpectrum())
+				{
+					SpectrumBridgeAttr* spattr = tangoAttr.spectrumAttribute();
+					string name(spattr->get_name());
+					if(spattr != NULL && spattr->connected())
+					{
+						DEBUG_STREAM << "Aggiunto alla mappa con nome " << name << " e " << spattr->get_name() << " 0x" << spattr << endl;
+						spectrumNamesMap[name] = spattr;
+						add_attribute(spattr);
+					}
+					
+				}
+				else
+				{
+					BridgeAttr * att = tangoAttr.scalarAttribute();
+					string name(att->get_name());
+					if(att != NULL && att->connected())
+					{
+						/* insert the couple attribute name/BridgeAttr* into the names map */
+						namesMap[name] = att; 
+						add_attribute(att);
+					}
+					
+				}
+			}
+			catch(Tango::DevFailed &e)
+			{
+				printException("Error creating attribute", e);	
+			}
+		} /* else: element not already present in the map */
+	}
+	RPCHandleSet::instance()->handleCount();
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::always_executed_hook()
+// 
+// description : 	method always executed before any command is executed
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridge::always_executed_hook()
+{
+	
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::read_attr_hardware
+// 
+// description : 	Hardware acquisition for attributes.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridge::read_attr_hardware(vector<long> &attr_list)
+{
+	DEBUG_STREAM << "RPC2TangoBridge::read_attr_hardware(vector<long> &attr_list) entering... "<< endl;
+
+//	Add your own code here
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::read_AlarmAttribute
+// 
+// description : 	Extract real attribute values for AlarmAttribute acquisition result.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridge::read_BridgeAttr(Tango::Attribute &attr)
+{
+	DEBUG_STREAM << "RPC2TangoBridge::read_AlarmAttribute(Tango::Attribute &attr) entering... "<< endl;
+
+	read_dynamic_attribute(attr);
+}
+
+void RPC2TangoBridge::write_BridgeAttr(Tango::WAttribute &attr)
+{
+	bool res;
+	DEBUG_STREAM<<"write_BridgeAttr()" << endl;
+	res = write_dynamic_attribute(attr);
+	if(!res)
+		Except::throw_exception("Error writing attribute " + attr.get_name(),
+				"Probably the format is not supported.\nSupported formats: long, double, short, boolean - SCALARS -",
+				"RPC2TangoBridge::write_BridgeAttr()");
+}
+
+void RPC2TangoBridge::print_progress(int tot, int part)
+{
+        return;
+//         const int numbars_tot = 20;
+//         int current_bar = part * 20 / tot;
+//         int i = 0;
+//         int percent = part * 100 / tot;
+//         printf("\r             \r");
+//         //printf("\r\b\b\b\b\b\b\b\b\b\b\b\b\r");
+//         fflush(stdout);
+//         if(part < tot)
+//         {
+//                 if(part % 4 == 0)
+//                         printf("|");
+//                 else if(part % 4 == 1)
+//                         printf( "\\");
+//                 else if(part % 4 == 2)
+//                         printf("-");
+//                 else if(part % 4 == 3)
+//                         printf("/");
+//                 fflush(stdout);
+//                 printf("\t[%d%%]", percent);
+//         }
+//         fflush(stdout);
+}
+
+void RPC2TangoBridge::printException(const char* msg, Tango::DevFailed &e)
+{
+	string err, descr, orig;
+        int i;
+        for(i = e.errors.length() - 1; i >= 0;  i--)
+        {
+                err = e.errors[i].reason;
+                descr = e.errors[i].desc;
+                orig = e.errors[i].origin;
+	}
+// 	printf("\n* \e[1;31m%s:\e[0m\n\t%s\n\t%s\n\t%s\n\e[0m", msg, err.c_str(), 
+// 		descr.c_str(), orig.c_str());
+}
+
+//+------------------------------------------------------------------
+/**
+ *	method:	RPC2TangoBridge::rpcdata_for_attribute
+ *
+ *	description:	method to execute "RPCDataForAttribute"
+ *	[3]the connection state (connected,disconnected)
+ *
+ * @param	argin	The name of an attribute representing an RPC call, such as SIP120_S2.1_PRES_RR
+ * @return	Three values: [1]the RPC host name; [2]the RPC port; [3]the connection state (connected,disconnected)
+ *
+ */
+//+------------------------------------------------------------------
+Tango::DevVarStringArray *RPC2TangoBridge::rpcdata_for_attribute(Tango::DevString argin)
+{
+	//	POGO has generated a method core with argout allocation.
+	//	If you would like to use a static reference without copying,
+	//	See "TANGO Device Server Programmer's Manual"
+	//		(chapter : Writing a TANGO DS / Exchanging data)
+	//------------------------------------------------------------
+	Tango::DevVarStringArray	*argout  = new Tango::DevVarStringArray();
+	DEBUG_STREAM << "RPC2TangoBridge::rpcdata_for_attribute(): entering... !" << endl;
+
+	//	Add your own code to control device here
+	bool found = true;
+	map<string, BridgeAttr*>::iterator smapiter;
+	RPCHandle *handle = NULL;
+	map<string, SpectrumBridgeAttr*>::iterator spmapiter;
+	char port[8];
+
+	for(smapiter= namesMap.begin(); smapiter != namesMap.end(); smapiter++)
+	{
+		if(!strcmp(smapiter->first.c_str(), argin))
+		{
+			handle = smapiter->second->rpcHandle();
+			break;
+		}
+	}
+	for(spmapiter= spectrumNamesMap.begin(); spmapiter != spectrumNamesMap.end(); spmapiter++)
+	{
+		if(!strcmp(spmapiter->first.c_str(), argin))
+		{
+			handle = spmapiter->second->rpcHandle();
+			break;
+		}
+	}
+	if(smapiter == namesMap.end() && spmapiter == spectrumNamesMap.end())
+		found = false;
+
+	/* could avoid found variable and test for NULL, but this gives the possibility
+	 * to have an attribute with a handle NULL
+	 */
+	if(!found)
+	{
+		argout->length(1);
+		(*argout)[0] = CORBA::string_dup("No attribute with that name!");
+	}
+	else if(handle == NULL)
+	{
+		argout->length(1);
+		(*argout)[0] = CORBA::string_dup("invalid handle: this won't work");
+	}
+	else
+	{
+		argout->length(3);
+		(*argout)[0] = CORBA::string_dup(handle->host().c_str());
+		snprintf(port, 8, "%d", handle->port());
+		(*argout)[1] = CORBA::string_dup(port);
+		if(handle->connected())
+			(*argout)[2] = CORBA::string_dup("connected");
+		else
+			(*argout)[2] = CORBA::string_dup("disconnected");
+	}		
+	
+	return argout;
+}
+
+//+------------------------------------------------------------------
+/**
+ *	method:	RPC2TangoBridge::standby
+ *
+ *	description:	method to execute "Standby"
+ *	Puts the server in Standby mode: RPC calls are disabled.
+ *
+ *
+ */
+//+------------------------------------------------------------------
+void RPC2TangoBridge::standby()
+{
+	DEBUG_STREAM << "RPC2TangoBridge::standby(): entering... !" << endl;
+
+	//	Add your own code to control device here
+	set_state(Tango::STANDBY);
+	set_status("Standby mode: no RPC calls will be made");
+
+}
+
+bool RPC2TangoBridge::is_BridgeAttr_allowed(Tango::AttReqType type)
+{
+	if(get_state() != Tango::ON)
+		return false;
+	else 
+		return true;
+}
+
+//+------------------------------------------------------------------
+/**
+ *	method:	RPC2TangoBridge::on
+ *
+ *	description:	method to execute "On"
+ *	From the Standby state, the command On enables the RPC calls again.
+ *
+ *
+ */
+//+------------------------------------------------------------------
+void RPC2TangoBridge::on()
+{
+	DEBUG_STREAM << "RPC2TangoBridge::on(): entering... !" << endl;
+
+	//	Add your own code to control device here
+	set_state(Tango::ON);
+	set_status("On: RPC calls enabled");
+}
+
+
+
+bool RPC2TangoBridge::force_spectrum(char *s)
+{
+	int i;
+	for(i = 0; i < strlen(s); i++)
+		if(s[i] == ',')
+			break;
+	if(i == strlen(s))
+		return false;
+	if(strncmp(s + i + 1, "spectrum", strlen("spectrum")) == 0)
+	{
+		s[i] = '\0'; /* remove the spectrum force keyword */
+		return true;
+	}
+	return false;
+
+}
+
+}	//	namespace
diff --git a/RPC2TangoBridge.h b/RPC2TangoBridge.h
new file mode 100644
index 0000000..870ff36
--- /dev/null
+++ b/RPC2TangoBridge.h
@@ -0,0 +1,271 @@
+//=============================================================================
+//
+// file :        RPC2TangoBridge.h
+//
+// description : Include for the RPC2TangoBridge class.
+//
+// project :	Provides a conversion from RPC alarms to Tango alarm attributes.
+//
+// $Author: claudio $
+//
+// $Revision: 1.4 $
+//
+// $Log: RPC2TangoBridge.h,v $
+// Revision 1.4  2017-03-28 09:39:02  claudio
+// ticket 2413: tango-9
+//
+// Revision 1.3  2012-08-09 13:04:39  claudio
+// tango 4 impl
+//
+// Revision 1.2  2009/02/26 08:15:45  giacomo
+// Versione di RPC2TangoBridge con supporto ad attributi SCALARI READ WRITE.
+// La parte WRITE va specificata nelle device properties separata da : dalla
+// parte rpc read.
+//
+// Revision 1.1.1.1  2008/04/28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :    European Synchrotron Radiation Facility
+//               BP 220, Grenoble 38043
+//               FRANCE
+//
+//=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+#ifndef _RPCALARMTANGO_H
+#define _RPCALARMTANGO_H
+
+#include <tango.h>
+#include <map>
+//#include "RPC2TangoBridgeThread.h"
+
+
+using namespace Tango;
+using namespace std;
+
+/**
+ * @author	$Author: claudio $
+ * @version	$Revision: 1.4 $
+ */
+
+ //	Add your own constants definitions here.
+ //-----------------------------------------------
+
+
+namespace RPC2TangoBridge_ns
+{
+
+class RPC2TangoBridgeThread;
+class BridgeAttr;
+class SpectrumBridgeAttr;
+class RPCHandle;
+
+/**
+ * Class Description:
+ * Every RPC client who emits alarms will send them to this server.
+ *	RPCAlarmTAngo will then map every alarm into a specific Tango attribute, so
+ *	that it can be notified to the Tango Alarm System.
+ *	The Tango Alarm System has to subscribe to all the attributes managed by this
+ *	RPC2TangoBridge.
+ */
+
+/*
+ *	Device States Description:
+*  Tango::ON :       The device is in on state: the dynamic attributes have been allocated and
+ *                    the server is ready for read operations on the RPC handles.
+*  Tango::INIT :     The server is allocating the dynamic attributes.
+ *                    The server is reading the device property named Rpc_items and for each line
+ *                    is allocating a new dynamic attribute that maps the RPC call into a READ ONLY
+ *                    tango attribute.
+*  Tango::FAULT :    A read attribute failed.
+ *                    This can be a transitional state, when an RPC call fails for instance, and so
+ *                    it can appear for a short time and then resolve to the ON state when the next
+ *                    read ends successfully.
+ *                    Anyway, a persistent state of FAULT can indicate network problems or
+ *                    continuous failures in reads.
+*  Tango::CLOSE :    Deallocating dynamic attributes and exiting
+*  Tango::STANDBY :  In this state the RPC calls are disabled.
+ */
+
+
+class RPC2TangoBridge: public TANGO_BASE_CLASS
+{
+public :
+	//	Add your own data members here
+	//----------------------------------------
+//	void read_AlarmAttribute(Attribute attr);
+//	void write_AlarmAttribute(WAttribute &att);
+//	bool is_AlarmAttribute_allowed(Tango::AttReqType ty);
+	//	Here is the Start of the automatic code generation part
+	//-------------------------------------------------------------	
+/**
+ *	@name attributes
+ *	Attributs member data.
+ */
+//@{
+//@}
+
+/**
+ *	@name Device properties
+ *	Device properties member data.
+ */
+//@{
+/**
+ *	Here you have to put the list of rpc items.
+ *	An RPC item is made up of RPCNAME:RPCHOST:RPCPORT, for instance:
+ *	PSB_T2.2_STAT_RF:rpcpsb.domain.com:9100
+ */
+	vector<string>	rpc_items;
+//@}
+
+/**@name Constructors
+ * Miscellaneous constructors */
+//@{
+/**
+ * Constructs a newly allocated Command object.
+ *
+ *	@param cl	Class.
+ *	@param s 	Device Name
+ */
+	RPC2TangoBridge(Tango::DeviceClass *cl,string &s);
+/**
+ * Constructs a newly allocated Command object.
+ *
+ *	@param cl	Class.
+ *	@param s 	Device Name
+ */
+	RPC2TangoBridge(Tango::DeviceClass *cl,const char *s);
+/**
+ * Constructs a newly allocated Command object.
+ *
+ *	@param cl	Class.
+ *	@param s 	Device name
+ *	@param d	Device description.
+ */
+	RPC2TangoBridge(Tango::DeviceClass *cl,const char *s,const char *d);
+//@}
+
+/**@name Destructor
+ * Only one desctructor is defined for this class */
+//@{
+/**
+ * The object desctructor.
+ */	
+	~RPC2TangoBridge() {delete_device();};
+/**
+ *	will be called at device destruction or at init command.
+ */
+	void delete_device();
+//@}
+
+	
+/**@name Miscellaneous methods */
+//@{
+/**
+ *	Initialize the device
+ */
+	virtual void init_device();
+/**
+ *	Always executed method befor execution command method.
+ */
+	virtual void always_executed_hook();
+
+//@}
+
+/**
+ * @name RPC2TangoBridge methods prototypes
+ */
+
+//@{
+/**
+ *	Execution allowed for RPCDataForAttribute command.
+ */
+	virtual bool is_RPCDataForAttribute_allowed(const CORBA::Any &any);
+/**
+ *	Execution allowed for Standby command.
+ */
+	virtual bool is_Standby_allowed(const CORBA::Any &any);
+/**
+ *	Execution allowed for On command.
+ */
+	virtual bool is_On_allowed(const CORBA::Any &any);
+/**
+ * [3]the connection state (connected,disconnected)
+ *	@param	argin	The name of an attribute representing an RPC call, such as SIP120_S2.1_PRES_RR
+ *	@return	Three values: [1]the RPC host name; [2]the RPC port; [3]the connection state (connected,disconnected)
+ *	@exception DevFailed
+ */
+	Tango::DevVarStringArray	*rpcdata_for_attribute(Tango::DevString);
+/**
+ * Puts the server in Standby mode: RPC calls are disabled.
+ *	@exception DevFailed
+ */
+	void	standby();
+/**
+ * From the Standby state, the command On enables the RPC calls again.
+ *	@exception DevFailed
+ */
+	void	on();
+
+/**
+ *	Read the device properties from database
+ */
+	 void get_device_property();
+//@}
+
+	//	Here is the end of the automatic code generation part
+	//-------------------------------------------------------------	
+	/* Returns the configuration */
+////	map<const char*, struct alarm_tango_info*>  *TangoAlarmMap() { return &tangoalmap; }
+
+	 /**
+	 *	Read/Write allowed for BridgeAttr attribute.
+	 */
+	virtual bool is_BridgeAttr_allowed(Tango::AttReqType type);
+
+	/**
+	 *	Extract real attribute values for BridgeAttr acquisition result.
+	 */
+	virtual void read_BridgeAttr(Tango::Attribute &attr);
+	
+	/**
+ 	*      Write attribute values to hardware.
+ 	*/
+        virtual void write_BridgeAttr(Tango::WAttribute &attr);
+
+
+	void read_attr_hardware(std::vector<long int, std::allocator<long int> >&);
+
+protected :	
+	//	Add your own data members here
+	//-----------------------------------------
+	
+		
+	Tango::DevShort btest1, btest2;		
+	RPC2TangoBridgeThread *rpcthread;
+private:
+	void AllocateAttributes();
+
+	void print_progress(int tot, int part);
+	
+	map<string, BridgeAttr*> namesMap;
+	map<string, SpectrumBridgeAttr*> spectrumNamesMap;
+
+	map<BridgeAttr*, const char*> lpcHostsMap;
+	
+	void read_dynamic_attribute(Tango::Attribute &attr);
+	bool write_dynamic_attribute(Tango::WAttribute &w);
+	void printException(const char* msg, Tango::DevFailed &e);
+	bool force_spectrum(char* device_property);
+	
+//	Tango::DevShort *attr_AlarmAttribute_read;
+};
+
+}	// namespace_ns
+
+#endif	// _RPCALARMTANGO_H
diff --git a/RPC2TangoBridgeClass.cpp b/RPC2TangoBridgeClass.cpp
new file mode 100644
index 0000000..ca87e86
--- /dev/null
+++ b/RPC2TangoBridgeClass.cpp
@@ -0,0 +1,501 @@
+static const char *RcsId     = "$Header: /home/cvsadm/cvsroot/elettra/server/RPC2TangoBridge/RPC2TangoBridgeClass.cpp,v 1.1.1.1 2008-04-28 09:13:16 giacomo Exp $";
+static const char *TagName   = "$Name:  $";
+static const char *HttpServer= "http://www.esrf.fr/computing/cs/tango/tango_doc/ds_doc/";
+//+=============================================================================
+//
+// file :        RPC2TangoBridgeClass.cpp
+//
+// description : C++ source for the RPC2TangoBridgeClass. A singleton
+//               class derived from DeviceClass. It implements the
+//               command list and all properties and methods required
+//               by the RPC2TangoBridge once per process.
+//
+// project :     TANGO Device Server
+//
+// $Author: giacomo $
+//
+// $Revision: 1.1.1.1 $
+//
+// $Log: RPC2TangoBridgeClass.cpp,v $
+// Revision 1.1.1.1  2008-04-28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :   European Synchrotron Radiation Facility
+//              BP 220, Grenoble 38043
+//              FRANCE
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+
+#include <tango.h>
+
+#include <RPC2TangoBridge.h>
+#include <RPC2TangoBridgeClass.h>
+
+
+//+----------------------------------------------------------------------------
+/**
+ *	Create RPC2TangoBridgeClass singleton and return it in a C function for Python usage
+ */
+//+----------------------------------------------------------------------------
+extern "C" {
+#ifdef WIN32
+
+__declspec(dllexport)
+
+#endif
+
+	Tango::DeviceClass *_create_RPC2TangoBridge_class(const char *name) {
+		return RPC2TangoBridge_ns::RPC2TangoBridgeClass::init(name);
+	}
+}
+
+
+namespace RPC2TangoBridge_ns
+{
+//+----------------------------------------------------------------------------
+//
+// method : 		OnClass::execute()
+// 
+// description : 	method to trigger the execution of the command.
+//                PLEASE DO NOT MODIFY this method core without pogo   
+//
+// in : - device : The device on which the command must be excuted
+//		- in_any : The command input data
+//
+// returns : The command output data (packed in the Any object)
+//
+//-----------------------------------------------------------------------------
+CORBA::Any *OnClass::execute(Tango::DeviceImpl *device,const CORBA::Any &in_any)
+{
+
+	cout2 << "OnClass::execute(): arrived" << endl;
+
+	((static_cast<RPC2TangoBridge *>(device))->on());
+	return new CORBA::Any();
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		StandbyClass::execute()
+// 
+// description : 	method to trigger the execution of the command.
+//                PLEASE DO NOT MODIFY this method core without pogo   
+//
+// in : - device : The device on which the command must be excuted
+//		- in_any : The command input data
+//
+// returns : The command output data (packed in the Any object)
+//
+//-----------------------------------------------------------------------------
+CORBA::Any *StandbyClass::execute(Tango::DeviceImpl *device,const CORBA::Any &in_any)
+{
+
+	cout2 << "StandbyClass::execute(): arrived" << endl;
+
+	((static_cast<RPC2TangoBridge *>(device))->standby());
+	return new CORBA::Any();
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPCDataForAttributeCmd::execute()
+// 
+// description : 	method to trigger the execution of the command.
+//                PLEASE DO NOT MODIFY this method core without pogo   
+//
+// in : - device : The device on which the command must be excuted
+//		- in_any : The command input data
+//
+// returns : The command output data (packed in the Any object)
+//
+//-----------------------------------------------------------------------------
+CORBA::Any *RPCDataForAttributeCmd::execute(Tango::DeviceImpl *device,const CORBA::Any &in_any)
+{
+
+	cout2 << "RPCDataForAttributeCmd::execute(): arrived" << endl;
+
+	Tango::DevString	argin;
+	extract(in_any, argin);
+
+	return insert((static_cast<RPC2TangoBridge *>(device))->rpcdata_for_attribute(argin));
+}
+
+
+
+
+
+
+
+//
+//----------------------------------------------------------------
+//	Initialize pointer for singleton pattern
+//----------------------------------------------------------------
+//
+RPC2TangoBridgeClass *RPC2TangoBridgeClass::_instance = NULL;
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::RPC2TangoBridgeClass(string &s)
+// 
+// description : 	constructor for the RPC2TangoBridgeClass
+//
+// in : - s : The class name
+//
+//-----------------------------------------------------------------------------
+RPC2TangoBridgeClass::RPC2TangoBridgeClass(string &s):DeviceClass(s)
+{
+
+	cout2 << "Entering RPC2TangoBridgeClass constructor" << endl;
+	set_default_property();
+	write_class_property();
+	get_class_property();
+	
+	cout2 << "Leaving RPC2TangoBridgeClass constructor" << endl;
+
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::~RPC2TangoBridgeClass()
+// 
+// description : 	destructor for the RPC2TangoBridgeClass
+//
+//-----------------------------------------------------------------------------
+RPC2TangoBridgeClass::~RPC2TangoBridgeClass()
+{
+	_instance = NULL;
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::instance
+// 
+// description : 	Create the object if not already done. Otherwise, just
+//			return a pointer to the object
+//
+// in : - name : The class name
+//
+//-----------------------------------------------------------------------------
+RPC2TangoBridgeClass *RPC2TangoBridgeClass::init(const char *name)
+{
+	if (_instance == NULL)
+	{
+		try
+		{
+			string s(name);
+			_instance = new RPC2TangoBridgeClass(s);
+		}
+		catch (bad_alloc)
+		{
+			throw;
+		}		
+	}		
+	return _instance;
+}
+
+RPC2TangoBridgeClass *RPC2TangoBridgeClass::instance()
+{
+	if (_instance == NULL)
+	{
+		cerr << "Class is not initialised !!" << endl;
+		exit(-1);
+	}
+	return _instance;
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::command_factory
+// 
+// description : 	Create the command object(s) and store them in the 
+//			command list
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridgeClass::command_factory()
+{
+	command_list.push_back(new RPCDataForAttributeCmd("RPCDataForAttribute",
+		Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+		"The name of an attribute representing an RPC call, such as SIP120_S2.1_PRES_RR",
+		"Three values: [1]the RPC host name; [2]the RPC port; [3]the connection state (connected,disconnected)",
+		Tango::OPERATOR));
+	command_list.push_back(new StandbyClass("Standby",
+		Tango::DEV_VOID, Tango::DEV_VOID,
+		"",
+		"",
+		Tango::OPERATOR));
+	command_list.push_back(new OnClass("On",
+		Tango::DEV_VOID, Tango::DEV_VOID,
+		"",
+		"",
+		Tango::OPERATOR));
+
+	//	add polling if any
+	for (unsigned int i=0 ; i<command_list.size(); i++)
+	{
+	}
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::get_class_property
+// 
+// description : 	Get the class property for specified name.
+//
+// in :		string	name : The property name
+//
+//+----------------------------------------------------------------------------
+Tango::DbDatum RPC2TangoBridgeClass::get_class_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<cl_prop.size() ; i++)
+		if (cl_prop[i].name == prop_name)
+			return cl_prop[i];
+	//	if not found, return  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::get_default_device_property()
+// 
+// description : 	Return the default value for device property.
+//
+//-----------------------------------------------------------------------------
+Tango::DbDatum RPC2TangoBridgeClass::get_default_device_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<dev_def_prop.size() ; i++)
+		if (dev_def_prop[i].name == prop_name)
+			return dev_def_prop[i];
+	//	if not found, return  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::get_default_class_property()
+// 
+// description : 	Return the default value for class property.
+//
+//-----------------------------------------------------------------------------
+Tango::DbDatum RPC2TangoBridgeClass::get_default_class_property(string &prop_name)
+{
+	for (unsigned int i=0 ; i<cl_def_prop.size() ; i++)
+		if (cl_def_prop[i].name == prop_name)
+			return cl_def_prop[i];
+	//	if not found, return  an empty DbDatum
+	return Tango::DbDatum(prop_name);
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::device_factory
+// 
+// description : 	Create the device object(s) and store them in the 
+//			device list
+//
+// in :		Tango::DevVarStringArray *devlist_ptr : The device name list
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridgeClass::device_factory(const Tango::DevVarStringArray *devlist_ptr)
+{
+
+	//	Create all devices.(Automatic code generation)
+	//-------------------------------------------------------------
+	for (unsigned long i=0 ; i < devlist_ptr->length() ; i++)
+	{
+		cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl;
+						
+		// Create devices and add it into the device list
+		//----------------------------------------------------
+		device_list.push_back(new RPC2TangoBridge(this, (*devlist_ptr)[i]));							 
+
+		// Export device to the outside world
+		// Check before if database used.
+		//---------------------------------------------
+		if ((Tango::Util::_UseDb == true) && (Tango::Util::_FileDb == false))
+			export_device(device_list.back());
+		else
+			export_device(device_list.back(), (*devlist_ptr)[i]);
+	}
+	//	End of Automatic code generation
+	//-------------------------------------------------------------
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::get_class_property()
+// 
+// description : 	Read the class properties from database.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridgeClass::get_class_property()
+{
+	//	Initialize your default values here (if not done with  POGO).
+	//------------------------------------------------------------------
+
+	//	Read class properties from database.(Automatic code generation)
+	//------------------------------------------------------------------
+
+	//	Call database and extract values
+	//--------------------------------------------
+	if (Tango::Util::instance()->_UseDb==true)
+		get_db_class()->get_property(cl_prop);
+	Tango::DbDatum	def_prop;
+	int	i = -1;
+
+
+	//	End of Automatic code generation
+	//------------------------------------------------------------------
+
+}
+
+//+----------------------------------------------------------------------------
+//
+// method : 	RPC2TangoBridgeClass::set_default_property
+// 
+// description: Set default property (class and device) for wizard.
+//              For each property, add to wizard property name and description
+//              If default value has been set, add it to wizard property and
+//              store it in a DbDatum.
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridgeClass::set_default_property()
+{
+	string	prop_name;
+	string	prop_desc;
+	string	prop_def;
+
+	vector<string>	vect_data;
+	//	Set Default Class Properties
+	//	Set Default Device Properties
+	prop_name = "Rpc_items";
+	prop_desc = "Here you have to put the list of rpc items.\nAn RPC item is made up of RPCNAME:RPCHOST:RPCPORT, for instance:\nPSB_T2.2_STAT_RF:rpcpsb.domain.com:9100";
+	prop_def  = "";
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridgeClass::write_class_property
+// 
+// description : 	Set class description as property in database
+//
+//-----------------------------------------------------------------------------
+void RPC2TangoBridgeClass::write_class_property()
+{
+	//	First time, check if database used
+	//--------------------------------------------
+	if (Tango::Util::_UseDb == false)
+		return;
+
+	Tango::DbData	data;
+	string	classname = get_name();
+	string	header;
+	string::size_type	start, end;
+
+	//	Put title
+	Tango::DbDatum	title("ProjectTitle");
+	string	str_title("Provides a conversion from RPC alarms to Tango alarm attributes.");
+	title << str_title;
+	data.push_back(title);
+
+	//	Put Description
+	Tango::DbDatum	description("Description");
+	vector<string>	str_desc;
+	str_desc.push_back("Every RPC client who emits alarms will send them to this server.");
+	str_desc.push_back("RPCAlarmTAngo will then map every alarm into a specific Tango attribute, so");
+	str_desc.push_back("that it can be notified to the Tango Alarm System.");
+	str_desc.push_back("The Tango Alarm System has to subscribe to all the attributes managed by this");
+	str_desc.push_back("RPC2TangoBridge.");
+	description << str_desc;
+	data.push_back(description);
+		
+	//	put cvs location
+	string	rcsId(RcsId);
+	string	filename(classname);
+	start = rcsId.find("/");
+	if (start!=string::npos)
+	{
+		filename += "Class.cpp";
+		end   = rcsId.find(filename);
+		if (end>start)
+		{
+			string	strloc = rcsId.substr(start, end-start);
+			//	Check if specific repository
+			start = strloc.find("/cvsroot/");
+			if (start!=string::npos && start>0)
+			{
+				string	repository = strloc.substr(0, start);
+				if (repository.find("/segfs/")!=string::npos)
+					strloc = "ESRF:" + strloc.substr(start, strloc.length()-start);
+			}
+			Tango::DbDatum	cvs_loc("cvs_location");
+			cvs_loc << strloc;
+			data.push_back(cvs_loc);
+		}
+	}
+
+	//	Get CVS tag revision
+	string	tagname(TagName);
+	header = "$Name: ";
+	start = header.length();
+	string	endstr(" $");
+	end   = tagname.find(endstr);
+	if (end!=string::npos && end>start)
+	{
+		string	strtag = tagname.substr(start, end-start);
+		Tango::DbDatum	cvs_tag("cvs_tag");
+		cvs_tag << strtag;
+		data.push_back(cvs_tag);
+	}
+
+	//	Get URL location
+	string	httpServ(HttpServer);
+	if (httpServ.length()>0)
+	{
+		Tango::DbDatum	db_doc_url("doc_url");
+		db_doc_url << httpServ;
+		data.push_back(db_doc_url);
+	}
+
+	//  Put inheritance
+	Tango::DbDatum	inher_datum("InheritedFrom");
+	vector<string> inheritance;
+	inheritance.push_back("Device_3Impl");
+	inher_datum << inheritance;
+	data.push_back(inher_datum);
+
+	//	Call database and and values
+	//--------------------------------------------
+	get_db_class()->put_property(data);
+}
+
+}	// namespace
diff --git a/RPC2TangoBridgeClass.h b/RPC2TangoBridgeClass.h
new file mode 100644
index 0000000..57b1406
--- /dev/null
+++ b/RPC2TangoBridgeClass.h
@@ -0,0 +1,161 @@
+//=============================================================================
+//
+// file :         RPC2TangoBridgeClass.h
+//
+// description :  Include for the RPC2TangoBridgeClass root class.
+//                This class is represents the singleton class for
+//                the RPC2TangoBridge device class.
+//                It contains all properties and methods which the 
+//                RPC2TangoBridge requires only once e.g. the commands.
+//			
+// project :      TANGO Device Server
+//
+// $Author: giacomo $
+//
+// $Revision: 1.1.1.1 $
+//
+// $Log: RPC2TangoBridgeClass.h,v $
+// Revision 1.1.1.1  2008-04-28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :     European Synchrotron Radiation Facility
+//                BP 220, Grenoble 38043
+//                FRANCE
+//
+//=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+#ifndef _RPCALARMTANGOCLASS_H
+#define _RPCALARMTANGOCLASS_H
+
+#include <tango.h>
+#include <RPC2TangoBridge.h>
+
+
+namespace RPC2TangoBridge_ns
+{
+//=====================================
+//	Define classes for attributes
+//=====================================
+//=========================================
+//	Define classes for commands
+//=========================================
+class OnClass : public Tango::Command
+{
+public:
+	OnClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	OnClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~OnClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<RPC2TangoBridge *>(dev))->is_On_allowed(any);}
+};
+
+
+
+class StandbyClass : public Tango::Command
+{
+public:
+	StandbyClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	StandbyClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~StandbyClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<RPC2TangoBridge *>(dev))->is_Standby_allowed(any);}
+};
+
+
+
+class RPCDataForAttributeCmd : public Tango::Command
+{
+public:
+	RPCDataForAttributeCmd(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	RPCDataForAttributeCmd(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~RPCDataForAttributeCmd() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<RPC2TangoBridge *>(dev))->is_RPCDataForAttribute_allowed(any);}
+};
+
+
+
+//
+// The RPC2TangoBridgeClass singleton definition
+//
+
+class RPC2TangoBridgeClass : public Tango::DeviceClass
+{
+public:
+//	properties member data
+
+//	add your own data members here
+//------------------------------------
+
+public:
+	Tango::DbData	cl_prop;
+	Tango::DbData	cl_def_prop;
+	Tango::DbData	dev_def_prop;
+
+//	Method prototypes
+	static RPC2TangoBridgeClass *init(const char *);
+	static RPC2TangoBridgeClass *instance();
+	~RPC2TangoBridgeClass();
+	Tango::DbDatum	get_class_property(string &);
+	Tango::DbDatum	get_default_device_property(string &);
+	Tango::DbDatum	get_default_class_property(string &);
+	
+protected:
+	RPC2TangoBridgeClass(string &);
+	static RPC2TangoBridgeClass *_instance;
+	void command_factory();
+	void get_class_property();
+	void write_class_property();
+	void set_default_property();
+
+private:
+	void device_factory(const Tango::DevVarStringArray *);
+};
+
+
+}	//	namespace RPC2TangoBridge_ns
+
+#endif // _RPC2TANGOBRIDGECLASS_H
diff --git a/RPC2TangoBridgeStateMachine.cpp b/RPC2TangoBridgeStateMachine.cpp
new file mode 100644
index 0000000..8cd9e8a
--- /dev/null
+++ b/RPC2TangoBridgeStateMachine.cpp
@@ -0,0 +1,116 @@
+static const char *RcsId = "$Header: /home/cvsadm/cvsroot/elettra/server/RPC2TangoBridge/RPC2TangoBridgeStateMachine.cpp,v 1.1.1.1 2008-04-28 09:13:16 giacomo Exp $";
+//+=============================================================================
+//
+// file :         RPC2TangoBridgeStateMachine.cpp
+//
+// description :  C++ source for the RPC2TangoBridge and its alowed. 
+//                method for commands and attributes
+//
+// project :      TANGO Device Server
+//
+// $Author: giacomo $
+//
+// $Revision: 1.1.1.1 $
+//
+// $Log: RPC2TangoBridgeStateMachine.cpp,v $
+// Revision 1.1.1.1  2008-04-28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :     European Synchrotron Radiation Facility
+//                BP 220, Grenoble 38043
+//                FRANCE
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+#include <tango.h>
+#include <RPC2TangoBridge.h>
+#include <RPC2TangoBridgeClass.h>
+
+/*====================================================================
+ *	This file contains the methods to allow commands and attributes
+ * read or write execution.
+ *
+ * If you wand to add your own code, add it between 
+ * the "End/Re-Start of Generated Code" comments.
+ *
+ * If you want, you can also add your own methods.
+ *====================================================================
+ */
+
+namespace RPC2TangoBridge_ns
+{
+
+//=================================================
+//		Attributes Allowed Methods
+//=================================================
+
+
+//=================================================
+//		Commands Allowed Methods
+//=================================================
+
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::is_RPCDataForAttribute_allowed
+// 
+// description : 	Execution allowed for RPCDataForAttribute command.
+//
+//-----------------------------------------------------------------------------
+bool RPC2TangoBridge::is_RPCDataForAttribute_allowed(const CORBA::Any &any)
+{
+		//	End of Generated Code
+
+		//	Re-Start of Generated Code
+	return true;
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::is_Standby_allowed
+// 
+// description : 	Execution allowed for Standby command.
+//
+//-----------------------------------------------------------------------------
+bool RPC2TangoBridge::is_Standby_allowed(const CORBA::Any &any)
+{
+	if (get_state() == Tango::INIT	||
+		get_state() == Tango::FAULT	||
+		get_state() == Tango::CLOSE	||
+		get_state() == Tango::STANDBY)
+	{
+		//	End of Generated Code
+
+		//	Re-Start of Generated Code
+		return false;
+	}
+	return true;
+}
+//+----------------------------------------------------------------------------
+//
+// method : 		RPC2TangoBridge::is_On_allowed
+// 
+// description : 	Execution allowed for On command.
+//
+//-----------------------------------------------------------------------------
+bool RPC2TangoBridge::is_On_allowed(const CORBA::Any &any)
+{
+	if (get_state() == Tango::ON	||
+		get_state() == Tango::INIT	||
+		get_state() == Tango::FAULT	||
+		get_state() == Tango::CLOSE)
+	{
+		//	End of Generated Code
+
+		//	Re-Start of Generated Code
+		return false;
+	}
+	return true;
+}
+
+}	// namespace RPC2TangoBridge_ns
diff --git a/RPC2TangoBridgeThread.cpp b/RPC2TangoBridgeThread.cpp
new file mode 100644
index 0000000..b9c307b
--- /dev/null
+++ b/RPC2TangoBridgeThread.cpp
@@ -0,0 +1,32 @@
+#include "RPC2TangoBridge.h"
+#include <iostream>
+#include "RPC2TangoBridgeThread.h"
+
+class RPC2TangoBridge;
+
+namespace RPC2TangoBridge_ns
+{
+
+RPC2TangoBridgeThread::RPC2TangoBridgeThread(RPC2TangoBridge* parent)
+{
+	tango_server = parent;
+	
+}
+
+RPC2TangoBridgeThread::~RPC2TangoBridgeThread()
+{
+
+}
+
+/* Calling this makes the server loop break */
+void RPC2TangoBridgeThread::stop_loop()
+{
+}
+
+void *RPC2TangoBridgeThread::RPC2TangoBridgeThread::run_undetached(void *data)
+{
+	return NULL;
+}
+
+}
+
diff --git a/RPC2TangoBridgeThread.h b/RPC2TangoBridgeThread.h
new file mode 100644
index 0000000..1f34698
--- /dev/null
+++ b/RPC2TangoBridgeThread.h
@@ -0,0 +1,28 @@
+#ifndef RPCALARM_THREAD_H
+#define RPCALARM_THREAD_H
+
+#include <omnithread.h>
+#include "RPC2TangoBridge.h"
+
+class RPC2TangoBridge;
+
+namespace RPC2TangoBridge_ns
+{
+
+class RPC2TangoBridgeThread : public omni_thread
+{
+	public:
+	  	RPC2TangoBridgeThread(RPC2TangoBridge* parent);
+		void StartUndetached() { start_undetached(); }
+		void stop_loop();
+		~RPC2TangoBridgeThread();
+	
+	private:
+		void* run_undetached(void *arg);
+		RPC2TangoBridge *tango_server;
+		
+};
+
+};
+
+#endif
diff --git a/RPCHandleSet.cpp b/RPCHandleSet.cpp
new file mode 100644
index 0000000..06d111e
--- /dev/null
+++ b/RPCHandleSet.cpp
@@ -0,0 +1,124 @@
+#include "RPCHandleSet.h"
+namespace RPC2TangoBridge_ns
+{
+
+RPCHandleSet* RPCHandleSet::_instance = NULL;
+
+RPCHandleSet::RPCHandleSet()
+{
+	
+}
+
+RPCHandleSet *RPCHandleSet::instance()
+{
+	if(_instance == NULL)
+		_instance = new RPCHandleSet();
+	return _instance;
+}
+	
+
+RPCReadHandle *RPCHandleSet::readHandleFromList(const char *rpc_call)
+{
+	int i, res;
+	RPCReadHandle *han;
+	char *host;
+	short int port;
+	res = RPCHandle::resolve_rpc(rpc_call, &host, &port);
+	if(host != NULL && res >= 0)
+	{
+		/* in host and port we have the host and port of the rpc service for that call */
+		for(i = 0; i < rpcRHandles.size(); i++)
+		{
+			han = rpcRHandles[i];
+			/* we must exclude the handles with host and port uninitialized */
+			if(han != NULL && han->host() != "" && han->port() != 0 &&
+					han->host() == string(host) && han->port() == port)
+				return han;
+		}
+	}
+	return NULL;
+}
+
+RPCWriteHandle *RPCHandleSet::writeHandleFromList(const char *rpc_call)
+{
+	int i, res;
+	RPCWriteHandle *han;
+	char *host;
+	short int port;
+	res = RPCHandle::resolve_rpc(rpc_call, &host, &port);
+	if(host != NULL && res >= 0)
+	{
+		/* in host and port we have the host and port of the rpc service for that call */
+		for(i = 0; i < rpcWHandles.size(); i++)
+		{
+			han = rpcWHandles[i];
+			/* we must exclude the handles with host and port uninitialized */
+			if(han != NULL && han->host() != "" && han->port() != 0 &&
+					han->host() == string(host) && han->port() == port)
+				return han;
+		}
+	}
+	return NULL;
+}
+
+void RPCHandleSet::removeHandle(RPCHandle *h)
+{
+	int i;
+	for(i = 0; i < rpcHandles.size(); i++)
+	{
+		if(rpcHandles[i] == h)
+			break;
+	}
+	if(i < rpcHandles.size())
+	{
+		//printf(" - removing handle \"%s\":%d from list\n", rpcHandles[i]->host().c_str(), rpcHandles[i]->port());
+		rpcHandles.erase(rpcHandles.begin() + i);
+	}
+	else{
+		//printf("\e[1;31m *\e[0m error: handle  \"%s\":%d  not found in list!\n", rpcHandles[i]->host().c_str(), rpcHandles[i]->port());
+	}
+}
+
+RPCHandle *RPCHandleSet::handleFromList(const char *rpc_call)
+{
+	int i, res;
+	RPCHandle *han;
+	char *host;
+	short int port;
+	res = RPCHandle::resolve_rpc(rpc_call, &host, &port);
+	if(host != NULL && res >= 0)
+	{
+		/* in host and port we have the host and port of the rpc service for that call */
+		for(i = 0; i < rpcHandles.size(); i++)
+		{
+			han = rpcHandles[i];
+			/* we must exclude the handles with host and port uninitialized */
+			if(han != NULL && han->host() != "" && han->port() != 0 &&
+					han->host() == string(host) && han->port() == port)
+				return han;
+		}
+	}
+	return NULL;
+}
+
+void RPCHandleSet::addReadHandle(RPCReadHandle* h)
+{
+	rpcRHandles.push_back(h);
+}
+
+void RPCHandleSet::addWriteHandle(RPCWriteHandle* h)
+{
+	rpcWHandles.push_back(h);
+}
+
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/RPCHandleSet.h b/RPCHandleSet.h
new file mode 100644
index 0000000..21b3094
--- /dev/null
+++ b/RPCHandleSet.h
@@ -0,0 +1,43 @@
+#ifndef RPC_HANDLE_SET_H
+#define RPC_HANDLE_SET_H
+
+#include <vector>
+#include "RpcReadHandle.h"
+#include "RpcWriteHandle.h"
+namespace RPC2TangoBridge_ns
+{
+
+class RPCHandleSet
+{
+	public:
+		static RPCHandleSet *instance();
+		RPCReadHandle *readHandleFromList(const char *rpcname);
+		RPCWriteHandle *writeHandleFromList(const char *rpcname);
+		
+		RPCHandle *handleFromList(const char* rpcname);
+		
+		void addReadHandle(RPCReadHandle* h);
+		void addWriteHandle(RPCWriteHandle *h);
+		
+		void addHandle(RPCHandle* h) { rpcHandles.push_back(h); }
+		void removeHandle(RPCHandle *h);
+		
+		unsigned handleCount() { return rpcHandles.size(); }
+		
+		void clear() { rpcRHandles.clear(); rpcWHandles.clear();  rpcHandles.clear();  }
+		
+	private:
+		
+		RPCHandleSet();
+		static RPCHandleSet *_instance;
+		
+		vector<RPCReadHandle* > rpcRHandles;
+		vector<RPCWriteHandle* > rpcWHandles;
+
+		vector<RPCHandle* > rpcHandles;
+};
+
+}
+
+#endif
+
diff --git a/RpcHandle.cpp b/RpcHandle.cpp
new file mode 100644
index 0000000..01fdd61
--- /dev/null
+++ b/RpcHandle.cpp
@@ -0,0 +1,159 @@
+#include <RpcHandle.h>
+#include <omnithread.h>
+#include <RpcResolver.h>
+#include <errtype.h>
+#include <cstdlib>
+
+#define MAXERRLEN	512
+
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+static omni_mutex rpcMutex;
+
+RPCHandle::RPCHandle(RPCHandle *other)
+{
+	_host = other->host();
+	_port = other->port();
+	_sid = other->sid();
+	_refcnt = other->_refcnt;
+	_lastRpcErr = lastRpcError();
+	
+}
+
+RPCHandle::RPCHandle(string rpccall)
+{
+	char *host = 0;
+	short int port = 0;
+	_host = "";
+	_port = 0;
+	_sid = -1;
+	_refcnt = 0;
+	if(resolve_rpc(rpccall.c_str(), &host, &port))	
+	{
+		_host = string(host);
+		free(host);
+		_port = (unsigned short) port;
+		if(!connect())
+			_lastRpcErr = "Connection error to host " + _host;
+		else
+			_lastRpcErr = std::string("No error");
+	}
+	else /* do not connect(): this will leave _sid to -1 */
+		_lastRpcErr = "failed resolving call " + rpccall;
+	 
+}
+
+bool RPCHandle::resolve_rpc(const char *call, char** host, short int *port)
+{
+	int res;
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+
+	RpcResolver resolver;
+	if(split_rpccall(call, fam, mem, act, mode) >= 0)
+	{
+		res = resolver.resolve(fam, mem, act, mode, host, port);
+		if(res >= 0 && host != NULL)
+			return true;
+	}
+	return false;
+}
+
+RPCHandle::~RPCHandle()
+{
+	if(_sid >= 0)
+	{
+		//printf("\e[1;32m x\e[0m freeing RPC resource associated with host \"%s\" and port %d\n",_host.c_str(), _port);
+		free_lpc(_sid);
+		_sid = -1;
+	}
+	else{
+		//printf("\e[1;31m !\e[0m not freeing RPC resource associated with host \"%s\" and port %d\n",_host.c_str(), _port);
+	}
+}
+
+bool RPCHandle::lockRpc()
+{
+	rpcMutex.acquire();
+	return 1;
+}
+
+bool RPCHandle::unlockRpc()
+{
+	rpcMutex.release();
+	return 1;
+}
+
+/* this is private */
+bool RPCHandle::connect()
+{
+	if((_sid = import_lpc(_host.c_str(), _port)) >= 0)
+		return true;
+	else
+		return false;
+}
+
+bool RPCHandle::connected()
+{
+	if(_sid >= 0)
+		return true;
+	else
+		return false;
+}
+
+int RPCHandle::split_rpccall(const char *call, char* fam, char *mem, char* act, char* mode)
+{
+	int i = 0, delim1, delim2, delim3;
+	int underline_cnt = 0;
+	int calllen = strlen(call);
+
+	delim1 = delim2 = delim3 = -1;
+	memset(fam, 0, RPCSPLITLEN);
+	memset(mem, 0, RPCSPLITLEN);
+	memset(act, 0, RPCSPLITLEN);
+	memset(mode, 0, RPCSPLITLEN);
+
+	for(i = 0; i < strlen(call) && i < MAXLEN; i++)
+		if(call[i] == '_')
+			underline_cnt++;
+
+	if(underline_cnt != 3)
+	{
+		//printf("\e[1;31m*\e[0m Bad name  \"%s\"\n""  RPC calls must be in the form FAMILY_MEMBER_ACTION_MODE,\n""  separated by underline (\"_\")", call);
+		return -1;
+	}
+
+	for(i = 0; i < strlen(call) && i < MAXLEN; i++)
+	{
+		if(call[i] == '_')
+		{
+			if(delim1 < 0)
+				delim1 = i;
+			else if(delim2 < 0)
+				delim2 = i;
+			else if(delim3 < 0)
+				delim3 = i;
+		}
+	}
+	if(delim2 - delim1 >= RPCSPLITLEN || delim3 - delim2 >= RPCSPLITLEN || calllen - delim3 >= RPCSPLITLEN ||
+		delim1 >= RPCSPLITLEN)
+	{
+		//printf("\t\e[1;31m* \e[0mRPC call subparts too long in \"%s\"\n\t""  \e[1;4;35minfo\e[0m: maximum length: %d\n",call, RPCSPLITLEN);
+		return -1;
+	}
+
+	/* should be alright here: */
+	strncpy(fam, call, delim1);
+	strncpy(mem, call + delim1 + 1, delim2 - delim1 - 1);
+	strncpy(act, call + delim2 + 1, delim3 - delim2 - 1);
+	strncpy(mode, call + delim3 + 1, calllen - delim3 - 1);
+
+	return 0;
+}
+
+
+
+}
+
diff --git a/RpcHandle.h b/RpcHandle.h
new file mode 100644
index 0000000..c7f68bb
--- /dev/null
+++ b/RpcHandle.h
@@ -0,0 +1,64 @@
+#ifndef RPC_HANDLE_H
+#define RPC_HANDLE_H
+
+#include <iostream>
+#include <omnithread.h>
+#include <tango.h>
+#include <vector>
+#include <lpc.h>
+
+#define RPCSPLITLEN     32
+#define MAXLEN 256
+
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+class RPCHandle/*: public Tango::LogAdapter*/
+{
+	public: 
+		RPCHandle(string call);
+		RPCHandle(RPCHandle *other);
+		~RPCHandle();
+
+		std::string host() { return _host; }
+		unsigned short port() { return _port; }
+		int sid() { return _sid; }
+
+		bool connected(); 
+
+		bool operator==(const  RPCHandle &other) const  
+			{ return _host == other._host && _port == other._port; }
+	
+		bool lockRpc();
+		bool unlockRpc();
+
+		std::string lastRpcError() { return _lastRpcErr; } 
+		
+		static int split_rpccall(const char *call, char* fam, char *mem, char* act, char* mode);
+		/* returns true if resolve takes place */
+		static bool resolve_rpc(const char *call, char** host, short int *port);
+		
+		unsigned _refcnt;
+		
+	protected:
+		std::string _lastRpcErr;
+		int _sid;
+		
+	private:
+		std::string _host;
+		unsigned short _port;
+
+		bool connect();
+
+
+};
+
+
+
+} /* namespace RPC2TangoBridge_ns ends */
+
+
+#endif
+
+
diff --git a/RpcReadHandle.cpp b/RpcReadHandle.cpp
new file mode 100644
index 0000000..3d2312b
--- /dev/null
+++ b/RpcReadHandle.cpp
@@ -0,0 +1,464 @@
+#include "RpcReadHandle.h"
+
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+RPCReadHandle::RPCReadHandle(RPCHandle* h) : RPCHandle(h)
+{
+	
+}
+
+long int RPCReadHandle::read_long(const char *callname, int* ok)
+{
+	long int ret;
+	char error[MAXERRLEN];
+	long res = -1;
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RI") || !strcmp(mode, "RII"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RI"))
+			res = lpc_RI(fam, mem, act, mode, &ret);
+		else if(!strcmp(mode, "RII"))
+				res = lpc_RII(fam, mem, act, mode, &ret);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return ret;
+
+}
+
+double RPCReadHandle::read_double(const char *callname, int* ok)
+{
+	double ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RR") || !strcmp(mode, "RRI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RR"))
+			res = lpc_RR(fam, mem, act, mode, &ret);
+		else if(!strcmp(mode, "RRI"))
+				res = lpc_RRI(fam, mem, act, mode, &ret);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return ret;
+
+}
+
+unsigned char RPCReadHandle::read_uchar(const char *callname, int* ok)
+{
+	unsigned char ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RE") || !strcmp(mode, "REI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RE"))
+			res = lpc_RE(fam, mem, act, mode, &ret);
+		else if(!strcmp(mode, "REI"))
+			res = lpc_REI(fam, mem, act, mode, &ret);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return ret;
+
+}
+
+short int RPCReadHandle::read_short(const char *callname, int* ok)
+{
+	short ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RS") || !strcmp(mode, "RSI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RS"))
+			res = lpc_RS(fam, mem, act, mode, &ret);
+		else if(!strcmp(mode, "RSI"))
+			res = lpc_RSI(fam, mem, act, mode, &ret);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return ret;
+
+}
+
+string RPCReadHandle::read_string(const char *callname, int* ok)
+{
+	string ret;
+	long res = -1;
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+        char* strdata;
+        //idata.length = 0;
+        //idata.sequence = NULL;
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RM") || !strcmp(mode, "RMI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RM"))
+			res = lpc_RM(fam, mem, act, mode, &strdata);
+		else if(!strcmp(mode, "RMI"))
+			res = lpc_RMI(fam, mem, act, mode, &strdata);
+		/* else: res remains initialized to -1 and will fail */
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+			 ret = "There was an error reading the value";
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+	ret = string(strdata);
+        return ret;
+
+}
+
+unsigned char RPCReadHandle::read_boolean(const char *callname, int* ok)
+{
+	unsigned char ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RB") || !strcmp(mode, "RBI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RB"))
+			res = lpc_RB(fam, mem, act, mode, &ret);
+		else if(!strcmp(mode, "RBI"))
+			res = lpc_RBI(fam, mem, act, mode, &ret);
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return ret;
+
+}
+
+intArray RPCReadHandle::read_slong(const char *callname, int* ok)
+{
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	long res = -1;
+        intArray idata;
+        idata.length = 0;
+        idata.sequence = NULL;
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RAI") || !strcmp(mode, "RAII"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RAI"))
+			res = lpc_RAI(fam, mem, act, mode, &idata);
+		else if(!strcmp(mode, "RAII"))
+			res = lpc_RAII(fam, mem, act, mode, &idata);
+		/* else: res remains initialized to -1 and will fail */
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return idata;
+}
+
+realArray RPCReadHandle::read_sdouble(const char *callname, int* ok)
+{
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	long res = -1;
+        realArray rdata;
+        rdata.length = 0;
+        rdata.sequence = NULL;
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RAR") || !strcmp(mode, "RAIR"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RAR"))
+			res = lpc_RAR(fam, mem, act, mode, &rdata);
+		else if(!strcmp(mode, "RAIR"))
+			res = lpc_RAIR(fam, mem, act, mode, &rdata);
+		/* else: res remains initialized to -1 and will fail */
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return rdata;
+
+}
+
+shortArray RPCReadHandle::read_sshort(const char *callname, int* ok)
+{
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	long res = -1;
+        shortArray rdata;
+        rdata.length = 0;
+        rdata.sequence = NULL;
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RAS") || !strcmp(mode, "RAIS"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RAS"))
+			res = lpc_RAS(fam, mem, act, mode, &rdata);
+		else if(!strcmp(mode, "RAIS"))
+			res = lpc_RAIS(fam, mem, act, mode, &rdata);
+		/* else res remains initialized to -1 and will fail */
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return rdata;
+
+}
+
+charArray RPCReadHandle::read_schar(const char *callname, int* ok)
+{
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	long res = -1;
+        charArray rdata;
+        rdata.length = 0;
+        rdata.sequence = NULL;
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RAC") || !strcmp(mode, "RAIC"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "RAC"))
+			res = lpc_RAC(fam, mem, act, mode, &rdata);
+		else if(!strcmp(mode, "RAIC"))
+			res = lpc_RAIC(fam, mem, act, mode, &rdata);
+		/* else: res remains initialized to -1 and this will fail */	
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return rdata;
+
+}
+
+booleanArray RPCReadHandle::read_sboolean(const char *callname, int* ok)
+{
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	char error[MAXERRLEN];
+	*ok = 1;
+	/* acquire lock! */
+	// lockRpc();
+	long res = -1;
+        booleanArray rdata;
+        rdata.length = 0;
+        rdata.sequence = NULL;
+	long rfLong;
+	
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		*ok = 0;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "RF") || !strcmp(mode, "RFI"))
+		{
+			bind_lpc(_sid);
+			//printf("_sid: %d\n", _sid);
+			/* long int interpreted as array of 32 booleans */
+			if(!strcmp(mode, "RF"))
+				res = lpc_RF(fam, mem, act, mode, &rfLong);
+			else if(!strcmp(mode, "RFI"))
+				res = lpc_RFI(fam, mem, act, mode, &rfLong);
+			if(res >= 0) /* convert a long of 32 bit into a booleanArray */
+			{
+				rdata.length = 32;
+				rdata.sequence = (idl_boolean *)malloc(sizeof(idl_boolean) * 32);
+				for(int i = 0; i < 32; i++)
+					rdata.sequence[i] = (rfLong >> i) & 1;
+			}
+			else
+				_lastRpcErr = string("failed lpc_RF or lpc_RFI");
+		}
+		else if(!strcmp(mode, "RAB"))
+		{
+			bind_lpc(_sid);
+			res = lpc_RAB(fam, mem, act, mode, &rdata);
+		}
+		else if(!strcmp(mode, "RAIB"))
+		{
+			bind_lpc(_sid);
+			res = lpc_RAIB(fam, mem, act, mode, &rdata);
+		}
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error reading rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 *ok = 0;
+		}
+	}
+	/* release lock */
+	// unlockRpc();
+        return rdata;
+}
+
+
+
+} /* namespace */
+
+
diff --git a/RpcReadHandle.h b/RpcReadHandle.h
new file mode 100644
index 0000000..923db32
--- /dev/null
+++ b/RpcReadHandle.h
@@ -0,0 +1,37 @@
+#ifndef RPC_READ_HANDLE_H
+#define RPC_READ_HANDLE_H
+
+#include <string>
+#include <omnithread.h>
+#include <RpcResolver.h>
+#include "RpcHandle.h"
+#include <errtype.h>
+
+#define MAXERRLEN	512
+
+namespace RPC2TangoBridge_ns
+{
+	
+class RPCReadHandle : public RPCHandle
+{
+	public:
+		RPCReadHandle(RPCHandle *h);
+		
+		long int read_long(const char *callname, int* ok);
+		double read_double(const char *callname, int* ok);
+		short int read_short(const char *callname, int* ok);
+		unsigned char read_uchar(const char *callname, int* ok);
+		unsigned char read_boolean(const char *callname, int* ok);
+		string read_string(const char *callname, int* ok);
+
+		intArray read_slong(const char *callname, int* ok);
+		charArray read_schar(const char *callname, int* ok);
+		realArray read_sdouble(const char *callname, int* ok);
+		shortArray read_sshort(const char *callname, int* ok);
+		booleanArray read_sboolean(const char *callname, int* ok);
+	
+};
+
+}
+
+#endif
diff --git a/RpcWriteHandle.cpp b/RpcWriteHandle.cpp
new file mode 100644
index 0000000..f31c841
--- /dev/null
+++ b/RpcWriteHandle.cpp
@@ -0,0 +1,274 @@
+#include <RpcWriteHandle.h>
+#include <RpcResolver.h>
+#include <errtype.h>
+
+#define MAXERRLEN	512
+
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+static omni_mutex rpcMutex;
+
+RPCWriteHandle::RPCWriteHandle(RPCHandle *h) : RPCHandle(h)
+{
+	
+}
+
+RPCWriteHandle::~RPCWriteHandle()
+{
+	
+}
+
+bool RPCWriteHandle::write_long(const char *callname, long lvalue)
+{
+	bool ret;
+	char error[MAXERRLEN];
+	long res = -1;
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+		return false;
+	}
+//	printf("\e[1;32mWRITE\e[0m scrivo %ld su %s %s %s %s\n",lvalue,  fam, mem, act, mode);
+	
+	/* acquire lock! */
+	lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "WI") || !strcmp(mode, "WII"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "WI"))
+			res = lpc_WI(fam, mem, act, mode, &lvalue);
+		else if(!strcmp(mode, "WII"))
+				res = lpc_WII(fam, mem, act, mode, &lvalue);
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error writeing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+		}
+	}
+	/* release lock */
+	unlockRpc();
+        return ret;
+
+}
+
+bool RPCWriteHandle::write_double(const char *callname,  double dvalue)
+{
+	bool ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+		return false;
+	}
+//	printf("\e[1;32mWRITE\e[0m scrivo double %lf su %s %s %s %s\n",dvalue,  fam, mem, act, mode);
+
+	/* acquire lock! */
+	lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		ret = false;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "WR") || !strcmp(mode, "WRI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "WR"))
+			res = lpc_WR(fam, mem, act, mode, &dvalue);
+		else if(!strcmp(mode, "WRI"))
+				res = lpc_WRI(fam, mem, act, mode, &dvalue);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error writing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 ret = false;
+		}
+		else 
+			ret = true;
+	}
+	/* release lock */
+	unlockRpc();
+        return ret;
+}
+
+bool RPCWriteHandle::write_short(const char *callname, short svalue)
+{
+	bool ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	
+	/* acquire lock! */
+	lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		ret = false;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+	//	printf("\e[1;32mWRITE\e[0m scrivo SHORT %d su %s %s %s %s\n", svalue,  fam, mem, act, mode);
+		if(!strcmp(mode, "WS") || !strcmp(mode, "WSI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "WS"))
+			res = lpc_WS(fam, mem, act, mode, &svalue);
+		else if(!strcmp(mode, "WSI"))
+				res = lpc_WSI(fam, mem, act, mode, &svalue);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error writing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 ret = false;
+		}
+		else 
+			ret = true;
+	}
+	/* release lock */
+	unlockRpc();
+        return ret;
+}
+
+bool RPCWriteHandle::write_string(const char *callname, char **s)
+{
+	bool ret;
+// 	long res = -1;
+// 	char error[MAXERRLEN];
+// 	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+// 
+// 	/* acquire lock! */
+// 	lockRpc();
+// 	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+// 	{
+// 		ret = false;
+// 		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+// 	}
+// 	else
+// 	{
+// 		if(!strcmp(mode, "WR") || !strcmp(mode, "WRI"))
+// 			bind_lpc(_sid);
+// 		if(!strcmp(mode, "WR"))
+// 			res = lpc_WR(fam, mem, act, mode, &dvalue);
+// 		else if(!strcmp(mode, "WRI"))
+// 				res = lpc_WRI(fam, mem, act, mode, &dvalue);
+// 		
+// 		if(res < 0)
+// 		{
+// 			snprintf(error, MAXERRLEN, "Error writing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+// 				callname, errno, errtype, errstring);
+// 			 _lastRpcErr = string(error);
+// 			 ret = false;
+// 		}
+// 		else 
+// 			ret = true;
+// 	}
+// 	/* release lock */
+// 	unlockRpc();
+	//printf("\e[1;35m;4minfo\e[0m write_string not implemented yet\n");
+	ret  = -1;
+        return false;
+
+}
+
+bool RPCWriteHandle::write_boolean(const char *callname, bool bvalue)
+{
+	bool ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	unsigned char boolval;
+	if(bvalue)
+		boolval = 1;
+	else
+		boolval = 0;
+
+	/* acquire lock! */
+	lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		ret = false;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "WB") || !strcmp(mode, "WBI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "WB"))
+			res = lpc_WB(fam, mem, act, mode, &boolval);
+		else if(!strcmp(mode, "WBI"))
+				res = lpc_WBI(fam, mem, act, mode, &boolval);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error writing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 ret = false;
+		}
+		else 
+			ret = true;
+	}
+	/* release lock */
+	unlockRpc();
+        return ret;
+}
+
+
+bool RPCWriteHandle::write_void(const char *callname)
+{
+	bool ret;
+	long res = -1;
+	char error[MAXERRLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	unsigned char dummy;
+
+	/* acquire lock! */
+	lockRpc();
+	if(split_rpccall(callname, fam, mem, act, mode) < 0)
+	{
+		ret = false;
+		_lastRpcErr = string("Failed to split ")  + string(callname) + " into family, member, action, mode";
+	}
+	else
+	{
+		if(!strcmp(mode, "WP") || !strcmp(mode, "WPI"))
+			bind_lpc(_sid);
+		if(!strcmp(mode, "WP"))
+			res = lpc_WP(fam, mem, act, mode, &dummy);
+		else if(!strcmp(mode, "WBI"))
+				res = lpc_WPI(fam, mem, act, mode, &dummy);
+		
+		if(res < 0)
+		{
+			snprintf(error, MAXERRLEN, "Error writing rpc \"%s\": errno: %d, errtype: %d, errstring: %s",
+				callname, errno, errtype, errstring);
+			 _lastRpcErr = string(error);
+			 ret = false;
+		}
+		else 
+			ret = true;
+	}
+	/* release lock */
+	unlockRpc();
+        return ret;
+}
+
+}
+
diff --git a/RpcWriteHandle.h b/RpcWriteHandle.h
new file mode 100644
index 0000000..7179715
--- /dev/null
+++ b/RpcWriteHandle.h
@@ -0,0 +1,43 @@
+#ifndef RPC_WHANDLE_H
+#define RPC_WHANDLE_H
+
+#include <iostream>
+#include <omnithread.h>
+#include <vector>
+#include <lpc.h>
+#include "RpcHandle.h"
+
+#define RPCSPLITLEN     32
+
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+
+class RPCWriteHandle : public RPCHandle
+{
+	public: 
+		RPCWriteHandle(RPCHandle *h);
+		~RPCWriteHandle();
+
+		bool write_long(const char *callname, long lvalue);
+		bool  write_double(const char *callname, double dvalue);
+		bool  write_short(const char *callname, short svalue);
+		bool  write_boolean(const char *callname, bool bval);
+		bool  write_string(const char *callname, char **string);
+                bool  write_void(const char *callname);
+
+	
+	private:
+
+};
+
+
+
+} /* namespace RPC2TangoBridge_ns ends */
+
+
+#endif
+
+
diff --git a/attribute_converter.cpp b/attribute_converter.cpp
new file mode 100644
index 0000000..0b2974b
--- /dev/null
+++ b/attribute_converter.cpp
@@ -0,0 +1,290 @@
+#include <attribute_converter.h>
+#include <RpcHandle.h>
+#include <tango.h>
+
+#define MAX_X  512
+
+/* RPCSPLITLEN and MAXLEN defined in RpcHandle.h */
+
+using namespace std;
+using namespace Tango;
+
+namespace RPC2TangoBridge_ns
+{
+
+
+AttributeConverter::AttributeConverter(char *propertyName, bool force_spectrum)
+{
+	sc_attr = NULL;
+	sp_attr = NULL;
+	spectrum = false;
+	bool readWrite;
+	int data_type;
+	char res[256];
+	
+	/* RPCSPLITLEN and MAXLEN defined in RpcHandle.h */
+	char writeCall[MAXLEN];
+	char readCall[MAXLEN];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	UserDefaultAttrProp default_att_prop;
+	
+	Database *db = new Database();
+	DbData data;
+	
+	memset(fam, 0, RPCSPLITLEN);
+	memset(mem, 0, RPCSPLITLEN);
+	memset(act, 0, RPCSPLITLEN);
+	memset(mode, 0, RPCSPLITLEN);
+	
+	/* isReadWrite() always copies _read_ RPC call in readCall.
+	* If read write, copies in writeCall the write RPC call and returns true, otherwise it 
+	* returns false and strlen(writeCall) is 0.
+	*/
+	readWrite = isReadWrite(propertyName, readCall, writeCall);
+	printf ("AttributeConverter %s readWrite: %d\n",propertyName,readWrite);
+	/* used to determine data_type below. We refer to read name, we are not
+	 * interested in write_name. The configuration of the device properties must
+	 * be consistent, but we do not check it.
+	 */
+	if(RPCHandle::split_rpccall(readCall, fam, mem, act, mode) < 0)
+	{
+		//printf("\e[1;31m*\e[0m Error in RPC split: \"%s\"\n", propertyName);
+		exit(EXIT_FAILURE);
+	}
+	
+	data_type = data_type_for_mode(mode);
+        printf("creating in converter attribute for \"%s\": data type: \"%s\"\n", propertyName, dataType(data_type).c_str());
+	if(data_type >= 0 && (is_spectrum(mode) ||  force_spectrum))
+	{	
+		spectrum = true;
+		sp_attr = createSpectrumAttribute(propertyName, data_type);
+	}
+	else if(data_type >= 0)
+	{
+		spectrum = false;
+		if(!readWrite)
+			sc_attr = createScalarAttribute(readCall, data_type);
+		else
+			sc_attr = createScalarAttribute(readCall, writeCall, data_type);
+	}
+	else if(data_type < 0)
+	{
+		snprintf(res, 256, "\e[1;31m* \e[0merror creating \"%s\""
+			"\e[0;37m [\e[1;31munrecognized data type \e[0;37m]\e[0m", propertyName);
+		result = string(res);
+	}
+}
+
+bool AttributeConverter::isSpectrum()
+{
+	return spectrum;
+}
+
+bool AttributeConverter::string1_contains2(const char* s1, const char* s2)
+{
+	int len1 = strlen(s1);
+	int len2 = strlen(s2);
+	int i;
+
+	for(i = 0; i <= len1 - len2; i++)
+	{
+		if(strncmp(s1 + i, s2, len2) == 0)
+			return true;
+	}
+	return false;
+}
+
+/* detects if the entry read from the tango attribute properties contains a ':' separator
+* and, if so, extracts and saves in rwname the Write part (the RPC WRITE call.
+* rwname must be a pointer to a MAXLEN char vector.
+* Always copies read RPC call in rname.
+* If read write, copies in rwname the write RPC call and returns true, otherwise it 
+* returns false and strlen(rwname) is 0
+*/
+bool AttributeConverter::isReadWrite(char* entry, char * rname, char *rwname)
+{
+	int i;
+	memset(rname, 0, MAXLEN);
+	memset(rwname, 0, MAXLEN);
+	for(i = 0; i< MAXLEN - 1 && i < strlen(entry); i++)
+		if(entry[i] == ':')
+			break;
+	if(i == strlen(entry))
+	{
+		strncpy(rname, entry, MAXLEN - 1);
+		return false;
+	}
+	else
+	{
+		strncpy(rname, entry , i );
+// 		printf("AttributeConverter::isReadWrite read part: %s\n", rname);
+		memset(rwname, 0, MAXLEN);
+		strncpy(rwname, entry + i + 1, MAXLEN - 1);
+// 		printf("AttributeConverter::isReadWrite write part: %s\n", rwname);
+		return true;
+	}
+}
+
+bool AttributeConverter::is_spectrum(const char *mode)
+{
+	/* Read Array (RA) or Read Flags (RF) means a spectrum */
+	if(string1_contains2(mode, "RA") || string1_contains2(mode, "RF"))
+		return true;
+	else
+		return false;
+}
+
+long int AttributeConverter::data_type_for_mode(const char *mode)
+{
+	if(!strcasecmp(mode, "RB") || !strcasecmp(mode, "RBI") ||
+		!strcasecmp(mode, "RAB") || !strcasecmp(mode, "RAIB"))
+		return Tango::DEV_BOOLEAN;
+	
+	/* flags type, is dev Boolean */
+	else if(!strcasecmp(mode, "RF") || !strcasecmp(mode, "RFI"))
+		return Tango::DEV_BOOLEAN;
+	
+	else if(!strcasecmp(mode, "RI") || !strcasecmp(mode, "RII") ||
+		!strcasecmp(mode, "RAI") || !strcasecmp(mode, "RAII"))
+		return Tango::DEV_LONG;
+	
+	else if(!strcasecmp(mode, "RR") || !strcasecmp(mode, "RRI") ||
+		!strcasecmp(mode, "RAR") || !strcasecmp(mode, "RAIR"))
+		return Tango::DEV_DOUBLE;
+	
+	else if(!strcasecmp(mode, "RE") || !strcasecmp(mode, "REI"))
+		return Tango::DEV_DOUBLE;
+	else if(!strcasecmp(mode, "RM") || !strcasecmp(mode, "RMI"))
+		return Tango::DEV_STRING;
+	else if(!strcasecmp(mode, "RS") || !strcasecmp(mode, "RSI") ||
+		!strcasecmp(mode, "RAS") || !strcasecmp(mode, "RAIS"))
+		return Tango::DEV_SHORT;
+        else if(!strcasecmp(mode, "WP") || !strcasecmp(mode, "WPI"))
+		return Tango::DEV_VOID;
+	else
+		return -1;
+ }
+
+SpectrumBridgeAttr* AttributeConverter::createSpectrumAttribute(const char* name, 
+	long int data_type)
+{
+		
+	UserDefaultAttrProp default_att_prop;
+	SpectrumBridgeAttr *spattr;
+	char desc[256];
+	char res[256];
+	char fam[RPCSPLITLEN], mem[RPCSPLITLEN], act[RPCSPLITLEN], mode[RPCSPLITLEN];
+	int max_x = MAX_X;
+
+	snprintf(desc, 255, "This attribute maps the RPC call \"%s\" in a tango "
+		"READ ONLY spectrum attribute with the same name", name);
+	
+	if(RPCHandle::split_rpccall(name, fam, mem, act, mode) < 0)
+	{
+	        //printf("\e[1;31m*\e[0m Error in RPC data_type: \"%s\"\n", name);
+	        exit(EXIT_FAILURE);
+	}
+	/* particular case in which we know that the RF is long 32 */
+	if(strcmp(mode, "RF") == 0)
+		max_x = 32;
+	
+	spattr = new SpectrumBridgeAttr(name, data_type, Tango::READ, max_x);
+
+	if(spattr != NULL)
+	{
+		snprintf(res, 256, "\e[1;32m* \e[0mcreated \"%s\"\t\e[0;37m[\e[0;32mspectrum"
+		"\e[0;37m, \e[0;32m%s\e[0;37m, \e[0;32mRO\e[0;37m]\e[0m",
+  		name, dataType(data_type).c_str());
+		result = string(res);
+	
+		default_att_prop.set_description(desc);
+		spattr->set_default_properties(default_att_prop);
+	}
+	return spattr;
+}
+
+BridgeAttr* AttributeConverter::createScalarAttribute(const char* name, long int data_type)          
+{
+
+        printf("createScalarAttribute %s\n",name);
+        char desc[256];
+	char res[256];
+	UserDefaultAttrProp default_att_prop;
+	BridgeAttr* attr;
+	snprintf(desc, 255, "This attribute maps the RPC call \"%s\" in a tango "
+		"READ ONLY scalar attribute with the same name", name);
+	attr = new BridgeAttr(name, data_type, Tango::READ);
+	
+	if(attr != NULL)
+	{
+		snprintf(res, 256, "\e[1;32m* \e[0mcreated \"%s\"\t\e[0;37m[\e[0;32mscalar"
+		"\e[0;37m, \e[0;32m%s\e[0;37m, \e[0;32mRO\e[0;37m]\e[0m",
+  		name, dataType(data_type).c_str());
+		result = string(res);
+		default_att_prop.set_description(desc);
+		attr->set_default_properties(default_att_prop);
+	}
+	return attr;	
+}
+
+BridgeAttr* AttributeConverter::createScalarAttribute(const char* name, const char* writeName, long int data_type)
+{
+        printf("createScalarAttribute_write %s\n",name);
+        char desc[256];
+	char res[256];
+	UserDefaultAttrProp default_att_prop;
+	BridgeAttr* attr;
+	snprintf(desc, 255, "This attribute maps the RPC call \"%s\" in a tango "
+		"READ WRITE scalar attribute. RPC read call: \"%s\" write call: \"%s\"", name, name, writeName);
+        printf("createScalarAttribute_write %s %s...\n",name,writeName);
+	attr = new BridgeAttr(name, writeName, data_type, Tango::READ_WRITE);
+	printf(".....createScalarAttribute_write %s %s\n",name,writeName);
+	if(attr != NULL)
+	{
+		snprintf(res, 256, "\e[1;32m* \e[0mcreated \"%s\"\t\e[0;37m[\e[0;32mscalar"
+		"\e[0;37m, \e[0;32m%s\e[0;37m, \e[0;32mRW\e[0;37m]\e[0m",
+  		name, dataType(data_type).c_str());
+		default_att_prop.set_description(desc);
+		attr->set_default_properties(default_att_prop);
+	}
+	return attr;	
+}
+
+string AttributeConverter::dataType(long int dt)
+{
+	string s = "";
+	switch(dt)
+	{
+		case Tango::DEV_DOUBLE:
+			s += "double";
+			break;
+		case Tango::DEV_SHORT:
+			s += "short";
+			break;
+		case Tango::DEV_LONG:
+			s += "(long) int";
+			break;
+		case Tango::DEV_STRING:
+			s += "string";
+			break;
+		case Tango::DEV_BOOLEAN:
+			s += "boolean";
+			break;
+		case Tango::DEV_UCHAR:
+			s += "unsigned char";
+			break;
+		case Tango::DEV_USHORT:
+			s += "unsigned short";
+			break;
+                case Tango::DEV_VOID:
+			s += "void";
+			break;
+		default:
+			s += "unrecognized";
+			break;
+	}
+	return s;
+}
+
+} /* end namespace */
+
diff --git a/attribute_converter.h b/attribute_converter.h
new file mode 100644
index 0000000..80369a4
--- /dev/null
+++ b/attribute_converter.h
@@ -0,0 +1,53 @@
+#ifndef _ATTRIBUTE_CONVERTER_H
+
+#define ATTRIBUTE_CONVERTER_H
+
+#include <BridgeAttr.h>
+
+namespace RPC2TangoBridge_ns
+{
+
+class AttributeConverter
+{
+	public:
+		AttributeConverter(char *rpc_call, bool force_spectrum = false);
+		
+		bool isSpectrum();
+		
+		BridgeAttr* scalarAttribute() { return sc_attr; }
+		SpectrumBridgeAttr *spectrumAttribute() { return sp_attr; }
+		string info() { return result; }
+		
+	private:
+		BridgeAttr *sc_attr;
+		SpectrumBridgeAttr* sp_attr;
+		
+		bool string1_contains2(const char* s1, const char* s2);
+		bool is_spectrum(const char *call);
+		long int data_type_for_mode(const char *mode);
+
+		BridgeAttr* createScalarAttribute(const char* name, long int data_type);
+		BridgeAttr* createScalarAttribute(const char* name, const char* writeName, long int data_type);
+		SpectrumBridgeAttr* createSpectrumAttribute(const char* name, 
+			long int data_type);
+		
+		/* detects if the entry read from the tango attribute properties contains a ':' separator
+	 	* and, if so, extracts and saves in rwname the Write part (the RPC WRITE call.
+	 	* rwname must be a pointer to a MAXLEN char vector.
+		* Always copies read RPC call in rname.
+		* If read write, copies in rwname the write RPC call and returns true, otherwise it 
+		* returns false and strlen(rwname) is 0
+		*/
+		bool isReadWrite(char* entry, char *rname, char *rwname);
+		string dataType(long int dt);
+		
+		bool spectrum;
+		string result;
+};
+
+} /* namespace */
+
+
+#endif
+
+
diff --git a/etc/fixsipformat.py b/etc/fixsipformat.py
new file mode 100644
index 0000000..c17fd06
--- /dev/null
+++ b/etc/fixsipformat.py
@@ -0,0 +1,28 @@
+#fix format fro SIP devices
+from PyTango import *
+
+
+sip120 = DeviceProxy('rpcbridge/rpc2tangobridge/sip120')
+sip400 = DeviceProxy('rpcbridge/rpc2tangobridge/sip400')
+
+
+
+sip120attrlist = sip120.get_attribute_list()
+
+for att in sip120attrlist:
+    atconf=sip120.get_attribute_config(att)
+    atconf.format='%6.2e'
+    try:
+        sip120.set_attribute_config(atconf)
+    except:
+        pass
+    
+sip400attrlist = sip400.get_attribute_list()
+
+for att in sip400attrlist:
+    atconf=sip400.get_attribute_config(att)
+    atconf.format='%6.2e'
+    try:
+        sip400.set_attribute_config(atconf)
+    except:
+        pass
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..797873b
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,71 @@
+static const char *RcsId = "$Header: /home/cvsadm/cvsroot/elettra/server/RPC2TangoBridge/main.cpp,v 1.1.1.1 2008-04-28 09:13:16 giacomo Exp $";
+//+=============================================================================
+//
+// file :        main.cpp
+//
+// description : C++ source for a TANGO device server main.
+//               The main rule is to initialise (and create) the Tango
+//               system and to create the DServerClass singleton.
+//               The main should be the same for every Tango device server.
+//
+// project :     TANGO Device Server
+//
+// $Author: giacomo $
+//
+// $Revision: 1.1.1.1 $ $
+//
+// $Log: main.cpp,v $
+// Revision 1.1.1.1  2008-04-28 09:13:16  giacomo
+// Prima versione di RPC2TangoBridge
+//
+//
+// copyleft :    European Synchrotron Radiation Facility
+//               BP 220, Grenoble 38043
+//               FRANCE
+//
+//-=============================================================================
+//
+//  		This file is generated by POGO
+//	(Program Obviously used to Generate tango Object)
+//
+//         (c) - Software Engineering Group - ESRF
+//=============================================================================
+
+#include <tango.h>
+
+
+int main(int argc,char *argv[])
+{
+
+	Tango::Util *tg;
+	try
+	{
+		// Initialise the device server
+		//----------------------------------------
+		tg = Tango::Util::init(argc,argv);
+
+		// Create the device server singleton 
+		//	which will create everything
+		//----------------------------------------
+		tg->server_init(false);
+
+		// Run the endless loop
+		//----------------------------------------
+		cout << "Ready to accept request" << endl;
+		tg->server_run();
+	}
+	catch (bad_alloc)
+	{
+		cout << "Can't allocate memory to store device object !!!" << endl;
+		cout << "Exiting" << endl;
+	}
+	catch (CORBA::Exception &e)
+	{
+		Tango::Except::print_exception(e);
+		
+		cout << "Received a CORBA_Exception" << endl;
+		cout << "Exiting" << endl;
+	}
+	tg->server_cleanup();
+	return(0);
+}
diff --git a/read_dynamic_attribute.cpp b/read_dynamic_attribute.cpp
new file mode 100644
index 0000000..50fc9d0
--- /dev/null
+++ b/read_dynamic_attribute.cpp
@@ -0,0 +1,311 @@
+#include <tango.h>
+#include <lpc.h>
+#include <RPC2TangoBridge.h>
+#include <BridgeAttr.h>
+#include <RpcHandle.h>
+
+using namespace Tango;
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+void RPC2TangoBridge::read_dynamic_attribute(Tango::Attribute &attr)
+{
+//  	 printf("\r                                                                    ");
+//  	 fflush(stdout);
+// 	 printf("\r                                                                  \r");
+//  	 printf("\e[1;32m* \e[1;37mreading \e[0m%s\e[0m", attr.get_name().c_str() );
+//  	 fflush(stdout);
+	
+	/* lpc arrays */
+	 intArray vresi;
+	realArray vresd;
+	shortArray sa;
+	booleanArray sb;
+	charArray sc;
+	unsigned char rpcBool;
+
+	long int resi;
+	double resd;
+	short s;
+	unsigned char uc;
+	string ress;
+
+	int i;
+	int ok;
+
+	bool release = true; /* tells Attribute::set_value to free memory after usage */
+	char error[256];
+
+	/* search name in scalars map first */
+ 	map<string, BridgeAttr*>::iterator mapiter;
+	mapiter = namesMap.find(attr.get_name());
+
+	if(mapiter != namesMap.end())
+ 	{
+		BridgeAttr *brattr = (*mapiter).second;
+		fflush(stdout);
+// 		printf("read_dynamic_attribute: name %s\n", brattr->get_name().c_str());
+		RPCReadHandle *rpch = brattr->rpcReadHandle();
+// 		printf("read_dynamic_attribute: name %s\n", brattr->get_name().c_str());
+		if(rpch)
+		{
+			rpch->lockRpc();
+			Tango::WAttribute *attr_set;
+			try{
+			        Tango::MultiAttribute *attr_list = get_device_attr();
+				attr_set = &(attr_list->get_w_attr_by_name(attr.get_name().c_str()));
+			}
+			catch(DevFailed &e)
+			{
+				//printf("\e[1;31mfailed to find attribute with name \"%s\"\e[0m\n", 
+				//	attr.get_name().c_str());
+				attr_set = NULL;
+			}
+			switch(brattr->get_type())
+			{
+				case Tango::DEV_LONG:
+				resi = rpch->read_long(attr.get_name().c_str(), &ok);
+				if(ok)
+				{
+					DevLong *readVal = new DevLong;
+					*readVal = resi;
+					attr.set_value(readVal, 1, 0, true);
+					if(attr_set)
+						attr_set->set_write_value(readVal);
+				}
+				break;
+				case Tango::DEV_DOUBLE:
+					resd = rpch->read_double(attr.get_name().c_str(), &ok);
+					if(ok)
+					{
+						DevDouble *readVald = new DevDouble;
+						*readVald = resd;
+
+						if(attr_set)
+						{
+						//	printf("\e[1;32msetto write value a %f\e[0m\n",
+						//		*readVald);
+							attr_set->set_write_value(readVald);
+						}
+						attr.set_value(readVald, 1, 0, true);
+
+					}
+					break;
+				
+				case Tango::DEV_SHORT:
+					s =  rpch->read_short(attr.get_name().c_str(), &ok);
+					if(ok)
+					{
+						DevShort *readVals = new DevShort;
+						*readVals = s;
+						attr.set_value(readVals, 1, 0, true);
+						if(attr_set)
+							attr_set->set_write_value(readVals);
+
+					}
+				break;
+				
+				case Tango::DEV_UCHAR:
+					uc =  rpch->read_uchar(attr.get_name().c_str(), &ok);
+					if(ok)
+					{
+						DevUChar *readValc = new DevUChar;
+						*readValc =uc;
+						attr.set_value(readValc, 1, 0, true);
+						if(attr_set)
+							attr_set->set_write_value(readValc);
+
+					}
+				break;
+				
+				case Tango::DEV_STRING:
+					ress =  rpch->read_string(attr.get_name().c_str(), &ok);
+					if(ok)
+					{
+						DevString *readVals = new DevString;
+						*readVals = new char[ress.length() + 1];
+						/* be sure it is null terminated */
+						memset(*readVals, 0, ress.length() + 1);
+						strncpy(*readVals, ress.c_str(), ress.length());
+						attr.set_value(readVals, 1, 0, true);
+						if(attr_set)
+							attr_set->set_write_value(readVals);
+
+					}
+				break;
+				
+				case Tango::DEV_BOOLEAN:
+					rpcBool = rpch->read_boolean(attr.get_name().c_str(), &ok);
+					if(ok)
+					{
+						DevBoolean *db = new DevBoolean;
+						if(rpcBool == 0)
+							*db = false;
+						else
+							*db = true;
+						attr.set_value(db, sb.length, 0, true);
+						if(attr_set)
+							attr_set->set_write_value(db);
+
+					}
+					break;
+				case Tango::DEV_VOID:
+					rpcBool = true;
+                                        ok = true; //all dummies
+					if(ok)
+					{
+						DevBoolean *db = new DevBoolean;
+						if(rpcBool == 0)
+							*db = false;
+						else
+							*db = true;
+						attr.set_value(db, sb.length, 0, true);
+						if(attr_set)
+							attr_set->set_write_value(db);
+
+					}
+					break;
+				default:
+					
+					//printf("\t[\e[1;31mfailed\e[0m] (format not supported - %d)\n", brattr->get_type());
+					Except::throw_exception("Error reading scalar attribute " + attr.get_name(),
+						"The format is not supported.\nSupported formats: long, double",
+						"RPC2TangoBridge::read_BridgeAttr()");
+					break;
+			}
+			rpch->unlockRpc();
+
+			if(!ok)
+			{
+// 				 printf("\r                                                                  \r");
+//  				 printf("\e[1;31m* \e[1;37mreading \e[0m%s\e[0m", attr.get_name().c_str() );
+// 				printf("\t[\e[1;31mfailed\e[0m]\n\t{%s\n\t\t[host: %s:%d]}\n", rpch->lastRpcError().c_str(), rpch->host().c_str(), rpch->port());
+
+				snprintf(error, 256, "Error reading scalar attribute \"%s\". Error: %s", attr.get_name().c_str(),
+						rpch->lastRpcError().c_str());
+			//	set_state(Tango::FAULT);
+				set_status(error);
+				Except::throw_exception("Error reading scalar attribute " + attr.get_name(),
+						"RPC call failed: " + rpch->lastRpcError() ,
+						"RPC2TangoBridge::read_BridgeAttr()");
+				
+			}
+		}
+ 	}
+	
+	/* look among spectrum */
+	map<string, SpectrumBridgeAttr*>::iterator spmapiter;
+	
+	spmapiter = spectrumNamesMap.find(attr.get_name());
+
+	if(spmapiter != spectrumNamesMap.end())
+	{
+		SpectrumBridgeAttr *spbrattr = (*spmapiter).second;
+ 		RPCReadHandle *rpch = spbrattr->rpcReadHandle();
+		if(rpch)
+		{
+			rpch->lockRpc();
+			switch(spbrattr->get_type())
+			{
+				case Tango::DEV_LONG:
+					vresi = rpch->read_slong(attr.get_name().c_str(), &ok);
+					if(ok && vresi.sequence != NULL)
+					{
+						DevLong *readVal = new DevLong[vresi.length];
+						for(i = 0; i < vresi.length; i++)
+							readVal[i] = vresi.sequence[i];
+						attr.set_value(readVal, vresi.length, 0, true);
+						free (vresi.sequence);
+					}
+					break;
+				case Tango::DEV_DOUBLE:
+					vresd = rpch->read_sdouble(attr.get_name().c_str(), &ok);
+					if(ok && vresd.sequence != NULL)
+					{
+						DevDouble *readVald = new DevDouble[vresd.length];
+						for(i = 0; i < vresd.length; i++)
+							readVald[i] = vresd.sequence[i];
+						attr.set_value(readVald, vresd.length, 0, true);
+						free (vresd.sequence);
+					}
+					break;
+				case Tango::DEV_SHORT:
+					sa = rpch->read_sshort(attr.get_name().c_str(), &ok);
+					if(ok && sa.sequence != NULL)
+					{
+						DevShort *ds = new DevShort[sa.length];
+						for(i = 0; i < sa.length; i++)
+							ds[i] = sa.sequence[i];
+						attr.set_value(ds, sa.length, 0, true);
+						free (sa.sequence);
+					}
+					break;
+				
+				case Tango::DEV_UCHAR:
+					sc = rpch->read_schar(attr.get_name().c_str(), &ok);
+					if(ok && sc.sequence != NULL)
+					{
+						DevUChar *dc = new DevUChar[sc.length];
+						for(i = 0; i < sc.length; i++)
+							dc[i] = sc.sequence[i];
+						attr.set_value(dc, sc.length, 0, true);
+						free (sc.sequence);
+					}
+					break;
+
+				case Tango::DEV_BOOLEAN:
+					sb = rpch->read_sboolean(attr.get_name().c_str(), &ok);
+					if(ok && sb.sequence != NULL)
+					{
+						DevBoolean *db = new DevBoolean[sb.length];
+						for(i = 0; i < sb.length; i++)
+							db[i] = sb.sequence[i];
+						attr.set_value(db, sb.length, 0, true);
+						free (sb.sequence);
+					}
+					else{
+						//printf("\e[1;31m*\e[0m error reading boolean array for \"%s\" : %s\n", attr.get_name().c_str(), rpch->lastRpcError().c_str());
+					}
+					break;
+
+				default:
+					//printf("\t[\e[1;31mfailed\e[0m] (format not supported)\n");
+					Except::throw_exception("Error reading spectrum attribute " + attr.get_name(),
+						"The format is not supported.\nSupported formats: long, double, uchar, boolean, short",
+						"RPC2TangoBridge::read_BridgeAttr()");
+					
+					break;
+			}
+			rpch->unlockRpc();
+
+			if(!ok)
+			{
+// 				 printf("\r                                                                  \r");
+//  				 printf("\e[1;31m* \e[1;37mreading \e[0m%s\e[0m", attr.get_name().c_str() );
+// 				printf("\t[\e[1;31mfailed\e[0m]\n\t{%s\n\t\t[host: %s:%d]}\n", rpch->lastRpcError().c_str(), rpch->host().c_str(), rpch->port());
+				snprintf(error, 256, "Error reading scalar attribute \"%s\". Error: %s", attr.get_name().c_str(),
+						rpch->lastRpcError().c_str());
+//				set_state(Tango::FAULT);
+				set_status(error);
+
+				Except::throw_exception("Error reading spectrum attribute " + attr.get_name(),
+					string("RPC call failed: ")  + rpch->lastRpcError(),
+					"RPC2TangoBridge::read_BridgeAttr()");
+				
+			}
+			else
+			{
+				set_state(Tango::ON);
+				set_status("server running");
+			}
+ 		}
+ 	}
+
+}
+
+
+} /* namespace ends here */
+
+
diff --git a/write_dynamic_attribute.cpp b/write_dynamic_attribute.cpp
new file mode 100644
index 0000000..c4753a2
--- /dev/null
+++ b/write_dynamic_attribute.cpp
@@ -0,0 +1,105 @@
+#include <tango.h>
+#include <lpc.h>
+#include <RPC2TangoBridge.h>
+#include <BridgeAttr.h>
+#include <RpcHandle.h>
+
+using namespace Tango;
+using namespace std;
+
+namespace RPC2TangoBridge_ns
+{
+
+bool RPC2TangoBridge::write_dynamic_attribute(Tango::WAttribute &attr)
+{
+//  	 printf("\r                                                                    ");
+//  	 fflush(stdout);
+// 	 printf("\r                                                                  \r");
+//  	 printf("\e[1;32m* \e[1;37mwriting \e[0m%s\e[0m\n", attr.get_name().c_str() );
+//  	 fflush(stdout);
+
+	DevLong dl;
+	DevShort ds;
+	DevDouble dd;
+	DevBoolean db;
+
+	long int l;
+	double d;
+	short s;
+	unsigned char uc;
+	string ress;
+	bool b;
+
+	int i;
+
+	bool release = true; /* tells Attribute::set_value to free memory after usage */
+	char error[256];
+
+	/* search name in scalars map first */
+ 	map<string, BridgeAttr*>::iterator mapiter;
+	mapiter = namesMap.find(attr.get_name());
+
+	if(mapiter != namesMap.end())
+ 	{
+		BridgeAttr *brattr = (*mapiter).second;
+		if(brattr->get_writable() != Tango::READ_WRITE)
+		{
+			//printf("\e[1;31m*\e[0m error: writable is not READ_WRITE\n");
+			return false;
+		}
+		fflush(stdout);
+// 		printf("read_dynamic_attribute: name %s\n", brattr->writeName().c_str());
+		RPCWriteHandle *rpch = brattr->rpcWriteHandle();
+// 		printf("read_dynamic_attribute: name %s\n", brattr->writeName().c_str());
+		if(rpch)
+		{
+			switch(brattr->get_type())
+			{
+				case Tango::DEV_LONG:
+					attr.get_write_value(dl);
+					l = (long) dl;
+					return rpch->write_long(brattr->writeName().c_str(), l);
+
+				case Tango::DEV_DOUBLE:
+					attr.get_write_value(dd);
+					d = (double) dd;
+					return rpch->write_double(brattr->writeName().c_str(), d);
+				
+				case Tango::DEV_SHORT:
+					attr.get_write_value(ds);
+					s = (short) ds;
+					return rpch->write_short(brattr->writeName().c_str(), s);
+// 				case Tango::DEV_STRING:
+// 					
+				
+				case Tango::DEV_BOOLEAN:
+					attr.get_write_value(db);
+					b = (bool) db;
+					return  rpch->write_boolean(brattr->writeName().c_str(), b);
+                                case Tango::DEV_VOID:
+					attr.get_write_value(db);
+					b = (bool) db; //dummy
+					return  rpch->write_void(brattr->writeName().c_str());
+				default:
+					
+					//printf("\t[\e[1;31mfailed\e[0m] (format not supported - %d)\n", brattr->get_type());
+					Except::throw_exception("Error reading scalar attribute " + brattr->writeName(),
+						"The format is not supported.\nSupported formats: long, double",
+						"RPC2TangoBridge::read_BridgeAttr()");
+					break;
+			}
+
+		}
+		else{
+			//printf("\e[1;31m*\e[0m error: rpc write handle not initialized\n");
+		}
+		
+		
+ 	}
+	return false;
+}
+
+
+} /* namespace ends here */
+
+
-- 
GitLab