//Author: Timothy Pearson , (C) 2012 //Copyright: See COPYING file that comes with this distribution #include "debug.h" #include "define.h" #include "part.h" #include //::createAboutData() #include #include #include //::start() #include #include #include #include //encodeName() #include //postInit() hack #include #include #include #include #include #include //access() #include #include "tracewidget.h" #include "floatspinbox.h" #include "layout.h" namespace RemoteLab { typedef KParts::GenericFactory 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;elementsreadstate() == 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"