diff --git a/include/ChannelData.hpp b/include/ChannelData.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9fd59c9a47f074e461448804daf3a687083c6b81 --- /dev/null +++ b/include/ChannelData.hpp @@ -0,0 +1,97 @@ +// ============================================================================ +// +// = CONTEXT +// ChannelData +// +// = File +// ChannelData.hpp +// +// = AUTHOR +// X. Elattaoui Synchrotron Soleil France +// +// ============================================================================ + +#ifndef _CHANNEL_DATA_H +#define _CHANNEL_DATA_H + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <vector> +#include <string> + +/** +* ChannelData class description: +* This class handles a specific channel data. +*/ + +// ============================================================================ +// class: ChannelData +// ============================================================================ +class ChannelData +{ +public: + //- ctor --------------------------------- + ChannelData(std::string chName) : channel_name_(chName) + { + reset(chName); + } + + //- reset : initialize members + void reset(std::string channelName) + { + channel_name_ = channelName; + trigger_time_ = "NaN"; + wave_array_count_ = 0; + vertical_offset_ = 0.; + vertical_gain_ = 0.; + horizontal_offset_ = 0.; + horizontal_interval_= 0.; + nominal_bits_ = 0; + wave_array_1_ = 0; + wave_array_2_ = 0; + vertical_scaled_data_.clear(); + raw_waveform_data_.clear(); + } + + //- operator= + ChannelData& operator=(const ChannelData& src) + { + this->channel_name_ = src.channel_name_; + this->trigger_time_ = src.trigger_time_; + this->wave_array_count_ = src.wave_array_count_; + this->vertical_offset_ = src.vertical_offset_; + this->vertical_gain_ = src.vertical_gain_; + this->horizontal_offset_ = src.horizontal_offset_; + this->horizontal_interval_ = src.horizontal_interval_; + this->nominal_bits_ = src.nominal_bits_; + this->wave_array_1_ = src.wave_array_1_; + this->wave_array_2_ = src.wave_array_2_; + this->vertical_scaled_data_ = src.vertical_scaled_data_; + this->raw_waveform_data_ = src.raw_waveform_data_; + + return *this; + } + + std::string channel_name_; + + std::string trigger_time_; + + long wave_array_count_; + + double vertical_offset_; + double vertical_gain_; + + double horizontal_offset_; + double horizontal_interval_; + + short nominal_bits_; + long wave_array_1_; + long wave_array_2_; + + std::vector < double > vertical_scaled_data_; + std::vector < short > raw_waveform_data_; + +}; + +#endif //- _CHANNEL_DATA_H diff --git a/include/SocketLecroy.h b/include/SocketLecroy.h index 83342c758be6cefcc9b1b41ac6b77e8fade984cb..81f13c46fee4462d1f4689496976bd4d53effc40 100644 --- a/include/SocketLecroy.h +++ b/include/SocketLecroy.h @@ -27,7 +27,7 @@ #include <winsock2.h> #endif #include "SocketException.h" - +#include <yat/threading/Mutex.h> //////////////////////////////////////////////////////////////////// // // SocketLecroy :: DEFINITION @@ -49,11 +49,11 @@ const int SERVER_PORT = 1861; //- It's the same port number for all Lecroy sco const int EOI_FLAG = 0x01; const int SRQ_FLAG = 0x08; const int CLEAR_FLAG = 0x10; -const int LOCKOUT_FLAG= 0x20; +const int LOCKOUT_FLAG = 0x20; const int REMOTE_FLAG = 0x40; const int DATA_FLAG = 0x80; -const int TCP_MINIMUM_PACKET_SIZE = 64; +const unsigned int TCP_MINIMUM_PACKET_SIZE = 64; class SocketLecroy { @@ -62,18 +62,28 @@ private: SocketLecroy(); //- just one instance of SocketLecroy must be done for all waveforms of a same Lecroy device ~SocketLecroy(); + yat::Mutex lock_; + static SocketLecroy* SL_instance; //- ptr on the SocketLecroy instance + static bool sConnectedFlag; + public: static SocketLecroy* get_instance(void); - static void delete_instance(SocketLecroy*); + static void delete_instance(); + + bool is_connected() { + return sConnectedFlag; + } + + void write_read (char* in_buf, unsigned int in_length, char* out_buf, int* out_length, bool eoi_flag); - void TCP_WriteDevice (char *buf, int length,bool eoi_flag) throw (lecroy::SocketException); //- send a cmd to the device - void TCP_ReadDevice (char *buf, int length, int* nb_byte_received) throw (lecroy::SocketException); //- read the device replie - void TCP_Connect (char *ip_address) throw (lecroy::SocketException); //- build TCP/IP connection - void TCP_Disconnect (void) throw (lecroy::SocketException); //- disconnect the device - void TCP_ClearDevice (void) throw (lecroy::SocketException); //- disconnect and reconnect the device + void TCP_WriteDevice (char *buf, int length,bool eoi_flag) throw (lecroy::SocketException); //- send a cmd to the device + void TCP_ReadDevice (char *buf, unsigned int length, int* nb_byte_received) throw (lecroy::SocketException); //- read the device replie + void TCP_Connect (char *ip_address) throw (lecroy::SocketException); //- build TCP/IP connection + void TCP_Disconnect (void) throw (lecroy::SocketException); //- disconnect the device + void TCP_ClearDevice (void) throw (lecroy::SocketException); //- disconnect and reconnect the device }; diff --git a/include/Waveform.h b/include/Waveform.h index 428fb0b26dcfdff2aa7af0c7bf708af94f83ce3e..19afd7a8475c1eed5f9eca6a271f3124aedcb0db 100644 --- a/include/Waveform.h +++ b/include/Waveform.h @@ -21,6 +21,8 @@ #include <string> #include "WaveformException.h" +#include "ChannelData.hpp" +#include "SocketLecroy.h" const long MAX_WAVEFORM_DATA_LENGTH = 1500000; @@ -42,52 +44,52 @@ const long MAX_WAVEFORM_DATA_LENGTH = 1500000; //- Structure to store the acquired data typedef struct { - char descriptor_name [16]; //- descriptor name (always begin with WAVEDESC string) - char template_name [16]; - short comm_type; //- 0 = BYTE ; 1 = WORD format - short comm_order; //- 0 = HIFIRST ; 1 = LOFIRST + char descriptor_name [16]; //- descriptor name (always begin with WAVEDESC string) + char template_name [16]; + short comm_type; //- 0 = BYTE ; 1 = WORD format + short comm_order; //- 0 = HIFIRST ; 1 = LOFIRST //- Blocks : - long wave_descriptor; //- length (in bytes) of block WAVEDESC - long user_text; //- length (in bytes) of block USERTEXT - long reserved_res_desc1; //- RESERVED + long wave_descriptor; //- length (in bytes) of block WAVEDESC + long user_text; //- length (in bytes) of block USERTEXT + long reserved_res_desc1; //- RESERVED //- Arrays : - long trigtime_array; //- length (in bytes) of TRIGTIME - long ris_time_array; //- length (in bytes) of RIS_TIME - long res_array1; //- RESERVED - long wave_array_1; //- length (in bytes) of 1st simple data array - long wave_array_2; //- length (in bytes) of 2nd simple data array + long trigtime_array; //- length (in bytes) of TRIGTIME + long ris_time_array; //- length (in bytes) of RIS_TIME + long res_array1; //- RESERVED + long wave_array_1; //- length (in bytes) of 1st simple data array + long wave_array_2; //- length (in bytes) of 2nd simple data array //- Instrument identification : NOT USED - char reserved_1[48]; //- RESERVED + char reserved_1[48]; //- RESERVED //- Waveform description and time at which the waveform was generated - long wave_array_count; //- nb of data points in the data array - long points_per_screen; //- nominal number of data points on the screen - long res_first_pnt_val; //- RESERVED - long res_last_pnt_val; //- RESERVED - long first_point; //- indicates the offset relative to the beginning of the trace buffer - char reserved_2[20]; //- RESERVED - float vertical_gain; //- - float vertical_offset; //- to get floating value from raw data : V_gain * data - V_offset - char reserved_3[8]; //- RESERVED - short nominal_bits; //- intrinsic presision - char reserved_4[2]; //- RESERVED - float horizontal_interval; //- sampling interval for time domain waveforms - double horizontal_offset; //- trigger offset for the first sweep of the trigger, seconds between - //- the trigger and the first data point - double pixel_offset; //- needed to know how to display the waveform - char vertical_unit[48]; //- units of the vertical axis - char horizontal_unit[48]; //- units of the horizontal axis - float reserved_5; + long wave_array_count; //- nb of data points in the data array + long points_per_screen; //- nominal number of data points on the screen + long res_first_pnt_val; //- RESERVED + long res_last_pnt_val; //- RESERVED + long first_point; //- indicates the offset relative to the beginning of the trace buffer + char reserved_2[20]; //- RESERVED + float vertical_gain; //- + float vertical_offset; //- to get floating value from raw data : V_gain * data - V_offset + char reserved_3[8]; //- RESERVED + short nominal_bits; //- intrinsic presision + char reserved_4[2]; //- RESERVED + float horizontal_interval; //- sampling interval for time domain waveforms + double horizontal_offset; //- trigger offset for the first sweep of the trigger, seconds between + //- the trigger and the first data point + double pixel_offset; //- needed to know how to display the waveform + char vertical_unit[48]; //- units of the vertical axis + char horizontal_unit[48]; //- units of the horizontal axis + float reserved_5; //- Trigger infos - double trigger_time_seconds; //- time (in sec) of the trigger - char trigger_time_minutes; //- time (in min) of the trigger - char trigger_time_hours; //- time (in hours) of the trigger - char trigger_time_days; //- day of the trigger - char trigger_time_months; //- month of the trigger - short trigger_time_year; //- year of the trigger - short trigger_time_unused; //- RESERVED - float acq_duration; //- duration of the acquisition (in sec) in multi-trigger waveforms - char reserved_6[30]; //- RESERVED for the moment - //- TODO : timebase, ... till wavesource (from the lecroy doc). + double trigger_time_seconds; //- time (in sec) of the trigger + char trigger_time_minutes; //- time (in min) of the trigger + char trigger_time_hours; //- time (in hours) of the trigger + char trigger_time_days; //- day of the trigger + char trigger_time_months; //- month of the trigger + short trigger_time_year; //- year of the trigger + short trigger_time_unused; //- RESERVED + float acq_duration; //- duration of the acquisition (in sec) in multi-trigger waveforms + char reserved_6[30]; //- RESERVED for the moment + //- TODO : timebase, ... till wavesource (from the lecroy doc). } WAVEDESC_BLOCK; //- RESTORE DEFAULT ALIGNEMENT @@ -97,53 +99,29 @@ class WaveForm_data { private: - char ptrRawData[MAX_WAVEFORM_DATA_LENGTH]; //- ptr on the received waveform data + char ptrRawData[MAX_WAVEFORM_DATA_LENGTH]; //- ptr on the received waveform data - std::string channel_name; + SocketLecroy* ptr_com; - //- Waveform data : - short* sh_raw_waveform_data; - double* vertical_scaled_waveform_data; + //- Waveform description : + WAVEDESC_BLOCK *waveBlockData; //- ptr on the struct WAVEDESC_BLOCK - //- time of the trigger in format "Date = month, day, year ; Time = hours:minutes:seconds" - std::string trigger_time_value; + //- time info to acquire waveform data + std::string time_to_get_waveformData; - //- Waveform description : - WAVEDESC_BLOCK *waveBlockData; //- ptr on the struct WAVEDESC_BLOCK - - //- time info to acquire waveform data - std::string time_to_get_waveformData; + void get_waveform_data (ChannelData* channelData) + throw (lecroy::WaveformException); //- acquire the waveform data from the scope + void get_trigger_time_value (ChannelData* channelData); + public: - //- CTOR - WaveForm_data(std::string channel_name); - //- DTOR - ~WaveForm_data(); - - //- Getters & Setters - std::string get_channel_name () - throw (lecroy::WaveformException); - - void set_channel_name (std::string); - - WAVEDESC_BLOCK *get_wavedesc_descriptor () - throw (lecroy::WaveformException); - - void get_waveform_data () - throw (lecroy::WaveformException); //- acquire the waveform data from the scope - - short* get_raw_waveform_data () - throw (lecroy::WaveformException); //- return the ptr on sh_raw_waveform_data - - double* get_vertical_scaled_waveform_data () - throw (lecroy::WaveformException); - - std::string get_trigger_time_value (); + //- CTOR + WaveForm_data(char* lecroyIpAddress); + //- DTOR + ~WaveForm_data(); - std::string get_times_to_get_waveformData () { - return time_to_get_waveformData; - } + void update_channel_data(ChannelData*); }; diff --git a/include/WaveformMgr.hpp b/include/WaveformMgr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a6cd474de4d1853ed150f40f6d634cff5d49306e --- /dev/null +++ b/include/WaveformMgr.hpp @@ -0,0 +1,97 @@ +// ============================================================================ +// +// = CONTEXT +// WaveformMgr +// +// = File +// WaveformMgr.hpp +// +// = AUTHOR +// X. Elattaoui Synchrotron Soleil France +// +// ============================================================================ + +#ifndef _WAVEFORM_MGR_H +#define _WAVEFORM_MGR_H + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <tango.h> +#include <string> +#include "ChannelData.hpp" +#include "Waveform.h" +#include <yat4tango/DeviceTask.h> +#include "SocketException.h" + +/** +* WaveformMgr class description: +* This class updates channels data. +*/ + +// ============================================================================ +// class: WaveformMgr +// ============================================================================ +class WaveformMgr : public yat4tango::DeviceTask +{ +public: + //- ctor --------------------------------- + WaveformMgr(Tango::DeviceImpl * host_device, char* lecroyIPAddress); + + //- dtor --------------------------------- + ~WaveformMgr(); + + //- add a channel to gather data + void add_channel(std::string); + + //- getters ------------------------------ + ChannelData* get_channel_data(); + + //- Lecroy direct communication + std::string write_read(std::string); + + //- check socket is opened + bool is_connected() { + return connected_; + } + + std::string get_errors() { + yat::AutoMutex<> guard(this->error_mutex_); + return errors_; + } + +protected: + + //- process_message (implements yat4tango::DeviceTask pure virtual method) + virtual void process_message (yat::Message& msg) throw (Tango::DevFailed); + + //- internal mutex + yat::Mutex data_mutex_; + yat::Mutex error_mutex_; + +private: + + //- waveform data access + WaveForm_data* waveform_ptr_; + + //- channel name and its VALUEs + ChannelData* channel_data_; + + //- Lecroy Write Read response + std::string lecroy_resp_; + + //- Lecroy IP address to connect to + char* ipAddress_; + + //- lecroy socket connection + bool connected_; + + //- error handling + std::string errors_; + + //- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception + Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de); + +}; + +#endif //- _WAVEFORM_MGR_H diff --git a/pom.xml b/pom.xml index 8b5d98c0ecf09dbeeeb670a3bee47b7f69a85ece..b89ee7775b8b7564a7b1aa12f96ab508105ccdd4 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ <groupId>fr.soleil.device</groupId> <artifactId>AcquireWaveformLecroy-${aol}-${mode}</artifactId> - <version>1.1.20-SNAPSHOT</version> + <version>1.2.0</version> <packaging>nar</packaging> <name>AcquireWaveformLecroy</name> <description>AcquireWaveformLecroy device</description> diff --git a/src/AcquireWaveformLecroy.cpp b/src/AcquireWaveformLecroy.cpp index 53552c53732fe550bcc65344b8bf88fc3ecd7724..ae47d2f8e08bbc51a8ab51a7d29586d80b489071 100644 --- a/src/AcquireWaveformLecroy.cpp +++ b/src/AcquireWaveformLecroy.cpp @@ -98,16 +98,14 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio // //=================================================================== - #include <AcquireWaveformLecroy.h> #include <AcquireWaveformLecroyClass.h> #include <yat/time/Timer.h> -static const int MAX_RESPONSE_LENGTH = 150000; +static const std::size_t MAX_STRING_LENGTH = 1024; namespace AcquireWaveformLecroy_ns { - //+---------------------------------------------------------------------------- // // method : AcquireWaveformLecroy::AcquireWaveformLecroy(string &s) @@ -135,6 +133,7 @@ AcquireWaveformLecroy::AcquireWaveformLecroy(Tango::DeviceClass *cl,const char * { init_device(); } + //+---------------------------------------------------------------------------- // // method : AcquireWaveformLecroy::delete_device() @@ -145,14 +144,14 @@ AcquireWaveformLecroy::AcquireWaveformLecroy(Tango::DeviceClass *cl,const char * void AcquireWaveformLecroy::delete_device() { //- Delete device's allocated object - //if (attr_rawWaveformData_read) { - // delete [] attr_rawWaveformData_read; - // attr_rawWaveformData_read = 0; - //} - //if (attr_verticalScaledData_read) { - // delete [] attr_verticalScaledData_read; - // attr_verticalScaledData_read = 0; - //} + if (attr_rawWaveformData_read) { + delete [] attr_rawWaveformData_read; + attr_rawWaveformData_read = 0; + } + if (attr_verticalScaledData_read) { + delete [] attr_verticalScaledData_read; + attr_verticalScaledData_read = 0; + } if (attr_waveArray1_read) { delete attr_waveArray1_read; attr_waveArray1_read = 0; @@ -189,30 +188,25 @@ void AcquireWaveformLecroy::delete_device() delete attr_triggerTime_read; attr_triggerTime_read = 0; } - - //- close the socket - ptr_com->TCP_Disconnect(); - - //- delete the SocketLecroy obj - SocketLecroy::delete_instance(ptr_com); - + //- delete the Waveform_Data obj - if(waveform_ptr) + if (waveform_mgr_) { - delete waveform_ptr; - waveform_ptr = 0; + //- ask the task to quit + this->waveform_mgr_->exit(); + //- !!!!! NEVER TRY TO <delete> a yat4tango::DeviceTask, it commits suicide + //- upon return of its main function (i.e. entry point)!!!!!! + this->waveform_mgr_ = 0; } - if(_deviceResponse) - { - delete [] _deviceResponse; - _deviceResponse = 0; - } - - DEBUG_STREAM << "Remove the InnerAppender." << endl; - yat4tango::InnerAppender::release(this); - - DEBUG_STREAM << "Remove the YatLogAdapter." << endl; - yat4tango::YatLogAdapter::release(); + +/*std::cout << "removing log" << std::endl; + // DEBUG_STREAM << "Remove the InnerAppender." << endl; + yat4tango::InnerAppender::release(this); + + // DEBUG_STREAM << "Remove the YatLogAdapter." << endl; + yat4tango::YatLogAdapter::release(); + +std::cout << "removed log : " << log_deleted << std::endl;*/ } //+---------------------------------------------------------------------------- @@ -228,14 +222,9 @@ void AcquireWaveformLecroy::init_device() //- create read attributes //-------------------------------------------- + attr_rawWaveformData_read = new short[MAX_WAVEFORM_DATA_LENGTH]; - //- The memory allocation is done in read_attr_hardware( ) method, - //- because the length of the received data block is not known here - attr_rawWaveformData_read = 0; - - //- The memory allocation is done in read_attr_hardware( ) method, - //- because the length of the received data block is not known here - attr_verticalScaledData_read = 0; + attr_verticalScaledData_read = new double[MAX_WAVEFORM_DATA_LENGTH]; attr_waveArray1_read = new Tango::DevLong; *attr_waveArray1_read = 0; @@ -265,59 +254,59 @@ void AcquireWaveformLecroy::init_device() *attr_triggerTime_read = new char[MAX_STRING_LENGTH]; ::memset(*attr_triggerTime_read, 0, MAX_STRING_LENGTH * sizeof(char)); - _deviceResponse = new char[MAX_RESPONSE_LENGTH]; - //- Initialise variables to default values //-------------------------------------------- - ptr_com = 0; - waveform_ptr= 0; - _deviceResponse = new char[MAX_RESPONSE_LENGTH]; - data_value = 0; - data_length = 0; - _is_communication_opened = false; + waveform_mgr_ = 0; + channel_data_ = 0; + data_length_ = 0; get_device_property(); - //--------------------------------------------------------- + //--------------------------------------------------------- //- instanciate the log_adapter & inner_appender in order to manage logs //--------------------------------------------------------- - try +// try +// { +// DEBUG_STREAM << "Create the YatLogAdapter in order to use logs from third party library." << endl; +// yat4tango::YatLogAdapter::initialize(this); +// +// DEBUG_STREAM << "Create the InnerAppender in order to manage logs." << endl; +// yat4tango::InnerAppender::initialize(this, 512); +// } +// catch (Tango::DevFailed& df) +// { +// ERROR_STREAM << df << endl; +// set_state(Tango::FAULT); +// set_status("OUT OF MEMORY : Failed to create log manager !"); +// return; +// } + + char * ipAdd = 0; + if (!waveform_mgr_) { - DEBUG_STREAM << "Create the YatLogAdapter in order to use logs from third party library." << endl; - yat4tango::YatLogAdapter::initialize(this); - - DEBUG_STREAM << "Create the InnerAppender in order to manage logs." << endl; - yat4tango::InnerAppender::initialize(this, 512); + //- transform string to char* + std::size_t length = iPaddress.size(); + ipAdd = new char[length+1]; + for(std::size_t i=0; i<length; i++) + ipAdd[i] = iPaddress[i]; + ipAdd[length] = '\0'; + //- create the waveform obj + waveform_mgr_ = new WaveformMgr(this, ipAdd); } - catch (Tango::DevFailed& df) + //- prepare task + if ( waveform_mgr_ ) { - ERROR_STREAM << df << endl; - set_state(Tango::FAULT); - set_status("OUT OF MEMORY : Failed to create log manager !"); - return; + //- add channel to monitor + waveform_mgr_->add_channel(channelName); + //- start thread (if not already started) + if ( !waveform_mgr_->periodic_msg_enabled() ) + waveform_mgr_->go(); } - - //- create the com obj - ptr_com = SocketLecroy::get_instance(); - - if ( !ptr_com ) - { - set_state(Tango::FAULT); - set_status("OUT OF MEMORY : communication link cannot be created !"); - return; - } - - //- create the waveform obj - waveform_ptr = new WaveForm_data(channelName); - if ( !waveform_ptr ) - { - set_state(Tango::FAULT); - set_status("OUT OF MEMORY : objects cannot be created !"); - } - else + //- release temporary allocation + if (ipAdd) { - set_state(Tango::ALARM); - set_status("Communication is not yet opened."); + delete [] ipAdd; + ipAdd = 0; } } @@ -403,31 +392,7 @@ void AcquireWaveformLecroy::get_device_property() //----------------------------------------------------------------------------- void AcquireWaveformLecroy::always_executed_hook() { - //- init communication - if ( !_is_communication_opened && ptr_com ) - { - try - { - ptr_com->TCP_Connect( (char*)iPaddress.c_str() ); - _is_communication_opened = true; - set_state(Tango::OPEN); - set_status("The communication is OK."); - } - catch(const lecroy::SocketException & se) - { - _is_communication_opened = false; - set_state(Tango::FAULT); - set_status("The communication is not well opened."); - Tango::DevFailed df = lecroy_to_tango_exception(se); - FATAL_STREAM << df << std::endl; - Tango::Except::re_throw_exception(df, - "TCP_CONNECTION_FAILED", - "Cannot built a socket connection.", - "AcquireWaveformLecroy::init_device()", - Tango::PANIC - ); - } - } + } //+---------------------------------------------------------------------------- @@ -442,56 +407,51 @@ void AcquireWaveformLecroy::read_attr_hardware(vector<long> &attr_list) //- DEBUG_STREAM << "In read_attr_hardware for " << attr_list.size(); //- DEBUG_STREAM << " attribute(s)" << endl; yat::Timer t; - DEBUG_STREAM << "\nREAD attr HW ENTERING ..." << std::endl; - //- Get the waveform data and description( ADC resolution, horizontal and vertical infos, data length ...) + //- check + if ( !waveform_mgr_ ) + { + FATAL_STREAM << "read_attr_hardware : device initialization failed!" << std::endl; + Tango::Except::throw_exception("COMMUNICATION_BROKEN", + "Device initialization failed : no Waveform manager.", + "AcquireWaveformLecroy::read_attr_hardware()" + ); + } + //- get waveform data try { - // First do a real read on the hardware - // - waveform_ptr->get_waveform_data(); - set_state(Tango::ON); - set_status("Waveform data acquired."); - INFO_STREAM << "\nTimes infos to get waveform data :\n" << waveform_ptr->get_times_to_get_waveformData() << std::endl; + channel_data_ = waveform_mgr_->get_channel_data(); + if (channel_data_) + { + data_length_ = channel_data_->wave_array_count_; + } } - catch(const lecroy::WaveformException &we) + catch(const lecroy::WaveformException& we) { - set_state(Tango::ALARM); - set_status("Failed to acquire waveform."); + FATAL_STREAM << "R ATTR HW -> caught Lecroy exception!" << std::endl; Tango::DevFailed df = lecroy_to_tango_exception(we); FATAL_STREAM << df << std::endl; Tango::Except::re_throw_exception(df, - "COMMUNICATION_BROKEN", - "Cannot call get_waveform_data.", - "AcquireWaveformLecroy::always_executed_hook()", + "COMMUNICATION_BROKEN", + "Cannot call get_waveform_data.", + "AcquireWaveformLecroy::read_attr_hardware()", Tango::ERR - ); - } - - //- get the waveform length - try - { - //- TODO : retirer les copies dans les attr !!!! - data_length = waveform_ptr->get_wavedesc_descriptor()->wave_array_count; - //- check data does not exceed the MAX defined : - if ( data_length > MAX_WAVEFORM_DATA_LENGTH ) - data_length = MAX_WAVEFORM_DATA_LENGTH; - //- get waveform data - attr_rawWaveformData_read = waveform_ptr->get_raw_waveform_data(); - attr_verticalScaledData_read = waveform_ptr->get_vertical_scaled_waveform_data(); + ); } - catch(const lecroy::WaveformException &we) + catch(Tango::DevFailed& df) { - set_state(Tango::ALARM); - set_status("Cannot acquire the waveform data."); - Tango::DevFailed df = lecroy_to_tango_exception(we); - + FATAL_STREAM << "R ATTR HW -> caught DevFailed exception :\n" << df << std::endl; Tango::Except::re_throw_exception(df, - "GET_FAILED", - "Cannot acquire the total length of the waveform data.", - "AcquireWaveformLecroy::read_attr_hardware()", + "COMMUNICATION_BROKEN", + "Failed to update channel data.", + "AcquireWaveformLecroy::read_attr_hardware()", Tango::ERR - ); + ); + } + catch(...) + { + FATAL_STREAM << "R ATTR HW -> caught [...] exception!" << std::endl; + throw; } INFO_STREAM << "READ_HW : all data are now updated. DONE in " << t.elapsed_msec() << " milliseconds.\n" << std::endl; @@ -509,11 +469,13 @@ void AcquireWaveformLecroy::read_verticalScaledData(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_verticalScaledData(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; - // Add your own code here - attr_verticalScaledData_read = waveform_ptr->get_vertical_scaled_waveform_data(); +// for(std::size_t idx = 0; idx < data_length_; idx++) +// attr_verticalScaledData_read[idx] = channel_data_->vertical_scaled_data_[idx]; +// attr.set_value(attr_verticalScaledData_read, data_length_); - attr.set_value(attr_verticalScaledData_read, data_length); - INFO_STREAM << "read_verticalScaledData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; + if ( data_length_ ) + attr.set_value(&channel_data_->vertical_scaled_data_[0], data_length_); + DEBUG_STREAM << "read_verticalScaledData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } //+---------------------------------------------------------------------------- @@ -529,7 +491,7 @@ void AcquireWaveformLecroy::read_triggerTime(Tango::Attribute &attr) yat::Timer t; // Add your own code here - std::string response = waveform_ptr->get_trigger_time_value(); + std::string response = channel_data_->trigger_time_; strcpy(*attr_triggerTime_read, response.c_str()); attr.set_value(attr_triggerTime_read); @@ -549,7 +511,7 @@ void AcquireWaveformLecroy::read_verticalOffset(Tango::Attribute &attr) yat::Timer t; //- Add your own code here - *attr_verticalOffset_read = waveform_ptr->get_wavedesc_descriptor()->vertical_offset; + *attr_verticalOffset_read = channel_data_->vertical_offset_; attr.set_value(attr_verticalOffset_read); DEBUG_STREAM << "read_verticalOffset : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; @@ -568,7 +530,7 @@ void AcquireWaveformLecroy::read_verticalGain(Tango::Attribute &attr) yat::Timer t; //- Add your own code here - *attr_verticalGain_read = (double) (waveform_ptr->get_wavedesc_descriptor()->vertical_gain); + *attr_verticalGain_read = channel_data_->vertical_gain_; attr.set_value(attr_verticalGain_read); DEBUG_STREAM << "read_verticalGain : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; @@ -586,8 +548,9 @@ void AcquireWaveformLecroy::read_horizontalOffset(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_horizontalOffset(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; - //- Add your own code here - *attr_horizontalOffset_read = waveform_ptr->get_wavedesc_descriptor()->horizontal_offset; + //- Add your own code here + *attr_horizontalOffset_read = channel_data_->horizontal_offset_; + attr.set_value(attr_horizontalOffset_read); DEBUG_STREAM << "read_horizontalOffset : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -604,8 +567,9 @@ void AcquireWaveformLecroy::read_horizontalInterval(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_horizontalInterval(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; - //- Add your own code here - *attr_horizontalInterval_read = (double) (waveform_ptr->get_wavedesc_descriptor()->horizontal_interval); + //- Add your own code here + *attr_horizontalInterval_read = channel_data_->horizontal_interval_; + attr.set_value(attr_horizontalInterval_read); DEBUG_STREAM << "read_horizontalInterval : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -622,7 +586,8 @@ void AcquireWaveformLecroy::read_nominalBits(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_nominalBits(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; //- Add your own code here - *attr_nominalBits_read = waveform_ptr->get_wavedesc_descriptor()->nominal_bits; + *attr_nominalBits_read = channel_data_->nominal_bits_; + attr.set_value(attr_nominalBits_read); DEBUG_STREAM << "read_nominalBits : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -639,7 +604,8 @@ void AcquireWaveformLecroy::read_waveArrayCount(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArrayCount(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; //- Add your own code here - *attr_waveArrayCount_read = data_length; + *attr_waveArrayCount_read = data_length_; + attr.set_value(attr_waveArrayCount_read); DEBUG_STREAM << "read_waveArrayCount : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -656,7 +622,8 @@ void AcquireWaveformLecroy::read_waveArray2(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArray2(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; // Add your own code here - *attr_waveArray2_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_2; + *attr_waveArray2_read = channel_data_->wave_array_2_; + attr.set_value(attr_waveArray2_read); DEBUG_STREAM << "read_waveArray2 : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -673,7 +640,8 @@ void AcquireWaveformLecroy::read_waveArray1(Tango::Attribute &attr) //- DEBUG_STREAM << "AcquireWaveformLecroy::read_waveArray1(Tango::Attribute &attr) entering... "<< endl; yat::Timer t; //- Add your own code here - *attr_waveArray1_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_1; + *attr_waveArray1_read = channel_data_->wave_array_1_; + attr.set_value(attr_waveArray1_read); DEBUG_STREAM << "read_waveArray1 : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } @@ -691,9 +659,13 @@ void AcquireWaveformLecroy::read_rawWaveformData(Tango::Attribute &attr) //- Add your own code here yat::Timer t; //- get waveform data - attr_rawWaveformData_read = waveform_ptr->get_raw_waveform_data(); - attr.set_value(attr_rawWaveformData_read, data_length); - INFO_STREAM << "read_rawWaveformData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; + //-for(std::size_t idx = 0; idx < data_length_; idx++) + //- attr_rawWaveformData_read[idx] = channel_data_->raw_waveform_data_[idx]; + //-attr.set_value(attr_rawWaveformData_read, data_length_); + + if ( data_length_ ) + attr.set_value(&channel_data_->raw_waveform_data_[0], data_length_); + DEBUG_STREAM << "read_rawWaveformData : " << t.elapsed_msec() << " milliseconds.\n" << std::endl; } //+---------------------------------------------------------------------------- @@ -753,27 +725,82 @@ Tango::DevString AcquireWaveformLecroy::write_read(Tango::DevString argin) // (chapter : Writing a TANGO DS / Exchanging data) //------------------------------------------------------------ //- DEBUG_STREAM << "AcquireWaveformLecroy::write_read(): entering... !" << endl; - - // Add your own code to control device here - std::string cmd_to_send(argin); - int bytes_received = -1; - - ptr_com->TCP_WriteDevice(argin, cmd_to_send.size(), true); - - //- check if a response is expected (must found ? character) - strcpy(_deviceResponse, "No response"); - if( cmd_to_send.find('?') != std::string::npos ) - { -#ifdef WIN32 - Sleep(100); //- milliseconds -#else - usleep(100000); -#endif - ptr_com->TCP_ReadDevice(_deviceResponse, MAX_RESPONSE_LENGTH, &bytes_received); - } - - return _deviceResponse; +yat::Timer t; + Tango::DevString argout; + + std::string resp = waveform_mgr_->write_read(argin); + + std::size_t length = resp.size(); + + if ( length > MAX_STRING_LENGTH ) + length = MAX_STRING_LENGTH; + + argout = new char[length+1]; + ::strcpy(argout, resp.c_str()); + + INFO_STREAM << "WRITE_READ DONE in " << t.elapsed_msec() << " milliseconds.\n" << std::endl; + + return argout; } +//+------------------------------------------------------------------ +/** + * method: AcquireWaveformLecroy::dev_state + * + * description: method to execute "State" + * This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller. + * + * @return State Code + * + */ +//+------------------------------------------------------------------ +Tango::DevState AcquireWaveformLecroy::dev_state() +{ + Tango::DevState argout = Tango::UNKNOWN; + DEBUG_STREAM << "AcquireWaveformLecroy::dev_state(): entering... !" << endl; + + // Add your own code to control device here + if ( !waveform_mgr_ ) + { + argout = Tango::FAULT; + set_status("Initialization failed : no manager to gather channel data."); + } + + if ( !waveform_mgr_->periodic_msg_enabled() ) + { + argout = Tango::ALARM; + set_status("Task is not started : cannot gather channel data."); + } + + if ( !waveform_mgr_->is_connected() ) + { + argout = Tango::ALARM; + set_status("No socket connection with Lecroy."); + } + + if ( !data_length_ ) + { + argout = Tango::ALARM; + set_status("Failed to gather channel data : no data."); + } + + if ( argout != Tango::FAULT && argout != Tango::ALARM ) + { + errors_ = waveform_mgr_->get_errors(); + if ( errors_.empty() ) + { + argout = Tango::ON; + set_status("No error(s)."); + } + else + { + argout = Tango::ALARM; + set_status(errors_.c_str()); + } + } + + set_state(argout); + return argout; +} } // namespace diff --git a/src/AcquireWaveformLecroy.h b/src/AcquireWaveformLecroy.h index 3ee8b1adf21a9d38fc71bebab7b25e93e5b2ee1a..b21b4643665f8e98ce8dc6daf90e3f21c275ec19 100644 --- a/src/AcquireWaveformLecroy.h +++ b/src/AcquireWaveformLecroy.h @@ -63,13 +63,12 @@ #define _ACQUIREWAVEFORMLECROY_H #include <tango.h> -#include <yat4tango/InnerAppender.h> -#include <yat4tango/YatLogAdapter.h> +// #include <yat4tango/InnerAppender.h> +// #include <yat4tango/YatLogAdapter.h> //using namespace Tango; -#include "SocketLecroy.h" #include "SocketException.h" -#include "Waveform.h" -#include "WaveformException.h" +#include "WaveformMgr.hpp" +#include "ChannelData.hpp" /** * @author $Author: xavela $ @@ -78,8 +77,6 @@ // Add your own constants definitions here. //----------------------------------------------- -const int MAX_STRING_LENGTH = 256; -const int MAX_SIZE = 150000; namespace AcquireWaveformLecroy_ns @@ -129,12 +126,12 @@ public : Tango::DevDouble *attr_verticalGain_read; Tango::DevDouble *attr_horizontalOffset_read; Tango::DevDouble *attr_horizontalInterval_read; - Tango::DevShort *attr_nominalBits_read; - Tango::DevLong *attr_waveArrayCount_read; - Tango::DevLong *attr_waveArray2_read; - Tango::DevLong *attr_waveArray1_read; + Tango::DevShort *attr_nominalBits_read; + Tango::DevLong *attr_waveArrayCount_read; + Tango::DevLong *attr_waveArray2_read; + Tango::DevLong *attr_waveArray1_read; Tango::DevDouble *attr_verticalScaledData_read; - Tango::DevShort *attr_rawWaveformData_read; + Tango::DevShort *attr_rawWaveformData_read; //@} /** @@ -192,7 +189,7 @@ public : /** * The object desctructor. */ - ~AcquireWaveformLecroy() {delete_device();}; + ~AcquireWaveformLecroy() {delete_device();} /** * will be called at device destruction or at init command. */ @@ -314,6 +311,12 @@ public : * Execution allowed for WriteRead command. */ virtual bool is_WriteRead_allowed(const CORBA::Any &any); +/** + * This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller. + * @return State Code + * @exception DevFailed + */ + virtual Tango::DevState dev_state(); /** * Command to send a specific command to the Lecroy device * @param argin command to send @@ -331,22 +334,18 @@ public : // Here is the end of the automatic code generation part //------------------------------------------------------------- - - protected : // Add your own data members here //----------------------------------------- - SocketLecroy* ptr_com; - WaveForm_data* waveform_ptr; - char* _deviceResponse; - short* data_value; - long data_length; - bool _is_communication_opened; + WaveformMgr* waveform_mgr_; + ChannelData* channel_data_; - //- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception - Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de); + std::size_t data_length_; + + std::string errors_; - void reallocate_spectrums(long new_data_size); + //- Method to convert all lecroy exceptions (type Waveform or Socket exceptions) on Tango exception + Tango::DevFailed lecroy_to_tango_exception(const lecroy::LecroyException& de); }; } // namespace_ns diff --git a/src/AcquireWaveformLecroyClass.cpp b/src/AcquireWaveformLecroyClass.cpp index 87ff1f764bf959a5e901a0f4e6d8ca665e5a7358..a6daa571120cebc622452267e2f7875a2121dedb 100644 --- a/src/AcquireWaveformLecroyClass.cpp +++ b/src/AcquireWaveformLecroyClass.cpp @@ -68,9 +68,9 @@ static const char *RCSfile = "$RCSfile: AcquireWaveformLecroyClass.cpp,v $"; //============================================================================= -#include <tango.h> +// #include <tango.h> -#include <AcquireWaveformLecroy.h> +// #include <AcquireWaveformLecroy.h> #include <AcquireWaveformLecroyClass.h> diff --git a/src/AcquireWaveformLecroyClass.h b/src/AcquireWaveformLecroyClass.h index 11b483e5364eaee0de03034b65f167c61901dbb4..885e72c7548a2efdb1ca6d921f26eaf89ff1c764 100644 --- a/src/AcquireWaveformLecroyClass.h +++ b/src/AcquireWaveformLecroyClass.h @@ -56,7 +56,7 @@ #ifndef _ACQUIREWAVEFORMLECROYCLASS_H #define _ACQUIREWAVEFORMLECROYCLASS_H -#include <tango.h> +// #include <tango.h> #include <AcquireWaveformLecroy.h> diff --git a/src/AcquireWaveformLecroyStateMachine.cpp b/src/AcquireWaveformLecroyStateMachine.cpp index 0920a582c36fcb8a25caf0871afda55ad884e0fd..9dcf749929ff4c9cfd892dd7de6d00da7981a3f0 100644 --- a/src/AcquireWaveformLecroyStateMachine.cpp +++ b/src/AcquireWaveformLecroyStateMachine.cpp @@ -37,8 +37,8 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio // (c) - Software Engineering Group - ESRF //============================================================================= -#include <tango.h> -#include <AcquireWaveformLecroy.h> +// #include <tango.h> +// #include <AcquireWaveformLecroy.h> #include <AcquireWaveformLecroyClass.h> /*==================================================================== diff --git a/src/ClassFactory.cpp b/src/ClassFactory.cpp index 7536c6935960814dd2ba9baa8dc18177611592d7..a12c481f4b932c86a11eb8b0a2185161d1cc2836 100644 --- a/src/ClassFactory.cpp +++ b/src/ClassFactory.cpp @@ -54,7 +54,7 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio //============================================================================= -#include <tango.h> +// #include <tango.h> #include <AcquireWaveformLecroyClass.h> /** diff --git a/src/LinuxSocketLecroy.cpp b/src/LinuxSocketLecroy.cpp index 2a6e05cb6cabce7b4905e41d56b52e38cfac2c2e..8e948e865917a22a315acd336bdb2ebac8c52a49 100644 --- a/src/LinuxSocketLecroy.cpp +++ b/src/LinuxSocketLecroy.cpp @@ -40,11 +40,13 @@ #include <unistd.h> #include <fcntl.h> #include <cstdio> +//- perf!!! +#include <yat/time/Timer.h> static int hSocket; -static int sTimeout = 1; //- second(s) +static int sTimeout = 2; //- second(s) static char sCurrentAddress[256]; -static int sConnectedFlag = false; +bool SocketLecroy::sConnectedFlag = false; const int CMD_BUF_LEN = 8192; static char sCommandBuffer[CMD_BUF_LEN]; @@ -61,14 +63,15 @@ SocketLecroy* SocketLecroy::get_instance() } -void SocketLecroy::delete_instance(SocketLecroy* SL_instance) +void SocketLecroy::delete_instance() { +// std::cout << "\t\t\tSocketLecroy::deleted_instance ... SL_instance = " << SL_instance << std::endl; if(SL_instance) { - delete SL_instance ; + delete SL_instance; SL_instance = 0; } - +// std::cout << "\t\t\tSocketLecroy::deleted_instance DONE -> SL_instance = " << SL_instance << std::endl; } //- CTOR @@ -76,16 +79,19 @@ SocketLecroy::SocketLecroy() { sConnectedFlag=false; } + //- DTOR SocketLecroy::~SocketLecroy() { +// std::cout << "\t\t\tSocketLecroy::DTOR SocketLecroy ..." << std::endl; TCP_Disconnect(); - +// std::cout << "\t\t\tSocketLecroy::DTOR DONE." << std::endl; } //- Build the connection void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) { +yat::Timer t; struct sockaddr_in serverAddr; int result; const int resp = 1; @@ -101,14 +107,14 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) return; strcpy(sCurrentAddress, ip_address); - tval.tv_sec = sTimeout; + tval.tv_sec = 1; tval.tv_usec = 0; //- build server socket address serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVER_PORT); - if ((serverAddr.sin_addr.s_addr = inet_addr(ip_address)) == -1) + if ((serverAddr.sin_addr.s_addr = inet_addr(ip_address)) == INADDR_NONE) { throw lecroy::SocketException("COMMUNICATION_BROKEN ", "Bad server address.", @@ -122,6 +128,14 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) "Unable to create client's socket.", "SocketLecroy::TCP_Connect( )."); } + + //- set Timeout for read operations + if (setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tval, sizeof(struct timeval)) != 0) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to set socket option to TCP_NODELAY.", + "SocketLecroy::TCP_Connect( )."); + } if (setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&resp, sizeof(resp)) != 0) { @@ -158,7 +172,7 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) if(errno == EALREADY) // This is the right error ! { time_to_sleep.tv_sec = 0; - time_to_sleep.tv_nsec = 15000000L; + time_to_sleep.tv_nsec = 150000000L; nanosleep(&time_to_sleep, &time_remaining); // Sleep for 150 ms } }// Connection is OK. @@ -168,9 +182,8 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) }// TODO : throw ; // Not the right error, so failure ! }// Connected at first attempt ! - result = select(hSocket, NULL, &wr_set, NULL, &tval); - argp = 0;//-blocking mode + argp = 0; //-blocking mode ioctl(hSocket, FIONBIO, &argp); //- connect to server (scope) if (result < 0) @@ -182,16 +195,21 @@ void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::SocketException) } sConnectedFlag = true; +// std::cout << "\t\t\t SocketLecroy::TCP_Connect done in " << t.elapsed_msec() << " ms" << std::endl; } //- DisconnectFromScope: disconnect from a network device void SocketLecroy::TCP_Disconnect(void) throw (lecroy::SocketException) { +// std::cout << "\t\t\tSocketLecroy::comm closing socket ENTREING ...." << std::endl; if (sConnectedFlag) { +// std::cout << "\t\t\tSocketLecroy::comm closing socket ...." << std::endl; close(hSocket); +// std::cout << "\t\t\tSocketLecroy::comm closed." << std::endl; sConnectedFlag = false; } +// std::cout << "\t\t\tSocketLecroy::comm closing socket DONE ...." << std::endl; } //- Clear a connection @@ -206,13 +224,23 @@ void SocketLecroy::TCP_ClearDevice(void) throw (lecroy::SocketException) TCP_Connect(sCurrentAddress); } +void SocketLecroy::write_read(char* in_buf, unsigned int in_length, char* out_buf, int* out_length, bool eoi_flag) +{ +yat::Timer t; + yat::AutoMutex<> guard(lock_); + TCP_WriteDevice(in_buf, in_length, eoi_flag); +// std::cout << "\t\t\t SocketLecroy::write_read WRITE done in " << t.elapsed_msec() << " ms" << std::endl; + TCP_ReadDevice(out_buf, *out_length, out_length); +// std::cout << "\t\t\t SocketLecroy::write_read done in " << t.elapsed_msec() << " ms" << std::endl; +} + //- Send commands to the remote device void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lecroy::SocketException) { TCP_HEADER header; int result, bytes_more, bytes_xferd; char *idxPtr; - +// std::cout << "\t\t\t TCP_WriteDevice -> ENTERING ..." << std::endl; //- test connection if ( !sConnectedFlag ) throw lecroy::SocketException("COMMUNICATION_BROKEN ", @@ -230,6 +258,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec header.reserved[2] = 0; header.iLength = htonl(len); +// std::cout << "\t\t\t TCP_WriteDevice -> send ..." << std::endl; //- write the header first if (send(hSocket, (char *) &header, sizeof(TCP_HEADER), 0) != sizeof(TCP_HEADER)) { @@ -238,6 +267,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec "SocketLecroy::TCP_WriteDevice( )."); } +// std::cout << "\t\t\t TCP_WriteDevice -> sent!" << std::endl; bytes_more = len; idxPtr = buf; bytes_xferd = 0; @@ -248,6 +278,7 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec if ((result = send(hSocket, (char *) idxPtr, bytes_more, 0)) < 0) { +// std::cout << "\t\t\tFATAL TCP_WriteDevice -> send ..." << std::endl; throw lecroy::SocketException("COMMUNICATION_BROKEN ", "Unable to send data to the server.", "SocketLecroy::TCP_WriteDevice( )."); @@ -258,10 +289,11 @@ void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lec if (bytes_more <= 0) break; } +// std::cout << "\t\t\tFATAL TCP_WriteDevice -> DONE." << std::endl; } //- Read the device answer -void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (lecroy::SocketException) +void SocketLecroy::TCP_ReadDevice(char *buf, unsigned int len, int *recv_count) throw (lecroy::SocketException) { TCP_HEADER header; int result; @@ -286,8 +318,8 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le "SocketLecroy::TCP_ReadDevice( )."); FD_SET(hSocket, &rd_set); - tval.tv_sec = sTimeout; - tval.tv_usec = 0; + tval.tv_sec = 0; + tval.tv_usec = 500000L; memset(buf, 0, len); buf_count = 0; @@ -298,18 +330,20 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le result = select(hSocket, &rd_set, NULL, NULL, &tval); if (result < 0) { +// std::cout << "\tSocketLecroy::TCP_ReadDevice -> result < 0." << std::endl; TCP_ClearDevice(); throw lecroy::SocketException("COMMUNICATION_BROKEN ", "Read Timeout.", "SocketLecroy::TCP_ReadDevice( )."); } - //- get the header info first + + //- get the header info first accum = 0; while (1) { memset(&header, 0, sizeof(TCP_HEADER)); - if ((result = recv(hSocket, (char *) &header + accum, sizeof(header) - accum, 0)) < 0) + if ((result = recv(hSocket, (char *) &header + accum, sizeof(header) - accum, 0)) <= 0) { TCP_ClearDevice(); throw lecroy::SocketException("COMMUNICATION_BROKEN ", @@ -322,15 +356,16 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le break; } - header.iLength = ntohl(header.iLength); +// header.iLength = ntohl(header.iLength); + unsigned int headerLength = ntohl(header.iLength); //- only read to len amount - if (header.iLength > space_left) + if (headerLength > space_left) { - header.iLength = space_left; - throw lecroy::SocketException("COMMUNICATION_BROKEN ", + headerLength = space_left; +/* throw lecroy::SocketException("COMMUNICATION_BROKEN ", "Read buffer size is too small.", - "SocketLecroy::TCP_ReadDevice( )."); + "SocketLecroy::TCP_ReadDevice( ).");*/ } //- read the rest of the block @@ -338,7 +373,7 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le while (1) { idxPtr = buf + (buf_count + accum); - bytes_more = header.iLength - accum; + bytes_more = headerLength - accum; if ((space_left-accum) < TCP_MINIMUM_PACKET_SIZE) { TCP_ClearDevice(); @@ -358,7 +393,7 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le } accum += result; - if (accum >= header.iLength) + if (accum >= headerLength) break; if ((accum + buf_count) >= len) break; @@ -374,4 +409,3 @@ void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (le *recv_count = buf_count; } - diff --git a/src/Waveform.cpp b/src/Waveform.cpp index 366242cca92b8bf9dee8de311576767c7173e4a4..660601748a9a9f66cc3698b083d7043cd2929c48 100644 --- a/src/Waveform.cpp +++ b/src/Waveform.cpp @@ -21,261 +21,176 @@ #include <Xstring.h> #include <string.h> #include "Waveform.h" -#include "SocketLecroy.h" #include <yat/time/Timer.h> //- CTOR -WaveForm_data::WaveForm_data(std::string ch_name) +WaveForm_data::WaveForm_data(char* lecroyIPAdd) +: ptr_com(0), + time_to_get_waveformData("") { - //- initialisation of all Waveform attributes - ::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH); - channel_name = ch_name; - sh_raw_waveform_data = 0; - vertical_scaled_waveform_data = 0; - trigger_time_value = "Not available"; - waveBlockData = 0; + //- initialisation of all Waveform attributes + ::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH); + //- struct which contains all Lecroy data + waveBlockData = 0; + //- communcation link + ptr_com = SocketLecroy::get_instance(); + //- connect to Lecroy + ptr_com->TCP_Connect(lecroyIPAdd); } + //- DTOR WaveForm_data::~WaveForm_data() { - if(sh_raw_waveform_data) - { - delete [] sh_raw_waveform_data; - sh_raw_waveform_data = 0; - } - if(vertical_scaled_waveform_data) - { - delete [] vertical_scaled_waveform_data; - vertical_scaled_waveform_data = 0; - } - -} - -//- Method to return the channel name -std::string WaveForm_data::get_channel_name( ) throw (lecroy::WaveformException) -{ - if( channel_name.empty() ) - throw lecroy::WaveformException("DATA_OUT_OF_RANGE ", - "get_channel_name( ) failed : channel_name is not initialized.", - "WaveForm_data::get_channel_name( )."); - - return channel_name; +// std::cout << "\t\tWaveForm_data::DTOR." << std::endl; + //- close the socket +// ptr_com->TCP_Disconnect(); +// std::cout << "\t\tWaveForm_data::TCP_Disconnect DNE." << std::endl; + //- delete the SocketLecroy obj + if ( ptr_com ) + SocketLecroy::delete_instance(); +// std::cout << "\t\tWaveForm_data::delete_instance DNE." << std::endl; +// std::cout << "\t\tWaveForm_data::ptrRawData DNE => ptr_com add = " << ptr_com << std::endl; } -//- Method to set the channel name -void WaveForm_data::set_channel_name (std::string name) +void WaveForm_data::update_channel_data(ChannelData* chdata) { - if( !name.empty() ) - channel_name = name; -} - -//- Method to return the ptr on the WAVEDESC struct -WAVEDESC_BLOCK* WaveForm_data::get_wavedesc_descriptor( ) throw (lecroy::WaveformException) -{ - if(!waveBlockData) - throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", - "get_waveform_data( ) method must be called before.", - "WaveForm_data::get_wavedesc_descriptor( )."); - - return waveBlockData; +// yat::Timer t; + get_waveform_data(chdata); + get_trigger_time_value(chdata); +// std::cout << "\t\tWaveForm_data::update_channel_data -> DONE in " << t.elapsed_msec() << " ms." << std::endl; } //- Method to return the raw data of the acquired waveform -void WaveForm_data::get_waveform_data( ) throw (lecroy::WaveformException) +void WaveForm_data::get_waveform_data(ChannelData* channelData ) throw (lecroy::WaveformException) { std::string cmd(""); char* cmdStr = 0; -//int ulTrace_Size = 0; -int response_length=0; unsigned short OFFSET_STRUCT = 0; std::ostringstream oss; //- FOR DEBUG : comment out Timer and STD::COUT !! -yat::Timer t; -double time_to_write_data; -double time_to_read_data; -double time_to_copy_data; - -oss << "WaveForm_data::get_waveform_data( ) -> ENTERING ..." << std::endl; +// yat::Timer t; - //- init ptr WaveBlocData which point on WAVEDESC_BLOCS structure - waveBlockData = 0; +// std::cout << "\t\t\tget_waveform_data ENTERING ..." << std::endl; - //- get channel name - std::string ch_name("") ; + //- init ptr waveblocdata which point on wavedesc_blocs structure + waveBlockData = 0; - ch_name = get_channel_name(); - //- prepare the cmd to get the waveform data - cmd = ch_name + ":WF? ALL"; - int length = cmd.size()+1; - cmdStr = new(std::nothrow) char[length]; - ::strcpy(cmdStr, cmd.c_str()); + //- get channel name + std::string ch_name("") ; + ch_name = channelData->channel_name_; +// std::cout << "\t\t\tget_waveform_data -> ch name = " << ch_name << std::endl; - //- send the request - SocketLecroy::get_instance( )->TCP_WriteDevice(cmdStr,length,true); - time_to_write_data = t.elapsed_msec(); -oss << "\tTime to WRITE command : " << time_to_write_data << std::endl; - - //- delete cmd allocation - if(cmdStr) - { - delete [] cmdStr; - cmdStr = 0; - } + //- prepare the cmd to get the waveform data + cmd = ch_name + std::string(":WF? ALL"); + std::size_t in_length = cmd.size() + 1; + cmdStr = new(std::nothrow) char[in_length]; + ::strncpy(cmdStr, cmd.c_str(), in_length); + //- send the request +// std::cout << "\t\tget_waveform_data -> write cmd..." << ptr_com << std::endl; + int out_length = MAX_WAVEFORM_DATA_LENGTH; + try + { //- erase previsous data - ::memset (ptrRawData, 0, MAX_WAVEFORM_DATA_LENGTH); - - //- delete previous raw data - if(sh_raw_waveform_data) - { - delete [] sh_raw_waveform_data; - sh_raw_waveform_data = 0; - } - - //- delete previous scaled data - if(vertical_scaled_waveform_data) - { - delete [] vertical_scaled_waveform_data; - vertical_scaled_waveform_data = 0; - } - - if(!ptrRawData) - throw lecroy::WaveformException("OUT_OF_MEMORY", - "The pointer (ptrRawData) for the receive data can't be allocated before the read operation.", - "WaveForm_data::get_waveform_data( )."); - - length = MAX_WAVEFORM_DATA_LENGTH; - - //- read the response - try - { - SocketLecroy::get_instance( )->TCP_ReadDevice(ptrRawData,length,&response_length); - time_to_read_data = t.elapsed_msec() - time_to_write_data; -oss << "\tTime to READ " << response_length << " data : " << time_to_read_data << std::endl; -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> READ DONE, respLgth = " << response_length << std::endl; - } - catch(const lecroy::WaveformException &) - { - //- XE : - throw lecroy::WaveformException("OPERATION_FAILED", - "The TCP_ReadDevice() method failed.", - "WaveForm_data::get_waveform_data( )."); - } - - //- calculation of the offset of the structure (it can be 15 or 21) - unsigned short i = 0; - for(i=0; i < 22 ; i++) - { - if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A') - { - //- the offset of the structure which contains the context of the waveform acquisition - OFFSET_STRUCT = i; -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> OFFSET AT = " << OFFSET_STRUCT << std::endl; - break; - } - } - - //- test if the OFFSET_STRUCT is found - if(!OFFSET_STRUCT) - throw lecroy::WaveformException("DATA_OUT_OF_RANGE", - "The offset of the structure is not found.", - "WaveForm_data::get_waveform_data( )."); - - - //- update the struct WAVEDESC_BLOC - waveBlockData = (WAVEDESC_BLOCK*) (ptrRawData+OFFSET_STRUCT); - if(!waveBlockData) - throw lecroy::WaveformException("OUT_OF_MEMORY", - "The pointer for the receive data can't be allocated before the read operation.", - "WaveForm_data::get_waveform_data( )."); - - //- allocate memory for the raw data - sh_raw_waveform_data = new(std::nothrow) short[waveBlockData->wave_array_count]; - if(!sh_raw_waveform_data) - throw lecroy::WaveformException("OUT_OF_MEMORY", - "The pointer for the receive data can't be allocated before the read operation.", - "WaveForm_data::get_waveform_data( )."); - - //- allocate memory for the vertical scaled data - vertical_scaled_waveform_data = new(std::nothrow) double[waveBlockData->wave_array_count]; - if(!vertical_scaled_waveform_data) - throw lecroy::WaveformException("OUT_OF_MEMORY", - "The pointer for the scaled data can't be allocated before the read operation.", - "WaveForm_data::get_waveform_data( )."); - - //- copy the data before sending them -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> DATA Lgth = " << waveBlockData->wave_array_count << std::endl; -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> descriptor idx = " << waveBlockData->wave_descriptor << std::endl; - - for(size_t idx=0; idx<waveBlockData->wave_array_count ; idx++) - { - sh_raw_waveform_data[idx] = (ptrRawData + OFFSET_STRUCT + waveBlockData->wave_descriptor)[idx]; - //- Found in the "Remote Control Manual" : calculation of the vertical scaled data - vertical_scaled_waveform_data[idx] = (waveBlockData->vertical_gain * sh_raw_waveform_data[idx]) - waveBlockData->vertical_offset; -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> LOOP idx = " << idx << std::endl; - } - time_to_copy_data = t.elapsed_msec() - time_to_read_data; -oss << "\tTime to COPY " << response_length << " data : " << time_to_copy_data << std::ends; - -time_to_get_waveformData = oss.str(); -//std::cout << "\t WaveForm_data::get_waveform_data( ) -> DONE in " << t.elapsed_msec() << " milliseconds." << std::endl; -} - -//- return the ptr on sh_raw_waveform_data ( = the waveform data acquired) -short* WaveForm_data::get_raw_waveform_data () throw (lecroy::WaveformException) -{ - if ( !sh_raw_waveform_data ) - throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", - "get_waveform_data( ) method must be called before.", - "WaveForm_data::get_raw_waveform_data( )."); - - return sh_raw_waveform_data; -} - - -//- Method to return the scaled data of the acquired waveform -double* WaveForm_data::get_vertical_scaled_waveform_data( ) throw (lecroy::WaveformException) -{ - if ( !vertical_scaled_waveform_data ) - throw lecroy::WaveformException("DESCRIPTOR_MEMORY_ ", - "get_waveform_data( ) method must be called before.", - "WaveForm_data::get_vertical_scaled_waveform_data( )."); - - return vertical_scaled_waveform_data; + ::memset (ptrRawData, 0, out_length); + ptr_com->write_read(cmdStr, in_length, ptrRawData, &out_length, true); +// time_to_read_data = t.elapsed_msec(); +// std::cout << "\t\tWaveForm_data::Time to WRITE_READ resp lgth = " << out_length << " data : " << t.elapsed_msec() << std::endl; + } + catch(const lecroy::WaveformException &) + { + //- XE : + throw lecroy::WaveformException("OPERATION_FAILED", + "The TCP_ReadDevice() method failed.", + "WaveForm_data::get_waveform_data( )."); + } + + //- delete cmd allocation + if(cmdStr) + { + delete [] cmdStr; + cmdStr = 0; + } + + //- calculation of the offset of the structure (it can be 15 or 21) + unsigned short i = 0; + for(i=0; i < 22 ; i++) + { + if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A') + { + //- the offset of the structure which contains the context of the waveform acquisition + OFFSET_STRUCT = i; + break; + } + } + + //- test if the OFFSET_STRUCT is found + if(!OFFSET_STRUCT) + throw lecroy::WaveformException("DATA_OUT_OF_RANGE", + "The offset of the structure is not found.", + "WaveForm_data::get_waveform_data( )."); +// std::cout << "\t\tOFFSET of struct = " << OFFSET_STRUCT << std::endl; + + //- update the struct WAVEDESC_BLOC + waveBlockData = (WAVEDESC_BLOCK*) (ptrRawData+OFFSET_STRUCT); + if(!waveBlockData) + throw lecroy::WaveformException("OUT_OF_MEMORY", + "The pointer for the receive data can't be allocated before the read operation.", + "WaveForm_data::get_waveform_data( )."); + + //- copy data + channelData->wave_array_count_ = waveBlockData->wave_array_count; + channelData->vertical_gain_ = waveBlockData->vertical_gain; + channelData->vertical_offset_ = waveBlockData->vertical_offset; + channelData->horizontal_interval_ = waveBlockData->horizontal_interval; + channelData->horizontal_offset_ = waveBlockData->horizontal_offset; + channelData->nominal_bits_ = waveBlockData->nominal_bits; + channelData->wave_array_1_ = waveBlockData->wave_array_1; + channelData->wave_array_2_ = waveBlockData->wave_array_2; + //- resize vectors + channelData->raw_waveform_data_.resize(waveBlockData->wave_array_count); + channelData->vertical_scaled_data_.resize(waveBlockData->wave_array_count); + //- populate vectors + for(long idx=0; idx < waveBlockData->wave_array_count; idx++) + { + //- raw data + channelData->raw_waveform_data_[idx] = (ptrRawData + OFFSET_STRUCT + waveBlockData->wave_descriptor)[idx]; + //- compute and copy scaled data + channelData->vertical_scaled_data_[idx] = (waveBlockData->vertical_gain * channelData->raw_waveform_data_[idx]) - waveBlockData->vertical_offset; + } + +// std::cout << "\t\tWaveForm_data::get_waveform_data done in : " << t.elapsed_msec() << " ms." << std::endl; } //- Method to return the trigger time of the acquired waveform - -std::string WaveForm_data::get_trigger_time_value ( ) +void WaveForm_data::get_trigger_time_value (ChannelData* channelData) { - //- The format is : "Date = month, day, year ; Time = hours:minutes:seconds" - std::string str_seconds(""); - std::string str_minutes(""); - std::string str_hours (""); - std::string str_days (""); - std::string str_months (""); - std::string str_years (""); - - //- hours, min, sec with 2 digits - str_seconds = XString<double>::convertToString(waveBlockData->trigger_time_seconds); - if(waveBlockData->trigger_time_seconds<10) - str_seconds = "0" + str_seconds; - - str_minutes = XString<int>::convertToString((int)waveBlockData->trigger_time_minutes); - if(waveBlockData->trigger_time_minutes<10) - str_minutes = "0" + str_minutes; - - str_hours = XString<int>::convertToString(waveBlockData->trigger_time_hours); - if(waveBlockData->trigger_time_hours<10) - str_hours = "0" + str_hours; - - str_days = XString<int>::convertToString(waveBlockData->trigger_time_days); - str_months = XString<int>::convertToString(waveBlockData->trigger_time_months); - str_years = XString<short>::convertToString(waveBlockData->trigger_time_year); - - //- Construct the string Trigger Time: - trigger_time_value = "Date = " + str_months + "/" + str_days + "/" + str_years + " ; Time = " + str_hours + ":" + str_minutes + ":" + str_seconds; - - return trigger_time_value; +//- The format is : "Date = month, day, year ; Time = hours:minutes:seconds" +std::string str_seconds(""); +std::string str_minutes(""); +std::string str_hours (""); +std::string str_days (""); +std::string str_months (""); +std::string str_years (""); + + //- hours, min, sec with 2 digits + str_seconds = XString<double>::convertToString(waveBlockData->trigger_time_seconds); + if(waveBlockData->trigger_time_seconds<10) + str_seconds = "0" + str_seconds; + + str_minutes = XString<int>::convertToString((int)waveBlockData->trigger_time_minutes); + if(waveBlockData->trigger_time_minutes<10) + str_minutes = "0" + str_minutes; + + str_hours = XString<int>::convertToString(waveBlockData->trigger_time_hours); + if(waveBlockData->trigger_time_hours<10) + str_hours = "0" + str_hours; + + str_days = XString<int>::convertToString(waveBlockData->trigger_time_days); + str_months= XString<int>::convertToString(waveBlockData->trigger_time_months); + str_years = XString<short>::convertToString(waveBlockData->trigger_time_year); + + //- Construct the string Trigger Time: + channelData->trigger_time_ = "Date = " + str_months + "/" + str_days + "/" + str_years + " ; Time = " + str_hours + ":" + str_minutes + ":" + str_seconds; } diff --git a/src/WaveformMgr.cpp b/src/WaveformMgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8552553bfabb4d200e1f45f4e82df17dcc3b8f7e --- /dev/null +++ b/src/WaveformMgr.cpp @@ -0,0 +1,353 @@ +// ============================================================================ +// +// = CONTEXT +// TANGO Project - Task to gather Lecroy channel(s) data +// +// = File +// WaveformMgr.cpp +// +// = AUTHOR +// X. Elattaoui - SOLEIL +// +// ============================================================================ + +// ============================================================================ +// DEPENDENCIES +// ============================================================================ +#include <yat/time/Time.h> +#include "WaveformMgr.hpp" +#include "SocketLecroy.h" //- write/read + +const std::size_t MAX_RESPONSE_LENGTH = 150000; + +const std::size_t PERIODIC_MSG_PERIOD = 1100; //- (in ms) : time to update one channel data, it cannot be less than 1100 ms! + +const std::size_t MSG_TIMEOUT = 2000; //- in ms +// ============================================================================ +// SOME USER DEFINED MESSAGES +// ============================================================================ +const std::size_t WRITE_READ = yat::FIRST_USER_MSG + 10; + +// ====================================================================== +// WaveformMgr::WaveformMgr +// ====================================================================== +WaveformMgr::WaveformMgr (Tango::DeviceImpl* host_device, char* ipAdd) + : yat4tango::DeviceTask(host_device), + waveform_ptr_(0), + channel_data_(0), + lecroy_resp_(""), + ipAddress_(ipAdd), + connected_(false), + errors_("") +{ + //- noop +} + +// ====================================================================== +// WaveformMgr::~WaveformMgr +// ====================================================================== +WaveformMgr::~WaveformMgr (void) +{ +// std::cout << "\tWaveformMgr::~WaveformMgr ..." << std::endl; + //- noop +// std::cout << "\tWaveformMgr::~WaveformMgr -> DONE" << std::endl; +} + +// ============================================================================ +// WaveformMgr::process_message +// ============================================================================ +void WaveformMgr::process_message (yat::Message& _msg) throw (Tango::DevFailed) +{ + DEBUG_STREAM << "WaveformMgr::handle_message::receiving msg " << _msg.to_string() << std::endl; + + //- handle msg + switch (_msg.type()) + { + //- THREAD_INIT ---------------------- + case yat::TASK_INIT: + { + DEBUG_STREAM << "WaveformMgr::handle_message::THREAD_INIT::thread is starting up" << std::endl; + //- "initialization" code goes here + //---------------------------------------------------- + yat::Timer t; + + if ( !waveform_ptr_ ) + waveform_ptr_ = new WaveForm_data(ipAddress_); + if (waveform_ptr_) + { + //- check socket is up + connected_ = SocketLecroy::get_instance()->is_connected(); + //- configure optional msg handling + this->enable_timeout_msg(false); + this->enable_periodic_msg(true); + this->set_periodic_msg_period(PERIODIC_MSG_PERIOD); + this->errors_.clear(); + INFO_STREAM << "\tWaveformMgr::TASK_INIT finished in " << t.elapsed_msec() << " ms." << std::endl; + } + else + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "Manager : failed to create channel structure to update data."; + } + } + break; + //- THREAD_EXIT ---------------------- + case yat::TASK_EXIT: + { + DEBUG_STREAM << "WaveformMgr::handle_message::THREAD_EXIT::thread is quitting" << std::endl; + //- "release" code goes here + //---------------------------------------------------- +// yat::Timer t; + if ( waveform_ptr_ ) + { + delete waveform_ptr_; + waveform_ptr_ = 0; + } +// std::cout << "\tWaveformMgr::TASK_EXIT -> waveform_ptr_ in " << t.elapsed_msec() << " ms." << std::endl; + yat::AutoMutex<> guard(this->data_mutex_); + if ( channel_data_ ) + { + delete channel_data_; + channel_data_ = 0; + } +// std::cout << "\tWaveformMgr::TASK_EXIT -> channel_data_" << t.elapsed_msec() << " ms." << std::endl; + } + break; + //- THREAD_PERIODIC ------------------ + case yat::TASK_PERIODIC: + { + DEBUG_STREAM << "WaveformMgr::handle_message::handling THREAD_PERIODIC msg" << std::endl; + //- code relative to the task's periodic job goes here + //---------------------------------------------------- + yat::Timer t; + + if (waveform_ptr_) + { + try + { + ChannelData tmp_channel(channel_data_->channel_name_); + waveform_ptr_->update_channel_data(&tmp_channel); +// std::cout << "\n\n\tWaveformMgr::TASK_PERIODIC -> update_channel_data in " << t.elapsed_msec() << " ms." << std::endl; + {//- critical section + yat::AutoMutex<> guard(this->data_mutex_); + *channel_data_ = tmp_channel; + } + {//- no error + yat::AutoMutex<> guard(this->error_mutex_); + errors_.clear(); + } + INFO_STREAM << "\tWaveformMgr::TASK_PERIODIC -> done in " << t.elapsed_msec() << " ms." << std::endl; + } + catch(const lecroy::WaveformException& we) + { + Tango::DevFailed df = lecroy_to_tango_exception(we); + FATAL_STREAM << df << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "Manager : failed to update channel structure to update data.\n Caught a Lecroy exception -> check logs."; + } +// std::cout << "[LECROY] WaveformMgr::handle_message::handling THREAD_PERIODIC -> [...]" << std::endl; + } + catch(Tango::DevFailed& df) + { + ERROR_STREAM << "[DF] WaveformMgr::handle_message::handling THREAD_PERIODIC -> caught DF :\n" << df << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "Manager : failed to update channel structure to update data.\n Caught a DevFailed exception -> check logs."; + } + } + catch(...) + { + ERROR_STREAM << "[...] WaveformMgr::handle_message::handling THREAD_PERIODIC -> [...]" << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "Manager : failed to update channel structure to update data.\n Caught a generic exception."; + } + } + } + else + { + ERROR_STREAM << "[ELSE] WaveformMgr::handle_message::handling THREAD_PERIODIC -> Cannot update channel data" << std::endl; + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "Failed to create channel structure to update data."; + } + + } + break; + //- WRITE_READ + case WRITE_READ: + { + //- code relative to the task's STORE_DATA handling goes here + YAT_LOG("CurrentTrendFileTask::handle_message::handling WRITE_READ msg"); +// std::cout << "\nCurrentTrendFileTask::handle_message::handling WRITE_READ msg" << std::endl; + yat::Timer t; + + try + { + SocketLecroy* ptr_com = SocketLecroy::get_instance(); + + std::string cmd = _msg.get_data<std::string>(); + int bytes_received = -1; + char resp[MAX_RESPONSE_LENGTH]; + char * command = 0; + + if(ptr_com) + { + ::strcpy(resp, "No response"); + //- transform string to char* + std::size_t length = cmd.size(); + command = new char[length+1]; + for(std::size_t i=0; i<length; i++) + command[i] = cmd[i]; + command[length] = '\0'; + + ptr_com->TCP_WriteDevice(command, length, true); + if( cmd.rfind('?') != std::string::npos ) + { + #ifdef WIN32 + Sleep(10); //- milliseconds + #else + usleep(10000); + #endif + ptr_com->TCP_ReadDevice(resp, MAX_RESPONSE_LENGTH, &bytes_received); + } + } + else + ::strcpy(resp, "No communication with Lecroy device!"); + + if (command) + { + delete [] command; + command = 0; + } + + this->lecroy_resp_ = resp; + {//- no error + yat::AutoMutex<> guard(this->error_mutex_); + errors_.clear(); + } + INFO_STREAM << "\t******WaveformMgr::WRITE_READ done in : " << t.elapsed_msec() << " ms.\n" << std::endl; + } + catch(const lecroy::WaveformException& we) + { + Tango::DevFailed df = lecroy_to_tango_exception(we); + FATAL_STREAM << df << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "WriteRead command failed : caught a Lecroy exception -> check logs."; + } + } + catch(Tango::DevFailed& df) + { + ERROR_STREAM << "WaveformMgr::handle_message::handling WRITE_READ -> caught DF :\n" << df << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "WriteRead command failed : caught a DevFailed exception -> check logs."; + } + } + catch(...) + { + ERROR_STREAM << "WaveformMgr::handle_message::handling WRITE_READ -> [...]" << std::endl; + { + yat::AutoMutex<> guard(this->error_mutex_); + errors_ = "WriteRead command failed : caught a generic exception."; + } + } + } + break; + //- THREAD_TIMEOUT ------------------- + case yat::TASK_TIMEOUT: + { + //- code relative to the task's tmo handling goes here + std::cout << "WaveformMgr::handle_message::handling THREAD_TIMEOUT msg" << std::endl; + } + break; + //- UNHANDLED MSG -------------------- + default: + FATAL_STREAM << "WaveformMgr::handle_message::unhandled msg type received" << std::endl; + break; + } + + DEBUG_STREAM << "WaveformMgr::handle_message::message_handler:msg " + << _msg.to_string() + << " successfully handled" + << std::endl; +} + +// ============================================================================ +// WaveformMgr::add_channel +// ============================================================================ +void WaveformMgr::add_channel(std::string ch_name) +{ + //- insert the new channel (in critical section) + yat::AutoMutex<> guard(this->data_mutex_); + if ( !channel_data_ ) + channel_data_ = new ChannelData(ch_name); + + //- allocate data memory + channel_data_->vertical_scaled_data_.reserve(MAX_WAVEFORM_DATA_LENGTH); + channel_data_->raw_waveform_data_.reserve(MAX_WAVEFORM_DATA_LENGTH); +} + +// ============================================================================ +// WaveformMgr::get_channel_data +// ============================================================================ +ChannelData* WaveformMgr::get_channel_data() +{ + yat::AutoMutex<> guard(this->data_mutex_); + + return channel_data_; +} + +// ============================================================================ +// WaveformMgr::write_read +// ============================================================================ +std::string WaveformMgr::write_read(std::string cmd_to_send) +{ + //- in case you want to wait for the msg to be handled before returning (synchronous approach) + //- be sure to allocate a "waitable" message... + bool waitable = true; + yat::Message * msg = new yat::Message(WRITE_READ, MAX_USER_PRIORITY, waitable); + + msg->attach_data(cmd_to_send); + + this->wait_msg_handled(msg, MSG_TIMEOUT); + + return lecroy_resp_; +} + +//+---------------------------------------------------------------------------- +// +// method : WaveformMgr::lecroy_to_tango_exception() +// +// description : convert Lecroy exception to a DevFailed. +// +//----------------------------------------------------------------------------- +Tango::DevFailed WaveformMgr::lecroy_to_tango_exception(const lecroy::LecroyException& de) +{ + Tango::DevErrorList error_list(de.errors.size()); + error_list.length(de.errors.size()); + + for(size_t i = 0; i < de.errors.size(); i++) + { + error_list[i].reason = CORBA::string_dup(de.errors[i].reason.c_str()); + error_list[i].desc = CORBA::string_dup(de.errors[i].desc.c_str()); + error_list[i].origin = CORBA::string_dup(de.errors[i].origin.c_str()); + + switch(de.errors[i].severity) + { + case lecroy::WARN: + error_list[i].severity = Tango::WARN; + break; + case lecroy::PANIC: + error_list[i].severity = Tango::PANIC; + break; + case lecroy::ERR: + default: + error_list[i].severity = Tango::ERR; + break; + } + } + + return Tango::DevFailed(error_list); +}