From 9d0fa065351a77530b0ebd3ff899f6c8a5a26165 Mon Sep 17 00:00:00 2001 From: Xavier Elattaoui <xavier.elattaoui@synchrotron-soleil.fr> Date: Thu, 24 Apr 2008 15:00:34 +0000 Subject: [PATCH] xavier : - SocketLecroy file splitted for Win32 and Linux like platforms - Bugs fixed in SocketLecroy --- include/SocketLecroy.h | 2 +- src/AcquireWaveformLecroy.cpp | 78 ++++--- src/LinuxSocketLecroy.cpp | 386 ++++++++++++++++++++++++++++++++++ src/Makefile.VC | 84 ++++---- src/Makefile.linux | 118 +++++++++++ src/SocketLecroy.cpp | 43 +++- src/Waveform.cpp | 39 ++-- src/Win32SocketLecroy.cpp | 351 +++++++++++++++++++++++++++++++ src/lecrMakefile | 104 +++++++++ 9 files changed, 1098 insertions(+), 107 deletions(-) create mode 100644 src/LinuxSocketLecroy.cpp create mode 100644 src/Makefile.linux create mode 100644 src/Win32SocketLecroy.cpp create mode 100644 src/lecrMakefile diff --git a/include/SocketLecroy.h b/include/SocketLecroy.h index 0cdab92..d377a2a 100644 --- a/include/SocketLecroy.h +++ b/include/SocketLecroy.h @@ -17,7 +17,7 @@ //- necessary includes #include <winsock2.h> -#include "..\include\SocketException.h" +#include "SocketException.h" //////////////////////////////////////////////////////////////////// diff --git a/src/AcquireWaveformLecroy.cpp b/src/AcquireWaveformLecroy.cpp index d638378..4f1cc71 100644 --- a/src/AcquireWaveformLecroy.cpp +++ b/src/AcquireWaveformLecroy.cpp @@ -1,4 +1,4 @@ -static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentation/AcquireWaveformLecroy/src/AcquireWaveformLecroy.cpp,v 1.11 2008-04-24 13:08:44 syldup Exp $"; +static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentation/AcquireWaveformLecroy/src/AcquireWaveformLecroy.cpp,v 1.12 2008-04-24 14:59:23 xavela Exp $"; //+============================================================================= // // file : AcquireWaveformLecroy.cpp @@ -11,11 +11,14 @@ static const char *RcsId = "$Header: /users/chaize/newsvn/cvsroot/Instrumentatio // // project : TANGO Device Server // -// $Author: syldup $ +// $Author: xavela $ // -// $Revision: 1.11 $ +// $Revision: 1.12 $ // // $Log: not supported by cvs2svn $ +// Revision 1.11 2008/04/24 13:08:44 syldup +// no message +// // Revision 1.10 2008/02/29 15:00:12 xavela // xavier: // sleep added after a write @@ -223,16 +226,16 @@ void AcquireWaveformLecroy::init_device() *attr_nominalBits_read = 0; attr_horizontalInterval_read = new Tango::DevDouble; - *attr_horizontalInterval_read = 0; + *attr_horizontalInterval_read = 0.; attr_horizontalOffset_read = new Tango::DevDouble; - *attr_horizontalOffset_read = 0; + *attr_horizontalOffset_read = 0.; attr_verticalGain_read = new Tango::DevDouble; - *attr_verticalGain_read = 0; + *attr_verticalGain_read = 0.; attr_verticalOffset_read = new Tango::DevDouble; - *attr_verticalOffset_read = 0; + *attr_verticalOffset_read = 0.; attr_triggerTime_read = new Tango::DevString; *attr_triggerTime_read = new char[MAX_STRING_LENGTH]; @@ -242,10 +245,10 @@ void AcquireWaveformLecroy::init_device() //- Initialise variables to default values //-------------------------------------------- - data_value=0; + data_value = 0; data_length = 0; - ptr_com = 0; - waveform_ptr = 0; + ptr_com = 0; + waveform_ptr= 0; get_device_property(); @@ -322,13 +325,13 @@ void AcquireWaveformLecroy::get_device_property() //------------------------------------------------------------- Tango::DbData data_put; - if (dev_prop[0].is_empty()==true) + if (dev_prop[0].is_empty()) { Tango::DbDatum property("IPaddress"); property << iPaddress; data_put.push_back(property); } - if (dev_prop[1].is_empty()==true) + if (dev_prop[1].is_empty()) { Tango::DbDatum property("ChannelName"); property << channelName; @@ -354,6 +357,7 @@ void AcquireWaveformLecroy::always_executed_hook() //- init communication if ( !_is_communication_opened ) { + cout<<"always!"<<endl; try { ptr_com->TCP_Connect( (char*)iPaddress.c_str() ); @@ -398,7 +402,7 @@ void AcquireWaveformLecroy::always_executed_hook() Tango::ERR ); } - + cout<<"always end!"<<endl; } //+---------------------------------------------------------------------------- @@ -467,63 +471,63 @@ void AcquireWaveformLecroy::read_attr_hardware(vector<long> &attr_list) //- Add your own code here //--------------------------------- - for (int i=0; i< attr_list.size(); i++) - { - string attr_name = dev_attr->get_attr_by_ind(attr_list[i]).get_name(); +// for (int i=0; i< attr_list.size(); i++) +// { +// string attr_name = dev_attr->get_attr_by_ind(attr_list[i]).get_name(); - if (attr_name == "rawWaveformData") +// if (attr_name == "rawWaveformData") { for( long j = 0 ; j < data_length ; j++) { attr_rawWaveformData_read[j] = data_value[j]; - } - } - if (attr_name == "verticalScaledData") - { - for( long j = 0 ; j < data_length ; j++) - { attr_verticalScaledData_read[j] = data_scaled_value[j]; } } - if (attr_name == "waveArray1") +// if (attr_name == "verticalScaledData") +// { +// for( long j = 0 ; j < data_length ; j++) +// { +// } +// } +// if (attr_name == "waveArray1") { *attr_waveArray1_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_1; } - if (attr_name == "waveArray2") +// if (attr_name == "waveArray2") { *attr_waveArray2_read = waveform_ptr->get_wavedesc_descriptor()->wave_array_2; } - if (attr_name == "waveArrayCount") +// if (attr_name == "waveArrayCount") { *attr_waveArrayCount_read = data_length; } - if (attr_name == "nominalBits") +// if (attr_name == "nominalBits") { *attr_nominalBits_read = waveform_ptr->get_wavedesc_descriptor()->nominal_bits; } - if (attr_name == "horizontalInterval") +// if (attr_name == "horizontalInterval") { *attr_horizontalInterval_read = (double) (waveform_ptr->get_wavedesc_descriptor()->horizontal_interval); } - if (attr_name == "horizontalOffset") +// if (attr_name == "horizontalOffset") { *attr_horizontalOffset_read = waveform_ptr->get_wavedesc_descriptor()->horizontal_offset; } - if (attr_name == "verticalGain") +// if (attr_name == "verticalGain") { *attr_verticalGain_read = (double) (waveform_ptr->get_wavedesc_descriptor()->vertical_gain); } - if (attr_name == "verticalOffset") +// if (attr_name == "verticalOffset") { *attr_verticalOffset_read = waveform_ptr->get_wavedesc_descriptor()->vertical_offset; } - if (attr_name == "triggerTime") +// if (attr_name == "triggerTime") { std::string response = waveform_ptr->get_trigger_time_value(); strcpy(*attr_triggerTime_read, response.c_str()); } - } +// } } //+---------------------------------------------------------------------------- // @@ -688,7 +692,7 @@ void AcquireWaveformLecroy::read_rawWaveformData(Tango::Attribute &attr) // hardware acquisition result. // //----------------------------------------------------------------------------- -#ifdef DEV_IMPL_2 +/*#ifdef DEV_IMPL_2 #ifdef DEV_IMPL_2 #ifdef DEV_IMPL_2 #ifdef DEV_IMPL_2 @@ -773,7 +777,7 @@ void AcquireWaveformLecroy::read_attr(Tango::Attribute &attr) #endif #endif #endif - +*/ //+---------------------------------------------------------------------------- // // method : AcquireWaveformLecroy::lecroy_to_tango_exception() @@ -880,7 +884,11 @@ Tango::DevString AcquireWaveformLecroy::write_read(Tango::DevString argin) strcpy(_deviceResponse, "No response"); if( cmd_to_send.find('?') != std::string::npos ) { +#ifdef WIN32 Sleep(100); +#else + usleep(100000); +#endif ptr_com->TCP_ReadDevice(_deviceResponse, MAX_RESPONSE_LENGTH, &bytes_received); } diff --git a/src/LinuxSocketLecroy.cpp b/src/LinuxSocketLecroy.cpp new file mode 100644 index 0000000..ccd171b --- /dev/null +++ b/src/LinuxSocketLecroy.cpp @@ -0,0 +1,386 @@ +//****************************************************************************************** +// +// +// september 13, 2004 : Source file for the communication in socket mode +// +// with a Lecroy scope (avaiable for all models) +// +// author : X.Elattaoui +// +// SocketLecroy.cpp: implementation of the SocketLecroy class. +// +//****************************************************************************************** + + +//- INCLUDE +#include <iostream> +#include "SocketLecroy.h" +#include <sys/time.h> +#include <time.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include <sys/select.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> + + +static int hSocket; +static int sTimeout = 1; //- second(s) +//static int sWinsockInitFlag = false; //- not used +static char sCurrentAddress[256]; +static int sConnectedFlag = false; + +const int CMD_BUF_LEN = 8192; +static char sCommandBuffer[CMD_BUF_LEN]; + +//- init of the static instance +SocketLecroy* SocketLecroy::SL_instance = 0; //- ptr on the SocketLecroy instance + +SocketLecroy* SocketLecroy::get_instance() +{ + if( !SL_instance ) + SL_instance = new SocketLecroy(); + + return SL_instance; + +} + +void SocketLecroy::delete_instance(SocketLecroy* SL_instance) +{ + if(SL_instance) + { + delete SL_instance ; + SL_instance = 0; + } + +} + +//- CTOR +SocketLecroy::SocketLecroy() +{ +sConnectedFlag=false; + +} +//- DTOR +SocketLecroy::~SocketLecroy() +{ + TCP_Disconnect(); + +} + + + +//- Build the connection +void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::LecroyException) +{ +struct sockaddr_in serverAddr; +int result; +const int resp = 1; +fd_set wr_set; +FD_ZERO(&wr_set); + +struct timeval tval; +unsigned long argp; +char tmpStr[256]; + + //- connection test + if (sConnectedFlag) + return; + + strcpy(sCurrentAddress, ip_address); + tval.tv_sec = sTimeout; + 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) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Bad server address.", + "SocketLecroy::TCP_Connect( )."); + } + + //- create client's socket + if ((hSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) //INVALID_SOCKET) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to create client's socket.", + "SocketLecroy::TCP_Connect( )."); + } + + if (setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&resp, sizeof(resp)) != 0) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to set socket option to TCP_NODELAY.", + "SocketLecroy::TCP_Connect( )."); + } + + FD_SET(hSocket, &wr_set); + argp = 1;//-non blocking mode + ioctl(hSocket, FIONBIO, &argp); + + int opts; + opts = fcntl (hSocket, F_GETFL); + if (opts >= 0) + opts = (opts | O_NONBLOCK); + fcntl (hSocket, F_SETFL, opts); + //connect(hSocket, (SOCKADDR FAR *) &serverAddr, sockAddrSize); + int status = ::connect(hSocket, ( sockaddr *)&serverAddr, sizeof(serverAddr)); + + if(status < 0) // We are not connected : so retry + { + if(errno == EINPROGRESS) // But the connection is in progress + { + int nb = 0; + struct timespec time_to_sleep, time_remaining; + + while(nb++ < 5) // We will attempt to connect every 100 ms for 5 times max. + { + status = ::connect (hSocket, ( sockaddr *)&serverAddr, sizeof(serverAddr)); + + if(status != 0) // Still not connected + { + if(errno == EALREADY) // This is the right error ! + { + time_to_sleep.tv_sec = 0; + time_to_sleep.tv_nsec = 15000000L; + nanosleep(&time_to_sleep, &time_remaining); // Sleep for 150 ms + } + }// Connection is OK. + else + break; + }//TODO : throw ; // Too much attempts, so failure ! + }// TODO : throw ; // Not the right error, so failure ! + }// Connected at first attempt ! + + + result = select(hSocket, NULL, &wr_set, NULL, &tval); + argp = 0;//-blocking mode + ioctl(hSocket, FIONBIO, &argp); + //- connect to server (scope) + if (result < 0) + { + sprintf(tmpStr, "Unable to make connection to IP:%s", ip_address); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + tmpStr, + "SocketLecroy::TCP_Connect( )."); + } + + sConnectedFlag = true; +} + + +//- DisconnectFromScope: disconnect from a network device +void SocketLecroy::TCP_Disconnect(void) +{ + + if (sConnectedFlag) + { + close(hSocket); + sConnectedFlag = false; + } + +} + +//- Clear a connection +void SocketLecroy::TCP_ClearDevice(void) throw (lecroy::LecroyException) +{ + + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN", + "Disconnection already done.", + "SocketLecroy::TCP_ClearDevice( )."); + + TCP_Disconnect(); + TCP_Connect(sCurrentAddress); + +} + +//- Send commands to the remote device +void SocketLecroy::TCP_WriteDevice(char *buf, int len, bool eoi_flag) throw (lecroy::LecroyException) +{ + +TCP_HEADER header; +int result, bytes_more, bytes_xferd; +char *idxPtr; + + //- test connection + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Device not connected.", + "SocketLecroy::TCP_WriteDevice( )."); + + if (len < CMD_BUF_LEN) + strcpy(sCommandBuffer, buf); + + //- set the header info + header.bEOI_Flag = DATA_FLAG; + header.bEOI_Flag |= (eoi_flag)? EOI_FLAG:0; + header.reserved[0] = 1; + header.reserved[1] = 0; + header.reserved[2] = 0; + header.iLength = htonl(len); + + + //- write the header first + if (send(hSocket, (char *) &header, sizeof(TCP_HEADER), 0) != sizeof(TCP_HEADER)) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to send header info to the server.", + "SocketLecroy::TCP_WriteDevice( )."); + } + + bytes_more = len; + idxPtr = buf; + bytes_xferd = 0; + while (1) + { + //- then write the rest of the block + idxPtr = buf + bytes_xferd; + + if ((result = send(hSocket, (char *) idxPtr, bytes_more, 0)) < 0) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to send data to the server.", + "SocketLecroy::TCP_WriteDevice( )."); + } + + bytes_xferd += result; + bytes_more -= result; + if (bytes_more <= 0) + break; + } + +} + +//- Read the device answer +void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (lecroy::LecroyException) +{ + +TCP_HEADER header; +int result; +unsigned int accum, space_left, bytes_more, buf_count; +char tmpStr[256]; +char *idxPtr; +//fd_set rd_set = {1, {0}}; +//TIMEVAL tval; +fd_set rd_set; +FD_ZERO(&rd_set); +struct timeval tval; + + //- test connection + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Device not connected.", + "SocketLecroy::TCP_ReadDevice( )."); + + *recv_count = 0; + + if (!buf) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Buffer memory not allocated.", + "SocketLecroy::TCP_ReadDevice( )."); + + FD_SET(hSocket, &rd_set); + tval.tv_sec = sTimeout; + tval.tv_usec = 0; + + memset(buf, 0, len); + buf_count = 0; + space_left = len; + + while (1) + { + result = select(hSocket, &rd_set, NULL, NULL, &tval); + if (result < 0) + { + TCP_ClearDevice(); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Read Timeout.", + "SocketLecroy::TCP_ReadDevice( )."); + } + //- 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) + { + TCP_ClearDevice(); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to receive header info from the server.", + "SocketLecroy::TCP_ReadDevice( )."); + } + + accum += result; + if (accum>=sizeof(header)) + break; + } + + header.iLength = ntohl(header.iLength); +// if (header.iLength < 1) +// return 0; + + //- only read to len amount + if (header.iLength > space_left) + { + header.iLength = space_left; + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Read buffer size is too small.", + "SocketLecroy::TCP_ReadDevice( )."); + } + + //- read the rest of the block + accum = 0; + while (1) + { + idxPtr = buf + (buf_count + accum); + bytes_more = header.iLength - accum; + if ((space_left-accum) < TCP_MINIMUM_PACKET_SIZE) + { + TCP_ClearDevice(); + sprintf(tmpStr, "Read buffer needs to be adjusted, must be minimum of %d bytes", TCP_MINIMUM_PACKET_SIZE); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + tmpStr, + "SocketLecroy::TCP_ReadDevice( )."); + } + + if ((result = recv(hSocket, (char *) idxPtr, (bytes_more>2048)?2048:bytes_more, 0)) < 0) + { + TCP_ClearDevice(); + //-MessageBox(0, "Unable to receive data from the server.", "ERROR", MB_OK); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to receive data from the server", + "SocketLecroy::TCP_ReadDevice( )."); + } + + accum += result; + if (accum >= header.iLength) + break; + if ((accum + buf_count) >= len) + break; + } + buf_count += accum; + space_left -= accum; + + if (header.bEOI_Flag & EOI_FLAG) + break; + if (space_left <= 0) + break; + } + + *recv_count = buf_count; +} + diff --git a/src/Makefile.VC b/src/Makefile.VC index 5d00135..e0b4348 100644 --- a/src/Makefile.VC +++ b/src/Makefile.VC @@ -1,44 +1,44 @@ -# -device_server= AcquireWaveformLecroy -# -# Des includes particuliers -# Mettre /Ic:\monchemininclude /:\monautrechemininclude -#INCUSER= /I..include\SocketLecroy.h/I..include\Waveform.h/I..include\LecroyException.h/I..include\SocketException.h/I..include\WaveformException.h/I..include\Xstring.h -# -# et vos Librairies -# style -# -# LIBUSER = "x:\moncheminlibrairie\malibrairie.lib" -LIBUSER= - -# -# ------------------Fin des modifications pour le end user ------------------------------------- -# -make_dir=$(SOLEIL_ROOT)\env\ - - -# Les d�finitions communes � tous les DeviceServeurs -!include $(make_dir)\tango.opt - -exe_device_server= $(EXEDIR)\ds_$(device_server).exe -pdb_name= $(TEMPLIBDIR)\$(device_server).pdb - -# -------------------------------------- -# Partie sp�cifique Device Server -# -------------------------------------- - -LISTEOBJ = \ - $(OBJDIR)\LecroyException.OBJ\ - $(OBJDIR)\SocketLecroy.OBJ\ - $(OBJDIR)\Waveform.OBJ\ - $(OBJDIR)\SocketException.OBJ\ - $(OBJDIR)\WaveformException.OBJ\ - $(OBJDIR)\$(device_server).OBJ\ - $(OBJDIR)\ClassFactory.OBJ\ - $(OBJDIR)\main.OBJ\ +# +device_server= AcquireWaveformLecroy +# +# Des includes particuliers +# Mettre /Ic:\monchemininclude /:\monautrechemininclude +#INCUSER= /I..include\SocketLecroy.h/I..include\Waveform.h/I..include\LecroyException.h/I..include\SocketException.h/I..include\WaveformException.h/I..include\Xstring.h +# +# et vos Librairies +# style +# +# LIBUSER = "x:\moncheminlibrairie\malibrairie.lib" +LIBUSER= + +# +# ------------------Fin des modifications pour le end user ------------------------------------- +# +make_dir=$(SOLEIL_ROOT)\env\ + + +# Les d�finitions communes � tous les DeviceServeurs +!include $(make_dir)\tango.opt + +exe_device_server= $(EXEDIR)\ds_$(device_server).exe +pdb_name= $(TEMPLIBDIR)\$(device_server).pdb + +# -------------------------------------- +# Partie sp�cifique Device Server +# -------------------------------------- + +LISTEOBJ = \ + $(OBJDIR)\LecroyException.OBJ\ + $(OBJDIR)\Win32SocketLecroy.OBJ\ + $(OBJDIR)\Waveform.OBJ\ + $(OBJDIR)\SocketException.OBJ\ + $(OBJDIR)\WaveformException.OBJ\ + $(OBJDIR)\$(device_server).OBJ\ + $(OBJDIR)\ClassFactory.OBJ\ + $(OBJDIR)\main.OBJ\ $(OBJDIR)\$(device_server)StateMachine.OBJ\ $(OBJDIR)\$(device_server)Class.OBJ - -# -------------------------------------- -!include $(make_dir)\common_target.opt - + +# -------------------------------------- +!include $(make_dir)\common_target.opt + diff --git a/src/Makefile.linux b/src/Makefile.linux new file mode 100644 index 0000000..cfcb9b9 --- /dev/null +++ b/src/Makefile.linux @@ -0,0 +1,118 @@ +#============================================================================= +# +# file : Makefile.linux +# +# description : Makefile for DeviceServer +# +# +#============================================================================= + + + +#============================================================================= +# OUTPUT_TYPE can be one of the following : +# - 'STATIC_LIB' for a static library (.a) +# - 'DYNAMIC_LIB' for a dynamic library (.so) +# - 'DEVICE' for a device server (will automatically include and link +# with Tango dependencies) +# - 'SIMPLE_EXE' for an executable with no dependency (for exemple the test tool +# of a library with no Tango dependencies) +# +OUTPUT_TYPE = DEVICE +#RELEASE_TYPE = DEBUG + +#============================================================================= +# OUTPUT_DIR is the directory which contains the build result. +# if not set, the standard location is : +# - $HOME/DeviceServers if OUTPUT_TYPE is DEVICE +# - ../bin for others +# +#OUTPUT_DIR = + +#============================================================================= +# PACKAGE_NAME is the name of the library/device/exe you want to build +# - for a device server, PACKAGE_NAME will be prefixed by 'ds_' +# - for a library (static or dynamic), PACKAGE_NAME will be prefixed by 'lib' +# - for a simple executable, PACKAGE_NAME will be the name of the executable +# +PACKAGE_NAME = AcquireWaveformLecroy + +#============================================================================= +# INC_DIR_USER is the list of all include path needed by your sources +# - for a device server, tango dependencies are automatically appended +# - '-I ../include' and '-I .' are automatically appended in all cases +# +# -I$(SOLEIL_ROOT)/hw-support/ace/include for ACE library +# -I$(SOLEIL_ROOT)/hw-support/asl/include for ASL library +# -I$(SOLEIL_ROOT)/sw-support/hkl/include for HKL library +# ...etc +# +#INC_DIR_USER= -I$(SOLEIL_ROOT)/sw-support/GSL/include/ -I$(SOLEIL_ROOT)/sw-support/Utils/include/ -I$(SOLEIL_ROOT)/sw-support/Monochromator/include/ -I$(SOLEIL_ROOT)/sw-support/Exceptions/include/ -I$(SOLEIL_ROOT)/sw-support/Interpolator/include/ + +#============================================================================= +# LIB_DIR_USER is the list of user library directories +# - for a device server, tango libraries directories are automatically appended +# - '-L ../lib' is automatically appended in all cases +# -L $(SOLEIL_ROOT)/hw-support/ace/lib for ACE library +# -L $(SOLEIL_ROOT)/hw-support/asl/lib for ASL library +# -L $(SOLEIL_ROOT)/sw-support/hkl/lib for HKL library +# ...etc +# +#LIB_DIR_USER= -L$(SOLEIL_ROOT)/sw-support/GSL/lib/ -L$(SOLEIL_ROOT)/sw-support/Utils/lib/ -L$(SOLEIL_ROOT)/sw-support/Monochromator/lib/ -L$(SOLEIL_ROOT)/sw-support/Exceptions/lib/ -L$(SOLEIL_ROOT)/sw-support/Interpolator/lib/ + +#============================================================================= +# LFLAGS_USR is the list of user link flags +# - for a device server, tango libraries directories are automatically appended +# - '-ldl -lpthread' is automatically appended in all cases +# +# !!! ATTENTION !!! +# Be aware that the order matters. +# For example if you must link with libA, and if libA depends itself on libB +# you must use '-lA -lB' in this order as link flags, otherwise you will get +# 'undefined reference' errors +# +# -lACE for ACE +# -lASL for ASL +# -lHKL for HKL +# +#LFLAGS_USR= -lInterpolator -lMonochromator -lGSL -lExceptions -lUtils + + +#============================================================================= +# CXXFLAGS_USR lists the compilation flags specific for your library/device/exe +# This is the place where to put your compile-time macros using '-Dmy_macro' +# +# -DACE_HAS_EXCEPTIONS -D__ACE_INLINE__ for ACE +# +#CXXFLAGS_USR=-DSIMULATED_AXIS + + +# +# include Standard TANGO compilation options +# +include $(SOLEIL_ROOT)/env/tango.opt + + +#============================================================================= +# SVC_OBJS is the list of all objects needed to make the output +# +SVC_OBJS = $(OBJDIR)/Waveform.o \ + $(OBJDIR)/LinuxSocketLecroy.o \ + $(OBJDIR)/LecroyException.o \ + $(OBJDIR)/WaveformException.o \ + $(OBJDIR)/SocketException.o \ + $(OBJDIR)/ClassFactory.o \ + $(OBJDIR)/main.o \ + $(OBJDIR)/$(PACKAGE_NAME)Class.o \ + $(OBJDIR)/$(PACKAGE_NAME).o \ + $(OBJDIR)/$(PACKAGE_NAME)StateMachine.o + +# +# Verbose mode +# +#.SILENT: + +# +# include common targets +# +include $(SOLEIL_ROOT)/env/common_target.opt diff --git a/src/SocketLecroy.cpp b/src/SocketLecroy.cpp index 66747d5..32fdee1 100644 --- a/src/SocketLecroy.cpp +++ b/src/SocketLecroy.cpp @@ -13,14 +13,14 @@ //- INCLUDE -#include "..\include\SocketLecroy.h" +#include "SocketLecroy.h" //- init of the static instance SocketLecroy* SocketLecroy::SL_instance = 0; //- ptr on the SocketLecroy instance SocketLecroy* SocketLecroy::get_instance() { - if(SL_instance==0) + if( !SL_instance ) SL_instance = new SocketLecroy(); return SL_instance; @@ -29,7 +29,7 @@ SocketLecroy* SocketLecroy::get_instance() void SocketLecroy::delete_instance(SocketLecroy* SL_instance) { - if(SL_instance!=0) + if(SL_instance) { delete SL_instance ; SL_instance = 0; @@ -40,7 +40,7 @@ void SocketLecroy::delete_instance(SocketLecroy* SL_instance) //- CTOR SocketLecroy::SocketLecroy() { -sConnectedFlag=false; + sConnectedFlag=false; } //- DTOR @@ -50,8 +50,6 @@ SocketLecroy::~SocketLecroy() } - - //- Build the connection void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::LecroyException) { @@ -66,7 +64,7 @@ char tmpStr[256]; //- connection test - if (sConnectedFlag==TRUE) + if (sConnectedFlag) return; strcpy(sCurrentAddress, ip_address); @@ -105,7 +103,34 @@ char tmpStr[256]; argp = 1;//-non blocking mode ioctlsocket(hSocket, FIONBIO, &argp); - connect(hSocket, (SOCKADDR FAR *) &serverAddr, sockAddrSize); + int status = connect(hSocket, (SOCKADDR FAR *) &serverAddr, sockAddrSize); + int error_code = WSAGetLastError(); + + //- already connected ! + if(status && error_code == WSAEISCONN) + return; + if(status != 0) // We are not connected : so retry + { + if(error_code == WSAEINPROGRESS || error_code == WSAEWOULDBLOCK) // But the connection is in progress + { + int nb = 0; + + while(nb++ < 5) // We will attempt to connect every 100 ms for 5 times max. + { + status = ::connect (hSocket, ( sockaddr *)&serverAddr, sizeof(serverAddr)); + error_code = WSAGetLastError(); + if(status != 0) // Still not connected + { + if(errno == WSAEISCONN) // This is the right error ! + { + Sleep(150); // Sleep for 150 ms + } + }// Connection is OK. + else + break; + }//TODO : throw ; // Too much attempts, so failure ! + }// TODO : throw ; // Not the right error, so failure ! + }// Connected at first attempt ! result = select(hSocket, NULL, &wr_set, NULL, &tval); @@ -113,7 +138,7 @@ char tmpStr[256]; ioctlsocket(hSocket, FIONBIO, &argp); //- connect to server (scope) - if (result < 1) + if (result == SOCKET_ERROR) { sprintf(tmpStr, "Unable to make connection to IP:%s", ip_address); throw lecroy::SocketException("COMMUNICATION_BROKEN ", diff --git a/src/Waveform.cpp b/src/Waveform.cpp index b272435..4d3446a 100644 --- a/src/Waveform.cpp +++ b/src/Waveform.cpp @@ -12,19 +12,19 @@ //- INCLUDE -#include "..\include\Waveform.h" -#include "..\include\SocketLecroy.h" +#include "Waveform.h" +#include "SocketLecroy.h" #include <iostream> -using namespace std; +//using namespace std; //- CTOR WaveForm_data::WaveForm_data(std::string ch_name) { //- initialisation of all Waveform attributes channel_name = ch_name; - sh_raw_waveform_data = NULL; - vertical_scaled_waveform_data = NULL; + sh_raw_waveform_data = 0; + vertical_scaled_waveform_data = 0; trigger_time_value = "Not available"; //- the memory allocation is done in the get_waveform_data( ) method ptrRawData = 0; @@ -53,9 +53,7 @@ WaveForm_data::~WaveForm_data() //- Method to return the channel name std::string WaveForm_data::get_channel_name( ) throw (lecroy::WaveformException) { - std::string error = " channel_name is not initialized !"; - - if(channel_name != "") + if( !channel_name.empty() ) return channel_name; else throw lecroy::WaveformException("DATA_OUT_OF_RANGE ", @@ -65,7 +63,7 @@ std::string WaveForm_data::get_channel_name( ) throw (lecroy::WaveformException //- Method to set the channel name void WaveForm_data::set_channel_name (std::string name) { - if(name != "") + if( !name.empty() ) channel_name = name; } @@ -84,9 +82,9 @@ WAVEDESC_BLOCK* WaveForm_data::get_wavedesc_descriptor( ) throw (lecroy::Wavefor //- Method to return the raw data of the acquired waveform void WaveForm_data::get_waveform_data( ) throw (lecroy::LecroyException) { -char* cmdStr; -int ulTrace_Size = 0; -string cmd = ""; +std::string cmd(""); +char* cmdStr = 0; +//int ulTrace_Size = 0; int response_length=0; short OFFSET_STRUCT = 0; @@ -94,7 +92,7 @@ short OFFSET_STRUCT = 0; waveBlockData = 0; //- get channel name - string ch_name ; + std::string ch_name("") ; ch_name = get_channel_name(); //- prepare the cmd to get the waveform data @@ -155,7 +153,8 @@ short OFFSET_STRUCT = 0; } //- calculation of the offset of the structure (it can be 15 or 21) - for(long i = 0; i < 22 ; i++) + long i = 0; + for(i=0; i < 22 ; i++) { if(ptrRawData[i] == 'W' && ptrRawData[i+1] == 'A') { @@ -233,12 +232,12 @@ std::string WaveForm_data::get_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; + 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); diff --git a/src/Win32SocketLecroy.cpp b/src/Win32SocketLecroy.cpp new file mode 100644 index 0000000..4dc79a7 --- /dev/null +++ b/src/Win32SocketLecroy.cpp @@ -0,0 +1,351 @@ +//****************************************************************************************** +// +// +// september 13, 2004 : Source file for the communication in socket mode +// +// with a Lecroy scope (avaiable for all models) +// +// author : X.Elattaoui +// +// SocketLecroy.cpp: implementation of the SocketLecroy class. +// +//****************************************************************************************** + + +//- INCLUDE +#include "SocketLecroy.h" + +//- init of the static instance +SocketLecroy* SocketLecroy::SL_instance = 0; //- ptr on the SocketLecroy instance + +SocketLecroy* SocketLecroy::get_instance() +{ + if( !SL_instance ) + SL_instance = new SocketLecroy(); + + return SL_instance; + +} + +void SocketLecroy::delete_instance(SocketLecroy* SL_instance) +{ + if(SL_instance) + { + delete SL_instance ; + SL_instance = 0; + } + +} + +//- CTOR +SocketLecroy::SocketLecroy() +{ + sConnectedFlag=false; + +} +//- DTOR +SocketLecroy::~SocketLecroy() +{ + TCP_Disconnect(); + +} + +//- Build the connection +void SocketLecroy::TCP_Connect(char *ip_address) throw (lecroy::LecroyException) +{ + +SOCKADDR_IN serverAddr; +int sockAddrSize = sizeof (SOCKADDR), result; +const int resp = 1; +fd_set wr_set = {1, {0}}; +TIMEVAL tval; +unsigned long argp; +char tmpStr[256]; + + + //- connection test + if (sConnectedFlag) + return; + + strcpy(sCurrentAddress, ip_address); + + tval.tv_sec = sTimeout; + 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) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Bad server address.", + "SocketLecroy::TCP_Connect( )."); + } + + //- create client's socket + if ((hSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to create client's socket.", + "SocketLecroy::TCP_Connect( )."); + } + + if (setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&resp, sizeof(resp)) != 0) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to set socket option to TCP_NODELAY.", + "SocketLecroy::TCP_Connect( )."); + } + + wr_set.fd_array[0] = hSocket; + + argp = 1;//-non blocking mode + ioctlsocket(hSocket, FIONBIO, &argp); + + int status = connect(hSocket, (SOCKADDR FAR *) &serverAddr, sockAddrSize); + int error_code = WSAGetLastError(); + + //- already connected ! + if(status && error_code == WSAEISCONN) + return; + if(status != 0) // We are not connected : so retry + { + if(error_code == WSAEINPROGRESS || error_code == WSAEWOULDBLOCK) // But the connection is in progress + { + int nb = 0; + + while(nb++ < 5) // We will attempt to connect every 100 ms for 5 times max. + { + status = ::connect (hSocket, ( sockaddr *)&serverAddr, sizeof(serverAddr)); + error_code = WSAGetLastError(); + if(status != 0) // Still not connected + { + if(errno == WSAEISCONN) // This is the right error ! + { + Sleep(150); // Sleep for 150 ms + } + }// Connection is OK. + else + break; + }//TODO : throw ; // Too much attempts, so failure ! + }// TODO : throw ; // Not the right error, so failure ! + }// Connected at first attempt ! + + result = select(hSocket, NULL, &wr_set, NULL, &tval); + + argp = 0;//-blocking mode + ioctlsocket(hSocket, FIONBIO, &argp); + + //- connect to server (scope) + if (result == SOCKET_ERROR) + { + sprintf(tmpStr, "Unable to make connection to IP:%s", ip_address); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + tmpStr, + "SocketLecroy::TCP_Connect( )."); + } + + sConnectedFlag = TRUE; +} + + +//- DisconnectFromScope: disconnect from a network device +void SocketLecroy::TCP_Disconnect(void) +{ + + if (sConnectedFlag) + { + closesocket(hSocket); + sConnectedFlag = FALSE; + } + +} + +//- Clear a connection +void SocketLecroy::TCP_ClearDevice(void) throw (lecroy::LecroyException) +{ + + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN", + "Disconnection already done.", + "SocketLecroy::TCP_ClearDevice( )."); + + TCP_Disconnect(); + TCP_Connect(sCurrentAddress); + +} + +//- Send commands to the remote device +void SocketLecroy::TCP_WriteDevice(char *buf, int len, BOOL eoi_flag) throw (lecroy::LecroyException) +{ + +TCP_HEADER header; +int result, bytes_more, bytes_xferd; +char *idxPtr; + + //- test connection + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Device not connected.", + "SocketLecroy::TCP_WriteDevice( )."); + + if (len < CMD_BUF_LEN) + strcpy(sCommandBuffer, buf); + + //- set the header info + header.bEOI_Flag = DATA_FLAG; + header.bEOI_Flag |= (eoi_flag)? EOI_FLAG:0; + header.reserved[0] = 1; + header.reserved[1] = 0; + header.reserved[2] = 0; + header.iLength = htonl(len); + + + //- write the header first + if (send(hSocket, (char *) &header, sizeof(TCP_HEADER), 0) != sizeof(TCP_HEADER)) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to send header info to the server.", + "SocketLecroy::TCP_WriteDevice( )."); + } + + bytes_more = len; + idxPtr = buf; + bytes_xferd = 0; + while (1) + { + //- then write the rest of the block + idxPtr = buf + bytes_xferd; + + if ((result = send(hSocket, (char *) idxPtr, bytes_more, 0)) < 0) + { + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to send data to the server.", + "SocketLecroy::TCP_WriteDevice( )."); + } + + bytes_xferd += result; + bytes_more -= result; + if (bytes_more <= 0) + break; + } + +} + +//- Read the device answer +void SocketLecroy::TCP_ReadDevice(char *buf, int len, int *recv_count) throw (lecroy::LecroyException) +{ + +TCP_HEADER header; +int result, accum, space_left, bytes_more, buf_count; +char tmpStr[256]; +char *idxPtr; +fd_set rd_set = {1, {0}}; +TIMEVAL tval; + + //- test connection + if ( !sConnectedFlag ) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Device not connected.", + "SocketLecroy::TCP_ReadDevice( )."); + + *recv_count = 0; + + if (!buf) + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Buffer memory not allocated.", + "SocketLecroy::TCP_ReadDevice( )."); + + rd_set.fd_array[0] = hSocket; + tval.tv_sec = sTimeout; + tval.tv_usec = 0; + + memset(buf, 0, len); + buf_count = 0; + space_left = len; + + while (1) + { + result = select(hSocket, &rd_set, NULL, NULL, &tval); + if ( !result || result == SOCKET_ERROR) + { + TCP_ClearDevice(); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Read Timeout.", + "SocketLecroy::TCP_ReadDevice( )."); + } + //- 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) + { + TCP_ClearDevice(); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to receive header info from the server.", + "SocketLecroy::TCP_ReadDevice( )."); + } + + accum += result; + if (accum>=sizeof(header)) + break; + } + + header.iLength = ntohl(header.iLength); +// if (header.iLength < 1) +// return 0; + + //- only read to len amount + if (header.iLength > space_left) + { + header.iLength = space_left; + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Read buffer size is too small.", + "SocketLecroy::TCP_ReadDevice( )."); + } + + //- read the rest of the block + accum = 0; + while (1) + { + idxPtr = buf + (buf_count + accum); + bytes_more = header.iLength - accum; + if ((space_left-accum) < TCP_MINIMUM_PACKET_SIZE) + { + TCP_ClearDevice(); + sprintf(tmpStr, "Read buffer needs to be adjusted, must be minimum of %d bytes", TCP_MINIMUM_PACKET_SIZE); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + tmpStr, + "SocketLecroy::TCP_ReadDevice( )."); + } + + if ((result = recv(hSocket, (char *) idxPtr, (bytes_more>2048)?2048:bytes_more, 0)) < 0) + { + TCP_ClearDevice(); + //-MessageBox(0, "Unable to receive data from the server.", "ERROR", MB_OK); + throw lecroy::SocketException("COMMUNICATION_BROKEN ", + "Unable to receive data from the server", + "SocketLecroy::TCP_ReadDevice( )."); + } + + accum += result; + if (accum >= header.iLength) + break; + if ((accum + buf_count) >= len) + break; + } + buf_count += accum; + space_left -= accum; + + if (header.bEOI_Flag & EOI_FLAG) + break; + if (space_left <= 0) + break; + } + + *recv_count = buf_count; +} + diff --git a/src/lecrMakefile b/src/lecrMakefile new file mode 100644 index 0000000..d6a68f4 --- /dev/null +++ b/src/lecrMakefile @@ -0,0 +1,104 @@ +#============================================================================= +# +# file : Makefile.h +# +# description : Include for the AcquireWaveformLecroy class. +# +# project : Makefile to generate a Tango server +# +# $Author: xavela $ +# +# $Revision: 1.1 $ +# +# $Log: not supported by cvs2svn $ +# Revision 1.4 2004/10/18 13:17:49 xavela +# xavier : add an attr waveArray2. +# Sorts attr in expert and operator view with Pogo. +# Inconsistencies removed. +# +# Revision 1.3 2004/10/07 09:21:19 xavela +# xavier : no cout now. +# +# Revision 1.2 2004/10/05 13:11:11 xavela +# Xavier : previous commit failed. +# +# Revision 1.1.1.1 2004/09/29 15:42:14 syldup +# Initial import. +# +# +# copyleft : European Synchrotron Radiation Facility +# BP 220, Grenoble 38043 +# FRANCE +# +#============================================================================= +# This file is generated by POGO +# (Program Obviously used to Generate tango Object) +# +# (c) - Software Engineering Group - ESRF +#============================================================================= +# + +CLASS = AcquireWaveformLecroy +NAME_SRV = lecroy-srv + +CC = g++ +AR = ar + +TANGO_DIR = /usr/local/tango +OMNIORB_DIR = /usr/local/omniorb +RUNTIME_DIR = /runtime +MYSQL_DIR = /usr/include/mysql + +TANGO_INC = ${TANGO_DIR}/include +OMNIORB_INC = ${OMNIORB_DIR}/include +RUNTIME_INC = ${RUNTIME_DIR}/include +MYSQL_INC = /usr/include/mysql +INC_DIR = -I${TANGO_INC} -I${OMNIORB_INC} -I${RUNTIME_INC} -I${MYSQL_INC} + +TANGO_LIB = ${TANGO_DIR}/lib +OMNIORB_LIB = ${OMNIORB_DIR}/lib +RUNTIME_LIB = ${RUNTIME_DIR}/lib +RUNTIME_BIN = ${RUNTIME_DIR}/bin +MYSQL_LIB = /usr/lib/mysql +LIB_DIR = -L${TANGO_LIB} -L${OMNIORB_LIB} -L${RUNTIME_LIB} -L${MYSQL_LIB} + +RPATH = ${TANGO_LIB} ${OMNIORB_LIB} ${RUNTIME_LIB} + +INCLUDE_DIRS = $(INC_DIR) -I. -I../include + +CXXFLAGS = -g -D_REENTRANT $(INCLUDE_DIRS) +LFLAGS = $(LIB_DIR) \ + -ltango \ + -llog4tango \ + -lomniORB4 \ + -lomniDynamic4 \ + -lomnithread \ + -lCOS4 \ + -ldl -lpthread + +SVC_OBJS = main.o \ + ClassFactory.o \ + $(CLASS)Class.o \ + $(CLASS)StateMachine.o \ + $(CLASS).o \ + Waveform.o \ + LinuxSocketLecroy.o \ + LecroyException.o \ + WaveformException.o \ + SocketException.o + +SVC_INC = $(CLASS)Class.h \ + $(CLASS).h + + +%.o: %.cpp $(SVC_INC) + $(CC) $(CXXFLAGS) -c $< + +all: $(CLASS) + +$(CLASS): $(SVC_OBJS) + $(CC) $(SVC_OBJS) -o $(CLASS) $(LFLAGS) + mv $(CLASS) $(NAME_SRV) + +clean: + rm -f *.o $(CLASS) core $(NAME_SRV) -- GitLab