From c725c419534d6db0baf1e1c7988e13f8a28390c4 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Thu, 20 Feb 2025 11:14:06 +0100 Subject: [PATCH 01/34] refactor: use Tango 8 attr memorization (removed workaround) --- src/SingleShotAO.cpp | 14 ++------- src/SingleShotAO.h | 70 -------------------------------------------- 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 8091197..21f3c40 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -505,9 +505,7 @@ void SingleShotAO::init_device() std::string attr_name = kINITIAL + oss.str(); std::string name = "__" + attr_name; - // To be activated with Tango 8 - //double l_val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this,name); - double l_val = get_memorized_attribute<double>(name); + double l_val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this,name); m_manager->set_initial(l_cpt, l_val); } catch (...) @@ -896,10 +894,7 @@ void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cb "could not write initial [unknown error]", "SingleShotAO::write_initial"); } - // To be activated with Tango 8 - //yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); - std::string name = "__" + l_attr_name; - store_value_as_property(l_val, name); + yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); } @@ -969,10 +964,7 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & "could not write initial [unknown error]", "SingleShotAO::write_initial"); } - // To be activated with Tango 8 - //yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); - std::string name = "__" + l_attr_name; - store_value_as_property(l_val, name); + yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); } diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 61f5f60..41ed361 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -279,76 +279,6 @@ protected : //- channel number unsigned short m_nb_chan; - // To be deleted with Tango 8 - //- Template class to store a current value in a Device property. - //- \param value Value to store. - //- \param property_name Name to use. - template <class T> - void store_value_as_property(T value, std::string property_name) - { - Tango::DbDatum current_value(property_name); - current_value << value; - Tango::DbData db_data; - db_data.push_back(current_value); - - try - { - get_db_device()->put_property(db_data); - } - catch(Tango::DevFailed &df) - { - ERROR_STREAM << df << endl; - RETHROW_DEVFAILED(df, - "SOFTWARE_FAILURE", - "Error while storing properties in database", - "SingleShotAO::store_value_as_property"); - } - } - - // To be deleted with Tango 8 - //- Template class to get a memorized attribute stored as a Device property. - //- \param property_name Name od the property to read. - template <class T> - T get_memorized_attribute(const std::string& property_name) - { - T value; - if (!Tango::Util::instance()->_UseDb) - { - //- throw exception - THROW_DEVFAILED("DEVICE_ERROR", - "No DATA BASE!", - "SingleShotAO::get_memorized_attribute"); - } - - Tango::DbData dev_prop; - dev_prop.push_back(Tango::DbDatum(property_name)); - - try - { - get_db_device()->get_property(dev_prop); - } - catch (Tango::DevFailed &df) - { - //- rethrow exception - RETHROW_DEVFAILED(df, - "DEVICE_ERROR", - "could not get Device properties! [caught Tango::DevFailed]", - "SingleShotAO::get_memorized_attribute"); - } - - if (dev_prop[0].is_empty()==false) - { - dev_prop[0] >> value; - } - else - { - //- throw exception - THROW_DEVFAILED("DATA_ERROR", - "No property stored in database!", - "SingleShotAO::get_memorized_attribute"); - } - return value; - } }; } // namespace_ns -- GitLab From 2973a71d7efc461e125db40db5e6b36e3579d2cc Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Thu, 20 Feb 2025 16:07:13 +0100 Subject: [PATCH 02/34] refactor: rename get_device_property to get_device_properties and extract channel number logic --- src/SingleShotAO.cpp | 72 +++++++++++++++++-------------------- src/SingleShotAO.h | 2 +- src/SingleShotAOManager.cpp | 2 -- 3 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 21f3c40..c312cc2 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -219,7 +219,7 @@ void SingleShotAO::init_device() //-------------------------------------------- try { - get_device_property(); + get_device_properties(); } catch (const Tango::DevFailed& df) { @@ -543,12 +543,12 @@ void SingleShotAO::init_device() //+---------------------------------------------------------------------------- // -// method : SingleShotAO::get_device_property() +// method : SingleShotAO::get_device_properties() // // description : Read the device properties from database. // //----------------------------------------------------------------------------- -void SingleShotAO::get_device_property() +void SingleShotAO::get_device_properties() { // Initialize your default values here (if not done with POGO). //------------------------------------------------------------------ @@ -664,8 +664,7 @@ void SingleShotAO::always_executed_hook() //----------------------------------------------------------------------------- void SingleShotAO::read_attr_hardware(vector<long> &attr_list) { - //DEBUG_STREAM << "SingleShotAO::read_attr_hardware(vector<long> &attr_list) entering... "<< endl; - // Add your own code here + // nothing to do } @@ -678,7 +677,6 @@ void SingleShotAO::read_attr_hardware(vector<long> &attr_list) //----------------------------------------------------------------------------- void SingleShotAO::read_frequency(Tango::Attribute &attr) { - //DEBUG_STREAM << "SingleShotAO::read_frequency(Tango::Attribute &attr) entering... "<< endl; attr.set_value(&m_frequency); } @@ -757,6 +755,26 @@ Tango::ConstDevString SingleShotAO::dev_status() } +//+------------------------------------------------------------------ +/** + * Extract the first number found in a string. + * Used for extracting the channel number from dynamic attribute names + * like "channelX", "speedX", "initialX" where X is the channel number. + * + * @param str The input string to search for numbers + * @return The first number found in the string + * @throws DevFailed if no number is found in the string + */ +int extractNumber(const std::string &str) +{ + size_t pos = str.find_first_of("0123456789"); + if (pos == std::string::npos) + raise_error("No number found in string", "extractNumber"); + + std::string numberStr = str.substr(pos); + return std::stoi(numberStr); +} + //+------------------------------------------------------------------ /** * method: SingleShotAO::read_channel @@ -768,15 +786,10 @@ Tango::ConstDevString SingleShotAO::dev_status() void SingleShotAO::read_channel(yat4tango::DynamicAttributeReadCallbackData & cbd) { yat::AutoMutex<> guard(m_lock); - std::string l_attr_name = cbd.dya->get_name(); - - // name will be channelX - std::string l_str = l_attr_name.substr(7, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); + yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb CHECK_MANAGER(); - // choose tab depending on l_idx double l_val = m_manager->get_channel(l_idx); cbd.tga->set_value(&l_val); } @@ -796,10 +809,7 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & cbd.tga->get_write_value(l_val); std::string l_attr_name = cbd.dya->get_name(); - - // name will be channelX - std::string l_str = l_attr_name.substr(7, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); + yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb CHECK_MANAGER(); try @@ -835,15 +845,10 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & 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); // extract channel nb - // name will be speedX - std::string l_str = l_attr_name.substr(5, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); - - CHECK_MANAGER(); - // choose tab depending on l_idx + CHECK_MANAGER(); double l_val = m_manager->get_speed(l_idx); cbd.tga->set_value(&l_val); } @@ -859,16 +864,13 @@ void SingleShotAO::read_speed(yat4tango::DynamicAttributeReadCallbackData & cbd) //+------------------------------------------------------------------ void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cbd) { - DEBUG_STREAM << "SingleShotAO::write_speed(): entering... !" << endl; + 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(); - - // name will be speedX - std::string l_str = l_attr_name.substr(5, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); + yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb if (l_val < 0) { l_val = -l_val; @@ -909,15 +911,10 @@ void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cb void SingleShotAO::read_initial(yat4tango::DynamicAttributeReadCallbackData & cbd) { yat::AutoMutex<> guard(m_lock); - std::string l_attr_name = cbd.dya->get_name(); - - // name will be initialX - std::string l_str = l_attr_name.substr(7, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); + yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb CHECK_MANAGER(); - // choose tab depending on l_idx double l_val = m_manager->get_initial(l_idx); cbd.tga->set_value(&l_val); } @@ -933,16 +930,13 @@ void SingleShotAO::read_initial(yat4tango::DynamicAttributeReadCallbackData & cb //+------------------------------------------------------------------ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & cbd) { - DEBUG_STREAM << "SingleShotAO::write_initial(): entering... !" << endl; + 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(); - - // name will be initialX - std::string l_str = l_attr_name.substr(7, 2); - yat::uint16 l_idx = atoi(l_str.c_str()); + yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb CHECK_MANAGER(); try diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 41ed361..d6d477f 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -219,7 +219,7 @@ public : /** * Read the device properties from database */ - void get_device_property(); + void get_device_properties(); //@} // Here is the end of the automatic code generation part diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index 1a71223..6e6c2e7 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -180,7 +180,6 @@ void SingleShotAOManager::process_message (yat::Message& msg) //- THREAD_PERIODIC ------------------ case yat::TASK_PERIODIC: { - //DEBUG_STREAM << "SingleShotAOManager::handle_message::THREAD_PERIODIC" << std::endl; periodic_job_i(); } break; @@ -209,7 +208,6 @@ void SingleShotAOManager::periodic_job_i() //test if a ramp step must occur if (m_currentIndex[l_cpt] != -1) { - //DEBUG_STREAM << "Current index for channel" << l_cpt << ": " << m_currentIndex[l_cpt] << endl; m_isRunning[l_cpt] = true; double l_val = 0; l_val = m_ramps[l_cpt][m_currentIndex[l_cpt]]; -- GitLab From d4c1f2526d1ff57ef2d8f6c587350a5b3cd68ad0 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Thu, 20 Feb 2025 16:37:36 +0100 Subject: [PATCH 03/34] refactor: enhance extractNumber function to validate prefixes and improve error handling --- src/SingleShotAO.cpp | 49 +++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index c312cc2..2c26d31 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -368,6 +368,7 @@ void SingleShotAO::init_device() return; } + // add dynamic attributes: channel, speed & initial for each channel std::vector<yat4tango::DynamicAttributeInfo> l_dynAttrList; for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) @@ -476,9 +477,9 @@ void SingleShotAO::init_device() l_dynAttrList.push_back(dai_initial); } - m_dyn_attr_manager->add_attributes(l_dynAttrList); + // Get memorized values from database for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { @@ -757,21 +758,37 @@ Tango::ConstDevString SingleShotAO::dev_status() //+------------------------------------------------------------------ /** - * Extract the first number found in a string. - * Used for extracting the channel number from dynamic attribute names - * like "channelX", "speedX", "initialX" where X is the channel number. + * 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 - * @return The first number found in the string - * @throws DevFailed if no number is found in the string + * @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) +int extractNumber(const std::string &str, const char* prefix) { - size_t pos = str.find_first_of("0123456789"); - if (pos == std::string::npos) - raise_error("No number found in string", "extractNumber"); + // 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); } @@ -787,7 +804,7 @@ void SingleShotAO::read_channel(yat4tango::DynamicAttributeReadCallbackData & cb { yat::AutoMutex<> guard(m_lock); std::string l_attr_name = cbd.dya->get_name(); - yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kCHANNEL); // extract channel nb CHECK_MANAGER(); double l_val = m_manager->get_channel(l_idx); @@ -809,7 +826,7 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & cbd.tga->get_write_value(l_val); std::string l_attr_name = cbd.dya->get_name(); - yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kCHANNEL); // extract channel nb CHECK_MANAGER(); try @@ -846,7 +863,7 @@ 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); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kSPEED); // extract channel nb CHECK_MANAGER(); double l_val = m_manager->get_speed(l_idx); @@ -870,7 +887,7 @@ void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cb cbd.tga->get_write_value(l_val); std::string l_attr_name = cbd.dya->get_name(); - yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kSPEED); // extract channel nb if (l_val < 0) { l_val = -l_val; @@ -912,7 +929,7 @@ void SingleShotAO::read_initial(yat4tango::DynamicAttributeReadCallbackData & cb { yat::AutoMutex<> guard(m_lock); std::string l_attr_name = cbd.dya->get_name(); - yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kINITIAL); // extract channel nb CHECK_MANAGER(); double l_val = m_manager->get_initial(l_idx); @@ -936,7 +953,7 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & cbd.tga->get_write_value(l_val); std::string l_attr_name = cbd.dya->get_name(); - yat::uint16 l_idx = extractNumber(l_attr_name); // extract channel nb + yat::uint16 l_idx = extractNumber(l_attr_name, kINITIAL); // extract channel nb CHECK_MANAGER(); try -- GitLab From a6daeef3f0f14b53fc87feb99c51ca25cd624a3c Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Thu, 20 Feb 2025 17:39:46 +0100 Subject: [PATCH 04/34] refactor: improve code readability and structure in SingleShotAOManager --- src/SingleShotAOManager.cpp | 247 ++++++++++++++++++------------------ 1 file changed, 123 insertions(+), 124 deletions(-) diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index 6e6c2e7..7e70818 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -145,12 +145,12 @@ void SingleShotAOManager::init(asl::SingleShotAO * p_ssao, unsigned short p_nb_c enable_periodic_msg(true); } - // initialize channel indexes (-1 means no ramp in progress) - // and ramp states - for (unsigned int l_cpt = 0;l_cpt < m_nb_chan;l_cpt++) + // initialize channel indexes (-1 means no ramp in progress) + // and ramp states + for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { m_currentIndex[l_cpt] = -1; - m_isRunning[l_cpt] = false; + m_isRunning[l_cpt] = false; } } @@ -164,36 +164,39 @@ void SingleShotAOManager::process_message (yat::Message& msg) switch (msg.type()) { //- THREAD_INIT ---------------------- - case yat::TASK_INIT: + case yat::TASK_INIT: { DEBUG_STREAM << "SingleShotAOManager::handle_message::THREAD_INIT::thread is starting up" << std::endl; } break; //- THREAD_EXIT ---------------------- - case yat::TASK_EXIT: + case yat::TASK_EXIT: { DEBUG_STREAM << "SingleShotAOManager::handle_message::THREAD_EXIT::thread is quitting" << std::endl; } break; //- THREAD_PERIODIC ------------------ - case yat::TASK_PERIODIC: + case yat::TASK_PERIODIC: { periodic_job_i(); } break; //- THREAD_TIMEOUT ------------------- - case yat::TASK_TIMEOUT: + case yat::TASK_TIMEOUT: { //- not used in this example } break; + //- UNHANDLED MSG -------------------- - default: - DEBUG_STREAM << "SingleShotAOManager::handle_message::unhandled msg type received" << std::endl; - break; + default: + { + DEBUG_STREAM << "SingleShotAOManager::handle_message::unhandled msg type received" << std::endl; + break; + } } } @@ -202,53 +205,52 @@ void SingleShotAOManager::process_message (yat::Message& msg) // ============================================================================ void SingleShotAOManager::periodic_job_i() { - //test all channels + // test all channels for (unsigned int l_cpt = 0;l_cpt < m_nb_chan;l_cpt++) { - //test if a ramp step must occur - if (m_currentIndex[l_cpt] != -1) + // test if a ramp step must occur + if (m_currentIndex[l_cpt] == -1) { - m_isRunning[l_cpt] = true; - double l_val = 0; - l_val = m_ramps[l_cpt][m_currentIndex[l_cpt]]; - DEBUG_STREAM << "Current value for channel" << l_cpt << ": " << l_val << endl; - try - { - CHECK_SSAO(); - m_ssao->write_scaled_channel((adl::ChanId)l_cpt, l_val); - m_channels[l_cpt] = l_val; - } - catch(const asl::DAQException& de) - { - Tango::DevFailed df = daq_to_tango_exception(de); - ERROR_STREAM << df<< endl; - m_state = Tango::FAULT; - RETHROW_DEVFAILED(df, - "DRIVER_FAILURE", - "could not write channel [caught asl::DAQException]", - "SingleShotAOManager::write_channel"); - } - catch(...) - { - ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught"<<std::endl; - m_state = Tango::FAULT; - THROW_DEVFAILED("DRIVER_FAILURE", - "could not write channel [unknown error]", - "SingleShotAOManager::write_channel"); - } - - //check if there is another value - m_currentIndex[l_cpt] +=1; - if (m_currentIndex[l_cpt] == m_ramps[l_cpt].capacity()) - { - m_currentIndex[l_cpt] = -1; - m_initials[l_cpt] = m_channels[l_cpt]; - m_ramps[l_cpt].clear(); - } + m_isRunning[l_cpt] = false; + continue; } - else + + m_isRunning[l_cpt] = true; + double l_val = 0; + l_val = m_ramps[l_cpt][m_currentIndex[l_cpt]]; + DEBUG_STREAM << "Current value for channel" << l_cpt << ": " << l_val << endl; + try { - m_isRunning[l_cpt] = false; + CHECK_SSAO(); + m_ssao->write_scaled_channel((adl::ChanId)l_cpt, l_val); + m_channels[l_cpt] = l_val; + } + catch(const asl::DAQException& de) + { + Tango::DevFailed df = daq_to_tango_exception(de); + ERROR_STREAM << df << endl; + m_state = Tango::FAULT; + RETHROW_DEVFAILED(df, + "DRIVER_FAILURE", + "could not write channel [caught asl::DAQException]", + "SingleShotAOManager::write_channel"); + } + catch(...) + { + ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught" << std::endl; + m_state = Tango::FAULT; + THROW_DEVFAILED("DRIVER_FAILURE", + "could not write channel [unknown error]", + "SingleShotAOManager::write_channel"); + } + + // check if there is another value + m_currentIndex[l_cpt] += 1; + if (m_currentIndex[l_cpt] == m_ramps[l_cpt].capacity()) + { + m_currentIndex[l_cpt] = -1; + m_initials[l_cpt] = m_channels[l_cpt]; + m_ramps[l_cpt].clear(); } } } @@ -266,8 +268,9 @@ double SingleShotAOManager::get_channel(ChannelId_t p_chIdx) // ============================================================================ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) { - DEBUG_STREAM << "write_channel : " << p_chIdx << " : " << p_val << " : " << endl; + DEBUG_STREAM << "write_channel " << p_chIdx << " : " << p_val << endl; + // if the speed is 0, write the value directly if (m_speeds[p_chIdx] == 0.0) { try @@ -276,11 +279,12 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) m_ssao->write_scaled_channel((adl::ChanId)p_chIdx, p_val); m_channels[p_chIdx] = p_val; m_initials[p_chIdx] = p_val; + DEBUG_STREAM << "Speed is 0, writing directly the value" << endl; } catch(const asl::DAQException& de) { Tango::DevFailed df = daq_to_tango_exception(de); - ERROR_STREAM << df<< endl; + ERROR_STREAM << df << endl; m_state = Tango::FAULT; RETHROW_DEVFAILED(df, "DRIVER_FAILURE", @@ -295,83 +299,78 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) "could not write channel [unknown error]", "SingleShotAOManager::write_channel"); } + return; } - else + + // if a ramp is not running, error + if (m_isRunning[p_chIdx]) + { + THROW_DEVFAILED("DEVICE_FAILURE", + "could not write channel : a ramp is still in progress on this channel", + "SingleShotAOManager::write_channel"); + } + + // if frequency = 0, error + if (m_frequency == 0) + { + THROW_DEVFAILED("DRIVER_FAILURE", + "could not set a ramp on this channel. The frequency is 0", + "SingleShotAOManager::write_channel"); + } + + // if initial = channel, skip + if (m_initials[p_chIdx] == p_val) + { + DEBUG_STREAM << "Initial value is the same as the given value, skipping" << endl; + return; + } + + // ramp determination + double l_delta = p_val - m_initials[p_chIdx]; + bool isDown = false; + l_delta = ((l_delta * m_frequency) / m_speeds[p_chIdx]) + 1; + if (l_delta < 0) + { + l_delta = -l_delta + 2; + isDown = true; + } + DEBUG_STREAM << "Computed ramp steps number : " << l_delta << endl; + + yat::Buffer<double> l_buffer; + size_t ramp_size = (size_t)(ceil(l_delta)); + l_buffer.capacity(ramp_size); + l_buffer.force_length(ramp_size); + + // check if ramp step is integer or not + bool isDeltaNotInt = (ramp_size != ((size_t)(floor(l_delta)))); + DEBUG_STREAM << "Real ramp steps number : " << ramp_size << endl; + + for (unsigned int l_cpt = 0; l_cpt < ramp_size; l_cpt++) { - // check if a ramp is not running - if (!m_isRunning[p_chIdx]) + if ((l_cpt == (ramp_size - 1)) && (isDeltaNotInt)) { - // check if initial = channel - if (m_initials[p_chIdx] != p_val) - { - if (m_frequency == 0) - { - THROW_DEVFAILED("DRIVER_FAILURE", - "could not set a ramp on this channel. The frequency is 0", - "SingleShotAOManager::write_channel"); - } - - //ramp determination - double l_delta = p_val - m_initials[p_chIdx]; - bool isDown = false; - l_delta = ((l_delta * m_frequency) / m_speeds[p_chIdx])+1; - if (l_delta < 0) - { - l_delta = -l_delta + 2; - isDown = true; - } - DEBUG_STREAM << "Computed ramp steps number : " << l_delta << endl; - - yat::Buffer<double> l_buffer; - size_t ramp_size = (size_t)(ceil(l_delta)); - l_buffer.capacity(ramp_size); - l_buffer.force_length(ramp_size); - - // check if ramp step is integer or not - bool isDeltaNotInt = false; - if (ramp_size != ((size_t)(floor(l_delta)))) - { - isDeltaNotInt = true; - } - - DEBUG_STREAM << "Real ramp steps number : " << ramp_size << endl; - - for (unsigned int l_cpt = 0; l_cpt < ramp_size; l_cpt++) - { - if ((l_cpt == (ramp_size - 1)) && - (isDeltaNotInt)) - { - // add the setpoint value at the end of table - l_buffer[l_cpt] = p_val; - } - else - { - if (isDown) - { - l_buffer[l_cpt] = m_initials[p_chIdx] - l_cpt*(m_speeds[p_chIdx]/m_frequency); - } - else - { - l_buffer[l_cpt] = m_initials[p_chIdx] + l_cpt*(m_speeds[p_chIdx]/m_frequency); - } - } - //DEBUG_STREAM << "Ramp buffer[" << l_cpt << "] = " << l_buffer[l_cpt] << endl; - } - m_ramps[p_chIdx].clear(); - m_ramps[p_chIdx].capacity(0); - m_ramps[p_chIdx].force_length(0); - m_currentIndex[p_chIdx] = 0; - m_ramps[p_chIdx] = l_buffer; - //m_channels[p_chIdx] = m_ramps[p_chIdx][0]; -- soso on ne met rien ici => à l'application - } + // add the setpoint value at the end of table + l_buffer[l_cpt] = p_val; } else { - THROW_DEVFAILED("DEVICE_FAILURE", - "could not write channel : a ramp is still in progress on this channel", - "SingleShotAOManager::write_channel"); + if (isDown) + { + l_buffer[l_cpt] = m_initials[p_chIdx] - l_cpt * (m_speeds[p_chIdx] / m_frequency); + } + else + { + l_buffer[l_cpt] = m_initials[p_chIdx] + l_cpt * (m_speeds[p_chIdx] / m_frequency); + } } + //DEBUG_STREAM << "Ramp buffer[" << l_cpt << "] = " << l_buffer[l_cpt] << endl; } + m_ramps[p_chIdx].clear(); + m_ramps[p_chIdx].capacity(0); + m_ramps[p_chIdx].force_length(0); + m_currentIndex[p_chIdx] = 0; + m_ramps[p_chIdx] = l_buffer; + //m_channels[p_chIdx] = m_ramps[p_chIdx][0]; -- soso on ne met rien ici => à l'application } // ============================================================================ -- GitLab From 1e77157f3e973921d7bb72459c344de18248f346 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 11:07:01 +0100 Subject: [PATCH 05/34] cleanup: fix typos, formatting and improve comments in SingleShotAO and SingleShotAOManager --- src/SingleShotAO.cpp | 23 ++++++++++++----------- src/SingleShotAOManager.cpp | 20 ++++++++++---------- src/SingleShotAOManager.h | 4 ++-- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 2c26d31..65643b0 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -326,7 +326,6 @@ void SingleShotAO::init_device() DEBUG_STREAM << "Failed to get frequency value. Maybe there is no value yet." << std::endl; } - // initialize the AO manager //-------------------------------------------- try @@ -348,6 +347,10 @@ void SingleShotAO::init_device() return; } + + // Create dynamic attributes + //-------------------------------------------- + // create dynamic attribute manager try { @@ -495,8 +498,7 @@ void SingleShotAO::init_device() double l_val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, name); m_manager->set_speed(l_cpt, l_val); } - catch (...) - { + catch (...) { // nothing to do } @@ -903,16 +905,17 @@ void SingleShotAO::write_speed(yat4tango::DynamicAttributeWriteCallbackData & cb ERROR_STREAM << df<< endl; RETHROW_DEVFAILED(df, "DRIVER_FAILURE", - "could not write initial [caught Tango::DevFailed]", - "SingleShotAO::write_initial"); + "could not write speed [caught Tango::DevFailed]", + "SingleShotAO::write_speed"); } catch(...) { - ERROR_STREAM << "SingleShotAO::write_initial::unknown exception caught"<<std::endl; + ERROR_STREAM << "SingleShotAO::write_speed::unknown exception caught" << std::endl; THROW_DEVFAILED("DRIVER_FAILURE", - "could not write initial [unknown error]", - "SingleShotAO::write_initial"); + "could not write speed [unknown error]", + "SingleShotAO::write_speed"); } + yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); } @@ -975,6 +978,7 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & "could not write initial [unknown error]", "SingleShotAO::write_initial"); } + yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); } @@ -986,14 +990,12 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & * description: method to execute "Abort" * Aborts ramps in progress. * - * */ //+------------------------------------------------------------------ void SingleShotAO::abort() { DEBUG_STREAM << "SingleShotAO::abort(): entering... !" << endl; - // Add your own code to control device here CHECK_MANAGER(); try { @@ -1014,7 +1016,6 @@ void SingleShotAO::abort() "could not abort [unknown error]", "SingleShotAO::abort"); } - } } // namespace diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index 7e70818..e78806d 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -270,7 +270,7 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) { DEBUG_STREAM << "write_channel " << p_chIdx << " : " << p_val << endl; - // if the speed is 0, write the value directly + // if the speed is 0, write the value directly and skip ramp if (m_speeds[p_chIdx] == 0.0) { try @@ -279,21 +279,21 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) m_ssao->write_scaled_channel((adl::ChanId)p_chIdx, p_val); m_channels[p_chIdx] = p_val; m_initials[p_chIdx] = p_val; - DEBUG_STREAM << "Speed is 0, writing directly the value" << endl; + DEBUG_STREAM << "Speed is 0, writing directly the value" << std::endl; } - catch(const asl::DAQException& de) + catch (const asl::DAQException &de) { Tango::DevFailed df = daq_to_tango_exception(de); - ERROR_STREAM << df << endl; + ERROR_STREAM << df << std::endl; m_state = Tango::FAULT; RETHROW_DEVFAILED(df, "DRIVER_FAILURE", "could not write channel [caught asl::DAQException]", "SingleShotAOManager::write_channel"); } - catch(...) + catch (...) { - ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught"<<std::endl; + ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught" << std::endl; m_state = Tango::FAULT; THROW_DEVFAILED("DRIVER_FAILURE", "could not write channel [unknown error]", @@ -302,7 +302,7 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) return; } - // if a ramp is not running, error + // if a ramp is running, error if (m_isRunning[p_chIdx]) { THROW_DEVFAILED("DEVICE_FAILURE", @@ -428,8 +428,8 @@ void SingleShotAOManager::set_speed(ChannelId_t p_chIdx, Intial_t p_speed) // ============================================================================ void SingleShotAOManager::abort() { - //test all channels and abort current ramps - for (unsigned int l_cpt = 0;l_cpt < m_nb_chan;l_cpt++) + // test all channels and abort current ramps + for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { if (m_isRunning[l_cpt]) { @@ -441,5 +441,5 @@ void SingleShotAOManager::abort() } } } -} // namespace SingleShotAO_ns +} // namespace SingleShotAO_ns diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index 27e73ce..05be89d 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -59,10 +59,10 @@ public: //- change period void write_frequency(double p_frequency); - //- get inital + //- get initial Intial_t get_initial(ChannelId_t p_chIdx); - //- set inital + //- set initial void set_initial(ChannelId_t p_chIdx, Intial_t p_initial); //- get speed -- GitLab From 29aa9c832bc5ef0d6921f5b2737097bf8d0c0a5d Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 11:16:49 +0100 Subject: [PATCH 06/34] fix/feature: memorize values and apply memorized values at init --- src/SingleShotAO.cpp | 45 +++++++++++++++++-------------------- src/SingleShotAOManager.cpp | 17 ++++++++++++++ src/SingleShotAOManager.h | 5 ++++- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 65643b0..8b886ad 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -489,32 +489,25 @@ void SingleShotAO::init_device() yat::OSStream oss; oss << l_cpt; - // speed value - try - { - std::string attr_name = kSPEED + oss.str(); - std::string name = "__" + attr_name; - - double l_val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, name); - m_manager->set_speed(l_cpt, l_val); - } - catch (...) { - // nothing to do - } - - // initial value - try + // Helper function to get and set memorized attributes + auto applyMemorizedAttr = [&](const std::string& attrPrefix, + void (SingleShotAOManager::*setter)(yat::uint16, double)) { - std::string attr_name = kINITIAL + oss.str(); - std::string name = "__" + attr_name; - - double l_val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this,name); - m_manager->set_initial(l_cpt, l_val); - } - catch (...) - { - //nothing to do - } + try { + std::string attrName = attrPrefix + oss.str(); + double val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, attrName); + (m_manager->*setter)(l_cpt, val); + } + catch (...) { + // nothing to do + } + }; + + // Get and set memorized values for speed, initial and channel + applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed); + applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); + applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); + // TODO: add a property to call write_channel instead of set_channel (false by default) } //- GO for task @@ -850,6 +843,8 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & "could not write channel [unknown error]", "SingleShotAO::write_channel"); } + + yat4tango::PropertyHelper::set_memorized_attribute(this, l_attr_name, l_val); } diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index e78806d..5d7b57a 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -263,6 +263,23 @@ double SingleShotAOManager::get_channel(ChannelId_t p_chIdx) return m_channels[p_chIdx]; } +// ============================================================================ +// SingleShotAOManager::set_channel () +// ============================================================================ +void SingleShotAOManager::set_channel(ChannelId_t p_chIdx, double p_val) +{ + if (m_isRunning[p_chIdx]) + { + THROW_DEVFAILED("DEVICE_FAILURE", + "could not write channel : a ramp is still in progress on this channel", + "SingleShotAOManager::set_channel"); + } + else + { + m_channels[p_chIdx] = p_val; + } +} + // ============================================================================ // SingleShotAOManager::write_channel () // ============================================================================ diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index 05be89d..ccabfce 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -52,7 +52,10 @@ public: //- get current channel value double get_channel(ChannelId_t p_chIdx); - + + //- set channel + void set_channel(ChannelId_t p_chIdx, double p_val); + //- write channel void write_channel(ChannelId_t p_chIdx, double p_val); -- GitLab From bcce86f18b6007a4810b3a8f142f6d1ff5d890b6 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 13:46:00 +0100 Subject: [PATCH 07/34] cleanup(doc): format HTML documentation files --- doc/doc_html/Attributes.html | 165 ++++++++------------ doc/doc_html/Description.html | 147 +++--------------- doc/doc_html/DevCommands.html | 232 ++++++++++------------------- doc/doc_html/DevCommandsFrame.html | 33 ++-- doc/doc_html/DevCommandsList.html | 31 ++-- doc/doc_html/DevCommandsTable.html | 183 ++++++++--------------- doc/doc_html/Properties.html | 204 ++++++++++--------------- doc/doc_html/TangoDevStates.html | 177 +++++++--------------- doc/doc_html/index.html | 178 ++++++---------------- 9 files changed, 435 insertions(+), 915 deletions(-) diff --git a/doc/doc_html/Attributes.html b/doc/doc_html/Attributes.html index 1c88911..9a6dff5 100755 --- a/doc/doc_html/Attributes.html +++ b/doc/doc_html/Attributes.html @@ -1,114 +1,69 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User's Guide </Title> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> +<html> +<head> -<P><!-------TITLE------></P> + <title> Tango Device Server User's Guide </title> +</head> -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> +<body> + <center> + <h1> + SingleShotAO Generic Device <br> + Device Attributes Description <br><Br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> + <table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td COLSPAN=4> + <font Size=+2><center><b>Scalar Attributes</b></center></font> + </td> + </tr> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td> + <center><b>Attribute name</b> + </td> + </center> + <td> + <center><b>Data Type</b> + </td> + </center> + <td> + <center><b>R/W Type</b> + </td> + </center> + <td> + <center><b>Expert</b> + </td> + </center> + <tr> + <td><b>frequency</b>: <font Size=-1>Sampling frequency for + ramp generation on the board output channels, in + Hz.</font> + </td> + <td> + <center> + <font Size=-1>DEV_DOUBLE</font> + </center> + </td> + <td> + <center> + <font Size=-1>READ_WRITE</font> + </center> + </td> + <td> + <center> + <font Size=-1>Yes</font> + </center> + </td> + </tr> -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Device Attributes Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> + </table> </center> - -<Br> -<Table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td COLSPAN=4> <Font Size=+2><Center><b>Scalar Attributes</b></td></Font></Center> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td><Center><b>Attribute name</b></td></Center> -<Td><Center><b>Data Type</b></td></Center> -<Td><Center><b>R/W Type</b></td></Center> -<Td><Center><b>Expert</b></td></Center> -<Tr><Td><b>frequency</b>: <Font Size=-1>Sampling frequency for ramp generation on the board output channels, in Hz.</Font></Td> -<Td><Center><Font Size=-1>DEV_DOUBLE</Font></Center></Td><Td><Center><Font Size=-1>READ_WRITE</Font></Center></Td><Td><Center><Font Size=-1>Yes</Font></Center></Td></Tr> - -</Table> -</Center> -<Br><Br><Br><Br><Br> - -<!--- html Footer ---> - -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> - - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> </html> diff --git a/doc/doc_html/Description.html b/doc/doc_html/Description.html index e9447e2..b63c5d3 100755 --- a/doc/doc_html/Description.html +++ b/doc/doc_html/Description.html @@ -1,129 +1,26 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User s Guide </Title> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> +<html> + +<head> + <title> Tango Device Server User s Guide </title> +</head> + +<body> + <center> + <h1> + SingleShotAO Generic Device <br> + Device Description <br> <br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> + + <center> + ADLink boards support for single shot AO operations [PCI-6208 and + compatible boards] + </center> -<P><!-------TITLE------></P> -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - - </TD> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - </TD> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </TD> - - <TD ALIGN="center"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="45"></A> - </TD> - <TD ALIGN="Right"> - <H2><FONT COLOR="#7F00FF"> - <Br><Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> TANGO </a> - </Center></FONT> - - </TD> - </TR> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="44"></A> - </TD> - <TD ALIGN="center"> - <A HREF="http://www.maxlab.lu.se/maxlab/max4/index.html" TARGET=new> - - <IMG SRC="http://www.esrf.fr/computing/cs/tango/maxlab.gif" BORDER=0 Height="40"></A> - </TD> - <TD ALIGN="center"> - <A HREF="http://www.frm2.tum.de/en/index.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/frm-2.jpg" BORDER=0 Height="45"></A> - </TD> - <TD> - <!-- Empty --> - </TD> - - <TD ALIGN="Right"> - <H2><FONT COLOR="#7F00FF"> - <Center> Device Servers - </Center></FONT> - </TD> - </TR> -</TABLE> - -<HR WIDTH="100%"></H5> - - - - -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Device Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> -</center> - - -<Center> -ADLink boards support for single shot AO operations [PCI-6208 and compatible boards] -<Br> -<Br> -</Center> - -<!--- html Footer ---> - -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> - - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> </html> diff --git a/doc/doc_html/DevCommands.html b/doc/doc_html/DevCommands.html index 306b671..9dbd3bf 100755 --- a/doc/doc_html/DevCommands.html +++ b/doc/doc_html/DevCommands.html @@ -1,162 +1,90 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> + <HEAD> -<Title> Tango Device Server User's Guide </Title> + <Title> Tango Device Server User's Guide </Title> </HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> - -<P><!-------TITLE------></P> - -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Device Commands Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> -</center> +<BODY> + <center> + <h1> + SingleShotAO Generic Device <br> + Device Commands Description <br> <br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> + <h2>1 - Init</h2> + <ul> + <Li><Strong>Description: </Strong><br> + This command re-initialises a device keeping the same network connection. <br> + After an Init command executed on a device, it is not necessary for the client to re-connect to the device. <br> + This command first calls the device <i>delete_device()</i> method and then executes its <i>init_device()</i> method. <br> + For C++ device server, all the memory allocated in the <i>init_device()</i> method must be freed in the <i>delete_device()</i> method.<br> + The language device destructor automatically calls the <i>delete_device()</i> method.<br> + </Li> + <Li><Strong>Argin: DEV_VOID</Strong></Li> + <Li><Strong>Argout: DEV_VOID</Strong></Li> + <Li><Strong>Command allowed for: </Strong> + <Ul> + <Li>Tango::FAULT</Li> + <Li>Tango::ON</Li> + <Li>Tango::INIT</Li> + <Li>Tango::MOVING</Li> + </Ul> + </Li> + </ul> + -<Br> -<Br> -<Br> -<A NAME="Init"><!-- --></A> -<A NAME="Init"><!-- --></A> -<h2>1 - Init</h2> -<ul> -<Li><Strong>Description: </Strong> This commands re-initialise a device keeping the same network connection.<Br> -After an Init command executed on a device, it is not necessary for client to re-connect to the device.<Br> -This command first calls the device <i> delete_device() </i>method and then execute its <i> init_device()</i> method.<Br> -For C++ device server, all the memory allocated in the <i> nit_device() </i> method must be freed in the <i> delete_device() </i> method.<Br> -The language device desctructor automatically calls the <i> delete_device() </i> method.<Br>  -<Li><Strong>Argin:<Br>DEV_VOID</Strong> - : none.<Br>  -<Li><Strong>Argout:<Br>DEV_VOID</Strong> - : none.<Br>  -<Li><Strong>Command allowed for: </Strong><Ul> -<Li>Tango::FAULT<Li>Tango::ON<Li>Tango::INIT<Li>Tango::MOVING</Ul> -<Br>  -</ul><Br> -<Br> -<A NAME="State"><!-- --></A> -<A NAME="State"><!-- --></A> -<h2>2 - State</h2> -<ul> -<Li><Strong>Description: </Strong> This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller.<Br>  -<Li><Strong>Argin:<Br>DEV_VOID</Strong> - : none.<Br>  -<Li><Strong>Argout:<Br>DEV_STATE</Strong> - : State Code<Br>  -<Li><Strong>Command allowed for: </Strong><Ul> -<Li>Tango::FAULT<Li>Tango::ON<Li>Tango::INIT<Li>Tango::MOVING</Ul> -<Br>  -</ul><Br> -<Br> -<A NAME="Status"><!-- --></A> -<A NAME="Status"><!-- --></A> -<h2>3 - Status</h2> -<ul> -<Li><Strong>Description: </Strong> This command gets the device status (stored in its <i>device_status</i> data member) and returns it to the caller.<Br>  -<Li><Strong>Argin:<Br>DEV_VOID</Strong> - : none.<Br>  -<Li><Strong>Argout:<Br>CONST_DEV_STRING</Strong> - : Status description<Br>  -<Li><Strong>Command allowed for: </Strong><Ul> -<Li>Tango::FAULT<Li>Tango::ON<Li>Tango::INIT<Li>Tango::MOVING</Ul> -<Br>  -</ul><Br> -<Br> -<A NAME="Abort"><!-- --></A> -<A NAME="Abort"><!-- --></A> -<h2>4 - Abort</h2> -<ul> -<Li><Strong>Description: </Strong> Aborts ramps in progress.<Br>  -<Li><Strong>Argin:<Br>DEV_VOID</Strong> - : <Br>  -<Li><Strong>Argout:<Br>DEV_VOID</Strong> - : <Br>  -<Li><Strong>Command allowed for: </Strong><Ul> -<Li>Tango::FAULT<Li>Tango::ON<Li>Tango::INIT<Li>Tango::MOVING</Ul> -<Br>  -</ul><Br> -<Br> + <h2>2 - State</h2> + <ul> + <Li><Strong>Description: </Strong> This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller. + <Li><Strong>Argin: DEV_VOID</Strong></Li> + <Li><Strong>Argout: DEV_STATE</Strong></Li> + <Li><Strong>Command allowed for: </Strong> + <Ul> + <Li>Tango::FAULT</Li> + <Li>Tango::ON</Li> + <Li>Tango::INIT</Li> + <Li>Tango::MOVING</Li> + </Ul> + </Li> + </ul> + -<!--- html Footer ---> + <h2>3 - Status</h2> + <ul> + <Li><Strong>Description: </Strong> This command gets the device status (stored in its <i>device_status</i> data member) and returns it to the caller.</Li> + <Li><Strong>Argin: DEV_VOID</Strong></Li> + <Li><Strong>Argout: CONST_DEV_STRING</Strong></Li> + <Li><Strong>Command allowed for: </Strong> + <Ul> + <Li>Tango::FAULT</Li> + <Li>Tango::ON</Li> + <Li>Tango::INIT</Li> + <Li>Tango::MOVING</Li> + </Ul> + </Li> + </ul> + -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> - - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> + <h2>4 - Abort</h2> + <ul> + <Li><Strong>Description: </Strong> Aborts ramps in progress.</Li> + <Li><Strong>Argin: DEV_VOID</Strong></Li> + <Li><Strong>Argout: DEV_VOID</Strong></Li> + <Li><Strong>Command allowed for: </Strong> + <Ul> + <Li>Tango::FAULT</Li> + <Li>Tango::ON</Li> + <Li>Tango::INIT</Li> + <Li>Tango::MOVING</Li> + </Ul> + </Li> + </ul> </body> -</html> + +</html> \ No newline at end of file diff --git a/doc/doc_html/DevCommandsFrame.html b/doc/doc_html/DevCommandsFrame.html index a696d50..8938ab2 100755 --- a/doc/doc_html/DevCommandsFrame.html +++ b/doc/doc_html/DevCommandsFrame.html @@ -1,19 +1,20 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User's Guide </Title> -</HEAD> +<html> + <head> + <title> Tango Device Server User's Guide </title> + </head> -<FRAMESET cols="20%,80%"> -<FRAME src="DevCommandsList.html" name="DevCommandsList"> -<FRAME src="DevCommands.html" name="DevCommands"> -</FRAMESET> -<NOFRAMES> -<H2> -Frame Alert</H2> + <frameset cols="20%,80%"> + <frame src="DevCommandsList.html" name="DevCommandsList"> + <frame src="DevCommands.html" name="DevCommands"> + </frameset> + <noframes> + <h2> + Frame Alert</h2> -<P> -This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. -<BR> -Link to <A HREF="DevCommands.html">Non-frame version.</A></NOFRAMES> -</HTML> + <p> + This document is designed to be viewed using the frames feature. If + you see this message, you are using a non-frame-capable web client. + <br> + Link to <a HREF="DevCommands.html">Non-frame version.</a></noframes> + </html> diff --git a/doc/doc_html/DevCommandsList.html b/doc/doc_html/DevCommandsList.html index dff7f08..c69789b 100755 --- a/doc/doc_html/DevCommandsList.html +++ b/doc/doc_html/DevCommandsList.html @@ -1,18 +1,17 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> -<HTML><HEAD> -<TITLE>Commands -</TITLE></HEAD> -<BODY BGCOLOR="white"> -<FONT size="+1" ID="FrameHeadingFont"> -<B>Commands:</B></FONT> -<Br> -<Br> -<Br> -<A Href="DevCommands.html#Init" TARGET="DevCommands"> Init</a><Br> -<A Href="DevCommands.html#State" TARGET="DevCommands"> State</a><Br> -<A Href="DevCommands.html#Status" TARGET="DevCommands"> Status</a><Br> -<A Href="DevCommands.html#Abort" TARGET="DevCommands"> Abort</a><Br> +<html><head> + <title>Commands + </title></head> + <body BGCOLOR="white"> + <font size="+1" ID="FrameHeadingFont"> + <b>Commands:</b></font> + <br> + <br> + <br> + <a Href="DevCommands.html#Init" TARGET="DevCommands"> Init</a><br> + <a Href="DevCommands.html#State" TARGET="DevCommands"> State</a><br> + <a Href="DevCommands.html#Status" TARGET="DevCommands"> Status</a><br> + <a Href="DevCommands.html#Abort" TARGET="DevCommands"> Abort</a><br> - -</BODY> -</HTML> + </body> +</html> diff --git a/doc/doc_html/DevCommandsTable.html b/doc/doc_html/DevCommandsTable.html index 7c2194a..4cd1eb4 100755 --- a/doc/doc_html/DevCommandsTable.html +++ b/doc/doc_html/DevCommandsTable.html @@ -1,126 +1,63 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User's Guide </Title> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> +<html> + +<head> + <title> Tango Device Server User's Guide </title> +</head> + +<body> + <center> + <h1> + SingleShotAO Generic Device <br> + Device Commands Description <br><br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> + + <center> + <br><a Href="DevCommandsFrame.html"> More Details on commands.... </a><br><br> + + <table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td COLSPAN=3> + <font Size=+2><center> + <b>Device Commands for Operator Level</b> + </center></font> + </td> + </tr> + + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td><b>Command name</b></td> + <td><b>Argument In</b></td> + <td><b>Argument Out</b></td> + </tr> + <tr> + <td><b>Init</b></td> + <td>DEV_VOID</td> + <td>DEV_VOID</td> + </tr> + <tr> + <td><b>State</b></td> + <td>DEV_VOID</td> + <td>DEV_STATE</td> + </tr> + <tr> + <td><b>Status</b></td> + <td>DEV_VOID</td> + <td>CONST_DEV_STRING</td> + </tr> + <tr> + <td><b>Abort</b></td> + <td>DEV_VOID</td> + <td>DEV_VOID</td> + </tr> + + </table> + </center> -<P><!-------TITLE------></P> - -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> - -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Device Commands Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> -</center> - - -<Center> -<Br><Br> -<A Href="DevCommandsFrame.html"> More Details on commands.... </a><Br> -<Br> <Br> -<Table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td COLSPAN=3> <Font Size=+2><Center><b>Device Commands for Operator Level</b></td></Font></Center> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td><Center><b>Command name</b></td></Center> -<Td><Center><b>Argument In</b></td></Center> -<Td><Center><b>Argument Out</b></td></Center> -<Tr><Td><b>Init</b></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> -<Tr><Td><b>State</b></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> -<Td><Font Size=-1>DEV_STATE</Font></Td> -<Tr><Td><b>Status</b></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> -<Td><Font Size=-1>CONST_DEV_STRING</Font></Td> -<Tr><Td><b>Abort</b></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> -<Td><Font Size=-1>DEV_VOID</Font></Td> - - - -</Table></Center> - -<!--- html Footer ---> - -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> - - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> -</html> + +</html> \ No newline at end of file diff --git a/doc/doc_html/Properties.html b/doc/doc_html/Properties.html index 3f676a0..388a562 100755 --- a/doc/doc_html/Properties.html +++ b/doc/doc_html/Properties.html @@ -1,144 +1,94 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> + <HEAD> -<Title> Tango Device Server User's Guide </Title> + <Title> Tango Device Server User's Guide </Title> </HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> - -<P><!-------TITLE------></P> - -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> - -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Properties Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> -</center> - - -<Center> -<Br> <Br> <Br> -<Table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td COLSPAN=3> <Font Size=+2><Center><b>Device Properties</b></td></Font></Center> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td><Center><b>Property name</b></td></Center> -<Td><Center><b>Property type</b></td></Center> -<Td><Center><b>Description</b></td></Center> -<Tr><Td><b><a href=#Dev_DefaultValues>BoardNum </a></b></Td> -<Td><Font Size=-1>Tango::DEV_SHORT</Font></Td> -<Td><Font Size=-1>The the board identifier in the cPCI crate [valid range is 0...7 - no default value] .</Font></Td></Tr> -<Tr><Td><b><a href=#Dev_DefaultValues>BoardType </a></b></Td> -<Td><Font Size=-1>Tango::DEV_STRING</Font></Td> -<Td><Font Size=-1>The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no default value]</Font></Td></Tr> +<BODY> + <center> + <h1> + SingleShotAO Generic Device <Br> + Properties Description <Br><Br> + SingleShotAO Class <Br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> -</Table> -</Center> -<Br><Br><Br> -<Br><Br><Br> - -<A name=Dev_DefaultValues><!--- ---></a> -<Font Size=+1>Device Properties Default Values:</Font><Br> -<Table Border=2 Cellpadding=2 CELLSPACING=2> - <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> - <Td><b>Property Name</b></td> - <td><b>Default Values</b></td> - </Tr> + <Center> + <Table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> + <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <Td COLSPAN=3> + <Font Size=+2> + <Center><b>Device Properties</b> + </td> + </Font> + </Center> + <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <Td> + <Center><b>Property name</b> + </td> + </Center> + <Td> + <Center><b>Property type</b> + </td> + </Center> + <Td> + <Center><b>Description</b> + </td> + </Center> <Tr> - <Td>BoardNum</Td> - <td>No default value</td> + <Td><b><a href=#Dev_DefaultValues>BoardNum </a></b></Td> + <Td> + <Font Size=-1>Tango::DEV_SHORT</Font> + </Td> + <Td> + <Font Size=-1>The the board identifier in the cPCI crate [valid range is 0...7 - no default value] .</Font> + </Td> </Tr> + <Tr> - <Td>BoardType</Td> - <td>No default value</td> + <Td><b><a href=#Dev_DefaultValues>BoardType </a></b></Td> + <Td> + <Font Size=-1>Tango::DEV_STRING</Font> + </Td> + <Td> + <Font Size=-1>The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no + default value]</Font> + </Td> </Tr> -</Table> -<Br><Br><Br> -<Center><b> -There is no Class properties.<Br><Br> -</Center></b> -<Br> <Br> <Br> + </Table> -<!--- html Footer ---> + </Center> -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> + <A name=Dev_DefaultValues><!--- ---></a> + <Font Size=+1>Device Properties Default Values:</Font><Br> + <Table Border=2 Cellpadding=2 CELLSPACING=2> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <Td><b>Property Name</b></td> + <td><b>Default Values</b></td> + </Tr> + <Tr> + <Td>BoardNum</Td> + <td>No default value</td> + </Tr> + <Tr> + <Td>BoardType</Td> + <td>No default value</td> + </Tr> + </Table> + + <Br><Br><Br> + <Center><b> + There is no Class properties.<Br><Br> + </Center></b> + <Br> <Br> <Br> - <br> - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> -</html> + +</html> \ No newline at end of file diff --git a/doc/doc_html/TangoDevStates.html b/doc/doc_html/TangoDevStates.html index 7d7aef3..57cc435 100755 --- a/doc/doc_html/TangoDevStates.html +++ b/doc/doc_html/TangoDevStates.html @@ -1,124 +1,59 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User's Guide </Title> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> +<html> + +<head> + <title> Tango Device Server User's Guide </title> +</head> + +<body> + <center> + <h1> + SingleShotAO Generic Device <br> + Device States Description <br> <br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau + </b> + </center> + + <center> + <table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td COLSPAN=2> + <font Size=+2><center> + <b>States</b> + </center></font> + </td> + </tr> + + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td><center><b>Names</b></center></td> + <td><center><b>Descriptions</b></center></td> + </tr> + + <tr> + <td><b>FAULT</b></td> + <td><font Size=-1>Hardware / driver failure or fatal error occurred</font></td> + </tr> + + <tr> + <td><b>ON</b></td> + <td><font Size=-1>Device ready to execute AO request</font></td> + </tr> + + <tr> + <td><b>INIT</b></td> + <td><font Size=-1>Device initialization in progress</font></td> + </tr> + + <tr> + <td><b>MOVING</b></td> + <td><font Size=-1>Ramp generation in progress</font></td> + </tr> + </table> + </center> -<P><!-------TITLE------></P> - -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> - -<HR WIDTH="100%"></H5> -<Br> -<center> -<h1> -SingleShotAO Generic Device <Br> -Device States Description <Br> <Br> -SingleShotAO Class <Br> -</h1> -<b> -Revision: - Author: buteau -</b> -</center> - - -<Center> -<Br> <Br> <Br> -<Table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td COLSPAN=2> <Font Size=+2><Center><b>States</b></td></Font></Center> -<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> -<Td><Center><b>Names</b></td></Center> -<Td><Center><b>Descriptions</b></td></Center> -<Tr><Td><b>FAULT</b></Td> -<Td><Font Size=-1>Hardware / driver failure or fatal error occurred</Font></Td></Tr> - -<Tr><Td><b>ON</b></Td> -<Td><Font Size=-1>Device ready to execute AO request</Font></Td></Tr> - -<Tr><Td><b>INIT</b></Td> -<Td><Font Size=-1>Device initialization in progress</Font></Td></Tr> - -<Tr><Td><b>MOVING</b></Td> -<Td><Font Size=-1>Ramp generation in progress</Font></Td></Tr> - - - - -</Table> -</Center> - -<!--- html Footer ---> - -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> - - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> -</html> + +</html> \ No newline at end of file diff --git a/doc/doc_html/index.html b/doc/doc_html/index.html index abd508c..43e3bc5 100755 --- a/doc/doc_html/index.html +++ b/doc/doc_html/index.html @@ -1,142 +1,60 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -<Title> Tango Device Server User's Guide </Title> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#7F00FF" ALINK="#FF0000"> - -<P><!-------TITLE------></P> -<TABLE BORDER="0" WIDTH="100%"> - <TR> - <TD ALIGN="left"> - <A HREF="http://www.esrf.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/gifs/logo/80.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="center"> - <A HREF="http://www.elettra.trieste.it/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/elettra_logo.gif" BORDER=0 Height="60"></A> - - </Td> - <TD ALIGN="center"> - <A HREF="http://www.synchrotron-soleil.fr/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/soleil_logo.gif" BORDER=0 Height="60"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.cells.es/" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/alba.jpg" BORDER=0 Height="54"></A> - </Td> - <TD ALIGN="right"> - <A HREF="http://www.desy.de/html/home/index_eng.html" TARGET=new> - <IMG SRC="http://www.esrf.fr/computing/cs/tango/desy.gif" BORDER=0 Height="60"></A> - </Td> - <Td> - <H2><FONT COLOR="#7F00FF"> - <Center><A HREF="http://www.tango-controls.org/" TARGET="_top"> - TANGO </a> <Br> Device Server - </Center></FONT> - </Td> - </TR> -</TABLE> +<html> + +<head> + <title> Tango Device Server User's Guide </title> +</head> + +<body> + <center> + <h1> + SingleShotAO Generic Device <br> + User's Guide <br><Br> + SingleShotAO Class <br> + </h1> + <b> + Revision: - Author: buteau <br> + Implemented in C++ + </b> + </center> + + <h2>Introduction:</h2> + <ul> + <li>ADLink boards support for single shot AO operations [PCI-6208 and compatible boards]</li> + </ul> -<HR WIDTH="100%"></H5> -<center> -<h1> -SingleShotAO Generic Device <Br> -User's Guide <Br><Br> -SingleShotAO Class<Br> + <h2>Class Identification:</h2> + <ul> + <li><b>Contact :</b> at synchrotron-soleil.fr - buteau</li> + <li><b>Class Family :</b> InputOutput</li> + <li><b>Platform :</b> All Platforms</li> + <li><b>Bus :</b> Compact PCI</li> + </ul> -</h1> -<b> -Revision: - Author: buteau <Br> - Implemented in C++ -</b> -</center> -<Br> -<Br> -<Br> -<Br> -<h2>Introduction:</h2> -<ul> - ADLink boards support for single shot AO operations [PCI-6208 and compatible boards]<Br> -</ul> -<Br><h2>Class Identification:</h2> -<ul> - <li><b>Contact :</b> at synchrotron-soleil.fr - buteau - <li><b>Class Family :</b> InputOutput - <li><b>Platform :</b> All Platforms - <li><b>Bus :</b> Compact PCI -</ul><Br> -<h2>Class Inheritance:</h2> + <h2>Class Inheritance:</h2> <ul> - <li> <a href="http://www.esrf.fr/computing/cs/tango/tango_doc/kernel_doc/cpp_doc/"> TANGO_BASE_CLASS</a></li> + <li> <a + href="http://www.esrf.fr/computing/cs/tango/tango_doc/kernel_doc/cpp_doc/"> + TANGO_BASE_CLASS</a></li> <ul> <li> SingleShotAO</li> - </ul> </ul> </ul> -</ul> -<Br> -<Br> -<h2>Class Description:</h2> -<ul> - <li> <a href=Description.html> Device description.</a> - <li> <a href=Properties.html> Properties description</a> - <li> <a href=TangoDevStates.html> States description</a> - <li> <a href=DevCommandsTable.html> Commands description</a> - <li> <a href=Attributes.html> Attributes description</a> -</ul> -<Br> -<Br> -<Br> -<h2>Conclusion:</h2> -<ul> - The device server is ready for distribution application programmers.<Br> - The author will be interested in any feedback which arise from their - usage of this device server. -</ul> -<Br> - -<!--- html Footer ---> - -<Center> -<Font size=-1> -<br> -<br> -<TABLE BORDER="1" WIDTH="100%"> - <Tr> - <!--- Hosted by Sourceforge ---> - <Td Align="Center"> - <Font size=-1> - <b>TANGO</b> is an open source project hosted by :<br> - <A href="http://sourceforge.net" Target="new"> - <IMG title="Sourceforge logo" - alt="Sourceforge logo small" - src="http://www.esrf.fr/computing/cs/tango/sourceforge.gif" - border=0> </a> - </Font> - </Td> - <!--- 2 Sourceforge Repositories ---> - <Td Align="Center"> - <Font size=-1> - Core and Tools : - <a href="http://tango-cs.cvs.sourceforge.net/tango-cs/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-cs" Target=new> - tango-cs project</a> - - <br> + <h2>Class Description:</h2> + <ul> + <li> <a href=Description.html> Device description.</a> </li> + <li> <a href=Properties.html> Properties description</a> </li> + <li> <a href=TangoDevStates.html> States description</a> </li> + <li> <a href=DevCommandsTable.html> Commands description</a> </li> + <li> <a href=Attributes.html> Attributes description</a> </li> + </ul> + + <h2>Conclusion:</h2> + <ul> + <li>The device server is ready for distribution application programmers.</li> + <li>The author will be interested in any feedback which arise from their usage of this device server.</li> + </ul> - Device Servers : - <a href="http://tango-ds.cvs.sourceforge.net/tango-ds/" Target="new"> - CVS repository</a> on - <a href="https://sourceforge.net/projects/tango-ds" Target=new> - tango-ds project</a> - </Font> - </Td> - </Tr> -</Table> -</Font> -</Center> </body> </html> -- GitLab From 854209fd040c83f0f911d4a68979b89fc65d6b8e Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 13:53:27 +0100 Subject: [PATCH 08/34] chore(doc): add dynamic attributes to HTML documentation --- doc/doc_html/Attributes.html | 87 ++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/doc/doc_html/Attributes.html b/doc/doc_html/Attributes.html index 9a6dff5..63ac70c 100755 --- a/doc/doc_html/Attributes.html +++ b/doc/doc_html/Attributes.html @@ -25,21 +25,18 @@ </tr> <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> <td> - <center><b>Attribute name</b> + <center><b>Attribute name</b></center> </td> - </center> <td> - <center><b>Data Type</b> + <center><b>Data Type</b></center> </td> - </center> <td> - <center><b>R/W Type</b> + <center><b>R/W Type</b></center> </td> - </center> <td> - <center><b>Expert</b> + <center><b>Expert</b></center> </td> - </center> + </tr> <tr> <td><b>frequency</b>: <font Size=-1>Sampling frequency for ramp generation on the board output channels, in @@ -61,7 +58,81 @@ </center> </td> </tr> + </table> + <br> + + <table Border=2 Cellpadding=3 CELLSPACING=0 WIDTH="100%"> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td COLSPAN=4> + <center> + <font Size=+2><b>Dynamic Scalar Attributes</b></font><br> + X is the channel number ranging from 0 to N-1 (<b>MAO_6208</b>: 8 channels, <b>MAO_6216</b>: 10 channels) + </center> + </td> + </tr> + <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> + <td> + <center><b>Attribute name</b></center> + </td> + <td> + <center><b>Data Type</b></center> + </td> + <td> + <center><b>R/W Type</b></center> + </td> + <td> + <center><b>Description</b></center> + </td> + </tr> + <tr> + <td><b>channelX</b></td> + <td> + <center> + <font Size=-1>DEV_DOUBLE</font> + </center> + </td> + <td> + <center> + <font Size=-1>READ_WRITE</font> + </center> + </td> + <td> + <font Size=-1>Output value for channel X (in V). Valid range: [-10V, +10V]</font> + </td> + </tr> + <tr> + <td><b>speedX</b></td> + <td> + <center> + <font Size=-1>DEV_DOUBLE</font> + </center> + </td> + <td> + <center> + <font Size=-1>READ_WRITE</font> + </center> + </td> + <td> + <font Size=-1>Speed for ramp generation on channel X (in V/s). If speed is 0, no ramp is generated but direct write on channel output.</font> + </td> + </tr> + <tr> + <td><b>initialX</b></td> + <td> + <center> + <font Size=-1>DEV_DOUBLE</font> + </center> + </td> + <td> + <center> + <font Size=-1>READ_WRITE</font> + </center> + </td> + <td> + <font Size=-1>Initial value for ramp function on channel X (in V). Defaults to last written value in channel attribute.</font> + </td> + </tr> </table> </center> -- GitLab From 4a82daf289fa54ec4f6c4b8205e9d0799f8fa96e Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 13:57:58 +0100 Subject: [PATCH 09/34] feature/fix: memorize channel values on abort and abort on init --- src/SingleShotAO.cpp | 50 ++++++++++++++++++++++++++++++++++--- src/SingleShotAO.h | 3 +++ src/SingleShotAOManager.cpp | 8 ++++++ src/SingleShotAOManager.h | 3 +++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 8b886ad..cc7f5b6 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -348,6 +348,28 @@ void SingleShotAO::init_device() } + // Make sure running processes are aborted properly + //-------------------------------------------- + try + { + _abort(); + } + catch (Tango::DevFailed &df) + { + ERROR_STREAM << df << endl; + RETHROW_DEVFAILED(df, + "DRIVER_FAILURE", + "could not abort [caught Tango::DevFailed]", + "SingleShotAO::init"); + } + catch (...) + { + ERROR_STREAM << "SingleShotAO::init::unknown exception caught" << std::endl; + THROW_DEVFAILED("DRIVER_FAILURE", + "could not abort [unknown error]", + "SingleShotAO::init"); + } + // Create dynamic attributes //-------------------------------------------- @@ -990,11 +1012,9 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & void SingleShotAO::abort() { DEBUG_STREAM << "SingleShotAO::abort(): entering... !" << endl; - - CHECK_MANAGER(); try { - m_manager->abort(); + _abort(); } catch(Tango::DevFailed& df) { @@ -1006,11 +1026,33 @@ void SingleShotAO::abort() } catch(...) { - ERROR_STREAM << "SingleShotAOManager::abort::unknown exception caught"<<std::endl; + 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); + yat4tango::PropertyHelper::set_memorized_attribute(this, kCHANNEL + std::to_string(l_cpt), l_val_channel); + DEBUG_STREAM << "Memorizing channel " << l_cpt << " to " << l_val_channel << std::endl; + + double l_val_initial = m_manager->get_initial(l_cpt); + yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_cpt), l_val_initial); + DEBUG_STREAM << "Memorizing initial " << l_cpt << " to " << l_val_initial << std::endl; + } + } + m_manager->abort(); +} + } // namespace diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index d6d477f..8e259d0 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -279,6 +279,9 @@ protected : //- channel number unsigned short m_nb_chan; + + void _abort(); + }; } // namespace_ns diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index 5d7b57a..e0519ec 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -440,6 +440,14 @@ void SingleShotAOManager::set_speed(ChannelId_t p_chIdx, Intial_t p_speed) } } +// ============================================================================ +// SingleShotAOManager::is_running () +// ============================================================================ +bool SingleShotAOManager::is_running(ChannelId_t p_chIdx) +{ + return m_isRunning[p_chIdx]; +} + // ============================================================================ // SingleShotAOManager::abort () // ============================================================================ diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index ccabfce..a021036 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -74,6 +74,9 @@ public: //- set speed void set_speed(ChannelId_t p_chIdx, Intial_t p_speed); + //- is running + bool is_running(ChannelId_t p_chIdx); + //- abort void abort(); -- GitLab From a9fd52415c2455043f4e7da54a5a8b0e3d5f221e Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 14:34:48 +0100 Subject: [PATCH 10/34] fix: abort in delete_device (and inherently in init and exit) --- src/SingleShotAO.cpp | 70 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index cc7f5b6..699767f 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -129,7 +129,32 @@ SingleShotAO::SingleShotAO(Tango::DeviceClass *cl,const char *s,const char *d) //----------------------------------------------------------------------------- void SingleShotAO::delete_device() { - // Delete device allocated objects + 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) @@ -138,14 +163,16 @@ void SingleShotAO::delete_device() m_manager = NULL; } - //- release the asl::SingleShotAO object + // Release the asl::SingleShotAO object + //-------------------------------------------- if (m_ssao) { delete m_ssao; m_ssao = NULL; } - // remove dynamic attributes + // Remove dynamic attributes + //-------------------------------------------- if (m_dyn_attr_manager) { try @@ -165,7 +192,8 @@ void SingleShotAO::delete_device() m_dyn_attr_manager = NULL; } - //- remove the inner appender + // Remove the inner appender + //-------------------------------------------- yat4tango::Logging::release(this); yat4tango::DeviceInfo::release(this); } @@ -315,17 +343,20 @@ void SingleShotAO::init_device() return; } + // get frequency value in database + //-------------------------------------------- try { - m_frequency = yat4tango::PropertyHelper::get_memorized_attribute<double>(this,"frequency"); + m_frequency = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, "frequency"); DEBUG_STREAM << "Frequency : " << m_frequency << endl; } catch (...) { DEBUG_STREAM << "Failed to get frequency value. Maybe there is no value yet." << std::endl; } - + + // initialize the AO manager //-------------------------------------------- try @@ -348,28 +379,6 @@ void SingleShotAO::init_device() } - // Make sure running processes are aborted properly - //-------------------------------------------- - try - { - _abort(); - } - catch (Tango::DevFailed &df) - { - ERROR_STREAM << df << endl; - RETHROW_DEVFAILED(df, - "DRIVER_FAILURE", - "could not abort [caught Tango::DevFailed]", - "SingleShotAO::init"); - } - catch (...) - { - ERROR_STREAM << "SingleShotAO::init::unknown exception caught" << std::endl; - THROW_DEVFAILED("DRIVER_FAILURE", - "could not abort [unknown error]", - "SingleShotAO::init"); - } - // Create dynamic attributes //-------------------------------------------- @@ -1047,9 +1056,8 @@ void SingleShotAO::_abort() yat4tango::PropertyHelper::set_memorized_attribute(this, kCHANNEL + std::to_string(l_cpt), l_val_channel); DEBUG_STREAM << "Memorizing channel " << l_cpt << " to " << l_val_channel << std::endl; - double l_val_initial = m_manager->get_initial(l_cpt); - yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_cpt), l_val_initial); - DEBUG_STREAM << "Memorizing initial " << l_cpt << " to " << l_val_initial << std::endl; + yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_cpt), l_val_channel); + DEBUG_STREAM << "Memorizing initial " << l_cpt << " to " << l_val_channel << std::endl; } } m_manager->abort(); -- GitLab From 4fe5634255053686359f6da63ceddf23db5951fd Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 14:48:05 +0100 Subject: [PATCH 11/34] bump: update version to 2.1.0 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 479a146..24ed606 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conan import ConanFile class SingleShotAORecipe(ConanFile): name = "singleshotao" executable = "ds_SingleShotAO" - version = "2.0.4" + version = "2.1.0" package_type = "application" user = "soleil" python_requires = "base/[>=1.0]@soleil/stable" -- GitLab From 3d756be15fa57fa37dc46c56a26138a47743e2ea Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 16:35:50 +0100 Subject: [PATCH 12/34] fix: update format precision for channelX and speedX attributes to match initialX attributes --- src/SingleShotAO.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 699767f..ee7b789 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -429,7 +429,7 @@ void SingleShotAO::init_device() 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 = "%1.1f"; + dai_channel.tai.format = "%1.2f"; dai_channel.memorized = true; dai_channel.cdb = false; @@ -461,7 +461,7 @@ void SingleShotAO::init_device() 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 = "%1.1f"; + dai_speed.tai.format = "%1.2f"; //- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db) dai_speed.memorized = true; -- GitLab From 915889e15d7f6e1d89442db101d42456127f3040 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 16:40:59 +0100 Subject: [PATCH 13/34] fix: rename get_device_properties back to get_device_property for consistency (+ add comments) --- src/SingleShotAO.cpp | 45 +++++++++++++++++++++----------------------- src/SingleShotAO.h | 2 +- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index ee7b789..96a72ba 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -247,7 +247,7 @@ void SingleShotAO::init_device() //-------------------------------------------- try { - get_device_properties(); + get_device_property(); } catch (const Tango::DevFailed& df) { @@ -570,57 +570,52 @@ void SingleShotAO::init_device() //+---------------------------------------------------------------------------- // -// method : SingleShotAO::get_device_properties() +// method : SingleShotAO::get_device_property() // // description : Read the device properties from database. // //----------------------------------------------------------------------------- -void SingleShotAO::get_device_properties() +void SingleShotAO::get_device_property() { - // Initialize your default values here (if not done with POGO). - //------------------------------------------------------------------ - - // Read device properties from database.(Automatic code generation) + // Read device properties from database //------------------------------------------------------------------ Tango::DbData dev_prop; dev_prop.push_back(Tango::DbDatum("BoardNum")); dev_prop.push_back(Tango::DbDatum("BoardType")); - // Call database and extract values + // Call database and extract values //-------------------------------------------- - if (Tango::Util::instance()->_UseDb==true) + 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())); + } + Tango::DbDatum def_prop, cl_prop; + SingleShotAOClass *ds_class = (static_cast<SingleShotAOClass *>(get_device_class())); int i = -1; - // Try to initialize BoardNum from class property + // 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 + // 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; } - // And try to extract BoardNum value from database + // And try to extract BoardNum value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> boardNum; - // Try to initialize BoardType from class property + // 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 + // 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; } - // And try to extract BoardType value from database + // And try to extract BoardType value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> boardType; - - - // End of Automatic code generation - //------------------------------------------------------------------ + // Check critical properties being present + //-------------------------------------------- critical_properties_missing = false; @@ -639,8 +634,11 @@ void SingleShotAO::get_device_properties() return; } + // Check critical properties being valid + //-------------------------------------------- + //- <BoardNum> ----------------------- - if (boardNum > 7) + if (boardNum < 0 || boardNum > 7) { boardNum = 0; ERROR_STREAM << "device property <BoardNum> is invalid. Valid range is [0..7]" << endl; @@ -665,7 +663,6 @@ void SingleShotAO::get_device_properties() ERROR_STREAM << "device property <BoardType> is invalid [supported hw: MAO_6208 or MAO_6216]" << endl; critical_properties_missing = true; } - } diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 8e259d0..7faa182 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -219,7 +219,7 @@ public : /** * Read the device properties from database */ - void get_device_properties(); + void get_device_property(); //@} // Here is the end of the automatic code generation part -- GitLab From 1085d8888f3e1935e49ac54ab85630cf9c67c76f Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 16:58:02 +0100 Subject: [PATCH 14/34] feat: add EnableRamps and WriteMemorizedValuesAtInit properties with default values (do nothing so far) --- doc/doc_html/Properties.html | 34 ++++++++- src/SingleShotAO.cpp | 31 ++++++++ src/SingleShotAO.h | 8 ++ src/SingleShotAOClass.cpp | 144 ++++++++++------------------------- 4 files changed, 109 insertions(+), 108 deletions(-) diff --git a/doc/doc_html/Properties.html b/doc/doc_html/Properties.html index 388a562..b0ca154 100755 --- a/doc/doc_html/Properties.html +++ b/doc/doc_html/Properties.html @@ -56,16 +56,34 @@ <Font Size=-1>Tango::DEV_STRING</Font> </Td> <Td> - <Font Size=-1>The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no - default value]</Font> + <Font Size=-1>The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no default value]</Font> </Td> </Tr> - </Table> + <Tr> + <Td><b><a href=#Dev_DefaultValues>EnableRamps </a></b></Td> + <Td> + <Font Size=-1>Tango::DEV_BOOLEAN</Font> + </Td> + <Td> + <Font Size=-1>Whether to enable or disable the ramp generation on the board output channels. If false, the speedX and initialX dynamic attributes will not be created for every channel, and the changes will happen instantly. [true/false - default value is true]</Font> + </Td> + + </Tr> + <Tr> + <Td><b><a href=#Dev_DefaultValues>WriteMemorizedValuesAtInit </a></b></Td> + <Td> + <Font Size=-1>Tango::DEV_BOOLEAN</Font> + </Td> + <Td> + <Font Size=-1>Whether to write the memorized values to the board at the device initialization. [true/false - default value is false]</Font> + </Td> + </Tr> + </Table> + </Center> - <A name=Dev_DefaultValues><!--- ---></a> <Font Size=+1>Device Properties Default Values:</Font><Br> <Table Border=2 Cellpadding=2 CELLSPACING=2> <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> @@ -80,6 +98,14 @@ <Td>BoardType</Td> <td>No default value</td> </Tr> + <Tr> + <Td>EnableRamps</Td> + <td>true</td> + </Tr> + <Tr> + <Td>WriteMemorizedValuesAtInit</Td> + <td>false</td> + </Tr> </Table> <Br><Br><Br> diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 96a72ba..56cb44d 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -582,6 +582,8 @@ void SingleShotAO::get_device_property() 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("WriteMemorizedValuesAtInit")); // Call database and extract values //-------------------------------------------- @@ -592,6 +594,7 @@ void SingleShotAO::get_device_property() 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; @@ -603,6 +606,7 @@ void SingleShotAO::get_device_property() // And try to extract BoardNum value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> boardNum; + //- <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; @@ -614,6 +618,33 @@ void SingleShotAO::get_device_property() // And try to extract BoardType value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> boardType; + //- <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; + } + // And try to extract EnableRamps value from database + if (dev_prop[i].is_empty() == false) dev_prop[i] >> enableRamps; + + //- <WriteMemorizedValuesAtInit> ----------------------- + // Try to initialize WriteMemorizedValuesAtInit from class property + cl_prop = ds_class->get_class_property(dev_prop[++i].name); + if (cl_prop.is_empty() == false) cl_prop >> writeMemorizedValuesAtInit; + else + { + // Try to initialize WriteMemorizedValuesAtInit from default device value + def_prop = ds_class->get_default_device_property(dev_prop[i].name); + if (def_prop.is_empty() == false) def_prop >> writeMemorizedValuesAtInit; + } + // And try to extract WriteMemorizedValuesAtInit value from database + if (dev_prop[i].is_empty() == false) dev_prop[i] >> writeMemorizedValuesAtInit; + + // Check critical properties being present //-------------------------------------------- diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 7faa182..f77367e 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -110,6 +110,14 @@ public : * The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no default value] */ string boardType; +/** + * Whether to enable or disable the ramp generation on the board output channels. If false, the speedX and initialX dynamic attributes will not be created for every channel, and the changes will happen instantly. [true/false - default value is true] + */ + Tango::DevBoolean enableRamps; +/** + * Whether to write the memorized values to the board at the device initialization. [true/false - default value is false] + */ + Tango::DevBoolean writeMemorizedValuesAtInit; //@} /** diff --git a/src/SingleShotAOClass.cpp b/src/SingleShotAOClass.cpp index e93187a..87816eb 100755 --- a/src/SingleShotAOClass.cpp +++ b/src/SingleShotAOClass.cpp @@ -369,10 +369,14 @@ void SingleShotAOClass::set_default_property() string prop_def; vector<string> vect_data; + // Set Default Class Properties + // ... + // Set Default Device Properties + //- <BoardNum> ----------------------- prop_name = "BoardNum"; - prop_desc = "The the board identifier in the cPCI crate [valid range is 0...7 - no default value] ."; + prop_desc = "The board identifier in the cPCI crate [valid range is 0...7 - no default value]."; prop_def = ""; vect_data.clear(); if (prop_def.length()>0) @@ -385,6 +389,7 @@ void SingleShotAOClass::set_default_property() else add_wiz_dev_prop(prop_name, prop_desc); + //- <BoardType> ----------------------- prop_name = "BoardType"; prop_desc = "The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no default value]"; prop_def = ""; @@ -399,7 +404,40 @@ void SingleShotAOClass::set_default_property() else add_wiz_dev_prop(prop_name, prop_desc); + //- <EnableRamps> ----------------------- + prop_name = "EnableRamps"; + prop_desc = "Whether to enable or disable the ramp generation on the board output channels. If false, the speedX and initialX dynamic attributes will not be created for every channel, and the changes will happen instantly. [true/false - default value is true]"; + prop_def = "true"; + vect_data.clear(); + vect_data.push_back("true"); + if (prop_def.length() > 0) + { + Tango::DbDatum data(prop_name); + data << vect_data; + dev_def_prop.push_back(data); + add_wiz_dev_prop(prop_name, prop_desc, prop_def); + } + else + add_wiz_dev_prop(prop_name, prop_desc); + + //- <WriteMemorizedValuesAt> ----------------------- + prop_name = "WriteMemorizedValuesAtInit"; + prop_desc = "Whether to write the memorized values to the board at the device initialization. [true/false - default value is false]"; + prop_def = "false"; + vect_data.clear(); + vect_data.push_back("false"); + if (prop_def.length() > 0) + { + Tango::DbDatum data(prop_name); + data << vect_data; + dev_def_prop.push_back(data); + add_wiz_dev_prop(prop_name, prop_desc, prop_def); + } + else + add_wiz_dev_prop(prop_name, prop_desc); } + + //+---------------------------------------------------------------------------- // // method : SingleShotAOClass::write_class_property @@ -431,107 +469,6 @@ void SingleShotAOClass::write_class_property() str_desc.push_back("ADLink boards support for single shot AO operations [PCI-6208 and compatible boards]"); description << str_desc; data.push_back(description); - - // put cvs or svn location - string filename(classname); - filename += "Class.cpp"; - - // Create a string with the class ID to - // get the string into the binary - string class_id(ClassId); - - // check for cvs information - string src_path(CvsPath); - start = src_path.find("/"); - if (start!=string::npos) - { - end = src_path.find(filename); - if (end>start) - { - string strloc = src_path.substr(start, end-start); - // Check if specific repository - start = strloc.find("/cvsroot/"); - if (start!=string::npos && start>0) - { - string repository = strloc.substr(0, start); - if (repository.find("/segfs/")!=string::npos) - strloc = "ESRF:" + strloc.substr(start, strloc.length()-start); - } - Tango::DbDatum cvs_loc("cvs_location"); - cvs_loc << strloc; - data.push_back(cvs_loc); - } - } - // check for svn information - else - { - string src_path(SvnPath); - start = src_path.find("://"); - if (start!=string::npos) - { - end = src_path.find(filename); - if (end>start) - { - header = "$HeadURL: "; - start = header.length(); - string strloc = src_path.substr(start, (end-start)); - - Tango::DbDatum svn_loc("svn_location"); - svn_loc << strloc; - data.push_back(svn_loc); - } - } - } - - // Get CVS or SVN revision tag - - // CVS tag - string tagname(TagName); - header = "$Name: "; - start = header.length(); - string endstr(" $"); - - end = tagname.find(endstr); - if (end!=string::npos && end>start) - { - string strtag = tagname.substr(start, end-start); - Tango::DbDatum cvs_tag("cvs_tag"); - cvs_tag << strtag; - data.push_back(cvs_tag); - } - - // SVN tag - string svnpath(SvnPath); - header = "$HeadURL: "; - start = header.length(); - - end = svnpath.find(endstr); - if (end!=string::npos && end>start) - { - string strloc = svnpath.substr(start, end-start); - - string tagstr ("/tags/"); - start = strloc.find(tagstr); - if ( start!=string::npos ) - { - start = start + tagstr.length(); - end = strloc.find(filename); - string strtag = strloc.substr(start, end-start-1); - - Tango::DbDatum svn_tag("svn_tag"); - svn_tag << strtag; - data.push_back(svn_tag); - } - } - - // Get URL location - string httpServ(HttpServer); - if (httpServ.length()>0) - { - Tango::DbDatum db_doc_url("doc_url"); - db_doc_url << httpServ; - data.push_back(db_doc_url); - } // Put inheritance Tango::DbDatum inher_datum("InheritedFrom"); @@ -540,8 +477,7 @@ void SingleShotAOClass::write_class_property() inher_datum << inheritance; data.push_back(inher_datum); - // Call database and and values - //-------------------------------------------- + // Call database and add values get_db_class()->put_property(data); } -- GitLab From a1e6b1c7fff680f637fdbd2f3031cc36943c6520 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 17:01:31 +0100 Subject: [PATCH 15/34] feat: write memorized value at init if writeMemorizedValuesAtInit is true (instead of just set_channel) --- src/SingleShotAO.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 56cb44d..dd92d5a 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -537,8 +537,10 @@ void SingleShotAO::init_device() // Get and set memorized values for speed, initial and channel applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed); applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); - applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); - // TODO: add a property to call write_channel instead of set_channel (false by default) + if (writeMemorizedValuesAtInit) + applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel); + else + applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); } //- GO for task -- GitLab From 2fbc7f47a8820d8af04f917b601c49f85bc442ee Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 17:26:14 +0100 Subject: [PATCH 16/34] feat: deactive ramp functionnality if enableRamps is false (don't create speed and initial attributes at init, and set changes instantly) --- src/SingleShotAO.cpp | 23 ++++++++++++++++------- src/SingleShotAOManager.cpp | 18 ++++++++++++++++-- src/SingleShotAOManager.h | 7 +++++-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index dd92d5a..5bce000 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -361,7 +361,7 @@ void SingleShotAO::init_device() //-------------------------------------------- try { - m_manager->init(m_ssao, m_nb_chan, m_frequency); + m_manager->init(m_ssao, m_nb_chan, m_frequency, enableRamps); } catch (Tango::DevFailed & df) { @@ -443,6 +443,11 @@ void SingleShotAO::init_device() 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 ║ @@ -535,12 +540,16 @@ void SingleShotAO::init_device() }; // Get and set memorized values for speed, initial and channel - applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed); - applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); - if (writeMemorizedValuesAtInit) - applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel); - else - applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); + if (enableRamps) { + applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed); + applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); + } + + if (writeMemorizedValuesAtInit) { + applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel); // write memorized value to board output + } else { + applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); // only apply memorized value to the device + } } //- GO for task diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index e0519ec..0eb1333 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -128,7 +128,7 @@ void SingleShotAOManager::write_frequency(double p_frequency) // ============================================================================ // SingleShotAOManager::init () // ============================================================================ -void SingleShotAOManager::init(asl::SingleShotAO * p_ssao, unsigned short p_nb_chan, double p_frequency) +void SingleShotAOManager::init(asl::SingleShotAO * p_ssao, unsigned short p_nb_chan, double p_frequency, bool p_enable_ramps) { m_ssao = p_ssao; CHECK_SSAO(); @@ -145,6 +145,8 @@ void SingleShotAOManager::init(asl::SingleShotAO * p_ssao, unsigned short p_nb_c enable_periodic_msg(true); } + m_enable_ramps = p_enable_ramps; + // initialize channel indexes (-1 means no ramp in progress) // and ramp states for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) @@ -288,7 +290,7 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) DEBUG_STREAM << "write_channel " << p_chIdx << " : " << p_val << endl; // if the speed is 0, write the value directly and skip ramp - if (m_speeds[p_chIdx] == 0.0) + if (m_speeds[p_chIdx] == 0.0 || !m_enable_ramps) { try { @@ -409,6 +411,12 @@ void SingleShotAOManager::set_initial(ChannelId_t p_chIdx, Intial_t p_initial) "could not write initial : a ramp is still in progress on this channel", "SingleShotAOManager::set_initial"); } + else if (!m_enable_ramps) + { + THROW_DEVFAILED("DEVICE_FAILURE", + "could not write initial : ramps are disabled", + "SingleShotAOManager::set_initial"); + } else { m_initials[p_chIdx] = p_initial; @@ -434,6 +442,12 @@ void SingleShotAOManager::set_speed(ChannelId_t p_chIdx, Intial_t p_speed) "could not write speed : a ramp is still in progress on this channel", "SingleShotAOManager::set_speed"); } + else if (!m_enable_ramps) + { + THROW_DEVFAILED("DEVICE_FAILURE", + "could not write speed : ramps are disabled", + "SingleShotAOManager::set_speed"); + } else { m_speeds[p_chIdx] = p_speed; diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index a021036..5351b59 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -48,7 +48,7 @@ public: std::string get_status (); //- init - void init(asl::SingleShotAO * p_ssao, unsigned short p_nb_chan, double p_frequency); + void init(asl::SingleShotAO *p_ssao, unsigned short p_nb_chan, double p_frequency, bool p_enable_ramps); //- get current channel value double get_channel(ChannelId_t p_chIdx); @@ -100,7 +100,10 @@ private: //- frequency double m_frequency; - + + //-enable ramps + bool m_enable_ramps; + //- initial buffer for all channels std::map<ChannelId_t, Intial_t> m_initials; -- GitLab From 9547d4baa7101eac7b0ea23562f1be24fe3ff15c Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 17:27:51 +0100 Subject: [PATCH 17/34] bump: update version to 2.2.0 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 24ed606..27e4801 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conan import ConanFile class SingleShotAORecipe(ConanFile): name = "singleshotao" executable = "ds_SingleShotAO" - version = "2.1.0" + version = "2.2.0" package_type = "application" user = "soleil" python_requires = "base/[>=1.0]@soleil/stable" -- GitLab From acaf27f501d07516df4cb72b913951affc84d7e3 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Fri, 21 Feb 2025 17:35:14 +0100 Subject: [PATCH 18/34] feat: add logging for parsed device properties in get_device_property method --- src/SingleShotAO.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 5bce000..b5ed3f3 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -601,6 +601,7 @@ void SingleShotAO::get_device_property() 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; @@ -616,6 +617,7 @@ void SingleShotAO::get_device_property() } // 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 @@ -628,39 +630,37 @@ void SingleShotAO::get_device_property() } // 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 - { + 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; } // 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; //- <WriteMemorizedValuesAtInit> ----------------------- // Try to initialize WriteMemorizedValuesAtInit from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty() == false) cl_prop >> writeMemorizedValuesAtInit; - else - { + else { // Try to initialize WriteMemorizedValuesAtInit from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty() == false) def_prop >> writeMemorizedValuesAtInit; } // And try to extract WriteMemorizedValuesAtInit value from database if (dev_prop[i].is_empty() == false) dev_prop[i] >> writeMemorizedValuesAtInit; - + INFO_STREAM << "WriteMemorizedValuesAtInit parsed: " << (writeMemorizedValuesAtInit ? "true" : "false") << endl; // Check critical properties being present //-------------------------------------------- - critical_properties_missing = false; - if (dev_prop[0].is_empty()) { ERROR_STREAM << "Required device property <BoardNum> is missing" << endl; @@ -671,20 +671,20 @@ void SingleShotAO::get_device_property() ERROR_STREAM << "Required device property <BoardType> is missing" << endl; critical_properties_missing = true; } - if (critical_properties_missing) { return; } // Check critical properties being valid //-------------------------------------------- - //- <BoardNum> ----------------------- if (boardNum < 0 || boardNum > 7) { boardNum = 0; ERROR_STREAM << "device property <BoardNum> is invalid. Valid range is [0..7]" << endl; critical_properties_missing = true; + } else { + INFO_STREAM << "BoardNum resolved to " << boardNum << endl; } //- <BoardType> ----------------------- @@ -692,11 +692,13 @@ void SingleShotAO::get_device_property() { 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; } else { -- GitLab From 64fc34e7f901f62dd54aa092b5354ffdbd13aa66 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Mon, 17 Mar 2025 18:20:47 +0100 Subject: [PATCH 19/34] feat: rename WriteMemorizedValuesAtInit to OutputMemorizedChannelsAtInit and update documentation --- doc/doc_html/Properties.html | 6 +++--- src/SingleShotAO.cpp | 20 ++++++++++---------- src/SingleShotAO.h | 2 +- src/SingleShotAOClass.cpp | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/doc_html/Properties.html b/doc/doc_html/Properties.html index b0ca154..95f05a3 100755 --- a/doc/doc_html/Properties.html +++ b/doc/doc_html/Properties.html @@ -72,12 +72,12 @@ </Tr> <Tr> - <Td><b><a href=#Dev_DefaultValues>WriteMemorizedValuesAtInit </a></b></Td> + <Td><b><a href=#Dev_DefaultValues>OutputMemorizedChannelsAtInit </a></b></Td> <Td> <Font Size=-1>Tango::DEV_BOOLEAN</Font> </Td> <Td> - <Font Size=-1>Whether to write the memorized values to the board at the device initialization. [true/false - default value is false]</Font> + <Font Size=-1>Whether to send the memorized values for the channels to the board at the device initialization (the device attribute will show the last memorized value regardless) [true/false - default value is false]</Font> </Td> </Tr> </Table> @@ -103,7 +103,7 @@ <td>true</td> </Tr> <Tr> - <Td>WriteMemorizedValuesAtInit</Td> + <Td>OutputMemorizedChannelsAtInit</Td> <td>false</td> </Tr> </Table> diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index b5ed3f3..748d7f1 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -545,7 +545,7 @@ void SingleShotAO::init_device() applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); } - if (writeMemorizedValuesAtInit) { + if (outputMemorizedChannelsAtInit) { applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel); // write memorized value to board output } else { applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::set_channel); // only apply memorized value to the device @@ -594,7 +594,7 @@ void SingleShotAO::get_device_property() 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("WriteMemorizedValuesAtInit")); + dev_prop.push_back(Tango::DbDatum("OutputMemorizedChannelsAtInit")); // Call database and extract values //-------------------------------------------- @@ -645,18 +645,18 @@ void SingleShotAO::get_device_property() if (dev_prop[i].is_empty() == false) dev_prop[i] >> enableRamps; INFO_STREAM << "EnableRamps parsed: " << (enableRamps ? "true" : "false") << endl; - //- <WriteMemorizedValuesAtInit> ----------------------- - // Try to initialize WriteMemorizedValuesAtInit from class property + //- <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 >> writeMemorizedValuesAtInit; + if (cl_prop.is_empty() == false) cl_prop >> outputMemorizedChannelsAtInit; else { - // Try to initialize WriteMemorizedValuesAtInit from default device value + // 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 >> writeMemorizedValuesAtInit; + if (def_prop.is_empty() == false) def_prop >> outputMemorizedChannelsAtInit; } - // And try to extract WriteMemorizedValuesAtInit value from database - if (dev_prop[i].is_empty() == false) dev_prop[i] >> writeMemorizedValuesAtInit; - INFO_STREAM << "WriteMemorizedValuesAtInit parsed: " << (writeMemorizedValuesAtInit ? "true" : "false") << endl; + // 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; // Check critical properties being present //-------------------------------------------- diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index f77367e..7cee441 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -117,7 +117,7 @@ public : /** * Whether to write the memorized values to the board at the device initialization. [true/false - default value is false] */ - Tango::DevBoolean writeMemorizedValuesAtInit; + Tango::DevBoolean outputMemorizedChannelsAtInit; //@} /** diff --git a/src/SingleShotAOClass.cpp b/src/SingleShotAOClass.cpp index 87816eb..29a1ef5 100755 --- a/src/SingleShotAOClass.cpp +++ b/src/SingleShotAOClass.cpp @@ -420,9 +420,9 @@ void SingleShotAOClass::set_default_property() else add_wiz_dev_prop(prop_name, prop_desc); - //- <WriteMemorizedValuesAt> ----------------------- - prop_name = "WriteMemorizedValuesAtInit"; - prop_desc = "Whether to write the memorized values to the board at the device initialization. [true/false - default value is false]"; + //- <OutputMemorizedChannelsAtInit> ----------------------- + prop_name = "OutputMemorizedChannelsAtInit"; + prop_desc = "Whether to send the memorized values for the channels to the board at the device initialization (the device attribute will show the last memorized value regardless) [true/false - default value is false]"; prop_def = "false"; vect_data.clear(); vect_data.push_back("false"); -- GitLab From 2c69e3b7c591c5cc9563e950096954a8b0a35a6d Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Mon, 17 Mar 2025 18:21:51 +0100 Subject: [PATCH 20/34] feat: add ASL dependency in info attribute (hardcoded version because I could not find a variable for the version) --- src/SingleShotAO.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 748d7f1..3257a7b 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -216,8 +216,7 @@ void SingleShotAO::init_device() 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, "Dependency Name", YAT_XSTR(dependency_name_PROJECT_VERSION)); - // TODO: Add dependencies + yat4tango::DeviceInfo::add_dependency(this, "ASL", ">=1.0"); } catch (Tango::DevFailed &df) { -- GitLab From 646f4650d6e3e4a4818b6be371dec2521b8cbfe5 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Mon, 17 Mar 2025 18:22:45 +0100 Subject: [PATCH 21/34] feat: added logging and consolidate dynamic attribute management --- src/SingleShotAO.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 3257a7b..cb204a0 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -318,6 +318,7 @@ void SingleShotAO::init_device() m_nb_chan = 16; } + INFO_STREAM << "Board has " << m_nb_chan << " channels" << endl; // construct the AO manager //-------------------------------------------- @@ -377,6 +378,20 @@ void SingleShotAO::init_device() 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 //-------------------------------------------- @@ -404,6 +419,17 @@ void SingleShotAO::init_device() // 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; + + // if enableRamps if false, skip speed and initial attributes + if (!enableRamps) + { + INFO_STREAM << "Ramps are disabled. Skipping speed and initial attributes" << std::endl; + } + for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { yat::OSStream oss; @@ -515,8 +541,45 @@ void SingleShotAO::init_device() l_dynAttrList.push_back(dai_initial); } - m_dyn_attr_manager->add_attributes(l_dynAttrList); + + // 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++) @@ -531,6 +594,7 @@ void SingleShotAO::init_device() try { std::string attrName = attrPrefix + oss.str(); double val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, attrName); + DEBUG_STREAM << "Found memorized value for " << attrName << ": " << val << endl; (m_manager->*setter)(l_cpt, val); } catch (...) { -- GitLab From 5551cf17caf5eefd2a2e6aa40bbe3f2b8d645dde Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Mon, 24 Mar 2025 17:50:41 +0100 Subject: [PATCH 22/34] refactor: split write_channel method into write_channel_direct and start_channel_ramp --- src/SingleShotAO.cpp | 5 +- src/SingleShotAOManager.cpp | 121 ++++++++++++++++++++---------------- src/SingleShotAOManager.h | 6 ++ 3 files changed, 79 insertions(+), 53 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index cb204a0..7bcea21 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -609,7 +609,7 @@ void SingleShotAO::init_device() } if (outputMemorizedChannelsAtInit) { - applyMemorizedAttr(kCHANNEL, &SingleShotAOManager::write_channel); // write memorized value to board output + 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 } @@ -978,8 +978,11 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & "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); + yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_idx), l_val); + DEBUG_STREAM << "SingleShotAO::write_channel(): memorized attribute " << l_attr_name << " set to " << l_val << endl; } diff --git a/src/SingleShotAOManager.cpp b/src/SingleShotAOManager.cpp index 0eb1333..e988c22 100755 --- a/src/SingleShotAOManager.cpp +++ b/src/SingleShotAOManager.cpp @@ -250,6 +250,7 @@ void SingleShotAOManager::periodic_job_i() m_currentIndex[l_cpt] += 1; if (m_currentIndex[l_cpt] == m_ramps[l_cpt].capacity()) { + DEBUG_STREAM << "Ramp finished for channel" << l_cpt << endl; m_currentIndex[l_cpt] = -1; m_initials[l_cpt] = m_channels[l_cpt]; m_ramps[l_cpt].clear(); @@ -283,67 +284,43 @@ void SingleShotAOManager::set_channel(ChannelId_t p_chIdx, double p_val) } // ============================================================================ -// SingleShotAOManager::write_channel () +// SingleShotAOManager::write_channel_direct () // ============================================================================ -void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) +void SingleShotAOManager::write_channel_direct(ChannelId_t p_chIdx, double p_val) { - DEBUG_STREAM << "write_channel " << p_chIdx << " : " << p_val << endl; - - // if the speed is 0, write the value directly and skip ramp - if (m_speeds[p_chIdx] == 0.0 || !m_enable_ramps) + try { - try - { - CHECK_SSAO(); - m_ssao->write_scaled_channel((adl::ChanId)p_chIdx, p_val); - m_channels[p_chIdx] = p_val; - m_initials[p_chIdx] = p_val; - DEBUG_STREAM << "Speed is 0, writing directly the value" << std::endl; - } - catch (const asl::DAQException &de) - { - Tango::DevFailed df = daq_to_tango_exception(de); - ERROR_STREAM << df << std::endl; - m_state = Tango::FAULT; - RETHROW_DEVFAILED(df, - "DRIVER_FAILURE", - "could not write channel [caught asl::DAQException]", - "SingleShotAOManager::write_channel"); - } - catch (...) - { - ERROR_STREAM << "SingleShotAOManager::write_channel::unknown exception caught" << std::endl; - m_state = Tango::FAULT; - THROW_DEVFAILED("DRIVER_FAILURE", - "could not write channel [unknown error]", - "SingleShotAOManager::write_channel"); - } - return; + CHECK_SSAO(); + m_ssao->write_scaled_channel((adl::ChanId)p_chIdx, p_val); + m_channels[p_chIdx] = p_val; + m_initials[p_chIdx] = p_val; + DEBUG_STREAM << "Writing directly the value" << std::endl; } - - // if a ramp is running, error - if (m_isRunning[p_chIdx]) + catch (const asl::DAQException &de) { - THROW_DEVFAILED("DEVICE_FAILURE", - "could not write channel : a ramp is still in progress on this channel", - "SingleShotAOManager::write_channel"); + Tango::DevFailed df = daq_to_tango_exception(de); + ERROR_STREAM << df << std::endl; + m_state = Tango::FAULT; + RETHROW_DEVFAILED(df, + "DRIVER_FAILURE", + "could not write channel [caught asl::DAQException]", + "SingleShotAOManager::write_channel_direct"); } - - // if frequency = 0, error - if (m_frequency == 0) + catch (...) { + ERROR_STREAM << "SingleShotAOManager::write_channel_direct::unknown exception caught" << std::endl; + m_state = Tango::FAULT; THROW_DEVFAILED("DRIVER_FAILURE", - "could not set a ramp on this channel. The frequency is 0", - "SingleShotAOManager::write_channel"); - } - - // if initial = channel, skip - if (m_initials[p_chIdx] == p_val) - { - DEBUG_STREAM << "Initial value is the same as the given value, skipping" << endl; - return; + "could not write channel [unknown error]", + "SingleShotAOManager::write_channel_direct"); } +} +// ============================================================================ +// SingleShotAOManager::start_channel_ramp () +// ============================================================================ +void SingleShotAOManager::start_channel_ramp(ChannelId_t p_chIdx, double p_val) +{ // ramp determination double l_delta = p_val - m_initials[p_chIdx]; bool isDown = false; @@ -389,7 +366,47 @@ void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) m_ramps[p_chIdx].force_length(0); m_currentIndex[p_chIdx] = 0; m_ramps[p_chIdx] = l_buffer; - //m_channels[p_chIdx] = m_ramps[p_chIdx][0]; -- soso on ne met rien ici => à l'application +} + +// ============================================================================ +// SingleShotAOManager::write_channel () +// ============================================================================ +void SingleShotAOManager::write_channel(ChannelId_t p_chIdx, double p_val) +{ + DEBUG_STREAM << "write_channel " << p_chIdx << " : " << p_val << endl; + + // if the speed is 0, write the value directly and skip ramp + if (m_speeds[p_chIdx] == 0.0 || !m_enable_ramps) + { + write_channel_direct(p_chIdx, p_val); + return; + } + + // if a ramp is running, error + if (m_isRunning[p_chIdx]) + { + THROW_DEVFAILED("DEVICE_FAILURE", + "could not write channel : a ramp is still in progress on this channel", + "SingleShotAOManager::write_channel"); + } + + // if frequency = 0, error + if (m_frequency == 0) + { + THROW_DEVFAILED("DRIVER_FAILURE", + "could not set a ramp on this channel. The frequency is 0", + "SingleShotAOManager::write_channel"); + } + + // if initial = channel, skip + if (m_initials[p_chIdx] == p_val) + { + DEBUG_STREAM << "Initial value is the same as the given value, skipping" << endl; + return; + } + + // Create and start a ramp + start_channel_ramp(p_chIdx, p_val); } // ============================================================================ diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index 5351b59..25c002e 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -59,6 +59,12 @@ public: //- write channel void write_channel(ChannelId_t p_chIdx, double p_val); + //- write a channel directly (without ramp) + void write_channel_direct(ChannelId_t p_chIdx, double p_val); + + //- create and start a ramp for channel + void start_channel_ramp(ChannelId_t p_chIdx, double p_val); + //- change period void write_frequency(double p_frequency); -- GitLab From e3d05be346d74b5a50b53dae0f9be0eb234fbf70 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Tue, 25 Mar 2025 10:26:35 +0100 Subject: [PATCH 23/34] fix: always synchronize read and write values (except during ramps) --- src/SingleShotAO.cpp | 61 +++++++++++++++++++++++++++++++++++++------- src/SingleShotAO.h | 4 +++ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 7bcea21..76ce807 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -455,7 +455,6 @@ void SingleShotAO::init_device() dai_channel.tai.min_value = "-10.0"; dai_channel.tai.description = "Output value for channel " + oss.str() + " (in measurementUnit)."; dai_channel.tai.format = "%1.2f"; - dai_channel.memorized = true; dai_channel.cdb = false; //- read callback @@ -494,7 +493,6 @@ void SingleShotAO::init_device() dai_speed.tai.format = "%1.2f"; //- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db) - dai_speed.memorized = true; dai_speed.cdb = false; //- read callback @@ -528,7 +526,6 @@ void SingleShotAO::init_device() dai_initial.tai.format = "%1.2f"; //- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db) - dai_initial.memorized = true; dai_initial.cdb = false; //- read callback @@ -595,7 +592,12 @@ void SingleShotAO::init_device() std::string attrName = attrPrefix + oss.str(); 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 (...) { // nothing to do @@ -954,6 +956,7 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & { 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 @@ -981,7 +984,12 @@ void SingleShotAO::write_channel(yat4tango::DynamicAttributeWriteCallbackData & 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); - yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_idx), 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; } @@ -1116,6 +1124,37 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & } +//+------------------------------------------------------------------ +/** + * 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 @@ -1160,11 +1199,15 @@ void SingleShotAO::_abort() DEBUG_STREAM << "Channel " << l_cpt << " is running. Memorizing values..." << std::endl; double l_val_channel = m_manager->get_channel(l_cpt); - yat4tango::PropertyHelper::set_memorized_attribute(this, kCHANNEL + std::to_string(l_cpt), l_val_channel); - DEBUG_STREAM << "Memorizing channel " << l_cpt << " to " << l_val_channel << std::endl; - - yat4tango::PropertyHelper::set_memorized_attribute(this, kINITIAL + std::to_string(l_cpt), l_val_channel); - DEBUG_STREAM << "Memorizing initial " << l_cpt << " to " << l_val_channel << std::endl; + 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(); diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 7cee441..17e2b74 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -290,6 +290,10 @@ protected : void _abort(); + // set the write value of a dynamic attribute + // used to keep read and write values in sync + bool setDynamicAttributeWriteValue(const std::string& attrName, double value); + }; } // namespace_ns -- GitLab From d77c4643378126b3d588ba492a619170dae27130 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 26 Mar 2025 11:30:58 +0100 Subject: [PATCH 24/34] fix: applied requested changes (by @langlois in !3) --- src/SingleShotAO.cpp | 75 +++++++++++++++++++++++---------------- src/SingleShotAOClass.cpp | 3 +- src/SingleShotAOManager.h | 2 ++ 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 76ce807..0c95671 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -380,14 +380,17 @@ void SingleShotAO::init_device() // Remove existing dynamic attributes to avoid duplicates or other issues // -------------------------------------------- - if (m_dyn_attr_manager) { - try { + 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 (...) { + catch (...) + { ERROR_STREAM << "Error cleaning up existing dynamic attributes manager, continuing..." << endl; // Continue anyway - we'll create a new one } @@ -424,12 +427,6 @@ void SingleShotAO::init_device() INFO_STREAM << "Creating dynamic attributes for " << m_nb_chan << " channels."; INFO_STREAM << "Total attributes: " << m_nb_chan * (enableRamps ? 3 : 1) << endl; - // if enableRamps if false, skip speed and initial attributes - if (!enableRamps) - { - INFO_STREAM << "Ramps are disabled. Skipping speed and initial attributes" << std::endl; - } - for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { yat::OSStream oss; @@ -454,7 +451,7 @@ void SingleShotAO::init_device() 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 = "%1.2f"; + dai_channel.tai.format = "%2.1f"; dai_channel.cdb = false; //- read callback @@ -468,7 +465,8 @@ void SingleShotAO::init_device() l_dynAttrList.push_back(dai_channel); // if enableRamps if false, skip speed and initial attributes - if (!enableRamps) { + if (!enableRamps) + { DEBUG_STREAM << "Ramps are disabled. Skipping speed and initial attributes for channel " << l_cpt << std::endl; continue; } @@ -490,7 +488,7 @@ void SingleShotAO::init_device() 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 = "%1.2f"; + dai_speed.tai.format = "%2.1f"; //- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db) dai_speed.cdb = false; @@ -523,7 +521,7 @@ void SingleShotAO::init_device() 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 = "%1.2f"; + dai_initial.tai.format = "%2.1f"; //- cleanup tango db option: cleanup tango db when removing this dyn. attr. (i.e. erase its properties from db) dai_initial.cdb = false; @@ -543,17 +541,20 @@ void SingleShotAO::init_device() INFO_STREAM << "Prepared " << l_dynAttrList.size() << " dynamic attributes for creation" << endl; // Add all attributes - try { + try + { m_dyn_attr_manager->add_attributes(l_dynAttrList); INFO_STREAM << "Successfully added all dynamic attributes" << endl; } - catch (Tango::DevFailed &df) { + 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 (...) { + catch (...) + { ERROR_STREAM << "Unknown exception when adding dynamic attributes" << endl; m_currStatus = "Failed to add dynamic attributes. Unknown error"; m_state = Tango::FAULT; @@ -561,17 +562,21 @@ void SingleShotAO::init_device() } // Initialize maps in manager class for all channels - try { - for (unsigned int l_cpt = 0; l_cpt < m_nb_chan; l_cpt++) { + 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) { + if (enableRamps) + { m_manager->set_speed(l_cpt, 0.0); m_manager->set_initial(l_cpt, 0.0); } } } - catch (Tango::DevFailed &df) { + 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; @@ -588,7 +593,8 @@ void SingleShotAO::init_device() auto applyMemorizedAttr = [&](const std::string& attrPrefix, void (SingleShotAOManager::*setter)(yat::uint16, double)) { - try { + try + { std::string attrName = attrPrefix + oss.str(); double val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, attrName); DEBUG_STREAM << "Found memorized value for " << attrName << ": " << val << endl; @@ -599,18 +605,21 @@ void SingleShotAO::init_device() // Write the value to the "write" attributes using helper function setDynamicAttributeWriteValue(attrName, val); } - catch (...) { + catch (...) + { // nothing to do } }; // Get and set memorized values for speed, initial and channel - if (enableRamps) { + if (enableRamps) + { applyMemorizedAttr(kSPEED, &SingleShotAOManager::set_speed); applyMemorizedAttr(kINITIAL, &SingleShotAOManager::set_initial); } - if (outputMemorizedChannelsAtInit) { + 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 @@ -663,7 +672,8 @@ void SingleShotAO::get_device_property() // Call database and extract values //-------------------------------------------- - if (Tango::Util::instance()->_UseDb==true) { + if (Tango::Util::instance()->_UseDb==true) + { get_db_device()->get_property(dev_prop); } @@ -736,7 +746,8 @@ void SingleShotAO::get_device_property() ERROR_STREAM << "Required device property <BoardType> is missing" << endl; critical_properties_missing = true; } - if (critical_properties_missing) { + if (critical_properties_missing) + { return; } @@ -1131,7 +1142,8 @@ void SingleShotAO::write_initial(yat4tango::DynamicAttributeWriteCallbackData & */ bool SingleShotAO::setDynamicAttributeWriteValue(const std::string& attrName, double value) { - try { + try + { Tango::DeviceImpl* dev = static_cast<Tango::DeviceImpl*>(this); Tango::DevDouble val_to_write = value; @@ -1142,12 +1154,14 @@ bool SingleShotAO::setDynamicAttributeWriteValue(const std::string& attrName, do DEBUG_STREAM << "Set write value for " << attrName << " to " << value << endl; return true; } - catch (Tango::DevFailed &df) { + catch (Tango::DevFailed &df) + { ERROR_STREAM << "Failed to set write value for " << attrName << ": " << df << endl; return false; } - catch (...) { + catch (...) + { ERROR_STREAM << "Unknown exception setting write value for " << attrName << endl; return false; @@ -1195,7 +1209,8 @@ void SingleShotAO::_abort() // 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)) { + 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); diff --git a/src/SingleShotAOClass.cpp b/src/SingleShotAOClass.cpp index 29a1ef5..d5b5ee1 100755 --- a/src/SingleShotAOClass.cpp +++ b/src/SingleShotAOClass.cpp @@ -87,7 +87,8 @@ __declspec(dllexport) #endif - Tango::DeviceClass *_create_SingleShotAO_class(const char *name) { + Tango::DeviceClass *_create_SingleShotAO_class(const char *name) + { return SingleShotAO_ns::SingleShotAOClass::init(name); } } diff --git a/src/SingleShotAOManager.h b/src/SingleShotAOManager.h index 25c002e..325e00f 100755 --- a/src/SingleShotAOManager.h +++ b/src/SingleShotAOManager.h @@ -54,9 +54,11 @@ public: double get_channel(ChannelId_t p_chIdx); //- set channel + // Updates the value for the channel in the device without sending it to hardware void set_channel(ChannelId_t p_chIdx, double p_val); //- write channel + // Writes value to the channel to the device and the hardware, with a ramp if speed is not null and EnableRamps property is true void write_channel(ChannelId_t p_chIdx, double p_val); //- write a channel directly (without ramp) -- GitLab From 481c3c032eec8638acb73b56c7e3d61aea54334d Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Tue, 22 Apr 2025 14:37:35 +0200 Subject: [PATCH 25/34] fix: update format for channel attributes to use three decimal digits (%5.3f) --- src/SingleShotAO.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 0c95671..e21ee35 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -451,7 +451,7 @@ void SingleShotAO::init_device() 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 = "%2.1f"; + dai_channel.tai.format = "%5.3f"; dai_channel.cdb = false; //- read callback @@ -488,7 +488,7 @@ void SingleShotAO::init_device() 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 = "%2.1f"; + 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; @@ -521,7 +521,7 @@ void SingleShotAO::init_device() 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 = "%2.1f"; + 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; -- GitLab From c84bae851f672b1a807c7ad34bf600f797a84b1f Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Tue, 22 Apr 2025 15:41:07 +0200 Subject: [PATCH 26/34] fix: improve debug messages for missing attribute values --- src/SingleShotAO.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index e21ee35..e6145dc 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -353,7 +353,7 @@ void SingleShotAO::init_device() } catch (...) { - DEBUG_STREAM << "Failed to get frequency value. Maybe there is no value yet." << std::endl; + DEBUG_STREAM << "No memorized value found for frequency. Defaulting to " << m_frequency << "." << std::endl; } @@ -607,7 +607,7 @@ void SingleShotAO::init_device() } catch (...) { - // nothing to do + DEBUG_STREAM << "No memorized value found for " << attrName << ". Setting default value." << std::endl; } }; -- GitLab From 3a0041bbe2167c25b2f4dfff9fcee047297f3335 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Tue, 22 Apr 2025 15:58:31 +0200 Subject: [PATCH 27/34] fix: create properties in init if they don't exist, and validate properties values --- src/SingleShotAO.cpp | 85 ++++++++++++++++++++++++++------------- src/SingleShotAOClass.cpp | 6 ++- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index e6145dc..19b614b 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -593,9 +593,9 @@ void SingleShotAO::init_device() auto applyMemorizedAttr = [&](const std::string& attrPrefix, void (SingleShotAOManager::*setter)(yat::uint16, double)) { + std::string attrName = attrPrefix + oss.str(); try { - std::string attrName = attrPrefix + oss.str(); double val = yat4tango::PropertyHelper::get_memorized_attribute<double>(this, attrName); DEBUG_STREAM << "Found memorized value for " << attrName << ": " << val << endl; @@ -652,14 +652,14 @@ void SingleShotAO::init_device() isInitOk = true; } - -//+---------------------------------------------------------------------------- -// -// method : SingleShotAO::get_device_property() -// -// description : Read the device properties from database. -// -//----------------------------------------------------------------------------- +//+------------------------------------------------------------------ +/** + * 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 @@ -733,38 +733,54 @@ void SingleShotAO::get_device_property() if (dev_prop[i].is_empty() == false) dev_prop[i] >> outputMemorizedChannelsAtInit; INFO_STREAM << "OutputMemorizedChannelsAtInit parsed: " << (outputMemorizedChannelsAtInit ? "true" : "false") << endl; - // Check critical properties being present + // Create properties if empty and set default values //-------------------------------------------- - critical_properties_missing = false; - if (dev_prop[0].is_empty()) - { - ERROR_STREAM << "Required device property <BoardNum> is missing" << endl; - critical_properties_missing = true; - } - if (dev_prop[1].is_empty()) - { - ERROR_STREAM << "Required device property <BoardType> is missing" << endl; - critical_properties_missing = true; - } - if (critical_properties_missing) - { - return; - } + DEBUG_STREAM << "Creating properties if empty" << endl; + yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardNum, "BoardNum"); + yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardType, "BoardType"); + yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, enableRamps, "EnableRamps"); + yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, outputMemorizedChannelsAtInit, "OutputMemorizedChannelsAtInit"); // Check critical properties being valid //-------------------------------------------- + DEBUG_STREAM << "Checking if critical properties are valid:" << endl; + critical_properties_missing = false; + yat::OSStream errorMessages; + //- <BoardNum> ----------------------- - if (boardNum < 0 || boardNum > 7) + Tango::DbDatum &boardNumDatum = Tango::DbDatum("BoardNum"); + std::string defaultBoardNum_str; + def_prop = ds_class->get_default_device_property(boardNumDatum.name); + if (def_prop.is_empty() == false) def_prop >> defaultBoardNum_str; + Tango::DevShort defaultBoardNum = atoi(defaultBoardNum_str.c_str()); + if (boardNum == defaultBoardNum) + { + errorMessages << "Device property <BoardNum> is not set (default value " << defaultBoardNum << " needs to be replaced)" << endl; + ERROR_STREAM << "Device property <BoardNum> is not set (default value " << defaultBoardNum << " needs to be replaced)" << endl; + critical_properties_missing = true; + } + else if (boardNum < 0 || boardNum > 7) { boardNum = 0; - ERROR_STREAM << "device property <BoardNum> is invalid. Valid range is [0..7]" << endl; + errorMessages << "Device property <BoardNum> is invalid. Valid range is [0..7]" << endl; + ERROR_STREAM << "Device property <BoardNum> is invalid. Valid range is [0..7]" << endl; critical_properties_missing = true; } else { INFO_STREAM << "BoardNum resolved to " << boardNum << endl; } //- <BoardType> ----------------------- - if (boardType == "MAO_6208") + Tango::DbDatum &boardTypeDatum = Tango::DbDatum("BoardType"); + std::string defaultBoardType; + def_prop = ds_class->get_default_device_property(boardTypeDatum.name); + if (def_prop.is_empty() == false) def_prop >> defaultBoardType; + if (boardType == defaultBoardType) + { + errorMessages << "Device property <BoardType> is not set (default value " << defaultBoardType << " needs to be replaced)" << endl; + ERROR_STREAM << "Device property <BoardType> is not set (default value " << defaultBoardType << " needs to be replaced)" << endl; + critical_properties_missing = true; + } + else if (boardType == "MAO_6208") { boardType = k6208_BOARD_TYPE; boardTypeId = adl::PCI6208; @@ -780,9 +796,20 @@ void SingleShotAO::get_device_property() { boardType = kDEFAULT_BOARD_TYPE; boardTypeId = adl::PCI6208; - ERROR_STREAM << "device property <BoardType> is invalid [supported hw: MAO_6208 or MAO_6216]" << endl; + errorMessages << "Device property <BoardType> is invalid [supported hw: MAO_6208 or MAO_6216]" << endl; + ERROR_STREAM << "Device property <BoardType> is invalid [supported hw: MAO_6208 or MAO_6216]" << endl; critical_properties_missing = true; } + + 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; + } } diff --git a/src/SingleShotAOClass.cpp b/src/SingleShotAOClass.cpp index d5b5ee1..d780498 100755 --- a/src/SingleShotAOClass.cpp +++ b/src/SingleShotAOClass.cpp @@ -378,8 +378,9 @@ void SingleShotAOClass::set_default_property() //- <BoardNum> ----------------------- prop_name = "BoardNum"; prop_desc = "The board identifier in the cPCI crate [valid range is 0...7 - no default value]."; - prop_def = ""; + prop_def = "-1"; vect_data.clear(); + vect_data.push_back("-1"); if (prop_def.length()>0) { Tango::DbDatum data(prop_name); @@ -393,8 +394,9 @@ void SingleShotAOClass::set_default_property() //- <BoardType> ----------------------- prop_name = "BoardType"; prop_desc = "The board type [MAO_xxxx - where <xxxx> is the ADlink board identifier - e.g. MAO_6208 - no default value]"; - prop_def = ""; + prop_def = "TO_BE_DEFINED"; vect_data.clear(); + vect_data.push_back("TO_BE_DEFINED"); if (prop_def.length()>0) { Tango::DbDatum data(prop_name); -- GitLab From 1dc39827d610f6d390c0eacb0e59bbb3f84cff0f Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Tue, 22 Apr 2025 18:33:50 +0200 Subject: [PATCH 28/34] fix: move SingleShotAOManager construction to dtart of init_device to allow init after an error in get_device_property() --- src/SingleShotAO.cpp | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 19b614b..e101a12 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -231,6 +231,30 @@ void SingleShotAO::init_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; + } + + // 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; + } + + // Initialise variables to default values //-------------------------------------------- @@ -320,29 +344,6 @@ void SingleShotAO::init_device() INFO_STREAM << "Board has " << m_nb_chan << " channels" << endl; - // 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; - } - - // 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 //-------------------------------------------- -- GitLab From ca7a47a167e40cc80aa77961815fb98d0e54ec28 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 23 Apr 2025 14:18:13 +0200 Subject: [PATCH 29/34] fix: enhance error handling and add comments in get_device_property() --- src/SingleShotAO.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index e101a12..b90b3c5 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -737,6 +737,8 @@ void SingleShotAO::get_device_property() // Create properties if empty and set default values //-------------------------------------------- DEBUG_STREAM << "Creating properties if empty" << endl; + // boardNum, boardType, enableRamps and outputMemorizedChannelsAtInit variables + // contain the default values at this point if the properties are not set in the database. yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardNum, "BoardNum"); yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardType, "BoardType"); yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, enableRamps, "EnableRamps"); @@ -747,8 +749,11 @@ void SingleShotAO::get_device_property() DEBUG_STREAM << "Checking if critical properties are valid:" << endl; critical_properties_missing = false; yat::OSStream errorMessages; + errorMessages << "\nCritical properties are missing or invalid:\n" << endl; //- <BoardNum> ----------------------- + // Case 1 (error): boardNum is set to the default value in the database + // (compare the current value with the default value) Tango::DbDatum &boardNumDatum = Tango::DbDatum("BoardNum"); std::string defaultBoardNum_str; def_prop = ds_class->get_default_device_property(boardNumDatum.name); @@ -757,20 +762,24 @@ void SingleShotAO::get_device_property() if (boardNum == defaultBoardNum) { errorMessages << "Device property <BoardNum> is not set (default value " << defaultBoardNum << " needs to be replaced)" << endl; - ERROR_STREAM << "Device property <BoardNum> is not set (default value " << defaultBoardNum << " 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; - ERROR_STREAM << "Device property <BoardNum> is invalid. Valid range is [0..7]" << endl; critical_properties_missing = true; - } else { + } + // 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 + // (compare the current value with the default value) Tango::DbDatum &boardTypeDatum = Tango::DbDatum("BoardType"); std::string defaultBoardType; def_prop = ds_class->get_default_device_property(boardTypeDatum.name); @@ -778,9 +787,9 @@ void SingleShotAO::get_device_property() if (boardType == defaultBoardType) { errorMessages << "Device property <BoardType> is not set (default value " << defaultBoardType << " needs to be replaced)" << endl; - ERROR_STREAM << "Device property <BoardType> is not set (default value " << defaultBoardType << " 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; @@ -793,15 +802,16 @@ void SingleShotAO::get_device_property() 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; - ERROR_STREAM << "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; -- GitLab From e9bc2d6945d4d3e7f4749b29bfa9d2e5b26ddd30 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 23 Apr 2025 14:30:03 +0200 Subject: [PATCH 30/34] refactor: improve clarity by removing redundancy in get_device_property() for default properties values --- src/SingleShotAO.cpp | 69 ++++++++++++++++++++++++-------------------- src/SingleShotAO.h | 20 +++++++++++-- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index b90b3c5..d56848a 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -671,6 +671,7 @@ void SingleShotAO::get_device_property() 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) @@ -689,23 +690,31 @@ void SingleShotAO::get_device_property() 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; + 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; + 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; + 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; + 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; + if (dev_prop[i].is_empty() == false) dev_prop[i] >> boardType; INFO_STREAM << "Raw BoardType parsed: " << boardType << endl; //- <EnableRamps> ----------------------- @@ -715,7 +724,11 @@ void SingleShotAO::get_device_property() 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; + 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; @@ -728,40 +741,38 @@ void SingleShotAO::get_device_property() 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; + 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; - // boardNum, boardType, enableRamps and outputMemorizedChannelsAtInit variables - // contain the default values at this point if the properties are not set in the database. - yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardNum, "BoardNum"); - yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, boardType, "BoardType"); - yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, enableRamps, "EnableRamps"); - yat4tango::PropertyHelper::create_property_if_empty(this, dev_prop, outputMemorizedChannelsAtInit, "OutputMemorizedChannelsAtInit"); + 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 << "\nCritical properties are missing or invalid:\n" << endl; + errorMessages << "Critical properties are missing or invalid:" << endl; //- <BoardNum> ----------------------- // Case 1 (error): boardNum is set to the default value in the database - // (compare the current value with the default value) - Tango::DbDatum &boardNumDatum = Tango::DbDatum("BoardNum"); - std::string defaultBoardNum_str; - def_prop = ds_class->get_default_device_property(boardNumDatum.name); - if (def_prop.is_empty() == false) def_prop >> defaultBoardNum_str; - Tango::DevShort defaultBoardNum = atoi(defaultBoardNum_str.c_str()); - if (boardNum == defaultBoardNum) - { - errorMessages << "Device property <BoardNum> is not set (default value " << defaultBoardNum << " needs to be replaced)" << endl; + 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 @@ -779,14 +790,9 @@ void SingleShotAO::get_device_property() //- <BoardType> ----------------------- // Case 1 (error): boardType is set to the default value in the database - // (compare the current value with the default value) - Tango::DbDatum &boardTypeDatum = Tango::DbDatum("BoardType"); - std::string defaultBoardType; - def_prop = ds_class->get_default_device_property(boardTypeDatum.name); - if (def_prop.is_empty() == false) def_prop >> defaultBoardType; - if (boardType == defaultBoardType) - { - errorMessages << "Device property <BoardType> is not set (default value " << defaultBoardType << " needs to be replaced)" << endl; + if (boardType == boardType_default) + { + 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 @@ -811,6 +817,7 @@ void SingleShotAO::get_device_property() critical_properties_missing = true; } + // If any critical property is missing or invalid, throw an exception if (critical_properties_missing) { diff --git a/src/SingleShotAO.h b/src/SingleShotAO.h index 17e2b74..2d680ca 100755 --- a/src/SingleShotAO.h +++ b/src/SingleShotAO.h @@ -121,10 +121,26 @@ public : //@} /** - * @name Device properties - * Device property member data. + * @name Device properties default values + * Device properties default values. */ //@{ +/** + * Default value for boardNum property + */ + Tango::DevShort boardNum_default; +/** + * Default value for boardType property + */ + string boardType_default; +/** + * Default value for enableRamps property + */ + Tango::DevBoolean enableRamps_default; +/** + * Default value for outputMemorizedChannelsAtInit property + */ + Tango::DevBoolean outputMemorizedChannelsAtInit_default; //@} /**@name Constructors -- GitLab From ccec3c51eec6851a706924e4da9804095889ebca Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 23 Apr 2025 14:59:47 +0200 Subject: [PATCH 31/34] fix: improve error logging for get_device_property in init_device (logs and status) --- src/SingleShotAO.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index d56848a..12080ad 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -277,8 +277,15 @@ void SingleShotAO::init_device() ERROR_STREAM << "SingleShotAO::init_device::Tango::DevFailed exception caught " << "while trying to read device properties from TANGO database" << std::endl; - ERROR_STREAM << df << std::endl; - m_currStatus = "Failed to get property. See log for details"; + 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; } -- GitLab From 4a660db36380f0f0395587da4b3362e1ddb3273b Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 23 Apr 2025 15:01:37 +0200 Subject: [PATCH 32/34] fix: handle empty boardType in get_device_property() to improve error handling --- src/SingleShotAO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 12080ad..9a61cc0 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -797,7 +797,7 @@ void SingleShotAO::get_device_property() //- <BoardType> ----------------------- // Case 1 (error): boardType is set to the default value in the database - if (boardType == boardType_default) + 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; -- GitLab From 24152f1e0e70daae45b3d28e4de3a929330bac71 Mon Sep 17 00:00:00 2001 From: MALFREYT <alexandre.malfreyt@synchrotron-soleil.fr> Date: Wed, 23 Apr 2025 18:27:41 +0200 Subject: [PATCH 33/34] refactor: revert e9bc2d69 partially to prevent pogo interference (get default values later in get_device_property) --- src/SingleShotAO.cpp | 60 ++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/SingleShotAO.cpp b/src/SingleShotAO.cpp index 9a61cc0..112ac3e 100755 --- a/src/SingleShotAO.cpp +++ b/src/SingleShotAO.cpp @@ -253,7 +253,7 @@ void SingleShotAO::init_device() m_state = Tango::FAULT; return; } - + // Initialise variables to default values //-------------------------------------------- @@ -681,83 +681,89 @@ void SingleShotAO::get_device_property() // Call database and extract values //-------------------------------------------- - if (Tango::Util::instance()->_UseDb==true) + 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; + 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 { + 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; + 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 { + 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; + 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 { + 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; + 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 { + 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; + if (dev_prop[i].is_empty() == false) + dev_prop[i] >> outputMemorizedChannelsAtInit; INFO_STREAM << "OutputMemorizedChannelsAtInit parsed: " << (outputMemorizedChannelsAtInit ? "true" : "false") << endl; + // Get default values from class + //-------------------------------------------- + ds_class->get_default_device_property(std::string("BoardNum")) >> boardNum_default; + ds_class->get_default_device_property(std::string("BoardType")) >> boardType_default; + ds_class->get_default_device_property(std::string("EnableRamps")) >> enableRamps_default; + ds_class->get_default_device_property(std::string("OutputMemorizedChannelsAtInit")) >> outputMemorizedChannelsAtInit_default; // Create properties if empty and set default values //-------------------------------------------- -- GitLab From 256f61e96f4de7c14eaef93633ed50f279cf4f7a Mon Sep 17 00:00:00 2001 From: Florent Langlois <florent.langlois@synchrotron-soleil.fr> Date: Thu, 24 Apr 2025 11:41:37 +0200 Subject: [PATCH 34/34] set version to 2.1.0 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 27e4801..24ed606 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conan import ConanFile class SingleShotAORecipe(ConanFile): name = "singleshotao" executable = "ds_SingleShotAO" - version = "2.2.0" + version = "2.1.0" package_type = "application" user = "soleil" python_requires = "base/[>=1.0]@soleil/stable" -- GitLab