Retake control of serial port after using QProcess



  • Hi,
    I'm writing a qt linux application to exchange files between two computers using zmodem protocol via Serial port and PSTN network. I'm using serial->write and waitforbytewritten functions to write data to serial port and readyRead() signal to read data from serial port. I open the serial port using the readwrite mode and i establish connection between the two computers.

        connect(serial, SIGNAL(readyRead()), SLOT(handleReadyRead()));
        connect(ui->chat,SIGNAL(returnPressed()),this,SLOT(chat()));//chat is a QLineEdit
    void MainWindow::chat(){
            QString str1= ui->chat->text();
            char* str2 = qstringToCharEtoile(str1);//function to convert qstring to char*
            quint16 byteWritten=serial->write(str2);
            serial->waitForBytesWritten(-1);
            qDebug()<<byteWritten<<":"<<str2;
    }
    void MainWindow::handleReadyRead()
    {
        char data[300];
        serial->readLine(data,300);
        this->outputerror->putData(data);//outputerror is a plainTextEdit
        if(strlen(data)>3){
            for(int i=3;i<strlen(data);i++)
                    if(data[i-3]=='r'&&data[i-2]=='z'&&data[i-1]=='r'&&dataSerial[i]=='z'){
                        receiveFile();//if we receive rzrz via serialport we start the zmodem receiving process
                    }
        }
    }
    

    Everything works fine. I can read and write data between the two computers. After that, I use QProcess to send a file using zmodem protocol.

        connect(ui->sendFile, SIGNAL(clicked()), this, SLOT(sendFile()));
    
    void MainWindow::sendFile()
    {
        serial->write("rzrz");//write rzrz to start receiving file in the other side
        serial->waitForBytesWritten(-1);
        m_sz = new QProcess(this);
        QStringList listProcessArgs;
        listProcessArgs.append("-c");
        QString device = ui->ports->currentText();
        QString tmp = "sz --zmodem --resume --binary " + filename + " <" + device + " >" + device;
        listProcessArgs.append(tmp);
        m_sz->setReadChannel(QProcess::StandardOutput);
        m_sz->setProcessChannelMode(QProcess::MergedChannels);
        m_sz->start("sh", listProcessArgs);
        if (!m_sz->waitForStarted()) {
            QMessageBox::information(this, tr("Comm error"), tr("Could not start sz"));
            delete m_sz;
            //openDevice();
            return;
        }
    
        m_progress = new QProgressDialog(tr("Sending file via %1 ...").arg("ZMODEM"), tr("Cancel"), 0, 100, this);
        m_progress->setMinimumDuration(100);
        m_progress->setValue(0);
    
       int i=0;
        while (m_rz->state() == QProcess::Running) {
            m_rprogress->setValue(i);
            i++;
           if(i==100)i=0;
            millisleep(10L);
        }
        m_sz->waitForFinished();
        m_sz->closeReadChannel(QProcess::StandardOutput);
        m_sz->closeReadChannel(QProcess::StandardError);
        m_sz->closeWriteChannel();
        if (m_sz != nullptr)
            m_sz->terminate();
        if (m_progress != nullptr)
            m_progress->close();
        delete m_sz;
        m_sz=nullptr;
        delete m_progress;
        m_progress=nullptr;
    }
    
    void MainWindow::receiveFile()
    {
        m_rz = new QProcess(this);
        QStringList listProcessArgs;
        listProcessArgs.append("-c");
        QString device = ui->ports->currentText();//the name of the serialport
        QString tmp = "rz --zmodem --resume --binary --overwrite --o-sync >" + device + " <" + device ;
        listProcessArgs.append(tmp);
        m_rz->setReadChannel(QProcess::StandardOutput);
        m_rz->setProcessChannelMode(QProcess::MergedChannels);
        m_rz->start("sh", listProcessArgs);
        if (!m_rz->waitForStarted()) {
            QMessageBox::information(this, tr("Comm error"), tr("Could not start sz"));
            delete m_rz;
            return;
        }
        m_rprogress = new QProgressDialog(tr("Receiving file via %1 ...").arg("ZMODEM"), tr("Cancel"), 0, 100, this);
        m_rprogress->setMinimumDuration(100);
        m_rprogress->setValue(0);
       int i=0;
        while (m_rz->state() == QProcess::Running) {
            m_rprogress->setValue(i);
            i++;
           if(i==100)i=0;
            millisleep(10L);
        }
        m_rz->waitForFinished();
        m_rz->closeReadChannel(QProcess::StandardOutput);
        m_rz->closeReadChannel(QProcess::StandardError);
        m_rz->closeWriteChannel();
        if (m_rz != nullptr)
            m_rz->terminate();
        if (m_rprogress != nullptr)
            m_rprogress->close();
        delete m_rz;
        m_rz=nullptr;
        delete m_rprogress;
        m_rprogress=nullptr;
    }
    

    I can transmit a file between the two computer. After that I can't write anything to the serial port, when I use the chat to send data nothing received by the other side.
    Do you have any idea why I can't send any data?
    Thanks,
    madababi


  • Qt Champions 2016

    Hi and welcome
    Since you are using zmodem to transfer file, have you tried
    to close comport and reopen in main app to make sure
    its no longer expecting zmodem control chars ?



  • Hi,
    Thanks for the reply,
    If i close and reopen the comport everything work fine. But the problem is that I will loose the connection established between the two computers and I must start a new session.
    I'm searching a way to retake control of the serial port without loosing connection.


  • Qt Champions 2016

    Ok I understand.
    Have you checked that QProcess with sz is 100% terminated ?
    Its not because sz is still running?

    Would it be possible to disable zmodem with sz ?



  • I use QProcess waitForFinished() function to ensure that it terminate. I checked process running using the command

    ps -aux
    

    but sz dosn't exist.
    the weired thing is that this problem occurs only in the sending (sz) side. in the receiving side (rz) I can send data and read it in the sending side using the chat function.


  • Qt Champions 2016

    Hmm
    sound it sounds terminated.
    Have you tested if running manually in shell also
    blocks the comport after?



  • Yes, it block the comport, I only can send data from the receiving side.
    It's for that reason that i think that my qt application loose the control over the serial port.


  • Qt Champions 2016

    @madababi
    so sz leaves the comport sort of blocked or in funny state?



  • Yes, This is the problem.
    So, I'm searching a way to free the serial port or to allow my application to retake the control after sending the file.
    Even flush doesn't work.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.