diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-04-30 16:46:20 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-04-30 16:46:20 -0500 |
commit | 408e828f4732c9bb4aa3673c87d85109e06c08e1 (patch) | |
tree | ecd25f872402cea120a442d3f2744d74d699b675 /clients/tde/src/part/commanalyzer/part.cpp | |
parent | f8d372779417eeb809088893ca58ad6a318ab418 (diff) | |
download | ulab-408e828f4732c9bb4aa3673c87d85109e06c08e1.tar.gz ulab-408e828f4732c9bb4aa3673c87d85109e06c08e1.zip |
Fixups for ca server
Add very preliminary client for ca and TDE
Diffstat (limited to 'clients/tde/src/part/commanalyzer/part.cpp')
-rw-r--r-- | clients/tde/src/part/commanalyzer/part.cpp | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/clients/tde/src/part/commanalyzer/part.cpp b/clients/tde/src/part/commanalyzer/part.cpp new file mode 100644 index 0000000..3fd89eb --- /dev/null +++ b/clients/tde/src/part/commanalyzer/part.cpp @@ -0,0 +1,396 @@ +//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() { + 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" |