/*
* Remote Laboratory Sensor Monitor Part
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* ( c ) 2012 - 2014 Timothy Pearson
* Raptor Engineering
* http : //www.raptorengineeringinc.com
*/
# include "define.h"
# include "part.h"
# include <tdeaboutdata.h> //::createAboutData()
# include <tdeaction.h>
# include <tdelocale.h>
# include <ktextedit.h>
# include <tdefiledialog.h>
# include <tdemessagebox.h> //::start()
# include <tdeparts/genericfactory.h>
# include <kstatusbar.h>
# include <kstdaction.h>
# include <knuminput.h>
# include <kmdcodec.h>
# include <kurlrequester.h>
# include <tqfile.h> //encodeName()
# include <tqtimer.h> //postInit() hack
# include <tqvbox.h>
# include <tqsocket.h>
# include <tqmutex.h>
# include <tqlayout.h>
# include <tqeventloop.h>
# include <tqapplication.h>
# include <tqgroupbox.h>
# include <tqcheckbox.h>
# include <tqpushbutton.h>
# include <tqprogressbar.h>
# include <unistd.h> //access()
# include <stdint.h>
# include <tqpainter.h>
# include "tracewidget.h"
# include "floatspinbox.h"
# include "layout.h"
# define NETWORK_COMM_TIMEOUT_MS 2500
enum connectionModes {
ModeIdle = 0 ,
ModeInterruptRequested = 1 ,
ModeGetSample = 2
} ;
enum connectionStates {
ModeIdle_StateSensorListRequest = 0 ,
ModeIdle_StateProcessSensorList = 1 ,
ModeIdle_StateStatusRequest = 2 ,
ModeIdle_StateProcessStatus = 3 ,
ModeIdle_StateResetRequest = 4 ,
ModeIdle_StateProcessReset = 5 ,
ModeIdle_StateDelay = 6 ,
ModeIdle_StatePaused = 7 ,
ModeIdle_StateExternalRequest = 8 ,
ModeGetSample_StateSampleRequest = 9 ,
ModeGetSample_StateProcessSample = 10
} ;
namespace RemoteLab {
typedef KParts : : GenericFactory < RemoteLab : : SensorMonitorPart > Factory ;
# define CLIENT_LIBRARY "libremotelab_sensormonitor"
K_EXPORT_COMPONENT_FACTORY ( libremotelab_sensormonitor , RemoteLab : : Factory )
TQValueTimer : : TQValueTimer ( TQObject * parent , const char * name )
: TQTimer ( parent , name )
{
connect ( this , SIGNAL ( timeout ( ) ) , this , SLOT ( timeoutHandler ( ) ) ) ;
}
TQValueTimer : : ~ TQValueTimer ( ) {
//
}
void TQValueTimer : : timeoutHandler ( ) {
emit ( valueTimeout ( m_value ) ) ;
}
int TQValueTimer : : value ( ) {
return m_value ;
}
void TQValueTimer : : setValue ( int value ) {
m_value = value ;
}
TraceControlWidget : : TraceControlWidget ( TQWidget * parent , const char * name )
: TQWidget ( parent , name ) , m_minimumTimeStep ( 0.0 ) , m_nominalTimeStep ( 1.0 )
{
TQGridLayout * topGrid = new TQGridLayout ( this ) ;
m_groupBox = new TQGroupBox ( this ) ;
m_groupBox - > setColumnLayout ( 0 , TQt : : Vertical ) ;
topGrid - > addMultiCellWidget ( m_groupBox , 0 , 0 , 0 , 0 ) ;
m_groupBox - > setTitle ( i18n ( " Unknown Channel " ) ) ;
m_primaryLayout = new TQGridLayout ( m_groupBox - > layout ( ) , 1 , 1 , KDialog : : spacingHint ( ) ) ;
m_channelEnabledCheckBox = new TQCheckBox ( m_groupBox ) ;
connect ( m_channelEnabledCheckBox , SIGNAL ( clicked ( ) ) , this , SLOT ( enableClicked ( ) ) ) ;
m_channelEnabledCheckBox - > setText ( i18n ( " Enable " ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_channelEnabledCheckBox , 0 , 0 , 0 , 2 ) ;
m_valueLabel = new TQLabel ( m_groupBox ) ;
m_valueLabel - > setText ( i18n ( " <qt><nobr>Value: <b>%1</b></qt> " ) . arg ( i18n ( " <unknown> " ) ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_valueLabel , 1 , 1 , 0 , 2 ) ;
m_valueLabel - > hide ( ) ;
m_timestampLabel = new TQLabel ( m_groupBox ) ;
m_timestampLabel - > setText ( i18n ( " <qt><nobr>Sampled: <b>%1</b></qt> " ) . arg ( i18n ( " <unknown> " ) ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_timestampLabel , 2 , 2 , 0 , 2 ) ;
m_timestampLabel - > hide ( ) ;
m_timestepLabel1 = new TQLabel ( m_groupBox ) ;
m_timestepLabel1 - > setText ( i18n ( " <qt><nobr>Sample every:</qt> " ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_timestepLabel1 , 3 , 3 , 0 , 0 ) ;
m_timestepLabel1 - > hide ( ) ;
m_timestepSpinBox = new FloatSpinBox ( m_groupBox ) ;
m_timestepSpinBox - > setFloatMax ( 60 * 60 * 24 ) ; // 1 day
connect ( m_timestepSpinBox , SIGNAL ( floatValueChanged ( double ) ) , this , SLOT ( timestepChanged ( double ) ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_timestepSpinBox , 3 , 3 , 1 , 1 ) ;
m_timestepSpinBox - > hide ( ) ;
m_timestepLabel2 = new TQLabel ( m_groupBox ) ;
m_timestepLabel2 - > setText ( i18n ( " <qt><nobr>seconds<qt> " ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_timestepLabel2 , 3 , 3 , 2 , 2 ) ;
m_timestepLabel2 - > hide ( ) ;
m_clearPushButton = new TQPushButton ( m_groupBox ) ;
m_clearPushButton - > setText ( i18n ( " Erase Existing Data " ) ) ;
connect ( m_clearPushButton , SIGNAL ( clicked ( ) ) , this , SLOT ( clearTraceDataClicked ( ) ) ) ;
m_primaryLayout - > addMultiCellWidget ( m_clearPushButton , 5 , 5 , 0 , 2 ) ;
m_clearPushButton - > setSizePolicy ( TQSizePolicy ( TQSizePolicy : : MinimumExpanding , TQSizePolicy : : Minimum ) ) ;
m_clearPushButton - > hide ( ) ;
m_sampleTimer = new TQTimer ( ) ;
connect ( m_sampleTimer , SIGNAL ( timeout ( ) ) , this , SIGNAL ( newSampleDesired ( ) ) ) ;
}
TraceControlWidget : : ~ TraceControlWidget ( ) {
m_sampleTimer - > stop ( ) ;
delete m_sampleTimer ;
}
void TraceControlWidget : : clearTraceDataClicked ( ) {
emit ( clearTraceRequested ( ) ) ;
}
void TraceControlWidget : : startSampleTimer ( int msecs ) {
if ( m_channelEnabledCheckBox - > isOn ( ) ) {
m_nominalTimeStep = msecs / 1.0e3 ;
m_sampleTimer - > start ( msecs , FALSE ) ;
}
else {
m_sampleTimer - > stop ( ) ;
}
}
void TraceControlWidget : : stopSampleTimer ( ) {
m_sampleTimer - > stop ( ) ;
}
void TraceControlWidget : : setTraceEnabled ( bool enabled ) {
m_channelEnabledCheckBox - > setChecked ( enabled ) ;
if ( enabled ) {
m_timestepLabel1 - > show ( ) ;
m_timestepLabel2 - > show ( ) ;
m_timestepSpinBox - > show ( ) ;
m_valueLabel - > show ( ) ;
m_timestampLabel - > show ( ) ;
m_clearPushButton - > show ( ) ;
}
else {
m_timestepLabel1 - > hide ( ) ;
m_timestepLabel2 - > hide ( ) ;
m_timestepSpinBox - > hide ( ) ;
m_valueLabel - > hide ( ) ;
m_timestampLabel - > hide ( ) ;
m_clearPushButton - > hide ( ) ;
}
}
void TraceControlWidget : : setTraceName ( TQString name ) {
m_groupBox - > setTitle ( name ) ;
}
double TraceControlWidget : : timestep ( ) {
return m_nominalTimeStep ;
}
void TraceControlWidget : : setTimestep ( double seconds ) {
m_nominalTimeStep = seconds ;
m_timestepSpinBox - > setFloatValue ( m_nominalTimeStep ) ;
startSampleTimer ( m_nominalTimeStep * 1.0e3 ) ;
}
void TraceControlWidget : : setMinTimestep ( double seconds ) {
m_minimumTimeStep = seconds ;
m_timestepSpinBox - > setFloatMin ( seconds ) ;
if ( seconds < 0.001 ) {
m_timestepSpinBox - > setPrecision ( 3 ) ;
}
else if ( seconds < 0.01 ) {
m_timestepSpinBox - > setPrecision ( 2 ) ;
}
else if ( seconds < 0.1 ) {
m_timestepSpinBox - > setPrecision ( 1 ) ;
}
else {
m_timestepSpinBox - > setPrecision ( 0 ) ;
}
}
void TraceControlWidget : : enableClicked ( ) {
bool enabled = m_channelEnabledCheckBox - > isOn ( ) ;
emit ( enableChanged ( enabled ) ) ;
startSampleTimer ( m_nominalTimeStep * 1.0e3 ) ;
}
void TraceControlWidget : : timestepChanged ( double value ) {
m_sampleTimer - > stop ( ) ;
startSampleTimer ( value * 1.0e3 ) ;
}
void TraceControlWidget : : setCurrentSampleValue ( double value , TQString units ) {
m_valueLabel - > setText ( i18n ( " <qt><nobr>Value: <b>%1%2</b></qt> " ) . arg ( value ) . arg ( units ) ) ;
}
void TraceControlWidget : : setCurrentSampleTimestamp ( TQDateTime timestamp ) {
m_timestampLabel - > setText ( i18n ( " <qt><nobr>Sampled: <b>%1 UTC</b></qt> " ) . arg ( timestamp . toString ( ) ) ) ;
}
SensorMonitorPart : : SensorMonitorPart ( TQWidget * parentWidget , const char * widgetName , TQObject * parent , const char * name , const TQStringList & )
: RemoteInstrumentPart ( parent , name ) , m_base ( NULL ) , m_commHandlerState ( 0 ) , m_connectionActiveAndValid ( false ) , m_tickerState ( 0 ) , stopTraceUpdate ( false )
{
// Initialize important base class variables
m_clientLibraryName = CLIENT_LIBRARY ;
// Initialize mutex
m_connectionMutex = new TQMutex ( false ) ;
// Initialize kpart
setInstance ( Factory : : instance ( ) ) ;
setWidget ( new TQVBox ( parentWidget , widgetName ) ) ;
// Create timers
m_forcedUpdateTimer = new TQTimer ( this ) ;
connect ( m_forcedUpdateTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( mainEventLoop ( ) ) ) ;
m_updateTimeoutTimer = new TQTimer ( this ) ;
connect ( m_updateTimeoutTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( mainEventLoop ( ) ) ) ;
m_pingDelayTimer = new TQTimer ( this ) ;
connect ( m_pingDelayTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( mainEventLoop ( ) ) ) ;
// Initialize data
m_hdivs = 10 ;
m_vdivs = 8 ;
m_maxNumberOfTraces = 0 ;
for ( int traceno = 0 ; traceno < = MAXTRACES ; traceno + + ) {
m_samplesInTrace [ traceno ] = 0 ;
m_channelActive [ traceno ] = false ;
m_traceUnits [ traceno ] = " " ;
m_traceControlWidgetList [ traceno ] = NULL ;
m_sampleRequestInProgress [ traceno ] = false ;
}
// Create widgets
m_base = new SensorMonitorBase ( widget ( ) ) ;
m_traceControlWidgetGrid = new TQGridLayout ( m_base - > traceControlLayoutWidget ) ;
m_traceWidget = m_base - > traceWidget ;
m_traceWidget - > setSizePolicy ( TQSizePolicy ( TQSizePolicy : : MinimumExpanding , TQSizePolicy : : MinimumExpanding ) ) ;
m_traceWidget - > setNumberOfCursors ( 4 ) ;
m_traceWidget - > setZoomCursorStartIndex ( 0 ) ;
m_traceWidget - > setCursorOrientation ( 0 , TQt : : Horizontal ) ;
m_traceWidget - > setCursorOrientation ( 1 , TQt : : Horizontal ) ;
m_traceWidget - > setCursorOrientation ( 2 , TQt : : Vertical ) ;
m_traceWidget - > setCursorOrientation ( 3 , TQt : : Vertical ) ;
m_traceWidget - > setCursorEnabled ( 0 , true ) ;
m_traceWidget - > setCursorEnabled ( 1 , true ) ;
m_traceWidget - > setCursorEnabled ( 2 , true ) ;
m_traceWidget - > setCursorEnabled ( 3 , true ) ;
m_traceWidget - > setCursorName ( 0 , " Cursor H1 " ) ;
m_traceWidget - > setCursorName ( 1 , " Cursor H2 " ) ;
m_traceWidget - > setCursorName ( 2 , " Cursor V1 " ) ;
m_traceWidget - > setCursorName ( 3 , " Cursor V2 " ) ;
m_traceWidget - > setCursorPosition ( 0 , 25 ) ;
m_traceWidget - > setCursorPosition ( 1 , 75 ) ;
m_traceWidget - > setCursorPosition ( 2 , 25 ) ;
m_traceWidget - > setCursorPosition ( 3 , 75 ) ;
TraceNumberList activeTraces ;
for ( uint trace = 0 ; trace < MAXTRACES ; trace + + ) {
activeTraces . append ( trace ) ;
}
m_traceWidget - > setCursorActiveTraceList ( 0 , activeTraces ) ;
m_traceWidget - > setCursorActiveTraceList ( 1 , activeTraces ) ;
m_traceWidget - > setCursorActiveTraceList ( 2 , activeTraces ) ;
m_traceWidget - > setCursorActiveTraceList ( 3 , activeTraces ) ;
m_traceWidget - > setZoomBoxEnabled ( true ) ;
m_base - > traceZoomWidget - > setSizePolicy ( TQSizePolicy ( TQSizePolicy : : MinimumExpanding , TQSizePolicy : : MinimumExpanding ) ) ;
connect ( m_traceWidget , SIGNAL ( zoomBoxChanged ( const TQRectF & ) ) , this , SLOT ( updateZoomWidgetLimits ( const TQRectF & ) ) ) ;
// Initialize widgets
connect ( m_base - > runControlStartButton , SIGNAL ( clicked ( ) ) , this , SLOT ( acquisitionStartButtonClicked ( ) ) ) ;
connect ( m_base - > runControlStopButton , SIGNAL ( clicked ( ) ) , this , SLOT ( acquisitionStopButtonClicked ( ) ) ) ;
connect ( m_base - > waveformSave , SIGNAL ( clicked ( ) ) , this , SLOT ( saveWaveforms ( ) ) ) ;
connect ( m_base - > waveformRecall , SIGNAL ( clicked ( ) ) , this , SLOT ( recallWaveforms ( ) ) ) ;
connect ( m_base - > autoSave , SIGNAL ( clicked ( ) ) , this , SLOT ( processLockouts ( ) ) ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( postInit ( ) ) ) ;
}
SensorMonitorPart : : ~ SensorMonitorPart ( ) {
if ( m_connectionMutex - > locked ( ) ) {
printf ( " [WARNING] Exiting when data transfer still in progress! \n \r " ) ; fflush ( stdout ) ;
}
disconnectFromServer ( ) ;
delete m_connectionMutex ;
}
void SensorMonitorPart : : processLockouts ( ) {
TQWidget * mainWidget = widget ( ) ;
if ( mainWidget ) {
if ( ( m_socket ) & & ( m_socket - > state ( ) = = TQSocket : : Connected ) & & ( connToServerState > 0 ) & & ( connToServerConnecting = = false ) ) {
mainWidget - > setEnabled ( true ) ;
}
else {
mainWidget - > setEnabled ( false ) ;
}
}
if ( stopTraceUpdate ) {
m_base - > runControlStartButton - > setEnabled ( true ) ;
m_base - > runControlStopButton - > setEnabled ( false ) ;
m_base - > waveformSave - > setEnabled ( true ) ;
m_base - > waveformRecall - > setEnabled ( true ) ;
m_base - > autoSave - > setEnabled ( true ) ;
if ( m_base - > autoSave - > isOn ( ) ) {
m_base - > autoSaveFile - > setEnabled ( true ) ;
}
else {
m_base - > autoSaveFile - > setEnabled ( false ) ;
}
}
else {
m_base - > runControlStartButton - > setEnabled ( false ) ;
m_base - > runControlStopButton - > setEnabled ( true ) ;
m_base - > waveformSave - > setEnabled ( false ) ;
m_base - > waveformRecall - > setEnabled ( false ) ;
m_base - > autoSave - > setEnabled ( false ) ;
m_base - > autoSaveFile - > setEnabled ( false ) ;
}
}
void SensorMonitorPart : : resizeToHint ( ) {
resize ( widget ( ) - > sizeHint ( ) ) ;
}
void SensorMonitorPart : : connectionClosed ( ) {
closeURL ( ) ;
}
void SensorMonitorPart : : postInit ( ) {
setUsingFixedSize ( false ) ;
}
bool SensorMonitorPart : : openURL ( const KURL & url ) {
int ret ;
ret = connectToServer ( url . url ( ) ) ;
processLockouts ( ) ;
return ( ret ! = 0 ) ;
}
bool SensorMonitorPart : : closeURL ( ) {
disconnectFromServer ( ) ;
m_url = KURL ( ) ;
return true ;
}
void SensorMonitorPart : : disconnectFromServerCallback ( ) {
m_forcedUpdateTimer - > stop ( ) ;
m_updateTimeoutTimer - > stop ( ) ;
}
void SensorMonitorPart : : connectionFinishedCallback ( ) {
connect ( m_socket , SIGNAL ( readyRead ( ) ) , m_socket , SLOT ( processPendingData ( ) ) ) ;
m_socket - > processPendingData ( ) ;
connect ( m_socket , SIGNAL ( newDataReceived ( ) ) , this , SLOT ( mainEventLoop ( ) ) ) ;
m_tickerState = 0 ;
m_commHandlerState = ModeIdle_StateSensorListRequest ;
m_commHandlerMode = ModeIdle ;
m_socket - > setDataTimeout ( NETWORK_COMM_TIMEOUT_MS ) ;
m_updateTimeoutTimer - > start ( NETWORK_COMM_TIMEOUT_MS , TRUE ) ;
processLockouts ( ) ;
mainEventLoop ( ) ;
return ;
}
void SensorMonitorPart : : connectionStatusChangedCallback ( ) {
processLockouts ( ) ;
}
# define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \
m_tickerState = 0 ; \
if ( m_commHandlerState ! = ModeIdle_StateProcessReset ) { \
m_commHandlerState = ModeIdle_StateResetRequest ; \
} \
m_commHandlerMode = ModeIdle ; \
for ( int traceno = 0 ; traceno < = MAXTRACES ; traceno + + ) { \
m_sampleRequestInProgress [ traceno ] = false ; \
} \
m_socket - > clearIncomingData ( ) ; \
setStatusMessage ( i18n ( " Server ping timeout. Please verify the status of your network connection. " ) ) ; \
m_updateTimeoutTimer - > start ( NETWORK_COMM_TIMEOUT_MS , TRUE ) ; \
m_connectionMutex - > unlock ( ) ; \
return ;
# define SET_WATCHDOG_TIMER if (!m_updateTimeoutTimer->isActive()) m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE);
# define PAT_WATCHDOG_TIMER m_updateTimeoutTimer->stop(); m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE);
# define SET_NEXT_STATE(x) if ((m_commHandlerMode == ModeIdle) || (m_commHandlerMode == ModeGetSample)) { \
m_commHandlerState = x ; \
} \
else { \
m_commHandlerState = ModeIdle_StateExternalRequest ; \
EXEC_NEXT_STATE_IMMEDIATELY \
}
# define SET_NEXT_STATE_DATA_WAITING(x) m_commHandlerState = x;
# define EXEC_NEXT_STATE_IMMEDIATELY m_forcedUpdateTimer->start(0, TRUE);
void SensorMonitorPart : : setTickerMessage ( TQString message ) {
m_connectionActiveAndValid = true ;
TQString tickerChar ;
switch ( m_tickerState ) {
case 0 :
tickerChar = " - " ;
break ;
case 1 :
tickerChar = " \\ " ;
break ;
case 2 :
tickerChar = " | " ;
break ;
case 3 :
tickerChar = " / " ;
break ;
}
setStatusMessage ( message + TQString ( " ... %1 " ) . arg ( tickerChar ) ) ;
m_tickerState + + ;
if ( m_tickerState > 3 ) {
m_tickerState = 0 ;
}
}
void SensorMonitorPart : : mainEventLoop ( ) {
TQDataStream ds ( m_socket ) ;
ds . setPrintableData ( true ) ;
if ( ! m_connectionMutex - > tryLock ( ) ) {
EXEC_NEXT_STATE_IMMEDIATELY
return ;
}
if ( m_socket ) {
if ( ( m_commHandlerMode = = ModeIdle ) | | ( m_commHandlerMode = = ModeInterruptRequested ) ) {
// Normal operation
switch ( m_commHandlerState ) {
case ModeIdle_StateSensorListRequest :
PAT_WATCHDOG_TIMER
ds < < TQString ( " SENSORS " ) ;
m_socket - > writeEndOfFrame ( ) ;
SET_NEXT_STATE_DATA_WAITING ( ModeIdle_StateProcessSensorList )
break ;
case ModeIdle_StateProcessSensorList :
if ( m_socket - > canReadFrame ( ) ) {
PAT_WATCHDOG_TIMER
ds > > m_sensorList ;
m_socket - > clearFrameTail ( ) ;
m_maxNumberOfTraces = m_sensorList . count ( ) ;
updateTraceControlWidgets ( ) ;
SET_NEXT_STATE ( ModeIdle_StateStatusRequest )
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
if ( ! m_updateTimeoutTimer - > isActive ( ) ) {
UPDATEDISPLAY_TIMEOUT
}
}
break ;
case ModeIdle_StateStatusRequest :
PAT_WATCHDOG_TIMER
// Ping remote system
ds < < TQString ( " PING " ) ;
m_socket - > writeEndOfFrame ( ) ;
SET_NEXT_STATE_DATA_WAITING ( ModeIdle_StateProcessStatus )
break ;
case ModeIdle_StateProcessStatus :
// Get all data
if ( m_socket - > canReadFrame ( ) ) {
PAT_WATCHDOG_TIMER
TQString status ;
ds > > status ;
m_socket - > clearFrameTail ( ) ;
if ( status = = " " ) {
// Transfer probably failed
UPDATEDISPLAY_TIMEOUT
}
else if ( status = = " PONG " ) {
// Do nothing
}
setTickerMessage ( i18n ( " Connected " ) ) ;
m_pingDelayTimer - > start ( 250 , TRUE ) ;
SET_NEXT_STATE ( ModeIdle_StateDelay ) ;
}
else {
if ( ! m_updateTimeoutTimer - > isActive ( ) ) {
UPDATEDISPLAY_TIMEOUT
}
}
break ;
case ModeIdle_StateResetRequest :
// Reset remote system
ds < < TQString ( " RESET " ) ;
m_socket - > writeEndOfFrame ( ) ;
SET_NEXT_STATE_DATA_WAITING ( ModeIdle_StateProcessReset )
break ;
case ModeIdle_StateProcessReset :
// Get all data
if ( m_socket - > canReadFrame ( ) ) {
PAT_WATCHDOG_TIMER
TQString status ;
ds > > status ;
m_socket - > clearFrameTail ( ) ;
if ( status = = " RESET " ) {
SET_NEXT_STATE ( ModeIdle_StateStatusRequest )
EXEC_NEXT_STATE_IMMEDIATELY
}
}
else {
if ( ! m_updateTimeoutTimer - > isActive ( ) ) {
UPDATEDISPLAY_TIMEOUT
}
}
break ;
case ModeIdle_StateDelay :
// Let the client and server rest for a bit to lower CPU/network overhead
if ( ! m_pingDelayTimer - > isActive ( ) ) {
EXEC_NEXT_STATE_IMMEDIATELY
// Execute query on next event loop
SET_NEXT_STATE ( ModeIdle_StateStatusRequest ) ;
}
PAT_WATCHDOG_TIMER
break ;
case ModeIdle_StatePaused :
PAT_WATCHDOG_TIMER
break ;
case ModeIdle_StateExternalRequest :
m_commHandlerMode = ModeGetSample ;
m_commHandlerState = m_commHandlerNextState ;
break ;
}
}
else if ( m_commHandlerMode = = ModeGetSample ) {
if ( m_commHandlerState = = ModeGetSample_StateSampleRequest ) {
PAT_WATCHDOG_TIMER
ds < < TQString ( " SAMPLE " ) ;
ds < < m_sampleRequestIndex ;
m_socket - > writeEndOfFrame ( ) ;
SET_NEXT_STATE_DATA_WAITING ( ModeGetSample_StateProcessSample )
setTickerMessage ( i18n ( " Obtaining new data point for sensor %1 " ) . arg ( m_sensorList [ m_sampleRequestIndex ] . name ) ) ;
}
else if ( m_commHandlerState = = ModeGetSample_StateProcessSample ) {
if ( m_socket - > canReadFrame ( ) ) {
PAT_WATCHDOG_TIMER
TQString result ;
double newValue ;
TQDateTime timestamp ;
ds > > result ;
if ( result = = " ACK " ) {
ds > > newValue ;
ds > > timestamp ;
TQDoubleArray sampleArray = m_traceWidget - > samples ( m_sampleRequestIndex ) ;
TQDoubleArray positionArray = m_traceWidget - > positions ( m_sampleRequestIndex ) ;
m_samplesInTrace [ m_sampleRequestIndex ] + + ;
sampleArray . resize ( m_samplesInTrace [ m_sampleRequestIndex ] ) ;
positionArray . resize ( m_samplesInTrace [ m_sampleRequestIndex ] ) ;
sampleArray [ m_samplesInTrace [ m_sampleRequestIndex ] - 1 ] = newValue ;
positionArray [ m_samplesInTrace [ m_sampleRequestIndex ] - 1 ] = ( timestamp . toTime_t ( ) + ( timestamp . time ( ) . msec ( ) * 1.0e-3 ) ) ;
m_traceWidget - > setSamples ( m_sampleRequestIndex , sampleArray ) ;
m_traceWidget - > setPositions ( m_sampleRequestIndex , positionArray ) ;
m_base - > traceZoomWidget - > setSamples ( m_sampleRequestIndex , sampleArray ) ;
m_base - > traceZoomWidget - > setPositions ( m_sampleRequestIndex , positionArray ) ;
m_traceControlWidgetList [ m_sampleRequestIndex ] - > setCurrentSampleValue ( newValue , m_sensorList [ m_sampleRequestIndex ] . units ) ;
m_traceControlWidgetList [ m_sampleRequestIndex ] - > setCurrentSampleTimestamp ( timestamp ) ;
updateGraticule ( ) ;
m_traceWidget - > repaint ( false ) ;
m_base - > traceZoomWidget - > repaint ( false ) ;
}
processAutosave ( ) ;
m_socket - > clearFrameTail ( ) ;
m_sampleRequestInProgress [ m_sampleRequestIndex ] = false ;
m_commHandlerMode = ModeIdle ;
m_pingDelayTimer - > start ( 250 , TRUE ) ;
SET_NEXT_STATE ( ModeIdle_StateDelay ) ;
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
if ( ! m_updateTimeoutTimer - > isActive ( ) ) {
UPDATEDISPLAY_TIMEOUT
}
}
}
}
SET_WATCHDOG_TIMER
}
else {
SET_NEXT_STATE ( ModeIdle_StateStatusRequest ) ;
m_commHandlerMode = ModeIdle ;
}
m_connectionMutex - > unlock ( ) ;
}
void SensorMonitorPart : : updateZoomWidgetLimits ( const TQRectF & zoomRect ) {
for ( int traceno = 0 ; traceno < m_maxNumberOfTraces ; traceno + + ) {
TQRectF fullZoomRect = m_traceWidget - > displayLimits ( traceno ) ;
double widthSpan = fullZoomRect . width ( ) - fullZoomRect . x ( ) ;
double heightSpan = fullZoomRect . height ( ) - fullZoomRect . y ( ) ;
TQRectF zoomLimitsRect ( ( fullZoomRect . x ( ) + ( widthSpan * ( zoomRect . x ( ) / 100.0 ) ) ) , ( fullZoomRect . y ( ) + ( heightSpan * ( zoomRect . y ( ) / 100.0 ) ) ) , ( fullZoomRect . x ( ) + ( widthSpan * ( ( zoomRect . x ( ) / 100.0 ) + ( zoomRect . width ( ) / 100.0 ) ) ) ) , ( fullZoomRect . y ( ) + ( heightSpan * ( ( zoomRect . y ( ) / 100.0 ) + ( zoomRect . height ( ) / 100.0 ) ) ) ) ) ;
m_base - > traceZoomWidget - > setDisplayLimits ( traceno , zoomLimitsRect ) ;
}
}
void SensorMonitorPart : : updateGraticule ( ) {
m_traceWidget - > setNumberOfHorizontalDivisions ( m_hdivs ) ;
m_traceWidget - > setNumberOfVerticalDivisions ( m_vdivs ) ;
m_base - > traceZoomWidget - > setNumberOfHorizontalDivisions ( m_hdivs ) ;
m_base - > traceZoomWidget - > setNumberOfVerticalDivisions ( m_vdivs ) ;
if ( m_maxNumberOfTraces > 0 ) m_traceWidget - > setTraceColor ( 0 , TQColor ( 255 , 255 , 255 ) ) ;
if ( m_maxNumberOfTraces > 1 ) m_traceWidget - > setTraceColor ( 1 , TQColor ( 128 , 255 , 128 ) ) ;
if ( m_maxNumberOfTraces > 2 ) m_traceWidget - > setTraceColor ( 2 , TQColor ( 255 , 255 , 128 ) ) ;
if ( m_maxNumberOfTraces > 3 ) m_traceWidget - > setTraceColor ( 3 , TQColor ( 128 , 128 , 255 ) ) ;
if ( m_maxNumberOfTraces > 0 ) m_base - > traceZoomWidget - > setTraceColor ( 0 , TQColor ( 255 , 255 , 255 ) ) ;
if ( m_maxNumberOfTraces > 1 ) m_base - > traceZoomWidget - > setTraceColor ( 1 , TQColor ( 128 , 255 , 128 ) ) ;
if ( m_maxNumberOfTraces > 2 ) m_base - > traceZoomWidget - > setTraceColor ( 2 , TQColor ( 255 , 255 , 128 ) ) ;
if ( m_maxNumberOfTraces > 3 ) m_base - > traceZoomWidget - > setTraceColor ( 3 , TQColor ( 128 , 128 , 255 ) ) ;
for ( int traceno = 0 ; traceno < m_maxNumberOfTraces ; traceno + + ) {
m_traceWidget - > setTraceEnabled ( traceno , m_channelActive [ traceno ] ) ;
m_traceWidget - > setTraceName ( traceno , i18n ( " Sensor %1 " ) . arg ( m_sensorList [ traceno ] . name ) ) ;
m_traceWidget - > setTraceHorizontalUnits ( traceno , " s " ) ;
m_traceWidget - > setTraceVerticalUnits ( traceno , m_sensorList [ traceno ] . units ) ;
m_base - > traceZoomWidget - > setTraceEnabled ( traceno , m_channelActive [ traceno ] , TraceWidget : : SummaryText ) ;
m_base - > traceZoomWidget - > setTraceName ( traceno , i18n ( " Sensor %1 " ) . arg ( m_sensorList [ traceno ] . name ) ) ;
m_base - > traceZoomWidget - > setTraceHorizontalUnits ( traceno , " s " ) ;
m_base - > traceZoomWidget - > setTraceVerticalUnits ( traceno , m_sensorList [ traceno ] . units ) ;
m_traceWidget - > setNumberOfSamples ( traceno , m_samplesInTrace [ traceno ] ) ;
m_base - > traceZoomWidget - > setNumberOfSamples ( traceno , m_samplesInTrace [ traceno ] ) ;
double starttime = 0.0 ;
double endtime = 0.0 ;
if ( m_samplesInTrace [ traceno ] > 0 ) {
starttime = m_traceWidget - > positions ( traceno ) [ 0 ] ;
endtime = m_traceWidget - > positions ( traceno ) [ m_samplesInTrace [ traceno ] - 1 ] ;
}
m_traceWidget - > setDisplayLimits ( traceno , TQRectF ( starttime , m_sensorList [ traceno ] . max , endtime , m_sensorList [ traceno ] . min ) ) ;
if ( m_traceControlWidgetList [ traceno ] ) {
m_traceControlWidgetList [ traceno ] - > setTraceEnabled ( m_channelActive [ traceno ] ) ;
}
}
updateZoomWidgetLimits ( m_traceWidget - > zoomBox ( ) ) ;
}
void SensorMonitorPart : : updateTraceControlWidgets ( ) {
// Add or remove trace control widgets as needed...
int i ;
for ( i = 0 ; i < m_maxNumberOfTraces ; i + + ) {
if ( ! m_traceControlWidgetList [ i ] ) {
m_traceControlWidgetList [ i ] = new TraceControlWidget ( m_base - > traceControlLayoutWidget ) ;
connect ( m_traceControlWidgetList [ i ] , SIGNAL ( enableChanged ( bool ) ) , this , SLOT ( traceControlEnableChanged ( bool ) ) ) ;
connect ( m_traceControlWidgetList [ i ] , SIGNAL ( newSampleDesired ( ) ) , this , SLOT ( processNewSampleRequest ( ) ) ) ;
connect ( m_traceControlWidgetList [ i ] , SIGNAL ( clearTraceRequested ( ) ) , this , SLOT ( traceControlClearRequested ( ) ) ) ;
m_traceControlWidgetGrid - > addMultiCellWidget ( m_traceControlWidgetList [ i ] , i , i , 0 , 0 ) ;
m_traceControlWidgetList [ i ] - > setTraceName ( i18n ( " Sensor %1 " ) . arg ( m_sensorList [ i ] . name ) ) ;
m_traceControlWidgetList [ i ] - > show ( ) ;
// Set sample rate
m_traceControlWidgetList [ i ] - > setMinTimestep ( m_sensorList [ i ] . mininterval ) ;
m_traceControlWidgetList [ i ] - > setTimestep ( m_sensorList [ i ] . nominalinterval ) ;
}
}
for ( i = m_maxNumberOfTraces ; i < MAXTRACES ; i + + ) {
if ( m_traceControlWidgetList [ i ] ) {
m_traceControlWidgetGrid - > remove ( m_traceControlWidgetList [ i ] ) ;
delete m_traceControlWidgetList [ i ] ;
}
}
}
void SensorMonitorPart : : traceControlEnableChanged ( bool enabled ) {
int i ;
int channel = - 1 ;
const TraceControlWidget * widget = dynamic_cast < const TraceControlWidget * > ( sender ( ) ) ;
if ( widget ) {
for ( i = 0 ; i < MAXTRACES ; i + + ) {
if ( m_traceControlWidgetList [ i ] = = widget ) {
channel = i ;
break ;
}
}
if ( ( channel > = 0 ) & & ( channel < = MAXTRACES ) ) {
m_channelActive [ channel ] = enabled ;
}
}
updateGraticule ( ) ;
m_traceWidget - > repaint ( false ) ;
m_base - > traceZoomWidget - > repaint ( false ) ;
updateTraceControlWidgets ( ) ;
}
void SensorMonitorPart : : traceControlClearRequested ( ) {
int i ;
int channel = - 1 ;
const TraceControlWidget * widget = dynamic_cast < const TraceControlWidget * > ( sender ( ) ) ;
if ( widget ) {
for ( i = 0 ; i < MAXTRACES ; i + + ) {
if ( m_traceControlWidgetList [ i ] = = widget ) {
channel = i ;
break ;
}
}
if ( ( channel > = 0 ) & & ( channel < = MAXTRACES ) ) {
m_samplesInTrace [ channel ] = 0 ;
TQDoubleArray sampleArray ;
TQDoubleArray positionArray ;
m_traceWidget - > setSamples ( m_sampleRequestIndex , sampleArray ) ;
m_traceWidget - > setPositions ( m_sampleRequestIndex , positionArray ) ;
m_base - > traceZoomWidget - > setSamples ( m_sampleRequestIndex , sampleArray ) ;
m_base - > traceZoomWidget - > setPositions ( m_sampleRequestIndex , positionArray ) ;
m_traceControlWidgetList [ m_sampleRequestIndex ] - > setCurrentSampleValue ( 0 , m_sensorList [ channel ] . units ) ;
m_traceControlWidgetList [ m_sampleRequestIndex ] - > setCurrentSampleTimestamp ( TQDateTime ( ) ) ;
}
}
updateGraticule ( ) ;
m_traceWidget - > repaint ( false ) ;
m_base - > traceZoomWidget - > repaint ( false ) ;
updateTraceControlWidgets ( ) ;
}
void SensorMonitorPart : : processNewSampleRequest ( ) {
int i ;
int channel = - 1 ;
const TraceControlWidget * widget = dynamic_cast < const TraceControlWidget * > ( sender ( ) ) ;
if ( widget ) {
for ( i = 0 ; i < MAXTRACES ; i + + ) {
if ( m_traceControlWidgetList [ i ] = = widget ) {
channel = i ;
break ;
}
}
if ( ( channel > = 0 ) & & ( channel < = MAXTRACES ) ) {
if ( ( ! stopTraceUpdate ) & & ( m_commHandlerState ! = ModeIdle_StateProcessReset ) & & ( m_commHandlerState ! = ModeIdle_StateResetRequest ) ) {
if ( ! m_sampleRequestInProgress [ channel ] ) {
m_sampleRequestInProgress [ channel ] = true ;
processNewSampleRequest ( channel ) ;
}
else {
setStatusMessage ( i18n ( " Sample request made while previous sample not collected. Some data was not captured (therefore lost) for sensor %1 " ) . arg ( m_sensorList [ channel ] . name ) ) ;
}
}
}
}
}
void SensorMonitorPart : : processNewSampleRequest ( int channel ) {
TQValueTimer * senderTimer = const_cast < TQValueTimer * > ( dynamic_cast < const TQValueTimer * > ( sender ( ) ) ) ;
if ( senderTimer ) {
senderTimer - > stop ( ) ;
delete senderTimer ;
}
if ( m_commHandlerMode = = ModeIdle ) {
// Request a sample
if ( m_commHandlerState = = ModeIdle_StateDelay ) {
m_commHandlerMode = ModeGetSample ;
m_commHandlerState = ModeGetSample_StateSampleRequest ;
EXEC_NEXT_STATE_IMMEDIATELY
}
else {
m_commHandlerMode = ModeInterruptRequested ;
m_commHandlerNextState = ModeGetSample_StateSampleRequest ;
}
m_sampleRequestIndex = channel ;
}
else {
// The main loop is already getting a sample
// Resubmit the request later on
if ( ( ! stopTraceUpdate ) & & ( m_commHandlerState ! = ModeIdle_StateProcessReset ) & & ( m_commHandlerState ! = ModeIdle_StateResetRequest ) ) {
TQValueTimer * timer = new TQValueTimer ;
timer - > setValue ( channel ) ;
connect ( timer , SIGNAL ( valueTimeout ( int ) ) , this , SLOT ( processNewSampleRequest ( int ) ) ) ;
timer - > start ( 10 , TRUE ) ;
}
}
}
void SensorMonitorPart : : acquisitionStartButtonClicked ( ) {
stopTraceUpdate = false ;
processLockouts ( ) ;
if ( m_socket ) m_socket - > clearIncomingData ( ) ;
m_commHandlerMode = ModeIdle ;
m_commHandlerState = ModeIdle_StateStatusRequest ;
EXEC_NEXT_STATE_IMMEDIATELY
}
void SensorMonitorPart : : acquisitionStopButtonClicked ( ) {
stopTraceUpdate = true ;
processLockouts ( ) ;
for ( int i = 0 ; i < MAXTRACES ; i + + ) {
m_sampleRequestInProgress [ i ] = false ;
}
m_commHandlerMode = ModeIdle ;
m_commHandlerState = ModeIdle_StatePaused ;
setStatusMessage ( i18n ( " Acquisition stopped " ) ) ;
mainEventLoop ( ) ;
}
void SensorMonitorPart : : processAutosave ( ) {
if ( m_base - > autoSave - > isOn ( ) ) {
if ( m_base - > autoSaveFile - > url ( ) ! = " " ) {
saveWaveforms ( m_base - > autoSaveFile - > url ( ) ) ;
}
}
}
# define WAVEFORM_MAGIC_NUMBER 2
# define WAVEFORM_FILE_VERSION 1
void SensorMonitorPart : : saveWaveforms ( ) {
saveWaveforms ( TQString : : null ) ;
}
void SensorMonitorPart : : saveWaveforms ( TQString fileName ) {
TQString saveFileName ;
if ( fileName ! = " " ) {
saveFileName = fileName ;
}
else {
saveFileName = KFileDialog : : getSaveFileName ( TQString : : null , " *.wfm|Waveform Files (*.wfm) " , 0 , i18n ( " Save waveforms... " ) ) ;
}
if ( saveFileName ! = " " ) {
TQFile file ( saveFileName ) ;
file . open ( IO_WriteOnly ) ;
TQDataStream ds ( & file ) ;
TQ_INT32 magicNumber = WAVEFORM_MAGIC_NUMBER ;
TQ_INT32 version = WAVEFORM_FILE_VERSION ;
ds < < magicNumber ;
ds < < version ;
ds < < m_sensorList ;
ds < < m_hdivs ;
ds < < m_vdivs ;
ds < < m_maxNumberOfTraces ;
for ( int traceno = 0 ; traceno < m_maxNumberOfTraces ; traceno + + ) {
TQ_UINT8 boolValue ;
boolValue = m_channelActive [ traceno ] ;
ds < < boolValue ;
ds < < m_traceControlWidgetList [ traceno ] - > timestep ( ) ;
ds < < m_samplesInTrace [ traceno ] ;
ds < < m_traceUnits [ traceno ] ;
ds < < m_traceWidget - > samples ( traceno ) ;
ds < < m_traceWidget - > positions ( traceno ) ;
}
for ( int cursorno = 0 ; cursorno < 4 ; cursorno + + ) {
ds < < m_traceWidget - > cursorPosition ( cursorno ) ;
}
}
}
void SensorMonitorPart : : recallWaveforms ( ) {
TQString openFileName = KFileDialog : : getOpenFileName ( TQString : : null , " *.wfm|Waveform Files (*.wfm) " , 0 , i18n ( " Open waveforms... " ) ) ;
if ( openFileName ! = " " ) {
TQFile file ( openFileName ) ;
file . open ( IO_ReadOnly ) ;
TQDataStream ds ( & file ) ;
TQ_INT32 magicNumber ;
TQ_INT32 version ;
ds > > magicNumber ;
if ( magicNumber = = WAVEFORM_MAGIC_NUMBER ) {
ds > > version ;
if ( version = = WAVEFORM_FILE_VERSION ) {
ds > > m_sensorList ;
ds > > m_hdivs ;
ds > > m_vdivs ;
ds > > m_maxNumberOfTraces ;
updateTraceControlWidgets ( ) ;
for ( int traceno = 0 ; traceno < m_maxNumberOfTraces ; traceno + + ) {
TQ_UINT8 boolValue ;
ds > > boolValue ;
m_channelActive [ traceno ] = ( boolValue ! = 0 ) ? true : false ;
double timestep ;
ds > > timestep ;
m_traceControlWidgetList [ traceno ] - > setTimestep ( timestep ) ;
ds > > m_samplesInTrace [ traceno ] ;
ds > > m_traceUnits [ traceno ] ;
TQDoubleArray values ;
TQDoubleArray positions ;
ds > > values ;
ds > > positions ;
m_traceWidget - > setNumberOfSamples ( traceno , m_samplesInTrace [ traceno ] , true ) ;
m_traceWidget - > setSamples ( traceno , values ) ;
m_traceWidget - > setPositions ( traceno , positions ) ;
m_base - > traceZoomWidget - > setSamples ( traceno , values ) ;
m_base - > traceZoomWidget - > setPositions ( traceno , positions ) ;
if ( m_samplesInTrace [ traceno ] > 0 ) {
m_traceControlWidgetList [ traceno ] - > setCurrentSampleValue ( values [ m_samplesInTrace [ traceno ] - 1 ] , m_sensorList [ traceno ] . units ) ;
TQDateTime lastSampleTime ;
lastSampleTime . setTime_t ( positions [ m_samplesInTrace [ traceno ] - 1 ] ) ;
m_traceControlWidgetList [ traceno ] - > setCurrentSampleTimestamp ( lastSampleTime ) ;
}
}
for ( int cursorno = 0 ; cursorno < 4 ; cursorno + + ) {
double cursorPos ;
ds > > cursorPos ;
m_traceWidget - > setCursorPosition ( cursorno , cursorPos ) ;
}
updateGraticule ( ) ;
m_traceWidget - > repaint ( false ) ;
m_base - > traceZoomWidget - > repaint ( false ) ;
updateTraceControlWidgets ( ) ;
}
else {
KMessageBox : : error ( 0 , i18n ( " <qt>The selected waveform file version does not match this client</qt> " ) , i18n ( " Invalid File " ) ) ;
}
}
else {
KMessageBox : : error ( 0 , i18n ( " <qt>Invalid waveform file selected</qt> " ) , i18n ( " Invalid File " ) ) ;
}
}
}
TDEAboutData * SensorMonitorPart : : createAboutData ( ) {
return new TDEAboutData ( APP_NAME , I18N_NOOP ( APP_PRETTYNAME ) , APP_VERSION ) ;
}
} //namespace RemoteLab
# include "part.moc"