Select Git revision
SingleShotAO.cpp
-
Alexandre MALFREYT authored
refactor: revert e9bc2d69 partially to prevent pogo interference (get default values later in get_device_property)
Alexandre MALFREYT authoredrefactor: revert e9bc2d69 partially to prevent pogo interference (get default values later in get_device_property)
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SingleShotAO.cpp 38.31 KiB
static const char *RcsId = "$Id: DevServ.cpp 13293 2009-04-07 10:53:56Z pascal_verdier $";
//+=============================================================================
//
// file : SingleShotAO.cpp
//
// description : C++ source for the SingleShotAO 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
// SingleShotAO are implemented in this file.
//
// project : TANGO Device Server
//
// $Author: pascal_verdier $
//
// $Revision: 13293 $
//
// $Revision: 13293 $
// $Date: 2009-04-07 12:53:56 +0200 (Tue, 07 Apr 2009) $
//
// SVN only:
// $HeadURL: $
//
// CVS only:
// $Source$
// $Log$
// Revision 3.5 2007/10/24 12:07:35 pascal_verdier
// Another spelling mistake correction
//
// Revision 3.4 2007/10/23 14:04:30 pascal_verdier
// Spelling mistakes correction
//
// Revision 3.3 2005/03/02 14:06:15 pascal_verdier
// namespace is different than class name.
//
// Revision 3.2 2004/11/08 11:33:16 pascal_verdier
// if device property not found in database, it takes class property value if exists.
//
// Revision 3.1 2004/09/06 09:27:05 pascal_verdier
// Modified for Tango 5 compatibility.
//
//
// copyleft : Synchrotron SOLEIL
// L'Orme des merisiers - Saint Aubin
// BP48 - 91192 Gif sur Yvette
// FRANCE
//
//-=============================================================================
//
// This file is generated by POGO
// (Program Obviously used to Generate tango Object)
//
// (c) - Software Engineering Group - ESRF
//=============================================================================
//===================================================================
//
// The following table gives the correspondence
// between commands and method name.
//
// Command name| Method name
// ----------------------------------------
// State | dev_state()
// Status | dev_status()
// Abort | abort()
//
//===================================================================
#include <tango.h>
#include <yat4tango/Logging.h>
#include <yat4tango/DeviceInfo.h>
#include <SingleShotAO.h>
#include <SingleShotAOClass.h>
#include "SingleShotAOTypesAndConsts.h"
namespace SingleShotAO_ns
{
//- check manager macro:
#define CHECK_MANAGER() \
do \
{ \
if (! m_manager) \
THROW_DEVFAILED("DEVICE_ERROR", \
"request aborted - the manager isn't accessible ", \
"SingleShotAO::check_manager"); \
} while (0)
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::SingleShotAO(string &s)
//
// description : constructor for simulated SingleShotAO
//
// in : - cl : Pointer to the DeviceClass object
// - s : Device name
//
//-----------------------------------------------------------------------------
SingleShotAO::SingleShotAO(Tango::DeviceClass *cl,string &s)
:TANGO_BASE_CLASS(cl,s.c_str())
{
init_device();
}
SingleShotAO::SingleShotAO(Tango::DeviceClass *cl,const char *s)
:TANGO_BASE_CLASS(cl,s)
{
init_device();
}
SingleShotAO::SingleShotAO(Tango::DeviceClass *cl,const char *s,const char *d)
:TANGO_BASE_CLASS(cl,s,d)
{
init_device();
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::delete_device()
//
// description : will be called at device destruction or at init command.
//
//-----------------------------------------------------------------------------
void SingleShotAO::delete_device()
{
DEBUG_STREAM << "SingleShotAO::delete_device(): entering... !" << endl;
// Make sure running processes are aborted properly if channels are running
//--------------------------------------------
try
{
_abort();
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << df << endl;
RETHROW_DEVFAILED(df,
"DRIVER_FAILURE",
"could not abort [caught Tango::DevFailed]",
"SingleShotAO::delete_device");
}
catch (...)
{
ERROR_STREAM << "SingleShotAO::init::unknown exception caught" << std::endl;
THROW_DEVFAILED("DRIVER_FAILURE",
"could not abort [unknown error]",
"SingleShotAO::delete_device");
}
// Delete device allocated objects
//--------------------------------------------
yat4tango::TraceHelper t("SingleShotAO::delete_device", this);
if (m_manager)
{
m_manager->exit();
m_manager = NULL;
}
// Release the asl::SingleShotAO object
//--------------------------------------------
if (m_ssao)
{
delete m_ssao;
m_ssao = NULL;
}
// Remove dynamic attributes
//--------------------------------------------
if (m_dyn_attr_manager)
{
try
{
m_dyn_attr_manager->remove_attributes();
}
catch (...)
{
//- ignore any error
}
}
// delete dynamic attributes manager
if (m_dyn_attr_manager)
{
delete m_dyn_attr_manager;
m_dyn_attr_manager = NULL;
}
// Remove the inner appender
//--------------------------------------------
yat4tango::Logging::release(this);
yat4tango::DeviceInfo::release(this);
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::init_device()
//
// description : will be called at device initialization.
//
//-----------------------------------------------------------------------------
void SingleShotAO::init_device()
{
//- initialize the inner appender (first thing to do)
try
{
INFO_STREAM << "Create the InnerAppender & FileAppender in order to manage logs." << endl;
yat4tango::Logging::initialize(this);
INFO_STREAM << "Create the DeviceInfo in order to manage info on versions." << endl;
yat4tango::DeviceInfo::initialize(this, YAT_XSTR(PROJECT_NAME), YAT_XSTR(PROJECT_VERSION));
yat4tango::DeviceInfo::add_dependency(this, "ASL", ">=1.0");
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << df << std::endl;
m_state = Tango::FAULT;
m_currStatus = "initialization failed - could not instantiate the InnerAppender";
return;
}
INFO_STREAM << "Initializing device";
//- trace/profile this method
yat4tango::TraceHelper t("SingleShotAO::init_device", this);
// construct the AO manager
//--------------------------------------------
try
{
m_manager = new SingleShotAOManager(this);
}
catch (...)
{
ERROR_STREAM << "initialization failed - failed to create manager" << std::endl;
m_currStatus = "initialization failed [failed to create manager]. See log for details";
m_state = Tango::FAULT;
return;
}
// Initialise variables to default values
//--------------------------------------------
//- init members
m_ssao = NULL;
critical_properties_missing = false;
isInitOk = false;
m_frequency = 0.0;
m_dyn_attr_manager = NULL;
m_state = Tango::INIT;
// Initialise variables to default values
//--------------------------------------------
try
{
get_device_property();
}
catch (const Tango::DevFailed& df)
{
ERROR_STREAM << "SingleShotAO::init_device::Tango::DevFailed exception caught "
<< "while trying to read device properties from TANGO database"
<< std::endl;
std::string error_msg = df.errors[0].desc;
std::istringstream error_stream(error_msg);
std::string line;
std::getline(error_stream, line); // Read the first line
ERROR_STREAM << line << std::endl;
while (std::getline(error_stream, line)) { // Read the rest of the lines
ERROR_STREAM << " - " << line << std::endl;
}
m_currStatus = error_msg;
m_state = Tango::FAULT;
return;
}
catch (...)
{
//- update internal state
ERROR_STREAM << "SingleShotAO::init_device::unknown exception caught "
<< "while trying to read device properties from TANGO database"
<< std::endl;
m_currStatus = "Failed to get property. See log for details";
m_state = Tango::FAULT;
return;
}
//- abort initialization if properties missing
if (critical_properties_missing)
{
ERROR_STREAM << "configuration error - unspecified or invalid device properties";
m_currStatus = "configuration error [unspecified or invalid device properties]. See log for details";
m_state = Tango::FAULT;
return;
}
//- allocate the asl::SingleShotAO object
m_ssao = new asl::SingleShotAO;
if (m_ssao == 0)
{
m_currStatus = "Failed to create the SignleShotAO. See log for details";
m_state = Tango::FAULT;
return;
}
try
{
//- initialze the hardware
m_ssao->init(boardTypeId, boardNum);
}
catch(const asl::DAQException& de)
{
ERROR_STREAM << daq_to_tango_exception(de) << endl;
m_currStatus = "Failed to init the SignleShotAO. See log for details";
m_state = Tango::FAULT;
return;
}
catch(...)
{
ERROR_STREAM << "SingleShotAO::init_device::unknown exception caught"<<std::endl;
m_currStatus = "Failed to init the SignleShotAO. See log for details";
m_state = Tango::FAULT;
return;
}
// initialize channel number according to board type
m_nb_chan = 0;
if (boardType == k6208_BOARD_TYPE)
{
m_nb_chan = 8;
}
if (boardType == k6216_BOARD_TYPE)
{
m_nb_chan = 16;
}
INFO_STREAM << "Board has " << m_nb_chan << " channels" << endl;
// test the manager
if (!m_manager)
{
ERROR_STREAM << "initialization failed - the manager is not created" << std::endl;
m_currStatus = "initialization failed [the manager is not created]. See log for details";
m_state = Tango::FAULT;
return;
}
// get frequency value in database
//--------------------------------------------
try
{
m_frequency = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, "frequency");
DEBUG_STREAM << "Frequency : " << m_frequency << endl;
}
catch (...)
{
DEBUG_STREAM << "No memorized value found for frequency. Defaulting to " << m_frequency << "." << std::endl;
}
// initialize the AO manager
//--------------------------------------------
try
{
m_manager->init(m_ssao, m_nb_chan, m_frequency, enableRamps);
}
catch (Tango::DevFailed & df)
{
ERROR_STREAM << df << std::endl;
m_currStatus = "initialization failed - Manager initialization failed [see device log for details]";
m_state = Tango::FAULT;
return;
}
catch (...)
{
ERROR_STREAM << "initialization failed - failed to initialize manager" << std::endl;
m_currStatus = "initialization failed [failed to initialize manager]. See log for details";
m_state = Tango::FAULT;
return;
}
// Remove existing dynamic attributes to avoid duplicates or other issues
// --------------------------------------------
if (m_dyn_attr_manager)
{
try
{
m_dyn_attr_manager->remove_attributes();
delete m_dyn_attr_manager;
m_dyn_attr_manager = NULL;
DEBUG_STREAM << "Existing dynamic attributes manager cleaned up" << endl;
}
catch (...)
{
ERROR_STREAM << "Error cleaning up existing dynamic attributes manager, continuing..." << endl;
// Continue anyway - we'll create a new one
}
}
// Create dynamic attributes
//--------------------------------------------
// create dynamic attribute manager
try
{
m_dyn_attr_manager = new yat4tango::DynamicAttributeManager(this);
}
catch (Tango::DevFailed &e)
{
ERROR_STREAM << e << std::endl;
m_currStatus = "Failed to create Dynamic Attribute Manager. See log for details";
m_state = Tango::FAULT;
return;
}
catch (...)
{
ERROR_STREAM << "Failed to create Dynamic Attribute Manager" << std::endl;
m_currStatus = "Failed to create Dynamic Attribute Manager. See log for details";
m_state = Tango::FAULT;
return;
}
// add dynamic attributes: channel, speed & initial for each channel
std::vector<yat4tango::DynamicAttributeInfo> l_dynAttrList;
// Log how many attributes we're going to create
INFO_STREAM << "Creating dynamic attributes for " << m_nb_chan << " channels.";
INFO_STREAM << "Total attributes: " << m_nb_chan * (enableRamps ? 3 : 1) << endl;
for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++)
{
yat::OSStream oss;
oss << l_cpt;
// ╔═══════════════╗
// ║ Channel value ║
// ╚═══════════════╝
yat4tango::DynamicAttributeInfo dai_channel;
dai_channel.dev = this;
dai_channel.tai.name = kCHANNEL + oss.str();
dai_channel.tai.label = kCHANNEL + oss.str();
//- describe the dyn attr we want...
dai_channel.tai.data_type = Tango::DEV_DOUBLE;
dai_channel.tai.data_format = Tango::SCALAR;
dai_channel.tai.writable = Tango::READ_WRITE; // soso
dai_channel.tai.disp_level = Tango::OPERATOR;
dai_channel.tai.unit = "V";
dai_channel.tai.standard_unit = "V";
dai_channel.tai.display_unit = "V";
dai_channel.tai.max_value = "10.0";
dai_channel.tai.min_value = "-10.0";
dai_channel.tai.description = "Output value for channel " + oss.str() + " (in measurementUnit).";
dai_channel.tai.format = "%5.3f";
dai_channel.cdb = false;
//- read callback
dai_channel.rcb = yat4tango::DynamicAttributeReadCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::read_channel);
//- write callback
dai_channel.wcb = yat4tango::DynamicAttributeWriteCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::write_channel);
l_dynAttrList.push_back(dai_channel);
// if enableRamps if false, skip speed and initial attributes
if (!enableRamps)
{
DEBUG_STREAM << "Ramps are disabled. Skipping speed and initial attributes for channel " << l_cpt << std::endl;
continue;
}
// ╔═══════════════╗
// ║ Speed value ║
// ╚═══════════════╝
yat4tango::DynamicAttributeInfo dai_speed;
dai_speed.dev = this;
dai_speed.tai.name = kSPEED + oss.str();
dai_speed.tai.label = kSPEED + oss.str();
//- describe the dyn attr we want...
dai_speed.tai.data_type = Tango::DEV_DOUBLE;
dai_speed.tai.data_format = Tango::SCALAR;
dai_speed.tai.writable = Tango::READ_WRITE;
dai_speed.tai.disp_level = Tango::OPERATOR;
dai_speed.tai.unit = "V/s";
dai_speed.tai.standard_unit = "V/s";
dai_speed.tai.display_unit = "V/s";
dai_speed.tai.description = "Speed for ramp generation, in V/s. If speed is NULL, no ramp generated but direct write on channel output " + oss.str() + " (in measurementUnit).";
dai_speed.tai.format = "%5.3f";
//- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db)
dai_speed.cdb = false;
//- read callback
dai_speed.rcb = yat4tango::DynamicAttributeReadCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::read_speed);
//- write callback
dai_speed.wcb = yat4tango::DynamicAttributeWriteCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::write_speed);
l_dynAttrList.push_back(dai_speed);
// ╔═══════════════╗
// ║ Initial value ║
// ╚═══════════════╝
yat4tango::DynamicAttributeInfo dai_initial;
dai_initial.dev = this;
dai_initial.tai.name = kINITIAL + oss.str();
dai_initial.tai.label = kINITIAL + oss.str();
//- describe the dyn attr we want...
dai_initial.tai.data_type = Tango::DEV_DOUBLE;
dai_initial.tai.data_format = Tango::SCALAR;
dai_initial.tai.writable = Tango::READ_WRITE;
dai_initial.tai.disp_level = Tango::OPERATOR;
dai_initial.tai.unit = "V";
dai_initial.tai.standard_unit = "V";
dai_initial.tai.display_unit = "V";
dai_initial.tai.description = "Initial value for ramp function, in V. Defaults to last written value in channel attribute " + oss.str() + ".";
dai_initial.tai.format = "%5.3f";
//- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db)
dai_initial.cdb = false;
//- read callback
dai_initial.rcb = yat4tango::DynamicAttributeReadCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::read_initial);
//- write callback
dai_initial.wcb = yat4tango::DynamicAttributeWriteCallback::instanciate(const_cast<SingleShotAO&>(*this),
&SingleShotAO::write_initial);
l_dynAttrList.push_back(dai_initial);
}
// Log the size of our attribute list before adding to manager
INFO_STREAM << "Prepared " << l_dynAttrList.size() << " dynamic attributes for creation" << endl;
// Add all attributes
try
{
m_dyn_attr_manager->add_attributes(l_dynAttrList);
INFO_STREAM << "Successfully added all dynamic attributes" << endl;
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << "Failed to add dynamic attributes: " << df << endl;
m_currStatus = "Failed to add dynamic attributes. See log for details";
m_state = Tango::FAULT;
return;
}
catch (...)
{
ERROR_STREAM << "Unknown exception when adding dynamic attributes" << endl;
m_currStatus = "Failed to add dynamic attributes. Unknown error";
m_state = Tango::FAULT;
return;
}
// Initialize maps in manager class for all channels
try
{
for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++)
{
// Initialize with default values
m_manager->set_channel(l_cpt, 0.0);
if (enableRamps)
{
m_manager->set_speed(l_cpt, 0.0);
m_manager->set_initial(l_cpt, 0.0);
}
}
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << "Failed to initialize channel maps: " << df << endl;
m_currStatus = "Failed to initialize channel maps. See log for details";
m_state = Tango::FAULT;
return;
}
// Get memorized values from database
for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++)
{
yat::OSStream oss;
oss << l_cpt;
// Helper function to get and set memorized attributes
auto applyMemorizedAttr = [&](const std::string& attrPrefix,
void (SingleShotAOManager::*setter)(yat::uint16, double))
{
std::string attrName = attrPrefix + oss.str();
try
{
double val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, attrName);
DEBUG_STREAM << "Found memorized value for " << attrName << ": " << val << endl;
// Write the value to the manager (that contains the "read" attributes values)
(m_manager->*setter)(l_cpt, val);
// Write the value to the "write" attributes using helper function
setDynamicAttributeWriteValue(attrName, val);
}
catch (...)
{
DEBUG_STREAM << "No memorized value found for " << attrName << ". Setting default value." << std::endl;
}
};
// Get and set memorized values for speed, initial and channel
if (enableRamps)
{
applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed);
applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial);
}
if (outputMemorizedChannelsAtInit)
{
applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel_direct); // write memorized value to board output (directly, without ramp)
} else {
applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); // only apply memorized value to the device
}
}
//- GO for task
try
{
m_manager->go();
}
catch (Tango::DevFailed & df)
{
ERROR_STREAM << df << std::endl;
m_currStatus = "initialization failed [failed to go for manager]";
m_state = Tango::FAULT;
return;
}
catch (...)
{
ERROR_STREAM << "initialization failed - failed to go for manager" << std::endl;
m_currStatus = "initialization failed [failed to go for manager]. See log for details";
m_state = Tango::FAULT;
return;
}
//- update internal state
m_state = Tango::ON;
m_currStatus = "Device ready to execute AO request.";
isInitOk = true;
}
//+------------------------------------------------------------------
/**
* method : SingleShotAO::get_device_property()
*
* description : Read the device properties from database.
*
* @throws DevFailed if any critical property is missing, not set, or invalid
*/
void SingleShotAO::get_device_property()
{
// Read device properties from database
//------------------------------------------------------------------
Tango::DbData dev_prop;
dev_prop.push_back(Tango::DbDatum("BoardNum"));
dev_prop.push_back(Tango::DbDatum("BoardType"));
dev_prop.push_back(Tango::DbDatum("EnableRamps"));
dev_prop.push_back(Tango::DbDatum("OutputMemorizedChannelsAtInit"));
// Call database and extract values
//--------------------------------------------
if (Tango::Util::instance()->_UseDb==true)
{
get_db_device()->get_property(dev_prop);
}
Tango::DbDatum def_prop, cl_prop;
SingleShotAOClass *ds_class = (static_cast<SingleShotAOClass *>(get_device_class()));
int i = -1;
//- <BoardNum> -----------------------
// Try to initialize BoardNum from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty()==false) cl_prop >> boardNum;
else {
// Try to initialize BoardNum from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty() == false)
{
def_prop >> boardNum_default;
def_prop >> boardNum;
}
}
// And try to extract BoardNum value from database
if (dev_prop[i].is_empty() == false) dev_prop[i] >> boardNum;
INFO_STREAM << "Raw BoardNum parsed: " << boardNum << endl;
//- <BoardType> -----------------------
// Try to initialize BoardType from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty() == false) cl_prop >> boardType;
else {
// Try to initialize BoardType from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty() == false)
{
def_prop >> boardType_default;
def_prop >> boardType;
}
}
// And try to extract BoardType value from database
if (dev_prop[i].is_empty() == false) dev_prop[i] >> boardType;
INFO_STREAM << "Raw BoardType parsed: " << boardType << endl;
//- <EnableRamps> -----------------------
// Try to initialize EnableRamps from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty() == false) cl_prop >> enableRamps;
else {
// Try to initialize EnableRamps from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty() == false)
{
def_prop >> enableRamps_default;
def_prop >> enableRamps;
}
}
// And try to extract EnableRamps value from database
if (dev_prop[i].is_empty() == false) dev_prop[i] >> enableRamps;
INFO_STREAM << "EnableRamps parsed: " << (enableRamps ? "true" : "false") << endl;
//- <OutputMemorizedChannelsAtInit> -----------------------
// Try to initialize OutputMemorizedChannelsAtInit from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty() == false) cl_prop >> outputMemorizedChannelsAtInit;
else {
// Try to initialize OutputMemorizedChannelsAtInit from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty() == false)
{
def_prop >> outputMemorizedChannelsAtInit_default;
def_prop >> outputMemorizedChannelsAtInit;
}
}
// And try to extract OutputMemorizedChannelsAtInit value from database
if (dev_prop[i].is_empty() == false) dev_prop[i] >> outputMemorizedChannelsAtInit;
INFO_STREAM << "OutputMemorizedChannelsAtInit parsed: " << (outputMemorizedChannelsAtInit ? "true" : "false") << endl;
// Create properties if empty and set default values
//--------------------------------------------
DEBUG_STREAM << "Creating properties if empty" << endl;
yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardNum_default, "BoardNum");
yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardType_default, "BoardType");
yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, enableRamps_default, "EnableRamps");
yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, outputMemorizedChannelsAtInit_default, "OutputMemorizedChannelsAtInit");
// Check critical properties being valid
//--------------------------------------------
DEBUG_STREAM << "Checking if critical properties are valid:" << endl;
critical_properties_missing = false;
yat::OSStream errorMessages;
errorMessages << "Critical properties are missing or invalid:" << endl;
//- <BoardNum> -----------------------
// Case 1 (error): boardNum is set to the default value in the database
if (boardNum == boardNum_default)
{
errorMessages << "Device property <BoardNum> is not set (default value " << boardNum_default << " needs to be replaced)" << endl;
critical_properties_missing = true;
}
// Case 2 (error): boardNum is set to a value outside the valid range
else if (boardNum < 0 || boardNum > 7)
{
boardNum = 0;
errorMessages << "Device property <BoardNum> is invalid. Valid range is [0..7]" << endl;
critical_properties_missing = true;
}
// Case 3 (ok): boardNum is set to a valid value
else
{
INFO_STREAM << "BoardNum resolved to " << boardNum << endl;
}
//- <BoardType> -----------------------
// Case 1 (error): boardType is set to the default value in the database
if (boardType == boardType_default || boardType == "")
{
errorMessages << "Device property <BoardType> is not set (default value " << boardType_default << " needs to be replaced)" << endl;
critical_properties_missing = true;
}
// Case 2 (ok): boardType is set to a valid
else if (boardType == "MAO_6208")
{
boardType = k6208_BOARD_TYPE;
boardTypeId = adl::PCI6208;
INFO_STREAM << "BoardType resolved to PCI6208" << endl;
}
else if (boardType == "MAO_6216")
{
boardType = k6216_BOARD_TYPE;
boardTypeId = adl::PCI6216;
INFO_STREAM << "BoardType resolved to PCI6216" << endl;
}
// Case 3 (error): boardType is set to an invalid value
else
{
boardType = kDEFAULT_BOARD_TYPE;
boardTypeId = adl::PCI6208;
errorMessages << "Device property <BoardType> is invalid [supported hw: MAO_6208 or MAO_6216]" << endl;
critical_properties_missing = true;
}
// If any critical property is missing or invalid, throw an exception
if (critical_properties_missing)
{
DEBUG_STREAM << "Critical properties are missing, throwing exception." << endl;
THROW_DEVFAILED("DEVICE_ERROR", errorMessages.str().c_str(), "SingleShotAO::get_device_property");
}
else
{
DEBUG_STREAM << "All critical properties are valid." << endl;
}
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::always_executed_hook()
//
// description : method always executed before any command is executed
//
//-----------------------------------------------------------------------------
void SingleShotAO::always_executed_hook()
{
// nothing to do
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::read_attr_hardware
//
// description : Hardware acquisition for attributes.
//
//-----------------------------------------------------------------------------
void SingleShotAO::read_attr_hardware(vector<long> &attr_list)
{
// nothing to do
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::read_frequency
//
// description : Extract real attribute values for Frequency acquisition result.
//
//-----------------------------------------------------------------------------
void SingleShotAO::read_frequency(Tango::Attribute &attr)
{
attr.set_value(&m_frequency);
}
//+----------------------------------------------------------------------------
//
// method : SingleShotAO::write_frequency
//
// description : Write Frequency attribute values to hardware.
//
//-----------------------------------------------------------------------------
void SingleShotAO::write_frequency(Tango::WAttribute &attr)
{
DEBUG_STREAM << "SingleShotAO::write_frequency(Tango::WAttribute &attr) entering... "<< endl;
if (dev_state() != Tango::ON)
{
THROW_DEVFAILED("DEVICE_ERROR",
"could not write frequency. The state must be ON.",
"SingleShotAO::write_frequency");
}
CHECK_MANAGER();
attr.get_write_value(m_frequency);
m_manager->write_frequency(m_frequency);
yat4tango::PropertyHelper::set_memorized_attribute(this, "frequency", m_frequency);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::dev_state
*
* description: method to execute "State"
* This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller.
*
* @return State Code
*
*/
//+------------------------------------------------------------------
Tango::DevState SingleShotAO::dev_state()
{
if (isInitOk)
{
CHECK_MANAGER();
m_state = m_manager->get_state();
}
return m_state;
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::dev_status
*
* description: method to execute "Status"
* This command gets the device status (stored in its <i>device_status</i> data member) and returns it to the caller.
*
* @return Status description
*
*/
//+------------------------------------------------------------------
Tango::ConstDevString SingleShotAO::dev_status()
{
static std::string s = "";
yat::OSStream oss;
if (isInitOk)
{
CHECK_MANAGER();
oss << m_manager->get_status() << std::endl;
}
else
{
oss << m_currStatus.c_str() << std::endl;
}
s = oss.str();
return s.c_str();
}
//+------------------------------------------------------------------
/**
* Extract the number from a dynamic attribute name with a specific prefix.
* Used for parsing dynamic attribute names like "channelX", "speedX", "initialX"
* where X is the channel number.
*
* @param str The input string to search for numbers
* @param prefix The expected prefix (e.g., "channel", "speed", "initial")
* @return The number found after the prefix
* @throws DevFailed if string doesn't start with prefix or no number is found
*/
int extractNumber(const std::string &str, const char* prefix)
{
// Validate string starts with the given prefix
if (str.find(prefix) != 0)
{
THROW_DEVFAILED("DEVICE_ERROR",
"String must start with the expected prefix",
"SingleShotAO::extractNumber");
}
// Find first digit after the prefix
size_t pos = strlen(prefix);
// Extract and convert the number
std::string numberStr = str.substr(pos);
if (numberStr.empty() || !isdigit(numberStr[0]))
{
THROW_DEVFAILED("DEVICE_ERROR",
"No number found after prefix",
"SingleShotAO::extractNumber");
}
return std::stoi(numberStr);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::read_channel
*
* description: method to execute "read_channel" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::read_channel(yat4tango::DynamicAttributeReadCallbackData & cbd)
{
yat::AutoMutex<> guard(m_lock);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kCHANNEL); // extract channel nb
CHECK_MANAGER();
double l_val = m_manager->get_channel(l_idx);
cbd.tga->set_value(&l_val);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::write_channel
*
* description: method to execute "write_channel" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & cbd)
{
double l_val;
cbd.tga->get_write_value(l_val);
cbd.tga->set_write_value(l_val);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kCHANNEL); // extract channel nb
CHECK_MANAGER();
try
{
m_manager->write_channel(l_idx, l_val);
}
catch(Tango::DevFailed& df)
{
ERROR_STREAM << df<< endl;
RETHROW_DEVFAILED(df,
"DRIVER_FAILURE",
"could not write channel [caught Tango::DevFailed]",
"SingleShotAO::write_channel");
}
catch(...)
{
ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught"<<std::endl;
THROW_DEVFAILED("DRIVER_FAILURE",
"could not write channel [unknown error]",
"SingleShotAO::write_channel");
}
DEBUG_STREAM << "SingleShotAO::write_channel(): channel " << l_idx << " value set to " << l_val << endl;
yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val);
// Update the initial attribute to match the channel value
std::string initialAttrName = kINITIAL + std::to_string(l_idx);
yat4tango::PropertyHelper::set_memorized_attribute(this, initialAttrName, l_val);
setDynamicAttributeWriteValue(initialAttrName, l_val);
DEBUG_STREAM << "SingleShotAO::write_channel(): memorized attribute " << l_attr_name << " set to " << l_val << endl;
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::read_speed
*
* description: method to execute "read_speed" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::read_speed(yat4tango::DynamicAttributeReadCallbackData & cbd)
{
yat::AutoMutex<> guard(m_lock);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kSPEED); // extract channel nb
CHECK_MANAGER();
double l_val = m_manager->get_speed(l_idx);
cbd.tga->set_value(&l_val);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::write_speed
*
* description: method to execute "write_speed" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cbd)
{
DEBUG_STREAM << "SingleShotAO::write_speed(): entering... !" << endl;
double l_val;
cbd.tga->get_write_value(l_val);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kSPEED); // extract channel nb
if (l_val < 0)
{
l_val = -l_val;
}
CHECK_MANAGER();
try
{
m_manager->set_speed(l_idx, l_val);
}
catch(Tango::DevFailed& df)
{
ERROR_STREAM << df<< endl;
RETHROW_DEVFAILED(df,
"DRIVER_FAILURE",
"could not write speed [caught Tango::DevFailed]",
"SingleShotAO::write_speed");
}
catch(...)
{
ERROR_STREAM << "SingleShotAO::write_speed::unknown exception caught" << std::endl;
THROW_DEVFAILED("DRIVER_FAILURE",
"could not write speed [unknown error]",
"SingleShotAO::write_speed");
}
yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::read_initial
*
* description: method to execute "read_initial" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::read_initial(yat4tango::DynamicAttributeReadCallbackData & cbd)
{
yat::AutoMutex<> guard(m_lock);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kINITIAL); // extract channel nb
CHECK_MANAGER();
double l_val = m_manager->get_initial(l_idx);
cbd.tga->set_value(&l_val);
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::write_initial
*
* description: method to execute "write_initial" for dynamic attributes
*
*/
//+------------------------------------------------------------------
void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & cbd)
{
DEBUG_STREAM << "SingleShotAO::write_initial(): entering... !" << endl;
double l_val;
cbd.tga->get_write_value(l_val);
std::string l_attr_name = cbd.dya->get_name();
yat::uint16 l_idx = extractNumber(l_attr_name, kINITIAL); // extract channel nb
CHECK_MANAGER();
try
{
m_manager->set_initial(l_idx, l_val);
}
catch(Tango::DevFailed& df)
{
ERROR_STREAM << df<< endl;
RETHROW_DEVFAILED(df,
"DRIVER_FAILURE",
"could not write initial [caught Tango::DevFailed]",
"SingleShotAO::write_initial");
}
catch(...)
{
ERROR_STREAM << "SingleShotAO::write_initial::unknown exception caught"<<std::endl;
THROW_DEVFAILED("DRIVER_FAILURE",
"could not write initial [unknown error]",
"SingleShotAO::write_initial");
}
yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val);
}
//+------------------------------------------------------------------
/**
* set the write value of a dynamic attribute
* used to keep read and write values in sync
*/
bool SingleShotAO::setDynamicAttributeWriteValue(const std::string& attrName, double value)
{
try
{
Tango::DeviceImpl* dev = static_cast<Tango::DeviceImpl*>(this);
Tango::DevDouble val_to_write = value;
// Get the attribute
Tango::WAttribute& attr = dev->get_device_attr()->get_w_attr_by_name(attrName.c_str());
// Set the write value
attr.set_write_value(&val_to_write, 1);
DEBUG_STREAM << "Set write value for " << attrName << " to " << value << endl;
return true;
}
catch (Tango::DevFailed &df)
{
ERROR_STREAM << "Failed to set write value for " << attrName
<< ": " << df << endl;
return false;
}
catch (...)
{
ERROR_STREAM << "Unknown exception setting write value for "
<< attrName << endl;
return false;
}
}
//+------------------------------------------------------------------
/**
* method: SingleShotAO::abort
*
* description: method to execute "Abort"
* Aborts ramps in progress.
*
*/
//+------------------------------------------------------------------
void SingleShotAO::abort()
{
DEBUG_STREAM << "SingleShotAO::abort(): entering... !" << endl;
try
{
_abort();
}
catch(Tango::DevFailed& df)
{
ERROR_STREAM << df<< endl;
RETHROW_DEVFAILED(df,
"DRIVER_FAILURE",
"could not abort [caught Tango::DevFailed]",
"SingleShotAO::abort");
}
catch(...)
{
ERROR_STREAM << "SingleShotAO::abort::unknown exception caught"<< std::endl;
THROW_DEVFAILED("DRIVER_FAILURE",
"could not abort [unknown error]",
"SingleShotAO::abort");
}
}
void SingleShotAO::_abort()
{
CHECK_MANAGER();
// memorize the current initial_values and value of channels
for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++)
{
if (m_manager->is_running(l_cpt))
{
DEBUG_STREAM << "Channel " << l_cpt << " is running. Memorizing values..." << std::endl;
double l_val_channel = m_manager->get_channel(l_cpt);
std::string l_channel_attr_name = kCHANNEL + std::to_string(l_cpt);
yat4tango::PropertyHelper::set_memorized_attribute(this, l_channel_attr_name, l_val_channel);
setDynamicAttributeWriteValue(l_channel_attr_name, l_val_channel);
DEBUG_STREAM << "Memorizing " << l_channel_attr_name << " to " << l_val_channel << std::endl;
std::string l_initial_attr_name = kINITIAL + std::to_string(l_cpt);
yat4tango::PropertyHelper::set_memorized_attribute(this, l_initial_attr_name, l_val_channel);
setDynamicAttributeWriteValue(l_initial_attr_name, l_val_channel);
DEBUG_STREAM << "Memorizing " << l_initial_attr_name << " to " << l_val_channel << std::endl;
}
}
m_manager->abort();
}
} // namespace