diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f768f7909ca84a190cd6d52a1522bf55d0a7e55d --- /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 0000000000000000000000000000000000000000..b83cd02517c99117d12b80b117b4590ccab71749 --- /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 0000000000000000000000000000000000000000..8a7e6bfa46cd2eec44e6c67284e6c4ffe3951ab4 --- /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 0000000000000000000000000000000000000000..24512175c4d11c0096dcf2b18fbad87f48761744 --- /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 0000000000000000000000000000000000000000..68d32abea2c361cb98504709a2eb469416ab3a3c --- /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 0000000000000000000000000000000000000000..3587dcb13bb6dba1273dc065c9fab50d65c8f219 --- /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 0000000000000000000000000000000000000000..d513ada9ac5c8190e4cd71f6a86790b27c061c9b --- /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 7c554bdeb84ef360cc3376a0cd2d0906001b3bf8..8d1c3683072083166cad15ae36af2396ea362d46 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 0000000000000000000000000000000000000000..861222a8c7916c0a5491d50fab8bdf7d324c14ae --- /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 0000000000000000000000000000000000000000..870ff365c79bf676f4796d5929c9dabb1edb9fdc --- /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 0000000000000000000000000000000000000000..ca87e868ca5a7bd05a27a4696f13859599548046 --- /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 0000000000000000000000000000000000000000..57b1406ebe3ab811083d9bba26954d04950b7e61 --- /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 0000000000000000000000000000000000000000..8cd9e8a6a9c15c0bbdd1d28dfa9e1bb227b85bf0 --- /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 0000000000000000000000000000000000000000..b9c307b1a88f660c1fe8493ddaa3b230c0eccdee --- /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 0000000000000000000000000000000000000000..1f34698211ea2134813d66fb79fa6b4786c9462e --- /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 0000000000000000000000000000000000000000..06d111eb8ee2d378dd217e42ae5dfd0fb81f9c31 --- /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 0000000000000000000000000000000000000000..21b30945bc54b858c2f9ab1af7971c7d807ca723 --- /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 0000000000000000000000000000000000000000..01fdd610e7070a8864499a3874bc98c03992cad0 --- /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 0000000000000000000000000000000000000000..c7f68bb22ddfd4c2f6310373d25818ae2404cd95 --- /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 0000000000000000000000000000000000000000..3d2312bb74d35e07e7a4502f8b2dd979dc9ab9ae --- /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 0000000000000000000000000000000000000000..923db3247c7af4a37ddf2ffdcd80cb49dbb19861 --- /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 0000000000000000000000000000000000000000..f31c8414cc38fc65e72be4395d7e5bd9c9c0b178 --- /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 0000000000000000000000000000000000000000..71797153375a0def42369f0ed631bb23d480cc4c --- /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 0000000000000000000000000000000000000000..0b2974bd04994285cc71880badc1d62af8b8db69 --- /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 0000000000000000000000000000000000000000..80369a4ae1b33f3b2db2df41b63b5fd076526358 --- /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 0000000000000000000000000000000000000000..c17fd06793fd0be9914f1eeb492caa17fd4d2507 --- /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 0000000000000000000000000000000000000000..797873b6b167602c98444a3bb8ec2b49c9958186 --- /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 0000000000000000000000000000000000000000..50fc9d0a6475b2d14516538b454bc0bbe2ee6f9e --- /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 0000000000000000000000000000000000000000..c4753a2aa19e84b33feec190c665e0f66b419319 --- /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 */ + +