From 1f5a3c2804333aec7258129e55a2726c56a1245a Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 22 Jul 2012 03:59:02 -0500 Subject: [PATCH] Fix sensor client server --- clients/tde/src/part/scope/part.cpp | 39 +-- clients/tde/src/part/sensormonitor/layout.ui | 55 +++- clients/tde/src/part/sensormonitor/part.cpp | 238 ++++++++++++++++-- clients/tde/src/part/sensormonitor/part.h | 13 + clients/tde/src/widgets/tracewidget.cpp | 39 ++- clients/tde/src/widgets/tracewidget.h | 1 + .../src/sensor_conn.cpp | 5 + 7 files changed, 337 insertions(+), 53 deletions(-) diff --git a/clients/tde/src/part/scope/part.cpp b/clients/tde/src/part/scope/part.cpp index 7e64592..2b76a49 100644 --- a/clients/tde/src/part/scope/part.cpp +++ b/clients/tde/src/part/scope/part.cpp @@ -398,6 +398,7 @@ void ScopePart::setTickerMessage(TQString message) { m_commHandlerState = ScopeState_ExternalCommandRequest; \ EXEC_NEXT_STATE_IMMEDIATELY \ } +#define SET_NEXT_STATE_DATA_WAITING(x) m_commHandlerState = x; #define EXEC_NEXT_STATE_IMMEDIATELY m_forcedUpdateTimer->start(0, TRUE); @@ -461,7 +462,7 @@ void ScopePart::mainEventLoop() { ds << TQString("RESET"); m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_ResetRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_ResetRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_ResetRequest+1) { @@ -494,7 +495,7 @@ void ScopePart::mainEventLoop() { ds << TQString("GETHORIZONTALDIVCOUNT"); m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_HorizontalDivCountRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_HorizontalDivCountRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_HorizontalDivCountRequest+1) { @@ -530,7 +531,7 @@ void ScopePart::mainEventLoop() { ds << TQString("GETVERTICALDIVCOUNT"); m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_VerticalDivCountRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_VerticalDivCountRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_VerticalDivCountRequest+1) { @@ -566,7 +567,7 @@ void ScopePart::mainEventLoop() { ds << TQString("GETNUMBEROFCHANNELS"); m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_ChannelCountRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_ChannelCountRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_ChannelCountRequest+1) { @@ -608,7 +609,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_ChannelActiveStateRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_ChannelActiveStateRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_ChannelActiveStateRequest+1) { @@ -660,7 +661,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TraceSampleCountRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TraceSampleCountRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TraceSampleCountRequest+1) { @@ -704,7 +705,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TracePermittedVoltsDivRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TracePermittedVoltsDivRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TracePermittedVoltsDivRequest+1) { @@ -752,7 +753,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TraceVoltsDivRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TraceVoltsDivRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TraceVoltsDivRequest+1) { @@ -796,7 +797,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TraceSecondsDivRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TraceSecondsDivRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TraceSecondsDivRequest+1) { @@ -839,7 +840,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TriggerChannelRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TriggerChannelRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TriggerChannelRequest+1) { @@ -876,7 +877,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_TriggerLevelRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TriggerLevelRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TriggerLevelRequest+1) { @@ -918,7 +919,7 @@ void ScopePart::mainEventLoop() { ds << m_currentOpChannel; m_socket->writeEndOfFrame(); - SET_NEXT_STATE(ScopeState_RunningRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_RunningRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_RunningRequest+1) { @@ -964,7 +965,7 @@ void ScopePart::mainEventLoop() { m_socket->writeEndOfFrame(); m_lastChangesRequireFullUpdate = false; - SET_NEXT_STATE(ScopeState_TraceRequest+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TraceRequest+1) EXEC_NEXT_STATE_IMMEDIATELY } else if (m_commHandlerState == ScopeState_TraceRequest+1) { @@ -1032,7 +1033,7 @@ void ScopePart::mainEventLoop() { m_lastChangesRequireFullUpdate = true; m_channelActiveSet[m_currentOpChannel] = false; - SET_NEXT_STATE(ScopeState_ChannelActiveStateUpdate+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_ChannelActiveStateUpdate+1) } else { if (m_currentOpChannel < m_maxNumberOfTraces) { @@ -1097,7 +1098,7 @@ void ScopePart::mainEventLoop() { m_socket->writeEndOfFrame(); m_voltsDivSet[m_currentOpChannel] = false; - SET_NEXT_STATE(ScopeState_TraceVoltsDivUpdate+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TraceVoltsDivUpdate+1) } else { m_currentOpChannel = getNextActiveChannel(m_currentOpChannel, m_channelActive, m_maxNumberOfTraces); @@ -1149,7 +1150,7 @@ void ScopePart::mainEventLoop() { m_socket->writeEndOfFrame(); m_triggerLevelSet = false; - SET_NEXT_STATE(ScopeState_TriggerLevelUpdate+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_TriggerLevelUpdate+1) } else { m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces); @@ -1191,7 +1192,7 @@ void ScopePart::mainEventLoop() { m_socket->writeEndOfFrame(); m_runningSet = false; - SET_NEXT_STATE(ScopeState_RunningUpdate+1) + SET_NEXT_STATE_DATA_WAITING(ScopeState_RunningUpdate+1) } else { m_currentOpChannel = getNextActiveChannel(0, m_channelActive, m_maxNumberOfTraces); @@ -1346,7 +1347,7 @@ void ScopePart::saveWaveforms() { ds << m_traceWidget->samples(traceno-1); ds << m_traceWidget->positions(traceno-1); } - for (int cursorno=0; cursorno<4; cursorno++) { + for (int cursorno=0; cursorno<5; cursorno++) { ds << m_traceWidget->cursorPosition(cursorno); } } @@ -1383,7 +1384,7 @@ void ScopePart::recallWaveforms() { m_base->traceZoomWidget->setSamples(traceno-1, values); m_base->traceZoomWidget->setPositions(traceno-1, positions); } - for (int cursorno=0; cursorno<4; cursorno++) { + for (int cursorno=0; cursorno<5; cursorno++) { double cursorPos; ds >> cursorPos; m_traceWidget->setCursorPosition(cursorno, cursorPos); diff --git a/clients/tde/src/part/sensormonitor/layout.ui b/clients/tde/src/part/sensormonitor/layout.ui index f6dacfc..de29914 100644 --- a/clients/tde/src/part/sensormonitor/layout.ui +++ b/clients/tde/src/part/sensormonitor/layout.ui @@ -101,7 +101,22 @@ groupMonitorCaptureControls - Capture Controls + Sensor Capture Controls + + + + + traceControlLayoutWidget + + + + + + + groupAcquisitionControls + + + Acquisition Controls @@ -109,7 +124,7 @@ runControlStartButton - Run + Start Acquisition @@ -117,12 +132,42 @@ runControlStopButton - Stop + Stop Acquisition - + - traceControlLayoutWidget + waveformSave + + + Save Waveforms + + + + + waveformRecall + + + Recall Waveforms + + + + + autoSave + + + Enable Automatic Saving + + + + + autoSaveFile + + + 25 + + + *.wfm|Waveform Files (*.wfm) diff --git a/clients/tde/src/part/sensormonitor/part.cpp b/clients/tde/src/part/sensormonitor/part.cpp index 31f1213..4d39b86 100644 --- a/clients/tde/src/part/sensormonitor/part.cpp +++ b/clients/tde/src/part/sensormonitor/part.cpp @@ -69,11 +69,13 @@ enum connectionStates { ModeIdle_StateProcessSensorList = 1, ModeIdle_StateStatusRequest = 2, ModeIdle_StateProcessStatus = 3, - ModeIdle_StateDelay = 4, - ModeIdle_StatePaused = 5, - ModeIdle_StateExternalRequest = 6, - ModeGetSample_StateSampleRequest = 7, - ModeGetSample_StateProcessSample = 8 + ModeIdle_StateResetRequest = 4, + ModeIdle_StateProcessReset = 5, + ModeIdle_StateDelay = 6, + ModeIdle_StatePaused = 7, + ModeIdle_StateExternalRequest = 8, + ModeGetSample_StateSampleRequest = 9, + ModeGetSample_StateProcessSample = 10 }; namespace RemoteLab { @@ -119,10 +121,31 @@ TraceControlWidget::TraceControlWidget(TQWidget *parent, const char *name) m_channelEnabledCheckBox->setText(i18n("Enable")); m_primaryLayout->addMultiCellWidget(m_channelEnabledCheckBox, 0, 0, 0, 0); + m_valueLabel = new TQLabel(m_groupBox); + m_valueLabel->setText(i18n("Value: %1").arg(i18n(""))); + m_primaryLayout->addMultiCellWidget(m_valueLabel, 1, 1, 0, 1); + m_valueLabel->hide(); + + m_timestampLabel = new TQLabel(m_groupBox); + m_timestampLabel->setText(i18n("Sampled: %1").arg(i18n(""))); + m_primaryLayout->addMultiCellWidget(m_timestampLabel, 2, 2, 0, 1); + m_timestampLabel->hide(); + + m_timestepLabel1 = new TQLabel(m_groupBox); + m_timestepLabel1->setText(i18n("Sample every:")); + 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, 0, 0, 1, 1); + m_primaryLayout->addMultiCellWidget(m_timestepSpinBox, 4, 4, 0, 0); + m_timestepSpinBox->hide(); + + m_timestepLabel2 = new TQLabel(m_groupBox); + m_timestepLabel2->setText(i18n("seconds")); + m_primaryLayout->addMultiCellWidget(m_timestepLabel2, 4, 4, 1, 1); + m_timestepLabel2->hide(); m_sampleTimer = new TQTimer(); connect(m_sampleTimer, SIGNAL(timeout()), this, SIGNAL(newSampleDesired())); @@ -149,12 +172,30 @@ void TraceControlWidget::stopSampleTimer() { 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(); + } + else { + m_timestepLabel1->hide(); + m_timestepLabel2->hide(); + m_timestepSpinBox->hide(); + m_valueLabel->hide(); + m_timestampLabel->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); @@ -177,6 +218,14 @@ void TraceControlWidget::timestepChanged(double value) { startSampleTimer(value*1.0e3); } +void TraceControlWidget::setCurrentSampleValue(double value, TQString units) { + m_valueLabel->setText(i18n("Value: %1%2").arg(value).arg(units)); +} + +void TraceControlWidget::setCurrentSampleTimestamp(TQDateTime timestamp) { + m_timestampLabel->setText(i18n("Sampled: %1").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) { @@ -249,6 +298,9 @@ SensorMonitorPart::SensorMonitorPart(TQWidget *parentWidget, const char *widgetN // 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())); } @@ -275,10 +327,23 @@ void SensorMonitorPart::processLockouts() { 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); } } @@ -332,7 +397,9 @@ void SensorMonitorPart::connectionStatusChangedCallback() { #define UPDATEDISPLAY_TIMEOUT m_connectionActiveAndValid = false; \ m_tickerState = 0; \ - m_commHandlerState = ModeIdle_StateStatusRequest; \ + if (m_commHandlerState != ModeIdle_StateProcessReset) { \ + m_commHandlerState = ModeIdle_StateResetRequest; \ + } \ m_commHandlerMode = ModeIdle; \ for (int traceno=0; traceno<=MAXTRACES; traceno++) { \ m_sampleRequestInProgress[traceno] = false; \ @@ -456,6 +523,33 @@ void SensorMonitorPart::mainEventLoop() { } } 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()) { @@ -508,12 +602,16 @@ void SensorMonitorPart::mainEventLoop() { 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; @@ -569,12 +667,12 @@ void SensorMonitorPart::updateGraticule() { for (int traceno=0; tracenosetTraceEnabled(traceno, m_channelActive[traceno]); - m_traceWidget->setTraceName(traceno, m_sensorList[traceno].name); + 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], false); - m_base->traceZoomWidget->setTraceName(traceno, m_sensorList[traceno].name); + 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); @@ -604,7 +702,7 @@ void SensorMonitorPart::updateTraceControlWidgets() { 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]->setTraceName(i18n("Sensor %1").arg(m_sensorList[i].name)); m_traceControlWidgetList[i]->show(); // Set sample rate m_traceControlWidgetList[i]->setMinTimestep(m_sensorList[i].mininterval); @@ -653,13 +751,13 @@ void SensorMonitorPart::processNewSampleRequest() { } } if ((channel >= 0) && (channel <=MAXTRACES)) { - if (!stopTraceUpdate) { + if ((!stopTraceUpdate) && (m_commHandlerState != ModeIdle_StateProcessReset) && (m_commHandlerState != ModeIdle_StateResetRequest)) { 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"); + 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)); } } } @@ -688,10 +786,12 @@ void SensorMonitorPart::processNewSampleRequest(int 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); + 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); + } } } @@ -716,6 +816,112 @@ void SensorMonitorPart::acquisitionStopButtonClicked() { 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; tracenotimestep(); + 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> 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->setSamples(traceno, values); + m_traceWidget->setPositions(traceno, positions); + m_base->traceZoomWidget->setSamples(traceno, values); + m_base->traceZoomWidget->setPositions(traceno, positions); + } + 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("The selected waveform file version does not match this client"), i18n("Invalid File")); + } + } + else { + KMessageBox::error(0, i18n("Invalid waveform file selected"), i18n("Invalid File")); + } + } +} + 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 27b40a5..478fda4 100644 --- a/clients/tde/src/part/sensormonitor/part.h +++ b/clients/tde/src/part/sensormonitor/part.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ class TQGridLayout; class TQCheckBox; class TQGroupBox; class TQFile; +class TQLabel; class SensorMonitorBase; namespace RemoteLab @@ -86,10 +88,13 @@ namespace RemoteLab public: void setTraceEnabled(bool enabled); void setTraceName(TQString name); + double timestep(); void setTimestep(double seconds); void setMinTimestep(double seconds); void startSampleTimer(int msecs); void stopSampleTimer(); + void setCurrentSampleValue(double value, TQString units); + void setCurrentSampleTimestamp(TQDateTime timestamp); signals: void enableChanged(bool enabled); @@ -105,6 +110,10 @@ namespace RemoteLab TQCheckBox* m_channelEnabledCheckBox; FloatSpinBox* m_timestepSpinBox; TQTimer* m_sampleTimer; + TQLabel* m_timestepLabel1; + TQLabel* m_timestepLabel2; + TQLabel* m_valueLabel; + TQLabel* m_timestampLabel; double m_minimumTimeStep; double m_nominalTimeStep; @@ -142,8 +151,12 @@ namespace RemoteLab void traceControlEnableChanged(bool enabled); void processNewSampleRequest(); void processNewSampleRequest(int channel); + void processAutosave(); void acquisitionStartButtonClicked(); void acquisitionStopButtonClicked(); + void saveWaveforms(); + void saveWaveforms(TQString fileName); + void recallWaveforms(); private: SensorMonitorBase* m_base; diff --git a/clients/tde/src/widgets/tracewidget.cpp b/clients/tde/src/widgets/tracewidget.cpp index 1ee9721..f4a19e0 100644 --- a/clients/tde/src/widgets/tracewidget.cpp +++ b/clients/tde/src/widgets/tracewidget.cpp @@ -736,7 +736,7 @@ void GraticuleWidget::mouseMoveEvent(TQMouseEvent *e) { #if 0 m_base->m_traceArray[trace]->graphStatusLabel->setText(TQString("%1
@%2,%3").arg(m_base->m_traceArray[trace]->traceName).arg(TraceWidget::prettyFormat(realCursorXPosition, horizontal_range, m_base->m_traceArray[trace]->horizontalUnits)).arg(TraceWidget::prettyFormat(realCursorYPosition, vertical_range, m_base->m_traceArray[trace]->verticalUnits))); #else - m_base->m_traceArray[trace]->graphStatusLabel->setText(TQString("
@%2,%3").arg(TraceWidget::prettyFormat(realCursorXPosition, horizontal_range, m_base->m_traceArray[trace]->horizontalUnits)).arg(TraceWidget::prettyFormat(realCursorYPosition, vertical_range, m_base->m_traceArray[trace]->verticalUnits))); + m_base->m_traceArray[trace]->graphStatusLabel->setText(TQString("@%2,%3").arg(TraceWidget::prettyFormat(realCursorXPosition, (m_base->m_useAbsoluteHorizontalRange)?m_base->m_traceArray[trace]->rightEdge:horizontal_range, m_base->m_traceArray[trace]->horizontalUnits)).arg(TraceWidget::prettyFormat(realCursorYPosition, vertical_range, m_base->m_traceArray[trace]->verticalUnits))); #endif m_base->m_traceArray[trace]->graphStatusLabelInner->setText(m_base->m_traceArray[trace]->graphStatusLabel->text()); } @@ -813,7 +813,8 @@ TraceWidget::TraceWidget(TQWidget* parent, const char* name) : TQWidget(parent, m_cursorDarkness(CURSOR_DARKNESS_FACTOR), m_zoomBoxDarkness(ZOOM_SHADING_DARKNESS_FACTOR), m_zoomCursorStartIndex(0), - m_zoomBoxEnabled(false) { + m_zoomBoxEnabled(false), + m_useAbsoluteHorizontalRange(true) { setBackgroundMode(NoBackground); setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::MinimumExpanding)); @@ -944,7 +945,7 @@ void TraceWidget::updateTraceText() { offsetText = TQString(" +%1").arg(prettyFormat(fabs(offset), vertical_range, m_traceArray[trace]->verticalUnits)); } } - m_traceArray[trace]->paramLabel->setText(TQString("%1%2
%3/div,%4/div
%5,%6
%7,%8").arg(m_traceArray[trace]->traceName).arg(offsetText).arg(prettyFormat(horizontal_units_per_division, horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(vertical_units_per_division, vertical_range, m_traceArray[trace]->verticalUnits)).arg(prettyFormat(m_traceArray[trace]->leftEdge, horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(m_traceArray[trace]->topEdge, vertical_range, m_traceArray[trace]->verticalUnits)).arg(prettyFormat(m_traceArray[trace]->rightEdge, horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(m_traceArray[trace]->bottomEdge, vertical_range, m_traceArray[trace]->verticalUnits))); + m_traceArray[trace]->paramLabel->setText(TQString("
%1%2
%3/div,%4/div
%5,%6
%7,%8").arg(m_traceArray[trace]->traceName).arg(offsetText).arg(prettyFormat(horizontal_units_per_division, horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(vertical_units_per_division, vertical_range, m_traceArray[trace]->verticalUnits)).arg(prettyFormat(m_traceArray[trace]->leftEdge, (m_useAbsoluteHorizontalRange)?m_traceArray[trace]->rightEdge:horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(m_traceArray[trace]->topEdge, vertical_range, m_traceArray[trace]->verticalUnits)).arg(prettyFormat(m_traceArray[trace]->rightEdge, (m_useAbsoluteHorizontalRange)?m_traceArray[trace]->rightEdge:horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(prettyFormat(m_traceArray[trace]->bottomEdge, vertical_range, m_traceArray[trace]->verticalUnits))); } } @@ -1005,7 +1006,7 @@ void TraceWidget::updateCursorText() { } } } - cursorText.append(TQString("
%1: %2%3").arg(m_traceArray[trace]->traceName).arg(prettyFormat(realCursorPosition, horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(deltaText)); + cursorText.append(TQString("
%1: %2%3").arg(m_traceArray[trace]->traceName).arg(prettyFormat(realCursorPosition, (m_useAbsoluteHorizontalRange)?m_traceArray[trace]->rightEdge:horizontal_range, m_traceArray[trace]->horizontalUnits)).arg(deltaText)); } } } @@ -1073,19 +1074,28 @@ void TraceWidget::setTraceEnabled(uint traceNumber, bool enabled, bool showText) VERIFY_TRACE_ARRAY_SIZE m_traceArray[traceNumber]->enabled = enabled; - if ((enabled) && (showText)) { - m_traceArray[traceNumber]->paramLabel->show(); - m_traceArray[traceNumber]->graphStatusLabel->show(); - m_traceArray[traceNumber]->graphStatusLabelInner->hide(); - m_traceArray[traceNumber]->singleIncrBtn->show(); - m_traceArray[traceNumber]->singleDecrBtn->show(); - m_traceArray[traceNumber]->posResetBtn->show(); - + if (enabled) { + if (showText) { + m_traceArray[traceNumber]->paramLabel->show(); + m_traceArray[traceNumber]->graphStatusLabel->show(); + m_traceArray[traceNumber]->graphStatusLabelInner->hide(); + m_traceArray[traceNumber]->singleIncrBtn->show(); + m_traceArray[traceNumber]->singleDecrBtn->show(); + m_traceArray[traceNumber]->posResetBtn->show(); + } + else { + m_traceArray[traceNumber]->paramLabel->hide(); + m_traceArray[traceNumber]->graphStatusLabel->hide(); + m_traceArray[traceNumber]->graphStatusLabelInner->show(); + m_traceArray[traceNumber]->singleIncrBtn->hide(); + m_traceArray[traceNumber]->singleDecrBtn->hide(); + m_traceArray[traceNumber]->posResetBtn->hide(); + } } else { m_traceArray[traceNumber]->paramLabel->hide(); m_traceArray[traceNumber]->graphStatusLabel->hide(); - m_traceArray[traceNumber]->graphStatusLabelInner->show(); + m_traceArray[traceNumber]->graphStatusLabelInner->hide(); m_traceArray[traceNumber]->singleIncrBtn->hide(); m_traceArray[traceNumber]->singleDecrBtn->hide(); m_traceArray[traceNumber]->posResetBtn->hide(); @@ -1502,6 +1512,9 @@ TQString TraceWidget::prettyFormat(double value, double rangeDetectValue, TQStri else { valueString.truncate(precision); } + if (valueString.endsWith(".")) { + valueString.truncate(valueString.length()-1); + } result = TQString("%1%2%3").arg(valueString).arg(unitMultiplier).arg(baseUnits); return result; diff --git a/clients/tde/src/widgets/tracewidget.h b/clients/tde/src/widgets/tracewidget.h index fec91e3..06defcd 100644 --- a/clients/tde/src/widgets/tracewidget.h +++ b/clients/tde/src/widgets/tracewidget.h @@ -270,6 +270,7 @@ class TraceWidget : public TQWidget TQVBoxLayout* m_statusLabelLayout; TQVBoxLayout* m_statusLabelLayoutInner; GraticuleWidget* m_graticuleWidget; + bool m_useAbsoluteHorizontalRange; friend class GraticuleWidget; friend class TraceData; diff --git a/servers/sensor_monitor_server_lin/src/sensor_conn.cpp b/servers/sensor_monitor_server_lin/src/sensor_conn.cpp index 86b8db0..60a42c9 100644 --- a/servers/sensor_monitor_server_lin/src/sensor_conn.cpp +++ b/servers/sensor_monitor_server_lin/src/sensor_conn.cpp @@ -285,6 +285,11 @@ void SensorSocket::commandLoop() { ds << TQString("PONG"); writeEndOfFrame(); } + else if (command == "RESET") { + clearFrameTail(); + ds << TQString("RESET"); + writeEndOfFrame(); + } else { clearFrameTail(); printf("[WARNING] Received unknown command %s from host %s\n\r", command.ascii(), m_remoteHost.ascii()); fflush(stdout);