/*----- PROTECTED REGION ID(AccessConf.cpp) ENABLED START -----*/
static const char *RcsId = "$Id: AccessConf.cpp,v 1.18 2019-11-06 08:28:04 graziano Exp $";
//=============================================================================
//
// file :        AccessConf.cpp
//
// description : C++ source for the AccessConf 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
//               AccessConf are implemented in this file.
//
// project :     Storage Ring Access.
//
// $Author: graziano $
//
// $Revision: 1.18 $
// $Date: 2019-11-06 08:28:04 $
//
// SVN only:
// $HeadURL:  $
//
// CVS only:
// $Source: /home/cvsadm/cvsroot/fermi/servers/accessconf/src/AccessConf.cpp,v $
// $Log: AccessConf.cpp,v $
// Revision 1.18  2019-11-06 08:28:04  graziano
// fixed archive events thresholds
//
// Revision 1.17  2019-11-06 08:23:36  graziano
// Added cutoff_ind to change/disable index for cutoff
//
// Revision 1.16  2019-02-06 16:06:41  graziano
// fixed ValveStat[4] (abi) value if not spare
//
// Revision 1.15  2019-01-17 12:31:49  graziano
// fixed
//
// Revision 1.14  2019-01-17 12:28:38  graziano
// fixed initial state/status
//
// Revision 1.13  2019-01-17 11:38:51  graziano
// Initialized state/status
//
// Revision 1.12  2018-12-31 14:19:50  graziano
// fixed 101 commands
//
// Revision 1.11  2018-12-31 14:07:59  graziano
// in valvestat fixed limit of 7 for inverted bits
//
// Revision 1.10  2018-06-26 10:22:42  graziano
// removed push event on status
//
// Revision 1.9  2017-08-23 14:16:23  claudio
// #1554 tango-9.2.5a
//
// Revision 1.8  2017-08-09 12:09:00  graziano
// fixed string attributes
//
// Revision 1.7  2016-11-21 09:06:22  graziano
// added archive event
//
// Revision 1.6  2016-01-07 10:44:44  graziano
// fixed
//
// Revision 1.5  2014-05-12 14:21:33  graziano
// fixed event errors
//
// Revision 1.4  2014-04-24 13:35:13  graziano
// fixed sync read
//
// Revision 1.3  2013-08-20 07:06:01  graziano
// event support
//
// Revision 1.2  2012-10-31 17:40:12  graziano
// fixed for valves
//
// Revision 1.1  2012-10-30 09:29:15  graziano
// *** empty log message ***
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include <AccessConf.h>
#include <AccessConfClass.h>
#include <math.h>
#include <stdint.h>

const char srvver[] = RELEASE;

/*----- PROTECTED REGION END -----*/


/**
 *	AccessConf class description:
 *	
 */

//================================================================
//
//  The following table gives the correspondence
//  between command and method names.
//
//  Command name  |  Method name
//----------------------------------------------------------------
//  State         |  Inherited (no method)
//  Status        |  Inherited (no method)
//================================================================

namespace AccessConf_ns
{
	/*----- PROTECTED REGION ID(AccessConf::namespace_starting) ENABLED START -----*/

	//	static initializations
bool compare_attr_index (attr_desc_t i,attr_desc_t j) { return (i.attr_index < j.attr_index); };

	/*----- PROTECTED REGION END -----*/	//	AccessConf::namespace_starting



//--------------------------------------------------------
/**
 *	Method      : AccessConf::AccessConf()
 *	Description : Constructors for a Tango device
 *	              implementing the class AccessConf
 */
//--------------------------------------------------------
AccessConf::AccessConf(Tango::DeviceClass *cl, string &s)
 	: TANGO_BASE_CLASS(cl, s.c_str())
{
	/*----- PROTECTED REGION ID(AccessConf::constructor_1) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	AccessConf::constructor_1
}
//--------------------------------------------------------
AccessConf::AccessConf(Tango::DeviceClass *cl, const char *s)
 	: TANGO_BASE_CLASS(cl, s)
{
	/*----- PROTECTED REGION ID(AccessConf::constructor_2) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	AccessConf::constructor_2
}
//--------------------------------------------------------
AccessConf::AccessConf(Tango::DeviceClass *cl, const char *s, const char *d)
 	: TANGO_BASE_CLASS(cl, s, d)
{
	/*----- PROTECTED REGION ID(AccessConf::constructor_3) ENABLED START -----*/

	init_device();

	/*----- PROTECTED REGION END -----*/	//	AccessConf::constructor_3
}


//--------------------------------------------------------
/**
 *	Method      : AccessConf::delete_device()()
 *	Description : will be called at device destruction or at init command
 */
//--------------------------------------------------------
void AccessConf::delete_device()
{
	/*----- PROTECTED REGION ID(AccessConf::delete_device) ENABLED START -----*/

	//	Delete device allocated objects
	DEBUG_STREAM << __FUNCTION__<<": entering..." << endl;
	delete[] attr_status_read;

	/*----- PROTECTED REGION END -----*/	//	AccessConf::delete_device
	delete[] attr_BoolScalarDyn_read;
	delete[] attr_BoolSpectrumDyn_read;
	delete[] attr_StringSpectrumDyn_read;
	delete[] attr_Version_read;
	
	delete lldevice;

}


//--------------------------------------------------------
/**
 *	Method      : AccessConf::init_device()
 *	Description : //	will be called at device initialization.
 */
//--------------------------------------------------------
void AccessConf::init_device()
{
	DEBUG_STREAM << "AccessConf::init_device() create device " << device_name << endl;

	/*----- PROTECTED REGION ID(AccessConf::init_device_before) ENABLED START -----*/

	//	Initialization before get_device_property() call
	ValveStat_initialized = false;
	created_attr = false;
	set_change_event("State", true, false);		//attribute name, implemented, detect, if not setting detect=false have to set abs_change or
	set_archive_event("State", true, true);		//attribute name, implemented, detect, if not setting detect=false have to set abs_change or
	//set_change_event("Status", true, false);		//attribute name, implemented, detect, if not setting detect=false have to set abs_change or
	ecb.init(this);
	/*----- PROTECTED REGION END -----*/	//	AccessConf::init_device_before
	
	//	Get the device properties (if any) from database
	get_device_property();
	
	attr_BoolScalarDyn_read = new Tango::DevBoolean[1];
	attr_BoolSpectrumDyn_read = new Tango::DevBoolean[MAX_ATTR_SIZE];
	attr_StringSpectrumDyn_read = new Tango::DevString[MAX_ATTR_SIZE];
	attr_Version_read = new Tango::DevString[1];
	
	/*----- PROTECTED REGION ID(AccessConf::init_device) ENABLED START -----*/
	lldevice = new Tango::DeviceProxy(low_level_srv);
	try {
		if (lldevice->ping())
		{
			set_state(Tango::ON);
			set_status("Connected to device " + low_level_srv);
			state_event = Tango::ON;
			sprintf(status_str,"Connected to device %s", low_level_srv.c_str());
		}
	}
	catch(Tango::DevFailed &e)
	{
		set_state(Tango::UNKNOWN);
		set_status("Failed to connect to device " + low_level_srv);
		state_event = Tango::UNKNOWN;
		sprintf(status_str,"Failed to connect to device %s", low_level_srv.c_str());
	}

	attr_status_read = new Tango::DevString[1];
	attr_status_read[0] = (char *)status_str;
	//	Initialize device
	gettimeofday(&last_read, NULL);

	/*----- PROTECTED REGION END -----*/	//	AccessConf::init_device
}



//--------------------------------------------------------
/**
 *	Method      : AccessConf::get_device_property()
 *	Description : //	Add your own code to initialize
 */
//--------------------------------------------------------
void AccessConf::get_device_property()
{
	/*----- PROTECTED REGION ID(AccessConf::get_device_property_before) ENABLED START -----*/

	//	Initialize property data members

	/*----- PROTECTED REGION END -----*/	//	AccessConf::get_device_property_before


	//	Read device properties from database.
	Tango::DbData	dev_prop;
	dev_prop.push_back(Tango::DbDatum("Low_level_srv"));
	dev_prop.push_back(Tango::DbDatum("Attr_config_file"));
	dev_prop.push_back(Tango::DbDatum("Attr_config_prop"));
	dev_prop.push_back(Tango::DbDatum("Cutoff_ind"));

	//	is there at least one property to be read ?
	if (dev_prop.size()>0)
	{
		//	Call database and extract values
		if (Tango::Util::instance()->_UseDb==true)
			get_db_device()->get_property(dev_prop);
	
		//	get instance on AccessConfClass to get class property
		Tango::DbDatum	def_prop, cl_prop;
		AccessConfClass	*ds_class =
			(static_cast<AccessConfClass *>(get_device_class()));
		int	i = -1;

		//	Try to initialize Low_level_srv from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  low_level_srv;
		else {
			//	Try to initialize Low_level_srv from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  low_level_srv;
		}
		//	And try to extract Low_level_srv value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  low_level_srv;

		//	Try to initialize Attr_config_file from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  attr_config_file;
		else {
			//	Try to initialize Attr_config_file from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  attr_config_file;
		}
		//	And try to extract Attr_config_file value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  attr_config_file;

		//	Try to initialize Attr_config_prop from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  attr_config_prop;
		else {
			//	Try to initialize Attr_config_prop from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  attr_config_prop;
		}
		//	And try to extract Attr_config_prop value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  attr_config_prop;

		//	Try to initialize Cutoff_ind from class property
		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
		if (cl_prop.is_empty()==false)	cl_prop  >>  cutoff_ind;
		else {
			//	Try to initialize Cutoff_ind from default device value
			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
			if (def_prop.is_empty()==false)	def_prop  >>  cutoff_ind;
		}
		//	And try to extract Cutoff_ind value from database
		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  cutoff_ind;


	}
	/*----- PROTECTED REGION ID(AccessConf::get_device_property_after) ENABLED START -----*/

	//	Check device property data members init

	/*----- PROTECTED REGION END -----*/	//	AccessConf::get_device_property_after

}

//--------------------------------------------------------
/**
 *	Method      : AccessConf::always_executed_hook()
 *	Description : method always executed before any command is executed
 */
//--------------------------------------------------------
void AccessConf::always_executed_hook()
{
	//INFO_STREAM << "AccessConf::always_executed_hook()  " << device_name << endl;
	/*----- PROTECTED REGION ID(AccessConf::always_executed_hook) ENABLED START -----*/

	//	code always executed before all requests
#if 0
	if(ValveStat_initialized)
	{
    map<string,attr_val_t >::iterator it_val = att_value.find("ValveStat");

	if((it_val->second.val[5])||(it_val->second.val[6])/*||(!valve_stat[2])*/)
	{//error occurred

		state_event = Tango::FAULT;
		if(it_val->second.val[5])
		{
			strcpy(status_str,"error opening");
		}
		if(it_val->second.val[6])
		{
			strcpy(status_str,"error closing");
		}
		set_state(state_event);
		set_status(status_str);
		DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
		try {
			push_change_event("state");
			push_archive_event("state");
			push_change_event("status");
		} catch(Tango::DevFailed &e)
		{
			DEBUG_STREAM << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
		}
		//	if(!valve_stat[2]){
		//		set_status("pressure not ok");
		//	}
	}
	else
	{//no errors
		if(it_val->second.val[0]){//opened?
			if(it_val->second.val[1])
			{//closed? error

				state_event = Tango::FAULT;
				strcpy(status_str,"SW both closed");
				set_state(state_event);
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
			else
			{//opened

				state_event = Tango::OPEN;
				strcpy(status_str,"----");
				set_state(state_event);
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING OPEN ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
		}
		else
		{
			if(it_val->second.val[1])
			{//closed?

				state_event = Tango::CLOSE;
				strcpy(status_str,"----");
				set_state(state_event);
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING CLOSE ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
			else
			{//moving

				state_event = Tango::MOVING;
				strcpy(status_str,"SW both opened");
				set_state(state_event);
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING MOVING ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
		}
//		if(is_local_ctrl){
//			set_status("local");
//		}
		if(cutoff_ind >=0 && cutoff_ind < MAX_ATTR_SIZE)
		{
			if(!it_val->second.val[cutoff_ind]){
				strcpy(status_str,"cutoff");
				set_status(status_str);
				try {
					push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing status="<<e.errors[0].desc<<endl;
				}
			}
		}
	}
	}
#endif

	/*----- PROTECTED REGION END -----*/	//	AccessConf::always_executed_hook
}



//--------------------------------------------------------
/**
 *	Method      : AccessConf::read_attr_hardware()
 *	Description : Hardware acquisition for attributes.
 */
//--------------------------------------------------------
void AccessConf::read_attr_hardware(vector<long> &attr_list)
{
	//DEBUG_STREAM << "AccessConf::read_attr_hardware(vector<long> &attr_list) entering... " << endl;
	/*----- PROTECTED REGION ID(AccessConf::read_attr_hardware) ENABLED START -----*/

	//	Add your own code

	struct timeval now;
	gettimeofday(&now, NULL);
	double diff_time_s = fabs((now.tv_sec - last_read.tv_sec) + ((double)(now.tv_usec - last_read.tv_usec))/1000000.0);

	if(diff_time_s < 1)
	{
		return;
	}
	gettimeofday(&last_read, NULL);

	try
	{
		vector<Tango::DeviceAttribute> *Dout;
		//Tango::DeviceAttribute Dout;

		Dout = lldevice->read_attributes(remote_attr);
		//Dout = lldevice->read_attribute(remote_attr[0]);

		//map<string,vector<Tango::DevBoolean> >::iterator attr_it;
		map<string,rem_val_t >::iterator attr_it;
		unsigned int i =0;
		//for(attr_it=remote_att_value.begin(); attr_it != remote_att_value.end(); attr_it++)
		for(vector<string>::iterator it = remote_attr.begin(); it != remote_attr.end(); it++)
		{
			attr_it = remote_att_value.find(*it);
			if(attr_it == remote_att_value.end())
			{
				WARN_STREAM << __FUNCTION__ << " remote attr=" << *it << " not found!";
				continue;
			}
			if(attr_it->first != "state")
			{
				map<string,string>::iterator it_type = remote_type.find(attr_it->first);
				DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second;
				if(it_type != remote_type.end() && it_type->second == "bool")
				{
					(*Dout)[i++] >> attr_it->second.val_b;	//TODO: string
					//Dout >> attr_it->second.val_b;	//TODO: string
					DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_b.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
				}
				else if(it_type != remote_type.end() && it_type->second == "string")
				{
					//(*Dout)[i++] >> attr_it->second.val_s;	//TODO: string
					DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_s.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
					Tango::DeviceAttribute Dout2 = lldevice->read_attribute(attr_it->first.c_str());
					Dout2 >> attr_it->second.val_s;	//TODO: string
				}
			}
			else
			{
				(*Dout)[i++] >> ll_state;
				DEBUG_STREAM << __FUNCTION__ << " read state=" << (int)ll_state;
			}
		}
		delete Dout;
	}
	catch(Tango::DevFailed &e)
	{
		ll_state = Tango::FAULT;
		stringstream tmp;
		tmp << "error reading low level attributes err: " << e.errors[0].desc;
		INFO_STREAM << __FUNCTION__ << ":  " << tmp.str();
	}
#if 0

    for(int i=0; i<attr_list.size(); i++)
    {
		string attr_name = dev_attr->get_attr_by_ind(attr_list[0]).get_name();
		DEBUG_STREAM << __func__<<": for attr="<<attr_name;
		if(attr_name != "State")
			return;
    }
    DEBUG_STREAM << __func__<<": State!!!!!!!!";

    map<string,attr_val_t >::iterator it_val = att_value.find("ValveStat");

	if((it_val->second.val[5])||(it_val->second.val[6])/*||(!valve_stat[2])*/)
	{//error occurred
		set_state(Tango::FAULT);
		if(it_val->second.val[5]){
			set_status("error opening");
		}
		if(it_val->second.val[6]){
			set_status("error closing");
		}
#if _PUSH_EVENTS
		Tango::DevState sta = Tango::FAULT;
		try {
			push_change_event("state");
			push_archive_event("state");
		} catch(Tango::DevFailed &e)
		{
			DEBUG_STREAM << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
		}
#endif
		//	if(!valve_stat[2]){
		//		set_status("pressure not ok");
		//	}
	}
	else
	{//no errors
		if(it_val->second.val[0]){//opened?
			if(it_val->second.val[1])
			{//closed? error
				set_state(Tango::FAULT);
				set_status("SW both closed");
#if _PUSH_EVENTS
				Tango::DevState sta = Tango::FAULT;
				try {
					push_change_event("state");
					push_archive_event("state");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
#endif
			}
			else
			{//opened
				set_state(Tango::OPEN);
				set_status("----");
#if _PUSH_EVENTS
				Tango::DevState sta = Tango::OPEN;
				try {
					push_change_event("state");
					push_archive_event("state");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
#endif
			}
		}
		else
		{
			if(it_val->second.val[1])
			{//closed?
				set_state(Tango::CLOSE);
				set_status("----");
#if _PUSH_EVENTS
				Tango::DevState sta = Tango::CLOSE;
				try {
					push_change_event("state");
					push_archive_event("state");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
#endif
			}
			else
			{//moving
				set_state(Tango::MOVING);
				set_status("SW both opened");
#if _PUSH_EVENTS
				Tango::DevState sta = Tango::MOVING;
				try {
					push_change_event("state");
					push_archive_event("state");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
#endif
			}
		}
//		if(is_local_ctrl){
//			set_status("local");
//		}
		if(cutoff_ind >=0 && cutoff_ind < MAX_ATTR_SIZE)
		{
			if(!it_val->second.val[cutoff_ind]){
				set_status("cutoff");
			}
		}
	}
#endif

	/*----- PROTECTED REGION END -----*/	//	AccessConf::read_attr_hardware

}


//--------------------------------------------------------
/**
 *	Read BoolScalarDyn attribute
 *	Description: 
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar 
 */
//--------------------------------------------------------
void AccessConf::read_BoolScalarDyn(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AccessConf::read_BoolScalarDyn(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AccessConf::read_BoolScalarDyn) ENABLED START -----*/

	map<string,attr_val_t >::iterator it_val = att_value.find(attr.get_name());

	if(it_val == att_value.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute Not Found", \
							(const char*)"Attribute Not Found", \
							__FUNCTION__, Tango::ERR);
	}

	map<string,vector<attr_desc_t> >::iterator it_data = att_data.find(attr.get_name());

	if(it_data == att_data.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute Not Found", \
							(const char*)"Attribute Not Found", \
							__FUNCTION__, Tango::ERR);
	}

	for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
	{
		DEBUG_STREAM << __FUNCTION__ << " looping " << it_rem_attr->remote_attr_name;
		//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		map<string,rem_val_t >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		if(ll_attr_it != remote_att_value.end())
		{
			DEBUG_STREAM << __FUNCTION__ << " ll_attr_it->second.size()= " << ll_attr_it->second.val_b.size();
			DEBUG_STREAM << __FUNCTION__ << " " << attr.get_name() <<"["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]";
			if(ll_attr_it->first != "state")
			{
				it_val->second.val[ it_rem_attr->attr_index ] = ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
				if(it_rem_attr->remote_index == 0)
					it_val->second.val[ it_rem_attr->attr_index ] = true;
			}
			else
			{
				it_val->second.val[ it_rem_attr->attr_index ] = (ll_state == Tango::ON);
			}
		}
	}

    //	Set the attribute value
    attr.set_value(&(it_val->second.val[0]));

	/*----- PROTECTED REGION END -----*/	//	AccessConf::read_BoolScalarDyn
}
//--------------------------------------------------------
/**
 *	Read BoolSpectrumDyn attribute
 *	Description: 
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Spectrum  max = 1000
 */
//--------------------------------------------------------
void AccessConf::read_BoolSpectrumDyn(Tango::Attribute &attr)
{
	DEBUG_STREAM << "AccessConf::read_BoolSpectrumDyn(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AccessConf::read_BoolSpectrumDyn) ENABLED START -----*/

	//	Set the attribute value
	map<string,attr_val_t >::iterator it_val = att_value.find(attr.get_name());

	if(it_val == att_value.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute Not Found", \
							(const char*)"Attribute Not Found", \
							__FUNCTION__, Tango::ERR);
	}

	map<string,vector<attr_desc_t> >::iterator it_data = att_data.find(attr.get_name());

	if(it_data == att_data.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute Not Found", \
							(const char*)"Attribute Not Found", \
							__FUNCTION__, Tango::ERR);
	}

	for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
	{
		DEBUG_STREAM << __FUNCTION__ << " looping " << it_rem_attr->remote_attr_name;
		//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		map<string,rem_val_t >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		if(ll_attr_it != remote_att_value.end())
		{
			//DEBUG_STREAM << __FUNCTION__ << " found value for " << it_rem_attr->remote_attr_name<<" attr idx="<<it_rem_attr->attr_index << " rem idx="<<it_rem_attr->remote_index;
			it_val->second.val[ it_rem_attr->attr_index ] = ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
			DEBUG_STREAM << __FUNCTION__ << " " << attr.get_name() <<"["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]="<<(int)ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
			if(it_rem_attr->remote_index == 0)
				it_val->second.val[ it_rem_attr->attr_index ] = true;
			if(attr.get_name() == "ValveStat")
			{
				int i=it_rem_attr->attr_index;
				if(i==2 && it_rem_attr->remote_index == 0)
					it_val->second.val[i]=true;
				else if(i==4 && it_rem_attr->remote_index == 0 /*it_rem_attr->descr == "spare"*/)
					it_val->second.val[i]=false;
				else if(i>4 && i<=7)
					it_val->second.val[i]=!it_val->second.val[i];//invert logic of ERR_ signals in order to have true -> error
			}
		}
	}

	if(attr.get_name() == "ValveStat")
	{
		ValveStat_initialized = true;
	}

    //	Set the attribute value
    attr.set_value(&(it_val->second.val[0]), it_data->second.size());


	if(attr.get_name() == "ValveStat" && ValveStat_initialized)
	{
    map<string,attr_val_t >::iterator it_val = att_value.find("ValveStat");

	if((it_val->second.val[5])||(it_val->second.val[6])/*||(!valve_stat[2])*/)
	{//error occurred

		state_event = Tango::FAULT;
		set_state(state_event);
		if(it_val->second.val[5])
		{
			strcpy(status_str,"error opening");
		}
		if(it_val->second.val[6])
		{
			strcpy(status_str,"error closing");
		}
		set_status(status_str);
		DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
		try {
			push_change_event("state");
			push_archive_event("state");
			//push_change_event("status");
		} catch(Tango::DevFailed &e)
		{
			DEBUG_STREAM << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
		}
		//	if(!valve_stat[2]){
		//		set_status("pressure not ok");
		//	}
	}
	else
	{//no errors
		if(it_val->second.val[0]){//opened?
			if(it_val->second.val[1])
			{//closed? error

				state_event = Tango::FAULT;
				set_state(state_event);
				strcpy(status_str,"SW both closed");
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					//push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
			else
			{//opened

				state_event = Tango::OPEN;
				set_state(state_event);
				strcpy(status_str,"----");
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING OPEN ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					//push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
		}
		else
		{
			if(it_val->second.val[1])
			{//closed?

				state_event = Tango::CLOSE;
				set_state(state_event);
				strcpy(status_str,"----");
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING CLOSE ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					//push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
			else
			{//moving

				state_event = Tango::MOVING;
				set_state(state_event);
				strcpy(status_str,"SW both opened");
				set_status(status_str);
				DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING MOVING ("<<status_str<<") "<<endl;
				try {
					push_change_event("state");
					push_archive_event("state");
					//push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
				}
			}
		}
//		if(is_local_ctrl){
//			set_status("local");
//		}
		if(cutoff_ind >=0 && cutoff_ind < MAX_ATTR_SIZE)
		{
			if(!it_val->second.val[cutoff_ind]){
				strcpy(status_str,"cutoff");
				set_status(status_str);
				try {
					//push_change_event("status", attr_status_read, 1, 0, false);
				} catch(Tango::DevFailed &e)
				{
					DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing status="<<e.errors[0].desc<<endl;
				}
			}
		}
	}
	}

	/*----- PROTECTED REGION END -----*/	//	AccessConf::read_BoolSpectrumDyn
}
//--------------------------------------------------------
/**
 *	Read StringSpectrumDyn attribute
 *	Description:
 *
 *	Data type:	Tango::DevString
 *	Attr type:	Spectrum  max = 1000
 */
//--------------------------------------------------------
void AccessConf::read_StringSpectrumDyn(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AccessConf::read_StringSpectrumDyn(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AccessConf::read_StringSpectrumDyn) ENABLED START -----*/

	//	Set the attribute value
	map<string,attr_val_string_t >::iterator it_val = att_value_string.find(attr.get_name());

	if(it_val == att_value_string.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute 1 Not Found", \
							(const char*)"Attribute 1 Not Found", \
							__FUNCTION__, Tango::ERR);
	}

	map<string,vector<attr_desc_t> >::iterator it_data = att_data.find(attr.get_name());

	if(it_data == att_data.end())
	{
		Tango::Except::throw_exception( \
							(const char*)"Attribute 2 Not Found", \
							(const char*)"Attribute 2 Not Found", \
							__FUNCTION__, Tango::ERR);
	}
	//DEBUG_STREAM << __FUNCTION__ << " 0";
	map<string,rem_val_t >::iterator ll_attr_it;
	for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
	{
		//DEBUG_STREAM << __FUNCTION__ << " looping " << it_rem_attr->remote_attr_name;
		//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
		//DEBUG_STREAM << __FUNCTION__ << " 1";
		if(ll_attr_it != remote_att_value.end())
		{
			//DEBUG_STREAM << __FUNCTION__ << " 2 it_rem_attr->attr_index="<<it_rem_attr->attr_index<<" it_rem_attr->remote_index="<<it_rem_attr->remote_index;
			strcpy(&(it_val->second.val[ it_rem_attr->attr_index ][0]),ll_attr_it->second.val_s.at(it_rem_attr->remote_index).c_str());
			//DEBUG_STREAM << __FUNCTION__ << " " << attr.get_name() <<"["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]";
			//DEBUG_STREAM << "ind=" << it_rem_attr->attr_index << " string=" << (char *) (it_val->second.val[ it_rem_attr->attr_index]) << " ind rem=" << it_rem_attr->remote_index << " rem size="<<ll_attr_it->second.val_s.size();
			attr_StringSpectrumDyn_read[it_rem_attr->attr_index] = (char *) (it_val->second.val[ it_rem_attr->attr_index]);
			//DEBUG_STREAM << __FUNCTION__ << " 3";
		}
	}

	//DEBUG_STREAM << __FUNCTION__ << " before set_value";
    //	Set the attribute value
    attr.set_value(attr_StringSpectrumDyn_read, it_data->second.size());
    //DEBUG_STREAM << __FUNCTION__ << " after set_value";
	/*----- PROTECTED REGION END -----*/	//	AccessConf::read_BoolSpectrumDyn
}

//--------------------------------------------------------
/**
 *	Read BoolScalarDyn attribute
 *	Description:
 *
 *	Data type:	Tango::DevBoolean
 *	Attr type:	Scalar
 */
//--------------------------------------------------------
void AccessConf::read_Version(Tango::Attribute &attr)
{
	//DEBUG_STREAM << "AccessConf::read_BoolScalarDyn(Tango::Attribute &attr) entering... " << endl;
	/*----- PROTECTED REGION ID(AccessConf::read_BoolScalarDyn) ENABLED START -----*/

	uint16_t plcver=0;
	map<string,rem_val_t >::iterator ll_attr_it = remote_att_value.find("Stat_image");
	if(ll_attr_it != remote_att_value.end())
	{
		for(int i=0; i<16; i++)
		{
			plcver |= ll_attr_it->second.val_b.at(16+i) << i;
			DEBUG_STREAM << __FUNCTION__ << " now plcver=" << plcver;
		}
	}

	string tmp(srvver);
	size_t pos = tmp.find("Name: ");
	tmp = tmp.substr(pos+strlen("Name: "));

	sprintf(version_str,"srv_ver:%s plc_ver:%d",tmp.c_str(),plcver);

	attr_Version_read[0] = (char *)version_str;
    //	Set the attribute value
    attr.set_value(attr_Version_read);

	/*----- PROTECTED REGION END -----*/	//	AccessConf::read_BoolScalarDyn
}

//--------------------------------------------------------
/**
 *	Method      : AccessConf::AccessConfClass::add_dynamic_attributes()
 *	Description : Create the dynamic attributes if any
 *	              for specified device.
 */
//--------------------------------------------------------
void AccessConf::add_dynamic_attributes()
{
	/*----- PROTECTED REGION ID(AccessConf::Class::add_dynamic_attributes) ENABLED START -----*/

	//	Add your own code to create and add dynamic attributes if any
	DEBUG_STREAM << __FUNCTION__ << " entering...";

    if (attr_config_prop.empty() == false)
    {
    	DEBUG_STREAM << __FUNCTION__ << " going to create from device property...";
    	create_dynamic_attributes(attr_config_prop);
    }

    if (attr_config_file.empty() == false)
    {
    	DEBUG_STREAM << __FUNCTION__ << " going to create from file...";
		vector<string> attr_config;
		string line;
		attr_config.clear();
		ifstream infile (attr_config_file.c_str(), ios_base::in);
		while (getline(infile, line, '\n'))
		{
		  attr_config.push_back (line);
		}
		infile.close();
		DEBUG_STREAM <<__FUNCTION__ << "Read " << attr_config.size() << " lines.\n";
    	create_dynamic_attributes(attr_config);
    }


    //if(done something)
    {
		map<string,vector<attr_desc_t> >::iterator attr_it;
		for(attr_it=att_data.begin(); attr_it != att_data.end(); attr_it++)
		{
			Tango::Attr *att;
			if (attr_it->second.size() == 1 && (attr_it->second.begin())->type == "bool")
			{
				att = new BoolScalarDynAttrib(attr_it->first);
			}
			else if((attr_it->second.begin())->type == "bool")
			{
				att = new BoolSpectrumDynAttrib(attr_it->first, attr_it->second.size());
			}
			else if((attr_it->second.begin())->type == "string")
			{
				att = new StringSpectrumDynAttrib(attr_it->first, attr_it->second.size());
			}

			add_attribute(att);
			set_change_event(attr_it->first, true, false);
			set_archive_event(attr_it->first, true, true);
			sort(attr_it->second.begin(), attr_it->second.end(),compare_attr_index);
		}
    }
    created_attr = true;
    init_attributeprop();

	/*----- PROTECTED REGION END -----*/	//	AccessConf::Class::add_dynamic_attributes

}

//--------------------------------------------------------
/**
 *	Method      : AccessConf::ControlBoxClass::create_dynamic_attributes()
 *	Description : Create the dynamic attributes if any
 *	              for specified device.
 */
//--------------------------------------------------------
void AccessConf::create_dynamic_attributes(vector<string> attr_config)
{
	DEBUG_STREAM << __FUNCTION__ << " entering...";

	attr_val_t tmp_val;
	vector<string> filter;
	for(unsigned int i=0; i<MAX_ATTR_SIZE; i++)
		tmp_val.val[i] = false;
	attr_val_string_t tmp_val_string;
	for(unsigned int i=0; i<MAX_ATTR_SIZE; i++)
		tmp_val_string.val[i][0] = 0;

	for (unsigned int i = 0;i < attr_config.size();i++)
	{
		vector<string> results;
		string_explode(attr_config[i], ":", &results);
		if((results.size() == 6 || results.size() == 7) && results[0] == "attr" && results[5] != "string")
		{
			attr_desc_t tmp;
			tmp.attr_index=atoi(results[2].c_str());
			tmp.remote_attr_name=results[3];
			//tmp.remote_index=atoi(results[4].c_str());
			int px1, px2;
			sscanf(results[4].c_str(), "%d.%d", &px1, &px2);	//byte.bit
			tmp.remote_index=(px1)*8+px2;
			tmp.descr=results[5];
			tmp.comment=(results.size() == 7) ? results[6] : "";
			tmp.type="bool";
			map<string,vector<attr_desc_t> >::iterator f = att_data.find(results[1]);
			if(f!=att_data.end())
			{
				f->second.push_back(tmp);
			}
			else
			{
				vector<attr_desc_t> tmp_v;
				tmp_v.push_back(tmp);
				att_data.insert(make_pair(results[1],tmp_v));
				att_value.insert(make_pair(results[1],tmp_val));
			}
			vector<string>::iterator it=find(remote_attr.begin(), remote_attr.end(), results[3]);
			if(it == remote_attr.end())
			{
				vector<Tango::DevBoolean> tmp_rem_v_b;
				vector<string> tmp_rem_v_s;
				rem_val_t tmp_rem;
				tmp_rem.val_b = tmp_rem_v_b;
				tmp_rem.val_s = tmp_rem_v_s;
				tmp_rem.loc_attr_name.push_back(results[1]);
				remote_attr.push_back(results[3]);
				remote_type.insert(make_pair(results[3], "bool"));
				remote_att_value.insert(make_pair(results[3],tmp_rem));
				unsigned int tmp_eid = lldevice->subscribe_event(results[3], Tango::CHANGE_EVENT, &ecb, filter,true);	//stateless subscription (doesn't fail if server not running)
				DEBUG_STREAM << __func__<<": subscribed change event for "<<results[3];
				eid.push_back(tmp_eid);
			}
			//remote attribute already used
			else
			{
				map<string,rem_val_t >::iterator it_rem_val = remote_att_value.find(results[3]);
				if(it_rem_val != remote_att_value.end())
				{
					if(find(it_rem_val->second.loc_attr_name.begin(),it_rem_val->second.loc_attr_name.end(),results[1]) == it_rem_val->second.loc_attr_name.end())
						it_rem_val->second.loc_attr_name.push_back(results[1]);
				}
			}
		}
		else if(results.size() == 6 && results[0] == "attr" && results[5] == "string")
		{
			attr_desc_t tmp;
			tmp.attr_index=atoi(results[2].c_str());
			tmp.remote_attr_name=results[3];
			tmp.remote_index=atoi(results[4].c_str());
			tmp.descr=results[5];
			tmp.comment="";
			tmp.type="string";
			map<string,vector<attr_desc_t> >::iterator f = att_data.find(results[1]);
			if(f!=att_data.end())
			{
				f->second.push_back(tmp);
			}
			else
			{
				vector<attr_desc_t> tmp_v;
				tmp_v.push_back(tmp);
				att_data.insert(make_pair(results[1],tmp_v));
				att_value_string.insert(make_pair(results[1],tmp_val_string));
			}
			vector<string>::iterator it=find(remote_attr.begin(), remote_attr.end(), results[3]);
			if(it == remote_attr.end())
			{
				vector<Tango::DevBoolean> tmp_rem_v_b;
				vector<string> tmp_rem_v_s;
				rem_val_t tmp_rem;
				tmp_rem.val_b = tmp_rem_v_b;
				tmp_rem.val_s = tmp_rem_v_s;
				tmp_rem.loc_attr_name.push_back(results[1]);
				remote_attr.push_back(results[3]);
				remote_type.insert(make_pair(results[3], "string"));
				remote_att_value.insert(make_pair(results[3],tmp_rem));
				unsigned int tmp_eid = lldevice->subscribe_event(results[3], Tango::CHANGE_EVENT, &ecb, filter,true);	//stateless subscription (doesn't fail if server not running)
				DEBUG_STREAM << __func__<<": subscribed change event for "<<results[3];
				eid.push_back(tmp_eid);
			}
			//remote attribute already used
			else
			{
				map<string,rem_val_t >::iterator it_rem_val = remote_att_value.find(results[3]);
				if(it_rem_val != remote_att_value.end())
				{
					if(find(it_rem_val->second.loc_attr_name.begin(),it_rem_val->second.loc_attr_name.end(),results[1]) == it_rem_val->second.loc_attr_name.end())
						it_rem_val->second.loc_attr_name.push_back(results[1]);
				}
			}
		}
		else if((results.size() == 5 || results.size() == 9) && results[0] == "cmd")
		{
			cmd_desc_t tmp;
			DEBUG_STREAM << __FUNCTION__ << " cmd, name="<<results[1];
			tmp.remote_cmd_name=results[2];
			tmp.cmd_code=atoi(results[3].c_str());
			//tmp.cmd_offset=atoi(results[4].c_str());
			int px1, px2;
			sscanf(results[4].c_str(), "%d.%d", &px1, &px2);	//byte.bit
			tmp.cmd_offset=(px1)*8+px2;
			if(results.size() == 9)
			{
				//tmp.cmd_offset2=atoi(results[5].c_str());
				sscanf(results[5].c_str(), "%d.%d", &px1, &px2);	//byte.bit
				tmp.cmd_offset2=(px1)*8+px2;
				//tmp.cmd_offset3=atoi(results[6].c_str());
				sscanf(results[6].c_str(), "%d.%d", &px1, &px2);	//byte.bit
				tmp.cmd_offset3=(px1)*8+px2;
				//tmp.cmd_offset4=atoi(results[7].c_str());
				sscanf(results[7].c_str(), "%d.%d", &px1, &px2);	//byte.bit
				tmp.cmd_offset4=(px1)*8+px2;
				tmp.pass=results[8];
			}
			else
			{
				tmp.cmd_offset2=-1;
				tmp.cmd_offset3=-1;
				tmp.cmd_offset4=-1;
				tmp.pass="";
			}
			//DEBUG_STREAM << __FUNCTION__ << " cmd name="<<tmp.remote_cmd_name;
			map<string,cmd_desc_t>::iterator f = cmd_data.find(results[1]);
			if(f!=cmd_data.end())
			{
				//TODO: alert duplicate name
			}
			else
			{
				cmd_data.insert(make_pair(results[1],tmp));
				//DEBUG_STREAM << __FUNCTION__ << " inserted in map cmd name="<<tmp.remote_cmd_name;
				switch(tmp.cmd_code)
				{
#ifdef _OLD_101
					case 101:
						create_dynamic_command(results[1].c_str(), Tango::DEV_USHORT, Tango::DEV_VOID, 1, 0);
						break;
#endif
					case 102:
						create_dynamic_command(results[1].c_str(), Tango::DEV_VOID, Tango::DEV_VOID, 0, 0);
						break;
					case 101:
					case 103:
						if(results.size() == 5)
							create_dynamic_command(results[1].c_str(), Tango::DEV_VOID, Tango::DEV_VOID, 0, 0);
						else
							create_dynamic_command(results[1].c_str(), Tango::DEVVAR_STRINGARRAY, Tango::DEV_VOID, 0, 0);
						break;
					default:
						create_dynamic_command(results[1].c_str(), Tango::DEV_VOID, Tango::DEV_VOID, 0, 0);
						break;
				}
			}
		}
	}
	//DEBUG_STREAM << __FUNCTION__ << " exiting...";
}



//========================================================
//	Command execution methods
//========================================================


	/*----- PROTECTED REGION ID(AccessConf::namespace_ending) ENABLED START -----*/

	//	Additional Methods

Tango::DevState AccessConf::dev_state()
{
	DEBUG_STREAM << __func__<<": entering...";
//	Tango::DevState  result;
	if(!ValveStat_initialized)
	{
		map<string,attr_val_t >::iterator it_val = att_value.find("ValveStat");

		if(it_val == att_value.end())
		{
			return state_event;
		}

		map<string,vector<attr_desc_t> >::iterator it_data = att_data.find("ValveStat");

		if(it_data == att_data.end())
		{
			return state_event;
		}


		try
		{
			vector<Tango::DeviceAttribute> *Dout;
			//Tango::DeviceAttribute Dout;

			Dout = lldevice->read_attributes(remote_attr);
			//Dout = lldevice->read_attribute(remote_attr[0]);

			//map<string,vector<Tango::DevBoolean> >::iterator attr_it;
			map<string,rem_val_t >::iterator attr_it;
			unsigned int i =0;
			for(attr_it=remote_att_value.begin(); attr_it != remote_att_value.end(); attr_it++)
			{
				if(attr_it->first != "state")
				{
					map<string,string>::iterator it_type = remote_type.find(attr_it->first);
					DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second;
					if(it_type != remote_type.end() && it_type->second == "bool")
					{
						(*Dout)[i++] >> attr_it->second.val_b;	//TODO: string
						//Dout >> attr_it->second.val_b;	//TODO: string
						DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_b.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
					}
					else if(it_type != remote_type.end() && it_type->second == "string")
					{
						//(*Dout)[i++] >> attr_it->second.val_s;	//TODO: string
						DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_s.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
						Tango::DeviceAttribute Dout2 = lldevice->read_attribute(attr_it->first.c_str());
						Dout2 >> attr_it->second.val_s;	//TODO: string
					}
				}
				else
				{
					(*Dout)[i++] >> ll_state;
					DEBUG_STREAM << __FUNCTION__ << " read state=" << (int)ll_state;
				}
			}
			delete Dout;
		}
		catch(Tango::DevFailed &e)
		{
			ll_state = Tango::FAULT;
			stringstream tmp;
			tmp << "error reading low level attributes err: " << e.errors[0].desc;
			INFO_STREAM << __FUNCTION__ << ":  " << tmp.str();
		}


		for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
		{
			DEBUG_STREAM << __FUNCTION__ << " looping " << it_rem_attr->remote_attr_name;
			//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
			map<string,rem_val_t >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
			if(ll_attr_it != remote_att_value.end())
			{
				//DEBUG_STREAM << __FUNCTION__ << " found value for " << it_rem_attr->remote_attr_name<<" attr idx="<<it_rem_attr->attr_index << " rem idx="<<it_rem_attr->remote_index;
				it_val->second.val[ it_rem_attr->attr_index ] = ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
				DEBUG_STREAM << __FUNCTION__ << " ValveStat["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]="<<(int)ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
				if(it_rem_attr->remote_index == 0)
					it_val->second.val[ it_rem_attr->attr_index ] = true;
				if(it_data->first == "ValveStat")
				{
					int i=it_rem_attr->attr_index;
					if(i==2 && it_rem_attr->remote_index == 0)
						it_val->second.val[i]=true;
					else if(i==4 && it_rem_attr->remote_index == 0 /*it_rem_attr->descr == "spare"*/)
						it_val->second.val[i]=false;
					else if(i>4 && i<=7)
						it_val->second.val[i]=!it_val->second.val[i];//invert logic of ERR_ signals in order to have true -> error
				}
			}
		}

		ValveStat_initialized = true;


		if((it_val->second.val[5])||(it_val->second.val[6])/*||(!valve_stat[2])*/)
		{//error occurred

			state_event = Tango::FAULT;
			set_state(state_event);
			if(it_val->second.val[5])
			{
				strcpy(status_str,"error opening");
			}
			if(it_val->second.val[6])
			{
				strcpy(status_str,"error closing");
			}
			set_status(status_str);
			DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
			try {
				push_change_event("state");
				push_archive_event("state");
				//push_change_event("status");
			} catch(Tango::DevFailed &e)
			{
				DEBUG_STREAM << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
			}
			//	if(!valve_stat[2]){
			//		set_status("pressure not ok");
			//	}
		}
		else
		{//no errors
			if(it_val->second.val[0]){//opened?
				if(it_val->second.val[1])
				{//closed? error

					state_event = Tango::FAULT;
					set_state(state_event);
					strcpy(status_str,"SW both closed");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
				else
				{//opened

					state_event = Tango::OPEN;
					set_state(state_event);
					strcpy(status_str,"----");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING OPEN ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
			}
			else
			{
				if(it_val->second.val[1])
				{//closed?

					state_event = Tango::CLOSE;
					set_state(state_event);
					strcpy(status_str,"----");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING CLOSE ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
				else
				{//moving

					state_event = Tango::MOVING;
					set_state(state_event);
					strcpy(status_str,"SW both opened");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING MOVING ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}


				}
			}
	//		if(is_local_ctrl){
	//			set_status("local");
	//		}
			if(cutoff_ind >=0 && cutoff_ind < MAX_ATTR_SIZE)
			{
				if(!it_val->second.val[cutoff_ind]){
					strcpy(status_str,"cutoff");
					set_status(status_str);
					try {
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing status="<<e.errors[0].desc<<endl;
					}
				}
			}
		}

	}
	return state_event;
}

Tango::ConstDevString 	AccessConf::dev_status()
{
	DEBUG_STREAM << __func__<<": entering...";
	Tango::ConstDevString  result;
	//sprintf(status_str,"The device is in UNKNOWN state.");
	result = status_str;

	if(!ValveStat_initialized)
	{
		map<string,attr_val_t >::iterator it_val = att_value.find("ValveStat");

		if(it_val == att_value.end())
		{
			return result;
		}

		map<string,vector<attr_desc_t> >::iterator it_data = att_data.find("ValveStat");

		if(it_data == att_data.end())
		{
			return result;
		}

		try
		{
			vector<Tango::DeviceAttribute> *Dout;
			//Tango::DeviceAttribute Dout;

			Dout = lldevice->read_attributes(remote_attr);
			//Dout = lldevice->read_attribute(remote_attr[0]);

			//map<string,vector<Tango::DevBoolean> >::iterator attr_it;
			map<string,rem_val_t >::iterator attr_it;
			unsigned int i =0;
			for(attr_it=remote_att_value.begin(); attr_it != remote_att_value.end(); attr_it++)
			{
				if(attr_it->first != "state")
				{
					map<string,string>::iterator it_type = remote_type.find(attr_it->first);
					DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second;
					if(it_type != remote_type.end() && it_type->second == "bool")
					{
						(*Dout)[i++] >> attr_it->second.val_b;	//TODO: string
						//Dout >> attr_it->second.val_b;	//TODO: string
						DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_b.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
					}
					else if(it_type != remote_type.end() && it_type->second == "string")
					{
						//(*Dout)[i++] >> attr_it->second.val_s;	//TODO: string
						DEBUG_STREAM << __FUNCTION__ << " remote type=" << it_type->second << " name="<<attr_it->first<<" copyed="<<attr_it->second.val_s.size();// << " dout len="<<(*Dout)[i-1].get_dim_x();
						Tango::DeviceAttribute Dout2 = lldevice->read_attribute(attr_it->first.c_str());
						Dout2 >> attr_it->second.val_s;	//TODO: string
					}
				}
				else
				{
					(*Dout)[i++] >> ll_state;
					DEBUG_STREAM << __FUNCTION__ << " read state=" << (int)ll_state;
				}
			}
			delete Dout;
		}
		catch(Tango::DevFailed &e)
		{
			ll_state = Tango::FAULT;
			stringstream tmp;
			tmp << "error reading low level attributes err: " << e.errors[0].desc;
			INFO_STREAM << __FUNCTION__ << ":  " << tmp.str();
		}

		for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
		{
			DEBUG_STREAM << __FUNCTION__ << " looping " << it_rem_attr->remote_attr_name;
			//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
			map<string,rem_val_t >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
			if(ll_attr_it != remote_att_value.end())
			{
				//DEBUG_STREAM << __FUNCTION__ << " found value for " << it_rem_attr->remote_attr_name<<" attr idx="<<it_rem_attr->attr_index << " rem idx="<<it_rem_attr->remote_index;
				it_val->second.val[ it_rem_attr->attr_index ] = ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
				DEBUG_STREAM << __FUNCTION__ << " ValveStat["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]="<<(int)ll_attr_it->second.val_b.at(it_rem_attr->remote_index);
				if(it_rem_attr->remote_index == 0)
					it_val->second.val[ it_rem_attr->attr_index ] = true;
				if(it_data->first == "ValveStat")
				{
					int i=it_rem_attr->attr_index;
					if(i==2 && it_rem_attr->remote_index == 0)
						it_val->second.val[i]=true;
					else if(i==4 && it_rem_attr->remote_index == 0 /*it_rem_attr->descr == "spare"*/)
						it_val->second.val[i]=false;
					else if(i>4 && i<=7)
						it_val->second.val[i]=!it_val->second.val[i];//invert logic of ERR_ signals in order to have true -> error
				}
			}
		}

		ValveStat_initialized = true;


		if((it_val->second.val[5])||(it_val->second.val[6])/*||(!valve_stat[2])*/)
		{//error occurred

			state_event = Tango::FAULT;
			set_state(state_event);
			if(it_val->second.val[5])
			{
				strcpy(status_str,"error opening");
			}
			if(it_val->second.val[6])
			{
				strcpy(status_str,"error closing");
			}
			set_status(status_str);
			DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
			try {
				push_change_event("state");
				push_archive_event("state");
				//push_change_event("status");
			} catch(Tango::DevFailed &e)
			{
				DEBUG_STREAM << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
			}
			//	if(!valve_stat[2]){
			//		set_status("pressure not ok");
			//	}
		}
		else
		{//no errors
			if(it_val->second.val[0]){//opened?
				if(it_val->second.val[1])
				{//closed? error

					state_event = Tango::FAULT;
					set_state(state_event);
					strcpy(status_str,"SW both closed");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING FAULT ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
				else
				{//opened

					state_event = Tango::OPEN;
					set_state(state_event);
					strcpy(status_str,"----");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING OPEN ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
			}
			else
			{
				if(it_val->second.val[1])
				{//closed?

					state_event = Tango::CLOSE;
					set_state(state_event);
					strcpy(status_str,"----");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING CLOSE ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
				else
				{//moving

					state_event = Tango::MOVING;
					set_state(state_event);
					strcpy(status_str,"SW both opened");
					set_status(status_str);
					DEBUG_STREAM << __FUNCTION__ << "    -> PUSHING MOVING ("<<status_str<<") "<<endl;
					try {
						push_change_event("state");
						push_archive_event("state");
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing state="<<e.errors[0].desc<<endl;
					}
				}
			}
	//		if(is_local_ctrl){
	//			set_status("local");
	//		}
			if(cutoff_ind >=0 && cutoff_ind < MAX_ATTR_SIZE)
			{
				if(!it_val->second.val[cutoff_ind]){
					strcpy(status_str,"cutoff");
					set_status(status_str);
					try {
						//push_change_event("status");
					} catch(Tango::DevFailed &e)
					{
						DEBUG_STREAM << "AccessConf::always_executed_hook() error pushing status="<<e.errors[0].desc<<endl;
					}
				}
			}
		}

	}
	return result;
}



//+------------------------------------------------------------------
/**
 *	method:	AccessConf::string_explode
 * Explode a string
*/
//+------------------------------------------------------------------
void AccessConf::string_explode(string str, string separator, vector<string>* results)
{
	size_t found;

	found = str.find_first_of(separator);
	while(found != string::npos) {
		if(found > 0) {
			results->push_back(str.substr(0,found));
		}
		str = str.substr(found+1);
		found = str.find_first_of(separator);
	}
	if(str.length() > 0) {
		results->push_back(str);
	}

}

//+------------------------------------------------------------------
/**
 *	method:	AccessConf::init_attributeprop
 *
 *	description:
 *
 *
 */
//+------------------------------------------------------------------
void AccessConf::init_attributeprop()
{

	//DEBUG_STREAM << __FUNCTION__ << " entering...";
    Tango::Database *db = new Tango::Database();
	vector <Tango::DbData> vdb_datastat;

	for(map<string,vector<attr_desc_t> >::iterator it_att = att_data.begin(); it_att != att_data.end(); it_att++)
	{
		vector <string> lastat;
		vector <string> destat;
		vector <string> costat;
		for(vector<attr_desc_t>::iterator it_v = it_att->second.begin(); it_v != it_att->second.end(); it_v++)
		{
			lastat.push_back(it_v->descr);
			stringstream tmp2;
			tmp2 << int(it_v->remote_index /8) << "." << it_v->remote_index %8 << " - " << it_v->comment;
			costat.push_back(tmp2.str());
			stringstream tmp;
			tmp << low_level_srv << "/" << it_v->remote_attr_name << "[" << it_v->remote_index << "]";
			destat.push_back(tmp.str());
			//DEBUG_STREAM << __FUNCTION__ << ": label=" << it_v->descr << " pos=" << tmp.str();
		}
		Tango::DbData db_datastat;
		Tango::DbDatum db_stat(it_att->first), lab_stat("labels"), des_stat("positions"), com_stat("comments");
		db_stat << (short int) 3;
		db_datastat.push_back(db_stat);
		lab_stat << lastat;
		des_stat << destat;
		com_stat << costat;
		db_datastat.push_back(lab_stat);
		db_datastat.push_back(des_stat);
		db_datastat.push_back(com_stat);
		vdb_datastat.push_back(db_datastat);
	}
	vector<Tango::DbData>::iterator ite;

	try {
		db->set_timeout_millis(10000);
		for( ite=vdb_datastat.begin() ; ite < vdb_datastat.end(); ite++ ){
			db->put_device_attribute_property(get_name(), *ite);
		}
	} catch (Tango::DevFailed &e) {
		INFO_STREAM << "Intlkconf::init_attributeprop() init attributeprop failed"<<endl;
		Tango::Except::print_exception(e);
	}
	delete db;
}

long AccessConf::create_dynamic_command(const char* cmd_name, Tango::CmdArgType type_in, Tango::CmdArgType type_out, long size_in, long size_out)
{

	std::vector< Tango::Command* >& command_list = get_device_class()->get_command_list();
	bool found = false;
	std::vector< Tango::Command* >::iterator it;
	for(it=command_list.begin(); it!= command_list.end(); it++)
	{
		if((*it)->get_name()==string(cmd_name))
		{
			found = true;
			break;
		}
	}
	if(!found)
		command_list.push_back(new CmdClass(cmd_name,
				type_in, type_out,
				"argin",
				"argout",
				Tango::OPERATOR,
				size_in,
				this));

	return 0;
}

void AccessConf::extract_values(Tango::DeviceAttribute *attr_value, vector<Tango::DevBoolean> &v_bo, vector<string> &v_string)
{

	v_bo.clear();
	v_string.clear();

	if (attr_value->get_type() == Tango::DEV_BOOLEAN)
	{
		*(attr_value) >> v_bo;
	}
	else if (attr_value->get_type() == Tango::DEV_STRING)
	{
		*(attr_value) >> v_string;
	}
	else
	{
		ostringstream o;
		o << "unknown type=" << (int)attr_value->get_type() << ends;
		throw o.str();
	}
}

/***************************************************************************

  CmdClass class

***************************************************************************/
CORBA::Any *CmdClass::execute(Tango::DeviceImpl *device,const CORBA::Any &in_any)
{

	cout << "CmdClass::" << get_name() << ": entering..." << endl;

	//const Tango::DevVarLongArray	*argin;
	//extract(in_any, argin);

	Tango::DevShort argin;
	mydevice = ((AccessConf*)device);
	map< string,cmd_desc_t >::iterator f;

	/*	for(f=mydevice->cmd_data.begin(); f!=mydevice->cmd_data.end(); f++)
	{
		cout << "cmd name="<<f->first<<" code="<<f->second.cmd_code<<" offset="<<f->second.cmd_offset<<endl;
	}*/

	if(mydevice!=0)
	{
		f = mydevice->cmd_data.find(get_name());
	}

	if(!mydevice || f== mydevice->cmd_data.end())
	{
		Tango::Except::throw_exception( \
					(const char*)"Command Error", \
					(const char*)"Command Not Found", \
					__FUNCTION__, Tango::ERR);
	}

	switch(f->second.cmd_code)
	{
#ifdef _OLD_101
		case 101:
		{
			Tango::DevUShort argin_u;
			extract(in_any, argin_u);
			if(argin_u < 0 || argin_u > 15)
				Tango::Except::throw_exception( \
							(const char*)"Command Error", \
							(const char*)"Argin out of range [0,15]", \
							__FUNCTION__, Tango::ERR);
			vector<Tango::DevShort> param;
			param.push_back(f->second.cmd_code);
			Tango::DevShort posto;
			if(f->second.cmd_offset != -1)
				posto = f->second.cmd_offset + argin_u + 14*8; //posti occupati 14.0 - 15.7
			else
				posto = argin_u + 14*8;	//posti occupati 14.0 - 15.7
			param.push_back(posto);
			cout << "CmdClass::" << get_name() << ": 101 - " << argin_u << " -> postioccupati="<< posto << endl;
			Tango::DeviceData Din;
			Din << param;
			mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din);
			break;
		}
#endif
		case 102:
		{
			vector<Tango::DevShort> param1;
			param1.push_back(f->second.cmd_code);
			if(f->second.cmd_offset != -1)
				param1.push_back(f->second.cmd_offset);
			param1.push_back(6);

			cout << "CmdClass::" << get_name() << ": 102 - " << f->second.cmd_offset << " - 6" << endl;
			Tango::DeviceData Din1;
			Din1 << param1;
			mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din1);

			usleep(1100000);

			vector<Tango::DevShort> param2;
			param2.push_back(f->second.cmd_code);
			if(f->second.cmd_offset != -1)
				param2.push_back(f->second.cmd_offset);
			param2.push_back(9);
			cout << "CmdClass::" << get_name() << ": 102 - " << f->second.cmd_offset << " - 9" << endl;
			Tango::DeviceData Din2;
			Din2 << param2;
			mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din2);
			break;
		}
		case 101:
		case 103:
		{
			int offset;
			vector<Tango::DevShort> param;
			param.push_back(f->second.cmd_code);
			if(f->second.cmd_offset2 == -1)
			{
				if(f->second.cmd_offset != -1)
				{
					param.push_back(f->second.cmd_offset);
					offset = f->second.cmd_offset;
				}
			}
			else
			{
				const Tango::DevVarStringArray *argin_s;
				extract(in_any, argin_s);
				vector<string> str;
				str << (*argin_s);
				vector<string>::iterator si;
				if(str.size() != 2)
				{
					cout << "CmdClass::" << get_name() << ": bad argin number" << endl;
					Tango::Except::throw_exception( \
									(const char*)"Invalid parameters", \
									(const char*)"Invalid parameters", \
									__FUNCTION__, Tango::ERR);
					return new CORBA::Any();
				}
				if(str.at(1) != f->second.pass)
				{
					cout << "CmdClass::" << get_name() << ": bad pass="<<str.at(1) << endl;
					Tango::Except::throw_exception( \
									(const char*)"Invalid parameters", \
									(const char*)"Invalid parameters", \
									__FUNCTION__, Tango::ERR);
					return new CORBA::Any();
				}
				switch(atoi(str.at(0).c_str()))
				{
					case 0:
						param.push_back(f->second.cmd_offset);
						offset = f->second.cmd_offset;
					break;
					case 1:
						param.push_back(f->second.cmd_offset2);
						offset = f->second.cmd_offset2;
					break;
					case 2:
						param.push_back(f->second.cmd_offset3);
						offset = f->second.cmd_offset3;
					break;
					case 3:
						param.push_back(f->second.cmd_offset4);
						offset = f->second.cmd_offset4;
					break;
					default:
						return new CORBA::Any();
				}
				cout << "CmdClass::" << get_name() << ": found offset="<<atoi(str.at(0).c_str()) << endl;
			}

			cout << "CmdClass::" << get_name() << ": 103 - " << offset << endl;
			Tango::DeviceData Din;
			Din << param;
			mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din);
			break;
		}
		default:
			switch(in_type)
			{
				case Tango::DEV_SHORT:
				{
					cout << "CmdClass::" << get_name() << ": found in type short" << endl;

					extract(in_any, argin);
					if(mydevice && f!= mydevice->cmd_data.end())
					{
						vector<Tango::DevShort> param;
						param.push_back(f->second.cmd_code);
						/*if(f->second.cmd_offset != -1)
							param.push_back(f->second.cmd_offset);*/
						param.push_back(argin); //TODO
						Tango::DeviceData Din;
						Din << param;
						mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din);
					}
					break;
				}
				case Tango::DEV_VOID:
				default:
				{
					cout << "CmdClass::" << get_name() << ": found in type void" << endl;
					if(mydevice && f!= mydevice->cmd_data.end())
					{
						vector<Tango::DevShort> param;
						param.push_back(f->second.cmd_code);
						if(f->second.cmd_offset != -1)
							param.push_back(f->second.cmd_offset);
						Tango::DeviceData Din;
						Din << param;
						mydevice->lldevice->command_inout(f->second.remote_cmd_name.c_str(),Din);
					}
					break;
				}
			}
			break;
	}


	return new CORBA::Any();

}

/*
 * EventCallBack class methods
 */
EventCallBack::EventCallBack()
{
	//cout<<"EventCallBack::EventCallBack entering..."<<endl;
	mydevice = NULL;
	//mydevices.clear();
}

EventCallBack::~EventCallBack(void)
{
	//cout<<"EventCallBack::~EventCallBack entering..."<<endl;
	mydevice = NULL;
	//mydevices.clear();
}

void EventCallBack::push_event(Tango::EventData* ev)
{
	string event_name = ev->attr_name;
	//cout << __func__<<": entering event="<<event_name << endl;
	//	Check if event is an error event.
	if (ev->err)
	{
		cout<< __func__ << ": Exception on " << ev->attr_name << " err=" << ev->errors[0].desc << endl;
		return;
	}
	//find event
	map<string,rem_val_t >::iterator it_ev;
	std::transform(event_name.begin(), event_name.end(), event_name.begin(), (int(*)(int))tolower);		//transform to lowercase

	for(it_ev = (static_cast<AccessConf *>(mydevice))->remote_att_value.begin(); it_ev != (static_cast<AccessConf *>(mydevice))->remote_att_value.end(); it_ev++)
	{
		string remote_name=(static_cast<AccessConf *>(mydevice))->low_level_srv + "/" + it_ev->first;
		std::transform(remote_name.begin(), remote_name.end(), remote_name.begin(), (int(*)(int))tolower);		//transform to lowercase
		//cout << __func__<<": 1 looking for: '"<<event_name<<"' now remote_name: '"<<remote_name<<"'"<<endl;
		if(remote_name.find(event_name) != string::npos)	//TODO: or ==
		{
			//cout << __func__<<": 1 looking for: '"<<event_name<<"' FOUND 1'"<<endl;
			break;
		}
	}

	if (it_ev == (static_cast<AccessConf *>(mydevice))->remote_att_value.end())
	{
		//try to remove network domain and FQDN
		string ev_name_str(event_name);
		string::size_type pos_slash = ev_name_str.find("tango://");
		if (pos_slash != string::npos)	//FQDN!!
		{
			//first remove network domain if any
			string::size_type pos_dot = ev_name_str.find(".",8);	//look for first . after tango://
			string::size_type pos_colon = ev_name_str.find(":",8);	//look for first : after tango://
			pos_slash = ev_name_str.find('/',8);					//look for first / after tango://
			if(pos_dot < pos_slash && pos_dot != string::npos && pos_colon != string::npos && pos_slash != string::npos)	//dot is in the TANGO_HOST part
			{
				string ev_name_str_no_domain = ev_name_str.substr(0,pos_dot) + ev_name_str.substr(pos_colon);
				for(it_ev = (static_cast<AccessConf *>(mydevice))->remote_att_value.begin(); it_ev != (static_cast<AccessConf *>(mydevice))->remote_att_value.end(); it_ev++)
				{
					string remote_name=(static_cast<AccessConf *>(mydevice))->low_level_srv + "/" + it_ev->first;
					std::transform(remote_name.begin(), remote_name.end(), remote_name.begin(), (int(*)(int))tolower);		//transform to lowercase
					//cout << __func__<<": 2 looking for: '"<<ev_name_str_no_domain<<"' now remote_name: '"<<remote_name<<"'"<<endl;
					if(remote_name.find(ev_name_str_no_domain) != string::npos)	//TODO: or ==
					{
						//cout << __func__<<": 2 looking for: '"<<ev_name_str_no_domain<<"' FOUND 2'"<<endl;
						break;
					}
				}
			}
			if (it_ev == (static_cast<AccessConf *>(mydevice))->remote_att_value.end() && pos_slash != string::npos)
			{
				ev_name_str = ev_name_str.substr(pos_slash + 1);//remove FQDN
				for(it_ev = (static_cast<AccessConf *>(mydevice))->remote_att_value.begin(); it_ev != (static_cast<AccessConf *>(mydevice))->remote_att_value.end(); it_ev++)
				{
					string remote_name=(static_cast<AccessConf *>(mydevice))->low_level_srv + "/" + it_ev->first;
					std::transform(remote_name.begin(), remote_name.end(), remote_name.begin(), (int(*)(int))tolower);		//transform to lowercase
					//cout << __func__<<": 3 looking for: '"<<ev_name_str<<"' now remote_name: '"<<remote_name<<"'"<<endl;
					if(remote_name.find(ev_name_str) != string::npos)	//TODO: or ==
					{
						//cout << __func__<<": 3 looking for: '"<<ev_name_str<<"' FOUND 3'"<<endl;
						break;
					}
				}
			}
		}
		if (it_ev == (static_cast<AccessConf *>(mydevice))->remote_att_value.end())
		{
			/*
			 * shouldn't happen!!!
			 */
			ostringstream o;
			o << "find_events(): event '" \
				<< event_name << "' not found!" << ends;
			cout <<__func__<< ": " << o.str() << endl;
			return;
		}
	}
	/*string remote_name=(static_cast<AccessConf *>(mydevice))->low_level_srv + "/" + it_ev->first;
	std::transform(remote_name.begin(), remote_name.end(), remote_name.begin(), (int(*)(int))tolower);		//transform to lowercase
	cout << __func__<<": FOUND event="<<remote_name << endl;*/

	/*if (it_ev == (static_cast<AccessConf *>(mydevice))->remote_att_value.end())
	{
		return;
	}*/

	(static_cast<AccessConf *>(mydevice))->extract_values(ev->attr_value, it_ev->second.val_b_ev, it_ev->second.val_s_ev);


	//iterate through local attributes, evaluates attrs involved and push events
	for(vector<string>::iterator it_loc_attr=it_ev->second.loc_attr_name.begin(); it_loc_attr!=it_ev->second.loc_attr_name.end(); it_loc_attr++)
	{
		//cout << __func__<<": NOW looping local attr="<<*it_loc_attr << endl;
		map<string,attr_val_t >::iterator it_val = (static_cast<AccessConf *>(mydevice))->att_value.find(*it_loc_attr);
		map<string,vector<attr_desc_t> >::iterator it_data = (static_cast<AccessConf *>(mydevice))->att_data.find(*it_loc_attr);

		for(vector<attr_desc_t>::iterator it_rem_attr = it_data->second.begin(); it_rem_attr != it_data->second.end(); it_rem_attr++)
		{
			//cout << __FUNCTION__ << "  -> looping " << it_rem_attr->remote_attr_name<<endl;
			//map<string,vector<Tango::DevBoolean> >::iterator ll_attr_it = remote_att_value.find(it_rem_attr->remote_attr_name);
			map<string,rem_val_t >::iterator ll_attr_it = (static_cast<AccessConf *>(mydevice))->remote_att_value.find(it_rem_attr->remote_attr_name);
			if(ll_attr_it != (static_cast<AccessConf *>(mydevice))->remote_att_value.end())
			{
				//cout << __FUNCTION__ << "  -> found value for " << it_rem_attr->remote_attr_name<<" attr idx="<<it_rem_attr->attr_index << " rem idx="<<it_rem_attr->remote_index<<endl;
				it_val->second.val[ it_rem_attr->attr_index ] = ll_attr_it->second.val_b_ev.at(it_rem_attr->remote_index);
				//cout << __FUNCTION__ << "  -> " << *it_loc_attr <<"["<< it_rem_attr->attr_index<<"]=" << it_rem_attr->remote_attr_name << "["<<it_rem_attr->remote_index<<"]="<<(int)ll_attr_it->second.val_b_ev.at(it_rem_attr->remote_index)<<endl;
				if(it_rem_attr->remote_index == 0)
					it_val->second.val[ it_rem_attr->attr_index ] = true;
				if(*it_loc_attr == "ValveStat")
				{
					int i=it_rem_attr->attr_index;
					if(i==2 && it_rem_attr->remote_index == 0)
						it_val->second.val[i]=true;
					else if(i==4 && it_rem_attr->remote_index == 0 /*it_rem_attr->descr == "spare"*/)
						it_val->second.val[i]=false;
					else if(i>4 && i<=7)
						it_val->second.val[i]=!it_val->second.val[i];//invert logic of ERR_ signals in order to have true -> error
				}

				/*else if string
				{
					strcpy(&(it_val->second.val[ it_rem_attr->attr_index ][0]),ll_attr_it->second.val_s_ev.at(it_rem_attr->remote_index).c_str());
					(static_cast<AccessConf *>(mydevice))->attr_StringSpectrumDyn_read[it_rem_attr->attr_index] = (char *) (it_val->second.val[ it_rem_attr->attr_index]);
				}*/
			}
		}

		//if ValveStat handle state for valves
		if(*it_loc_attr == "ValveStat")
		{
			if((static_cast<AccessConf *>(mydevice))->created_attr)	//first event arrives when attributes are not fully created
				(static_cast<AccessConf *>(mydevice))->ValveStat_initialized = true;



			if((it_val->second.val[5]||it_val->second.val[6]/*||!valve_stat[2]*/) && (static_cast<AccessConf *>(mydevice))->created_attr)
			{//error occurred

				(static_cast<AccessConf *>(mydevice))->state_event = Tango::FAULT;
				(static_cast<AccessConf *>(mydevice))->set_state((static_cast<AccessConf *>(mydevice))->state_event);
				if(it_val->second.val[5])
				{
					strcpy((static_cast<AccessConf *>(mydevice))->status_str,"error opening");
				}
				if(it_val->second.val[6])
				{
					strcpy((static_cast<AccessConf *>(mydevice))->status_str,"error closing");
				}
				(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
				//cout << __FUNCTION__ << "    -> PUSHING FAULT ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
				try {
					(static_cast<AccessConf *>(mydevice))->push_change_event("state");
					(static_cast<AccessConf *>(mydevice))->push_archive_event("state");
					//(static_cast<AccessConf *>(mydevice))->push_change_event("status");
				} catch(Tango::DevFailed &e)
				{
					cout << __func__<<": error pushing state="<<e.errors[0].desc<<endl;
				}
				//	if(!valve_stat[2]){
				//		set_status("pressure not ok");
				//	}
			}
			else if((static_cast<AccessConf *>(mydevice))->created_attr)
			{//no errors
				if(it_val->second.val[0]){//opened?
					if(it_val->second.val[1])
					{//closed? error

						(static_cast<AccessConf *>(mydevice))->state_event = Tango::FAULT;
						(static_cast<AccessConf *>(mydevice))->set_state((static_cast<AccessConf *>(mydevice))->state_event);
						strcpy((static_cast<AccessConf *>(mydevice))->status_str,"SW both closed");
						(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
						//cout << __FUNCTION__ << "    -> PUSHING FAULT ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
						try {
							(static_cast<AccessConf *>(mydevice))->push_change_event("state");
							(static_cast<AccessConf *>(mydevice))->push_archive_event("state");
							//(static_cast<AccessConf *>(mydevice))->push_change_event("status");
						} catch(Tango::DevFailed &e)
						{
							cout << __func__ <<" error pushing state="<<e.errors[0].desc<<endl;
						}
					}
					else
					{//opened

						(static_cast<AccessConf *>(mydevice))->state_event = Tango::OPEN;
						(static_cast<AccessConf *>(mydevice))->set_state((static_cast<AccessConf *>(mydevice))->state_event);
						strcpy((static_cast<AccessConf *>(mydevice))->status_str,"----");
						(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
						//cout << __FUNCTION__ << "    -> PUSHING OPEN ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
						try {
							(static_cast<AccessConf *>(mydevice))->push_change_event("state");
							(static_cast<AccessConf *>(mydevice))->push_archive_event("state");
							//(static_cast<AccessConf *>(mydevice))->push_change_event("status");
						} catch(Tango::DevFailed &e)
						{
							cout << __func__ <<" error pushing state="<<e.errors[0].desc<<endl;
						}
					}
				}
				else
				{
					if(it_val->second.val[1])
					{//closed?

						(static_cast<AccessConf *>(mydevice))->state_event = Tango::CLOSE;
						(static_cast<AccessConf *>(mydevice))->set_state((static_cast<AccessConf *>(mydevice))->state_event);
						strcpy((static_cast<AccessConf *>(mydevice))->status_str,"----");
						(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
						//cout << __FUNCTION__ << "    -> PUSHING CLOSE ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
						try {
							(static_cast<AccessConf *>(mydevice))->push_change_event("state");
							(static_cast<AccessConf *>(mydevice))->push_archive_event("state");
							//(static_cast<AccessConf *>(mydevice))->push_change_event("status");
						} catch(Tango::DevFailed &e)
						{
							cout << __func__ <<" error pushing state="<<e.errors[0].desc<<endl;
						}
					}
					else
					{//moving

						(static_cast<AccessConf *>(mydevice))->state_event = Tango::MOVING;
						(static_cast<AccessConf *>(mydevice))->set_state((static_cast<AccessConf *>(mydevice))->state_event);
						strcpy((static_cast<AccessConf *>(mydevice))->status_str,"SW both opened");
						(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
						//cout << __FUNCTION__ << "    -> PUSHING MOVING ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
						try {
							(static_cast<AccessConf *>(mydevice))->push_change_event("state");
							(static_cast<AccessConf *>(mydevice))->push_archive_event("state");
							//(static_cast<AccessConf *>(mydevice))->push_change_event("status");
						} catch(Tango::DevFailed &e)
						{
							cout << __func__ <<" error pushing state="<<e.errors[0].desc<<endl;
						}
					}
				}
		//		if(is_local_ctrl){
		//			set_status("local");
		//		}
				if((static_cast<AccessConf *>(mydevice))->cutoff_ind >=0 && (static_cast<AccessConf *>(mydevice))->cutoff_ind < MAX_ATTR_SIZE)
				{
					if(!it_val->second.val[(static_cast<AccessConf *>(mydevice))->cutoff_ind]){
						strcpy((static_cast<AccessConf *>(mydevice))->status_str,"cutoff");
						(static_cast<AccessConf *>(mydevice))->set_status((static_cast<AccessConf *>(mydevice))->status_str);
						//cout << __FUNCTION__ << "    -> PUSHING ?? ("<<(static_cast<AccessConf *>(mydevice))->status_str<<") "<<endl;
						try {
							//(static_cast<AccessConf *>(mydevice))->push_change_event("status", (static_cast<AccessConf *>(mydevice))->attr_status_read, 1, 0, false);
						} catch(Tango::DevFailed &e)
						{
							cout << __func__ <<" error pushing status="<<e.errors[0].desc<<endl;
						}
					}
				}
			}
		}
		if((static_cast<AccessConf *>(mydevice))->created_attr)
		{
			try {
				//	push the attribute value
				(static_cast<AccessConf *>(mydevice))->push_change_event(*it_loc_attr,&(it_val->second.val[0]), it_data->second.size());
				(static_cast<AccessConf *>(mydevice))->push_archive_event(*it_loc_attr,&(it_val->second.val[0]), it_data->second.size());
			} catch(Tango::DevFailed &e)
			{
				cout << __func__ <<" error pushing state="<<e.errors[0].desc<<endl;
			}
		/*else if string
		 (static_cast<AccessConf *>(mydevice))->push_change_event(*it_loc_attr,(static_cast<AccessConf *>(mydevice))->attr_StringSpectrumDyn_read, it_data->second.size());
		 */
		}
	}


}  /* push_event() */

void EventCallBack::init(Tango::DeviceImpl *p)
{
	//cout<<(int)now_log.tv_sec<<" "<<"EventCallBack::init entering..."<<endl;
	mydevice = p;
	//mydevices.push_back(p);
}

	/*----- PROTECTED REGION END -----*/	//	AccessConf::namespace_ending
} //	namespace