diff options
Diffstat (limited to 'clients/tde/src/part')
-rw-r--r-- | clients/tde/src/part/scope/part.cpp | 1 | ||||
-rw-r--r-- | clients/tde/src/part/sensormonitor/part.cpp | 468 | ||||
-rw-r--r-- | clients/tde/src/part/sensormonitor/part.h | 90 |
3 files changed, 535 insertions, 24 deletions
diff --git a/clients/tde/src/part/scope/part.cpp b/clients/tde/src/part/scope/part.cpp index 03b6b25..7e64592 100644 --- a/clients/tde/src/part/scope/part.cpp +++ b/clients/tde/src/part/scope/part.cpp @@ -396,6 +396,7 @@ void ScopePart::setTickerMessage(TQString message) { } \ else { \ m_commHandlerState = ScopeState_ExternalCommandRequest; \ + EXEC_NEXT_STATE_IMMEDIATELY \ } #define EXEC_NEXT_STATE_IMMEDIATELY m_forcedUpdateTimer->start(0, TRUE); diff --git a/clients/tde/src/part/sensormonitor/part.cpp b/clients/tde/src/part/sensormonitor/part.cpp index 469f24d..31f1213 100644 --- a/clients/tde/src/part/sensormonitor/part.cpp +++ b/clients/tde/src/part/sensormonitor/part.cpp @@ -40,6 +40,7 @@ #include <tqvbox.h> #include <tqsocket.h> #include <tqmutex.h> +#include <tqlayout.h> #include <tqeventloop.h> #include <tqapplication.h> #include <tqgroupbox.h> @@ -58,13 +59,21 @@ #define NETWORK_COMM_TIMEOUT_MS 2500 enum connectionModes { - ModeIdle = 0 + ModeIdle = 0, + ModeInterruptRequested = 1, + ModeGetSample = 2 }; enum connectionStates { - ModeIdle_StateStatusRequest = 0, - ModeIdle_StateProcessStatus = 1, - ModeIdle_StateDelay = 2 + ModeIdle_StateSensorListRequest = 0, + ModeIdle_StateProcessSensorList = 1, + ModeIdle_StateStatusRequest = 2, + ModeIdle_StateProcessStatus = 3, + ModeIdle_StateDelay = 4, + ModeIdle_StatePaused = 5, + ModeIdle_StateExternalRequest = 6, + ModeGetSample_StateSampleRequest = 7, + ModeGetSample_StateProcessSample = 8 }; namespace RemoteLab { @@ -73,8 +82,103 @@ 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(), KDialog::marginHint(), 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, 0); + + 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, 0, 0, 1, 1); + + m_sampleTimer = new TQTimer(); + connect(m_sampleTimer, SIGNAL(timeout()), this, SIGNAL(newSampleDesired())); +} + +TraceControlWidget::~TraceControlWidget() { + m_sampleTimer->stop(); + delete m_sampleTimer; +} + +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); +} + +void TraceControlWidget::setTraceName(TQString name) { + m_groupBox->setTitle(name); +} + +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); +} + +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); +} + 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) + : 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; @@ -94,12 +198,57 @@ SensorMonitorPart::SensorMonitorPart(TQWidget *parentWidget, const char *widgetN 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(programStartButtonClicked())); - connect(m_base->runControlStopButton, SIGNAL(clicked()), this, SLOT(programStopButtonClicked())); + connect(m_base->runControlStartButton, SIGNAL(clicked()), this, SLOT(acquisitionStartButtonClicked())); + connect(m_base->runControlStopButton, SIGNAL(clicked()), this, SLOT(acquisitionStopButtonClicked())); TQTimer::singleShot(0, this, TQT_SLOT(postInit())); } @@ -123,6 +272,14 @@ void SensorMonitorPart::processLockouts() { mainWidget->setEnabled(false); } } + if (stopTraceUpdate) { + m_base->runControlStartButton->setEnabled(true); + m_base->runControlStopButton->setEnabled(false); + } + else { + m_base->runControlStartButton->setEnabled(false); + m_base->runControlStopButton->setEnabled(true); + } } void SensorMonitorPart::resizeToHint() { @@ -160,7 +317,7 @@ void SensorMonitorPart::connectionFinishedCallback() { m_socket->processPendingData(); connect(m_socket, SIGNAL(newDataReceived()), this, SLOT(mainEventLoop())); m_tickerState = 0; - m_commHandlerState = ModeIdle_StateStatusRequest; + m_commHandlerState = ModeIdle_StateSensorListRequest; m_commHandlerMode = ModeIdle; m_socket->setDataTimeout(NETWORK_COMM_TIMEOUT_MS); m_updateTimeoutTimer->start(NETWORK_COMM_TIMEOUT_MS, TRUE); @@ -177,6 +334,9 @@ void SensorMonitorPart::connectionStatusChangedCallback() { m_tickerState = 0; \ m_commHandlerState = ModeIdle_StateStatusRequest; \ 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); \ @@ -186,7 +346,14 @@ void SensorMonitorPart::connectionStatusChangedCallback() { #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) m_commHandlerState = x; +#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); @@ -224,17 +391,42 @@ void SensorMonitorPart::mainEventLoop() { } if (m_socket) { - if (m_commHandlerMode == ModeIdle) { + 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: - // Get status of remote system - // Clear buffers to synchronize frames in case of data corruption - m_socket->clearIncomingData(); - ds << TQString("STATUS"); + PAT_WATCHDOG_TIMER + + // Ping remote system + ds << TQString("PING"); m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ModeIdle_StateProcessStatus) + SET_NEXT_STATE_DATA_WAITING(ModeIdle_StateProcessStatus) break; case ModeIdle_StateProcessStatus: // Get all data @@ -249,16 +441,14 @@ void SensorMonitorPart::mainEventLoop() { // Transfer probably failed UPDATEDISPLAY_TIMEOUT } - else if (status == "IDLE") { + else if (status == "PONG") { // Do nothing } setTickerMessage(i18n("Connected")); - if (m_commHandlerState == ModeIdle_StateProcessStatus) { - m_pingDelayTimer->start(250, TRUE); - SET_NEXT_STATE(ModeIdle_StateDelay); - } + m_pingDelayTimer->start(250, TRUE); + SET_NEXT_STATE(ModeIdle_StateDelay); } else { if (!m_updateTimeoutTimer->isActive()) { @@ -275,6 +465,67 @@ void SensorMonitorPart::mainEventLoop() { } 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); + + updateGraticule(); + m_traceWidget->repaint(false); + m_base->traceZoomWidget->repaint(false); + } + + 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 + } + } } } @@ -288,6 +539,183 @@ void SensorMonitorPart::mainEventLoop() { 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, 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], false); + m_base->traceZoomWidget->setTraceName(traceno, 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())); + m_traceControlWidgetGrid->addMultiCellWidget(m_traceControlWidgetList[i], i, i, 0, 0); + m_traceControlWidgetList[i]->setTraceName(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::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) { + if (!m_sampleRequestInProgress[channel]) { + m_sampleRequestInProgress[channel] = true; + processNewSampleRequest(channel); + } + else { + printf("[WARNING] Sample request made while previous sample not collected. Some data was not captured (therefore lost)...\n\r"); + } + } + } + } +} + +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 + 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(); +} + KAboutData* SensorMonitorPart::createAboutData() { return new KAboutData( APP_NAME, I18N_NOOP( APP_PRETTYNAME ), APP_VERSION ); } diff --git a/clients/tde/src/part/sensormonitor/part.h b/clients/tde/src/part/sensormonitor/part.h index a6c176c..27b40a5 100644 --- a/clients/tde/src/part/sensormonitor/part.h +++ b/clients/tde/src/part/sensormonitor/part.h @@ -33,21 +33,83 @@ #include <kparts/statusbarextension.h> #include <kparts/part.h> #include <kurl.h> -#include <kled.h> #include <tqtrla.h> +#include "floatspinbox.h" + +#define MAXTRACES 255 + class KAboutData; using KParts::StatusBarExtension; class TraceWidget; class TQSocket; class TQTimer; class TQMutex; +class TQRectF; +class TQGridLayout; +class TQCheckBox; +class TQGroupBox; class TQFile; class SensorMonitorBase; namespace RemoteLab { + class Q_EXPORT TQValueTimer : public TQTimer + { + Q_OBJECT + + public: + TQValueTimer(TQObject *parent=0, const char *name=0); + ~TQValueTimer(); + int value(); + void setValue(int); + + signals: + void valueTimeout(int); + + private slots: + void timeoutHandler(); + + private: + int m_value; + }; + + class TraceControlWidget : public TQWidget + { + Q_OBJECT + + public: + TraceControlWidget(TQWidget *parent=0, const char *name=0); + ~TraceControlWidget(); + + public: + void setTraceEnabled(bool enabled); + void setTraceName(TQString name); + void setTimestep(double seconds); + void setMinTimestep(double seconds); + void startSampleTimer(int msecs); + void stopSampleTimer(); + + signals: + void enableChanged(bool enabled); + void newSampleDesired(); + + private slots: + void enableClicked(); + void timestepChanged(double); + + private: + TQGroupBox* m_groupBox; + TQGridLayout* m_primaryLayout; + TQCheckBox* m_channelEnabledCheckBox; + FloatSpinBox* m_timestepSpinBox; + TQTimer* m_sampleTimer; + + double m_minimumTimeStep; + double m_nominalTimeStep; + }; + class SensorMonitorPart : public KParts::RemoteInstrumentPart { Q_OBJECT @@ -62,6 +124,7 @@ namespace RemoteLab public slots: virtual bool openURL(const KURL &url); + void updateZoomWidgetLimits(const TQRectF& zoomRect); private slots: void postInit(); @@ -73,9 +136,19 @@ namespace RemoteLab void disconnectFromServerCallback(); void connectionStatusChangedCallback(); void setTickerMessage(TQString message); + + void updateGraticule(); + void updateTraceControlWidgets(); + void traceControlEnableChanged(bool enabled); + void processNewSampleRequest(); + void processNewSampleRequest(int channel); + void acquisitionStartButtonClicked(); + void acquisitionStopButtonClicked(); private: SensorMonitorBase* m_base; + TraceWidget* m_traceWidget; + TQGridLayout* m_traceControlWidgetGrid; TQMutex* m_connectionMutex; TQTimer* m_pingDelayTimer; TQTimer* m_forcedUpdateTimer; @@ -87,9 +160,18 @@ namespace RemoteLab int m_commHandlerNextMode; bool m_connectionActiveAndValid; unsigned char m_tickerState; - TQByteArray m_programmingFileData; - TQ_ULONG m_programmingFileTotalSize; - TQ_ULONG m_programmingFileTransferredBytes; + + bool stopTraceUpdate; + SensorList m_sensorList; + TQ_INT16 m_maxNumberOfTraces; + TQ_INT16 m_hdivs; + TQ_INT16 m_vdivs; + TQ_INT32 m_samplesInTrace[MAXTRACES+1]; + bool m_channelActive[MAXTRACES+1]; + TQString m_traceUnits[MAXTRACES+1]; + TraceControlWidget* m_traceControlWidgetList[MAXTRACES]; + TQ_UINT32 m_sampleRequestIndex; + bool m_sampleRequestInProgress[MAXTRACES+1]; }; } |