//Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (C) 2012
//Copyright: See COPYING file that comes with this distribution
# include "debug.h"
# include "define.h"
# include "part.h"
# include <kaboutdata.h> //::createAboutData()
# include <kaction.h>
# include <klocale.h>
# include <kmessagebox.h> //::start()
# include <kparts/genericfactory.h>
# include <kstatusbar.h>
# include <kstdaction.h>
# include <tqfile.h> //encodeName()
# include <tqtimer.h> //postInit() hack
# include <tqvbox.h>
# include <tqsocket.h>
# include <tqmutex.h>
# include <tqeventloop.h>
# include <tqapplication.h>
# include <unistd.h> //access()
# include <stdint.h>
# include "tracewidget.h"
# include "floatspinbox.h"
# include "layout.h"
namespace RemoteLab {
typedef KParts : : GenericFactory < RemoteLab : : CommAnalyzerPart > Factory ;
K_EXPORT_COMPONENT_FACTORY ( libremotelab_commanalyzer , RemoteLab : : Factory )
CommAnalyzerPart : : CommAnalyzerPart ( TQWidget * parentWidget , const char * widgetName , TQObject * parent , const char * name , const TQStringList & )
: ReadOnlyPart ( parent , name ) , m_traceWidget ( 0 ) , m_socket ( 0 ) , m_base ( 0 ) , stopTraceUpdate ( false )
{
// Initialize mutex
m_instrumentMutex = new TQMutex ( false ) ;
// Initialize kpart
setInstance ( Factory : : instance ( ) ) ;
setWidget ( new TQVBox ( parentWidget , widgetName ) ) ;
// Create widgets
m_base = new CommAnalyzerBase ( widget ( ) ) ;
m_traceWidget = m_base - > traceWidget ;
m_base - > saRefLevel - > setFloatMin ( - 128 ) ;
m_base - > saRefLevel - > setFloatMax ( 128 ) ;
m_base - > saRefLevel - > setLineStep ( 1 ) ;
connect ( m_base - > saRefLevel , SIGNAL ( floatValueChanged ( double ) ) , this , SLOT ( saRefLevelChanged ( double ) ) ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( postInit ( ) ) ) ;
}
CommAnalyzerPart : : ~ CommAnalyzerPart ( ) {
if ( m_traceWidget ) {
delete m_traceWidget ;
}
if ( m_socket ) {
m_socket - > close ( ) ;
while ( m_socket - > state ( ) = = TQSocket : : Closing ) {
tqApp - > processEvents ( ) ;
}
delete m_socket ;
}
delete m_instrumentMutex ;
}
void CommAnalyzerPart : : postInit ( ) {
m_updateTimer = new TQTimer ( this ) ;
connect ( m_updateTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateTrace ( ) ) ) ;
}
bool CommAnalyzerPart : : openURL ( const KURL & url ) {
connectToServer ( url . url ( ) ) ;
}
bool CommAnalyzerPart : : closeURL ( ) {
if ( m_socket ) {
m_socket - > close ( ) ;
while ( m_socket - > state ( ) ! = TQSocket : : Idle ) {
tqApp - > processEvents ( ) ;
}
}
m_url = KURL ( ) ;
return true ;
}
TQString CommAnalyzerPart : : callServerMethod ( int command ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return TQString : : null ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
cmd . append ( ' \r ' ) ;
m_socket - > writeBlock ( cmd . latin1 ( ) , cmd . length ( ) ) ;
// Read from the server
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
m_instrumentMutex - > unlock ( ) ;
return serverRet ;
}
else {
m_instrumentMutex - > unlock ( ) ;
return TQString : : null ;
}
}
int16_t CommAnalyzerPart : : callServerMethodInt16 ( int command ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return 0 ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
cmd . append ( ' \r ' ) ;
m_socket - > writeBlock ( cmd . latin1 ( ) , cmd . length ( ) ) ;
// Read from the server
int bytesread = 0 ;
int16_t data [ 1 ] ;
while ( ( bytesread < 2 ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
int ret = m_socket - > readBlock ( ( ( char * ) data ) + bytesread , 1 ) ;
if ( ret > 0 ) {
bytesread + = ret ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
m_instrumentMutex - > unlock ( ) ;
return data [ 0 ] ;
}
else {
m_instrumentMutex - > unlock ( ) ;
return 0 ;
}
}
double CommAnalyzerPart : : callServerMethodDouble ( int command ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return 0 ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
cmd . append ( ' \r ' ) ;
m_socket - > writeBlock ( cmd . latin1 ( ) , cmd . length ( ) ) ;
// Read from the server
unsigned int bytesread = 0 ;
double data [ 1 ] ;
while ( ( bytesread < sizeof ( double ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
int ret = m_socket - > readBlock ( ( ( char * ) data ) + bytesread , 1 ) ;
if ( ret > 0 ) {
bytesread + = ret ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
m_instrumentMutex - > unlock ( ) ;
return data [ 0 ] ;
}
else {
m_instrumentMutex - > unlock ( ) ;
return 0 ;
}
}
void CommAnalyzerPart : : sendServerCommandWithParameter ( int command , TQString param ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
param = TQString ( " %1%2%3 " ) . arg ( param ) . arg ( TQChar ( ' ° ' ) ) . arg ( TQChar ( ' \r ' ) ) ;
cmd + = param ;
m_socket - > writeBlock ( cmd . ascii ( ) , cmd . length ( ) ) ;
// Read from the server
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
}
m_instrumentMutex - > unlock ( ) ;
}
void CommAnalyzerPart : : sendServerCommand ( int command ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
cmd . append ( ' \r ' ) ;
m_socket - > writeBlock ( cmd . latin1 ( ) , cmd . length ( ) ) ;
// Read from the server
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
}
m_instrumentMutex - > unlock ( ) ;
}
void CommAnalyzerPart : : callServerMethodDoubleArray ( int command , double * array , int arrayLen ) {
if ( m_instrumentMutex - > locked ( ) = = true ) {
printf ( " [WARN] An attempt was made to access the instrument asynchronously, and was rejected to prevent a lockup \n \r " ) ; fflush ( stdout ) ;
return ;
}
m_instrumentMutex - > lock ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
TQString cmd = TQChar ( command ) ;
cmd . append ( ' \r ' ) ;
m_socket - > writeBlock ( cmd . latin1 ( ) , cmd . length ( ) ) ;
// Read from the server
TQString serverRet ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
unsigned int bytesread = 0 ;
int16_t data [ 1 ] ;
while ( ( bytesread < 2 ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
int ret = m_socket - > readBlock ( ( ( char * ) data ) + bytesread , 1 ) ;
if ( ret > 0 ) {
bytesread + = ret ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
serverRet = " " ;
while ( ( ! serverRet . contains ( ' \r ' ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
char data [ 1 ] ;
if ( m_socket - > readBlock ( data , 1 ) > 0 ) {
serverRet . append ( data [ 0 ] ) ;
}
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
bytesread = 0 ;
int elementsread = 0 ;
for ( elementsread = 0 ; elementsread < arrayLen ; elementsread + + ) {
bytesread = 0 ;
while ( ( bytesread < sizeof ( double ) ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) ) {
if ( m_socket - > size ( ) < 1 ) {
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
int ret = m_socket - > readBlock ( ( ( char * ) array ) + bytesread + ( elementsread * sizeof ( double ) ) , 1 ) ;
if ( ret > 0 ) {
bytesread + = ret ;
}
}
}
}
m_instrumentMutex - > unlock ( ) ;
}
int CommAnalyzerPart : : connectToServer ( TQString server ) {
if ( ! m_socket ) {
m_socket = new TQSocket ( this ) ;
// connect(m_socket, SIGNAL(connected()), SLOT(socketConnected()));
// connect(m_socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()));
// connect(m_socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
// connect(m_socket, SIGNAL(error(int)), SLOT(socketError(int)));
}
m_socket - > connectToHost ( server , 4002 ) ;
while ( ( m_socket - > state ( ) ! = TQSocket : : Connected ) & & ( m_socket - > state ( ) ! = TQSocket : : Idle ) ) {
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : AllEvents ) ;
}
if ( m_socket - > state ( ) ! = TQSocket : : Connected ) {
return - 1 ;
}
// Gather information from the server
if ( callServerMethod ( 41 ) = = " NCK " ) {
// FIXME
// Display message and exit
return - 1 ;
}
sendServerCommand ( 40 ) ; // Set spectrum analyzer mode
m_samplesInTrace = callServerMethodInt16 ( 63 ) ; // Get number of samples in trace
m_traceWidget - > setNumberOfSamples ( m_samplesInTrace ) ;
m_hdivs = callServerMethodInt16 ( 62 ) ; // Get number of horizontal divisions
m_traceWidget - > setNumberOfHorizontalDivisions ( m_hdivs ) ;
m_vdivs = callServerMethodInt16 ( 64 ) ; // Get number of vertical divisions
m_traceWidget - > setNumberOfVerticalDivisions ( m_vdivs ) ;
m_rpower = callServerMethodDouble ( 65 ) ; // Get reference power level
m_vscale = callServerMethodDouble ( 66 ) ; // Get vertical division scale
m_centerfreq = callServerMethodDouble ( 67 ) ; // Get center frequency
m_spanfreq = callServerMethodDouble ( 68 ) ; // Get frequency span
updateGraticule ( ) ;
// Start trace update timer
m_updateTimer - > start ( 10 , FALSE ) ;
}
void CommAnalyzerPart : : postProcessTrace ( ) {
return ;
}
void CommAnalyzerPart : : updateTrace ( ) {
m_updateTimer - > stop ( ) ;
callServerMethodDoubleArray ( 42 , m_traceWidget - > samples ( ) , m_samplesInTrace ) ;
postProcessTrace ( ) ;
m_traceWidget - > repaint ( ) ;
if ( m_socket - > state ( ) = = TQSocket : : Connected ) {
if ( stopTraceUpdate = = true ) {
stopTraceUpdate = false ;
}
else {
m_updateTimer - > start ( 10 , FALSE ) ;
}
}
}
void CommAnalyzerPart : : updateGraticule ( ) {
m_leftFrequency = m_centerfreq - ( m_spanfreq / 2.0 ) ;
m_rightFrequency = m_centerfreq + ( m_spanfreq / 2.0 ) ;
m_traceWidget - > setDisplayLimits ( m_leftFrequency , m_rpower , m_rightFrequency , m_rpower - ( m_vscale * m_hdivs ) ) ;
// Also update controls
m_base - > saRefLevel - > blockSignals ( true ) ;
m_base - > saRefLevel - > setFloatValue ( m_rpower ) ;
m_base - > saRefLevel - > blockSignals ( false ) ;
}
void CommAnalyzerPart : : saRefLevelChanged ( double newval ) {
// We cannot directly send data to the remote instrument because the GUI event may have ocurred during a remote instrument transaction
// This "flaw" is a direct result of maximizing performance by processing GUI events during network transfers, as well as the fact that this client is a multithreaded application
m_rpower = newval ;
stopTraceUpdate = true ;
TQTimer : : singleShot ( 0 , this , SLOT ( changeSaRefLevel ( ) ) ) ;
}
void CommAnalyzerPart : : changeSaRefLevel ( ) {
// Keep trying to set the new power level
if ( m_instrumentMutex - > locked ( ) = = false ) {
sendServerCommandWithParameter ( 61 , TQString ( " %1 " ) . arg ( m_rpower , 0 , ' E ' ) ) ; // Set reference power level
m_rpower = callServerMethodDouble ( 65 ) ; // Get reference power level
updateGraticule ( ) ; // Update the display grid
m_updateTimer - > start ( 10 , FALSE ) ; // Restart trace update timer
}
else {
tqApp - > eventLoop ( ) - > processEvents ( TQEventLoop : : ExcludeUserInput ) ;
TQTimer : : singleShot ( 0 , this , SLOT ( changeSaRefLevel ( ) ) ) ;
}
}
KAboutData * CommAnalyzerPart : : createAboutData ( ) {
return new KAboutData ( APP_NAME , I18N_NOOP ( APP_PRETTYNAME ) , APP_VERSION ) ;
}
} //namespace RemoteLab
# include "part.moc"