Example #1
0
void B9PrinterComm::RefreshCommPortItems()
{
    if(m_bIsPrinting)return; // We assume we stay connected during the print proccess.  If we are disconnected, the watchdog timer will fire
    QString sCommPortStatus = MSG_SEARCHING;
    QString sCommPortDetailedStatus = MSG_SEARCHING;
    QString sPortName;
    // Load the current enumerated available ports
    *pPorts = pEnumerator->getPorts();

    if(m_serialDevice){
        // We've previously located the printer, are we still connected?
        for (int i = 0; i < pPorts->size(); i++) {
        // Check each existing port to see if our's still exists
        #ifdef Q_WS_X11
            if(pPorts->at(i).physName == m_serialDevice->portName()){
        #else
            if(pPorts->at(i).portName == m_serialDevice->portName()){
        #endif
                // We're still connected, set a timer to check again in 5 seconds and then exit
                QTimer::singleShot(5000, this, SLOT(RefreshCommPortItems()));
                return;
            }
        }
        // We lost the previous connection and should delete this port connection
        if (m_serialDevice->isOpen())
            m_serialDevice->close();
        delete m_serialDevice;
        m_serialDevice = NULL;
        m_Status.reset();
        qDebug() << sCommPortStatus;
        emit updateConnectionStatus(sCommPortStatus);
        sCommPortDetailedStatus = "Lost Comm on previous port. Searching...";
        emit BC_ConnectionStatusDetailed("Lost Comm on previous port. Searching...");
        handleLostComm();
    }

    // Now we search for a B9Creator
    int eTime = 1000;  // 1 second search cylce time for while not connected

    sNoFirmwareAurdinoPort = "";  // Reset to null string before scanning ports
    if(pPorts->size()>0){
        // Some ports are available, are they the B9Creator?
        qDebug() << "Scanning For Serial Port Devices (" << pPorts->size() << "found )";
        for (int i = 0; i < pPorts->size(); i++) {
            qDebug() << "  port name   " << pPorts->at(i).portName;
            qDebug() << "  locationInfo" << pPorts->at(i).physName;
         #ifndef Q_WS_X11
            //Note: We only trust friendName, vendorID and productID with Windows and OS_X
            qDebug() << "  description " << pPorts->at(i).friendName;
            qDebug() << "  vendorID    " << pPorts->at(i).vendorID;
            qDebug() << "  productID   " << pPorts->at(i).productID;
         #endif
         #ifdef Q_WS_X11
            // linux ID's ports by physName
            sPortName = pPorts->at(i).physName;
            // We filter ports by requiring the portName to begin with "ttyA"
            if(pPorts->at(i).portName.left(4) == "ttyA" && OpenB9CreatorCommPort(sPortName)){
         #else
            // Windows and OSX use portName to ID ports
            sPortName = pPorts->at(i).portName;
            // We filter ports by requiring vendorID value of 9025 (Arduino)
            if(pPorts->at(i).vendorID==9025 && OpenB9CreatorCommPort(sPortName)){
         #endif
                // Connected!
                sCommPortStatus = MSG_CONNECTED;
                sCommPortDetailedStatus = "Connected on Port: "+m_serialDevice->portName();
                eTime = 5000;  // Re-check connection again in 5 seconds
                if(m_serialDevice && m_Status.isCurrentVersion())startWatchDogTimer();  // Start B9Creator "crash" watchDog
                break;
            }
        }
        bool bUpdateFirmware = false;
        if( m_serialDevice==NULL && sNoFirmwareAurdinoPort!=""){
            // We did not find a B9Creator with valid firmware, but we did find an Arduino
            // We assume this is a new B9Creator and needs firmware!
            // However, we will not upload firmware unless m_bCloneBlanks is true!
            if(m_bCloneBlanks){
                qDebug() << "\"Clone Firmware\" Option is enabled.  Attempting Firmware Upload to possible B9Creator found on port: "<< sNoFirmwareAurdinoPort;
                bUpdateFirmware = true;
                sPortName = sNoFirmwareAurdinoPort;
            }
            else {
                qDebug() << "\"Clone Firmware\" Option is disabled.  No Firmware upload attempted on possible B9Creator found on port: " << sNoFirmwareAurdinoPort;
                bUpdateFirmware = false;
            }
        }
        else if (m_serialDevice!=NULL && !m_Status.isCurrentVersion()){
            // We found a B9Creator with the wrong firmware version, update it!
            qDebug() << "Incorrect Firmware version found on connected B9Creator"<< sPortName << "  Attempting B9Creator Firmware Update to" << CURRENTFIRMWARE;
            bUpdateFirmware = true;
            if(m_serialDevice!=NULL) {
                m_serialDevice->flush();
                m_serialDevice->close();
                delete m_serialDevice;
            }
            m_serialDevice = NULL;
            m_Status.reset();
        }
        if(bUpdateFirmware){
            // Update the firmware on device on sPortName
            emit updateConnectionStatus(MSG_FIRMUPDATE);
            emit BC_ConnectionStatusDetailed("Updating Firmware on port: "+sPortName);
            B9FirmwareUpdate Firmware;
            QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
            Firmware.UploadHex(sPortName);
            QApplication::restoreOverrideCursor();
            emit updateConnectionStatus(MSG_SEARCHING);
            emit BC_ConnectionStatusDetailed("Firmware Update Complete.  Searching...");
        }
        emit updateConnectionStatus(sCommPortStatus);
        emit BC_ConnectionStatusDetailed(sCommPortDetailedStatus);
    }
    QTimer::singleShot(eTime, this, SLOT(RefreshCommPortItems())); // Check again in 5 seconds if connected, 1 secs if not
}

bool B9PrinterComm::OpenB9CreatorCommPort(QString sPortName)
{
    if(m_serialDevice!=NULL) qFatal("Error:  We found an open port handle that should have been deleted!");

    // Attempt to establish a serial connection with the B9Creator
    m_serialDevice = new QextSerialPort(sPortName, QextSerialPort::EventDriven, this);
    if (m_serialDevice->open(QIODevice::ReadWrite) == true) {
        m_serialDevice->setBaudRate(BAUD115200);
        m_serialDevice->setDataBits(DATA_8);
        m_serialDevice->setParity(PAR_NONE);
        m_serialDevice->setStopBits(STOP_1);
        m_serialDevice->setFlowControl(FLOW_OFF);
        m_serialDevice->setDtr(true);   // Reset the Aurduino
        m_serialDevice->setDtr(false);

        connect(m_serialDevice, SIGNAL(readyRead()), this, SLOT(ReadAvailable()));
        qDebug() << "Opened Comm port:" << sPortName;
    }
    else {
        // device failed to open
        if(m_serialDevice!=NULL) delete m_serialDevice;
        m_serialDevice = NULL;
        m_Status.reset();
        qDebug() << "Failed to open Comm port:" << sPortName;
        return false;
    }

    // Delay for up to 5 seconds while we wait for response from printer
    QTime delayTime = QTime::currentTime().addSecs(5);
    while( QTime::currentTime() < delayTime && !m_Status.isValidVersion() )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

    if(!m_Status.isValidVersion()){
        if(m_serialDevice!=NULL) {
            m_serialDevice->flush();
            m_serialDevice->close();
            delete m_serialDevice;
        }
        m_serialDevice = NULL;
        m_Status.reset();
        qDebug() << "Found a possible Arduino Device, perhaps a B9Creator without firmware loaded, on Port: " << sPortName;
        sNoFirmwareAurdinoPort = sPortName;
        return false;
    }
    return true;
}

QString B9PrinterComm::errorString(){
    return m_serialDevice->errorString();
}

void B9PrinterComm::ReadAvailable() {
    if(m_serialDevice==NULL) qFatal("Error:  slot 'ReadAvailable()' but NULL Port Handle");

    m_Status.resetLastMsgTime();  //update for watchdog

    if(m_Status.getHomeStatus() == B9PrinterStatus::HS_SEEKING) {
        m_Status.setHomeStatus(B9PrinterStatus::HS_UNKNOWN); // if we are receiving data, we must no longer be seeking Home
        // we'll set the status to HS_FOUND once we recieve a 'X' diff broadcast
    }

    QByteArray ba = m_serialDevice->readAll();  // read block of available raw data

    // We process the raw data one line at a time, keeping in mind they may be spread across multiple blocks.
    int iCurPos = 0;
    int iLampHrs = -1;
    int iInput = -1;
    char c;
    while(iCurPos<ba.size()){
        c = ba.at(iCurPos);
        iCurPos++;
        if(c!='\r') m_sSerialString+=QString(c);
        if(c=='\n'){
            // Line Read Complete, process data

           if(m_sSerialString.left(1) != "P" && m_sSerialString.left(1) != "L" && m_sSerialString.length()>0){
                // We only emit this data for display & log purposes
                if(m_sSerialString.left(1) == "C"){
                    qDebug() << m_sSerialString.right(m_sSerialString.length()-1) << "\n";
                }
                else{
                    emit BC_RawData(m_sSerialString);
                    qDebug() << m_sSerialString << "\n";
                }
            }

            int iCmdID = m_sSerialString.left(1).toUpper().toAscii().at(0);
            switch (iCmdID){
            case 'U':  // Mechanical failure of encoder?
                qDebug() << "WARNING:  Printer has sent 'U' report, runaway X Motor indication: " + m_sSerialString << "\n";
                break;
            case 'Q':  // Printer got tired of waiting for command and shut down projectors
                       // We will likely never see this as something bad has happened
                       // (like we have crashed or been shut off during a print process
                       // So if we get it, we'll just post it to the log and wait for
                       // timeouts to correct things.
                qDebug() << "WARNING:  Printer has sent 'Q' report, lost comm with host." << "\n";
                break;
            case 'P':  // take care of projector status
                iInput = m_sSerialString.right(m_sSerialString.length()-1).toInt();
                if(iInput!=1)iInput = 0;
                if(handleProjectorBC(iInput)){
                    //projector status changed
                    emit BC_RawData(m_sSerialString);
                    qDebug() << m_sSerialString << "\n";
                }
                break;
            case 'L':  // take care of projector Lamp hours update
                iLampHrs = m_sSerialString.right(m_sSerialString.length()-1).toInt();
                if(m_Status.getLampHrs()!= iLampHrs){
                    m_Status.setLampHrs(iLampHrs);
                    emit BC_ProjectorStatusChanged();
                    emit BC_RawData(m_sSerialString);
                    qDebug() << m_sSerialString << "\n";
                }
                break;

            case 'X':  // Found Home with this Difference Offset
                m_Status.setHomeStatus(B9PrinterStatus::HS_FOUND);
                m_Status.setLastHomeDiff(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_HomeFound();
                break;

            case 'R':  // Needs Reset?
                iInput = m_sSerialString.right(m_sSerialString.length()-1).toInt();
                if(iInput==0) m_Status.setHomeStatus(B9PrinterStatus::HS_FOUND);
                else m_Status.setHomeStatus(B9PrinterStatus::HS_UNKNOWN);
                break;

            case 'K':  // Current Lamp 1/2 life
                m_Status.setHalfLife(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_HalfLife(m_Status.getHalfLife());
                break;

            case 'D':  // Current Native X Projector resolution
                m_Status.setNativeX(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_NativeX(m_Status.getNativeX());
                break;

            case 'E':  // Current Native Y Projector resolution
                m_Status.setNativeY(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_NativeY(m_Status.getNativeY());
                break;

            case 'H':  // Current XY Pixel Size
                m_Status.setXYPixelSize(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_XYPixelSize(m_Status.getXYPixelSize());
                break;

            case 'I':  // Current PU
                m_Status.setPU(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_PU(m_Status.getPU());
                break;

            case 'A':  // Projector Control capability
                m_Status.setProjectorRemoteCapable(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_ProjectorRemoteCapable(m_Status.isProjectorRemoteCapable());
                break;

            case 'J':  // Projector Shutter capability
                m_Status.setHasShutter(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_HasShutter(m_Status.hasShutter());
                break;

            case 'M':  // Current Z Upper Limit in PUs
                m_Status.setUpperZLimPU(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_UpperZLimPU(m_Status.getUpperZLimPU());
                break;

            case 'Z':  // Current Z Position Update
                m_Status.setCurZPosInPU(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_CurrentZPosInPU(m_Status.getCurZPosInPU());
                break;

            case 'S':  // Current Vat(Shutter) Percent Open Position Update
                m_Status.setCurVatPercentOpen(m_sSerialString.right(m_sSerialString.length()-1).toInt());
                emit BC_CurrentVatPercentOpen(m_Status.getCurVatPercentOpen());
                break;

            case 'C':  // Comment
                emit BC_Comment(m_sSerialString.right(m_sSerialString.length()-1));
                break;

            case 'F':  // Print release cycle finished
                emit BC_PrintReleaseCycleFinished();
                break;

            case 'V':  // Version
                m_Status.setVersion(m_sSerialString.right(m_sSerialString.length()-1).trimmed());
                emit BC_FirmVersion(m_Status.getVersion());
                break;

            case 'W':  // Model
                m_Status.setModel(m_sSerialString.right(m_sSerialString.length()-1).trimmed());
                emit BC_ModelInfo(m_Status.getModel());
                break;

            case 'Y':  // Current Z Home position in PU's
                // ignored
                break;

            default:
                qDebug() <<"WARNING:  IGNORED UNKNOWN CMD:  " << m_sSerialString << "\n";
                break;
            }
            m_sSerialString=""; // Line processed, clear it for next line
        }
    }
}

void B9PrinterComm::setProjectorPowerCmd(bool bPwrFlag){
    if(bPwrFlag){
        SendCmd("P1"); // Turn On Command
        m_Status.setProjectorStatus(B9PrinterStatus::PS_TURNINGON);
    }
    else {
        SendCmd("P0"); // Turn On Command
        m_Status.setProjectorStatus(B9PrinterStatus::PS_COOLING);
    }
    m_Status.resetLastProjCmdTime();
    emit BC_ProjectorStatusChanged();
}

bool B9PrinterComm::handleProjectorBC(int iBC){
    bool bStatusChanged = false;
    if(m_Status.isProjectorPowerCmdOn() && iBC == 0){
        // Projector commanded ON but current report is OFF
        switch(m_Status.getProjectorStatus()){
        case B9PrinterStatus::PS_OFF:
        case B9PrinterStatus::PS_UNKNOWN:
        case B9PrinterStatus::PS_TIMEOUT:
        case B9PrinterStatus::PS_FAIL:
            setProjectorPowerCmd(true); // turn it on now
            bStatusChanged = true;
            break;
        case B9PrinterStatus::PS_TURNINGON:
            if(m_Status.getLastProjCmdElapsedTime()>45000){
                // Taking too long to turn on, something is wrong!
                m_Status.setProjectorStatus(B9PrinterStatus::PS_TIMEOUT);
                emit BC_ProjectorFAIL();
                m_Status.cmdProjectorPowerOn(false);
                bStatusChanged = true;
            }
            break;
        case B9PrinterStatus::PS_WARMING:
        case B9PrinterStatus::PS_ON:
            // Uncommanded Power off!  Lost power or bulb failure?
            m_Status.setProjectorStatus(B9PrinterStatus::PS_FAIL);
            emit BC_ProjectorFAIL();
            m_Status.cmdProjectorPowerOn(false);
            bStatusChanged = true;
            break;
        case B9PrinterStatus::PS_COOLING:
            // Done cooling off
            m_Status.setProjectorStatus(B9PrinterStatus::PS_OFF);
            emit BC_ProjectorStatusChanged();
            bStatusChanged = true;
            break;
        default:
            // Nothing we can do
            break;
        }
    }
    else if(m_Status.isProjectorPowerCmdOn() && iBC == 1){
        // Projector commanded ON and current report is ON
        switch(m_Status.getProjectorStatus()){
        case B9PrinterStatus::PS_COOLING:
        case B9PrinterStatus::PS_OFF:
        case B9PrinterStatus::PS_UNKNOWN:
        case B9PrinterStatus::PS_TIMEOUT:
        case B9PrinterStatus::PS_FAIL:
            // We were turning off, off, failed, timed out or unknown and suddenly we're cmd on and actually on?
            // Best we can do is set the status on and report
            m_Status.setProjectorStatus(B9PrinterStatus::PS_ON);
            emit BC_ProjectorStatusChanged();
            bStatusChanged = true;
            break;
        case B9PrinterStatus::PS_TURNINGON:
            // We were turning on and now we need to warm up a bit
            m_Status.setProjectorStatus(B9PrinterStatus::PS_WARMING);
            startWarmingTime.start();
            emit BC_ProjectorStatusChanged();
            bStatusChanged = true;
            break;
        case B9PrinterStatus::PS_WARMING:
            if(startWarmingTime.elapsed()>m_iWarmUpDelayMS){
                // All warmed up now, ready to use.
                m_Status.setProjectorStatus(B9PrinterStatus::PS_ON);
                emit BC_ProjectorStatusChanged();
                bStatusChanged = true;
            }
            break;
        case B9PrinterStatus::PS_ON:
        default:
            // No change, we're good.
            break;
        }
    }
    else if(!m_Status.isProjectorPowerCmdOn() && iBC == 0){
        // Projector commanded OFF and current report is OFF
        switch(m_Status.getProjectorStatus()){
        case B9PrinterStatus::PS_UNKNOWN:
        case B9PrinterStatus::PS_TURNINGON:
        case B9PrinterStatus::PS_WARMING:
        case B9PrinterStatus::PS_ON:
        case B9PrinterStatus::PS_COOLING:
        case B9PrinterStatus::PS_TIMEOUT:
        case B9PrinterStatus::PS_FAIL:
            // We were turning on, warming up, on, cooling off, unknown, timed out or failed and now we're off
            m_Status.setProjectorStatus(B9PrinterStatus::PS_OFF);
            emit BC_ProjectorStatusChanged();
            bStatusChanged = true;
            break;
        case B9PrinterStatus::PS_OFF:
        default:
            // No change, we're good
            break;
        }
    }
    else if(!m_Status.isProjectorPowerCmdOn() && iBC == 1){
        // Projector commanded OFF but current report is ON
        switch(m_Status.getProjectorStatus()){
        case B9PrinterStatus::PS_COOLING:
            if(m_Status.getLastProjCmdElapsedTime()>30000){
                // Taking too long to turn off, send the off command again
                m_Status.setProjectorStatus(B9PrinterStatus::PS_ON);
                emit BC_ProjectorStatusChanged();
                bStatusChanged = true;
            }
            break;
        case B9PrinterStatus::PS_OFF:
            //User must have switched it on manually, we'll accept that and set the status to commanded on and Turning on
            cmdProjectorPowerOn(true);
            setProjectorPowerCmd(true);
            bStatusChanged = true;
            break;

        case B9PrinterStatus::PS_TURNINGON:
        case B9PrinterStatus::PS_WARMING:
        case B9PrinterStatus::PS_ON:
        case B9PrinterStatus::PS_UNKNOWN:
        case B9PrinterStatus::PS_TIMEOUT:
        case B9PrinterStatus::PS_FAIL:
        default:
            setProjectorPowerCmd(false); // turn it off now
            bStatusChanged = true;
            break;
        }
    }
    return bStatusChanged;
}
Example #2
0
B9Terminal::B9Terminal(QWidget *parent, Qt::WFlags flags) :
    QWidget(parent, flags),
    ui(new Ui::B9Terminal)
{
    setWindowFlags(Qt::WindowContextHelpButtonHint);
    m_bWaiverPresented = false;
    m_bWaiverAccepted = false;
    m_bWavierActive = false;
    m_bNeedsWarned = true;
    m_iFillLevel = -1;

    ui->setupUi(this);
    ui->commStatus->setText("Searching for B9Creator...");

    qDebug() << "Terminal Start";

    m_pCatalog = new B9MatCat;
    onBC_ModelInfo("B9C1");

    pSettings = new PCycleSettings;
    resetLastSentCycleSettings();

    // Always set up the B9PrinterComm in the Terminal constructor
    pPrinterComm = new B9PrinterComm;
    pPrinterComm->enableBlankCloning(true); // Allow for firmware update of suspected "blank" B9Creator Arduino's

    // Always set up the B9Projector in the Terminal constructor
    m_pDesktop = QApplication::desktop();
    pProjector = NULL;
    m_bPrimaryScreen = false;
    m_bPrintPreview = false;
    m_bUsePrimaryMonitor = false;

    connect(m_pDesktop, SIGNAL(screenCountChanged(int)),this, SLOT(onScreenCountChanged(int)));

    connect(pPrinterComm,SIGNAL(updateConnectionStatus(QString)), this, SLOT(onUpdateConnectionStatus(QString)));
    connect(pPrinterComm,SIGNAL(BC_ConnectionStatusDetailed(QString)), this, SLOT(onBC_ConnectionStatusDetailed(QString)));
    connect(pPrinterComm,SIGNAL(BC_LostCOMM()),this,SLOT(onBC_LostCOMM()));

    connect(pPrinterComm,SIGNAL(BC_RawData(QString)), this, SLOT(onUpdateRAWPrinterComm(QString)));
    connect(pPrinterComm,SIGNAL(BC_Comment(QString)), this, SLOT(onUpdatePrinterComm(QString)));

    connect(pPrinterComm,SIGNAL(BC_ModelInfo(QString)),this,SLOT(onBC_ModelInfo(QString)));
    connect(pPrinterComm,SIGNAL(BC_FirmVersion(QString)),this,SLOT(onBC_FirmVersion(QString)));
    connect(pPrinterComm,SIGNAL(BC_ProjectorRemoteCapable(bool)), this, SLOT(onBC_ProjectorRemoteCapable(bool)));
    connect(pPrinterComm,SIGNAL(BC_HasShutter(bool)), this, SLOT(onBC_HasShutter(bool)));
    connect(pPrinterComm,SIGNAL(BC_ProjectorStatusChanged()), this, SLOT(onBC_ProjStatusChanged()));
    connect(pPrinterComm,SIGNAL(BC_ProjectorFAIL()), this, SLOT(onBC_ProjStatusFAIL()));

    // Z Position Control
    connect(pPrinterComm, SIGNAL(BC_PU(int)), this, SLOT(onBC_PU(int)));
    connect(pPrinterComm, SIGNAL(BC_UpperZLimPU(int)), this, SLOT(onBC_UpperZLimPU(int)));
    m_pResetTimer = new QTimer(this);
    connect(m_pResetTimer, SIGNAL(timeout()), this, SLOT(onMotionResetTimeout()));
    connect(pPrinterComm, SIGNAL(BC_HomeFound()), this, SLOT(onMotionResetComplete()));
    connect(pPrinterComm, SIGNAL(BC_CurrentZPosInPU(int)), this, SLOT(onBC_CurrentZPosInPU(int)));
    connect(pPrinterComm, SIGNAL(BC_HalfLife(int)), this, SLOT(onBC_HalfLife(int)));
    connect(pPrinterComm, SIGNAL(BC_NativeX(int)), this, SLOT(onBC_NativeX(int)));
    connect(pPrinterComm, SIGNAL(BC_NativeY(int)), this, SLOT(onBC_NativeY(int)));
    connect(pPrinterComm, SIGNAL(BC_XYPixelSize(int)), this, SLOT(onBC_XYPixelSize(int)));


    m_pVatTimer = new QTimer(this);
    connect(m_pVatTimer, SIGNAL(timeout()), this, SLOT(onMotionVatTimeout()));
    connect(pPrinterComm, SIGNAL(BC_CurrentVatPercentOpen(int)), this, SLOT(onBC_CurrentVatPercentOpen(int)));

    m_pPReleaseCycleTimer = new QTimer(this);
    connect(m_pPReleaseCycleTimer, SIGNAL(timeout()), this, SLOT(onReleaseCycleTimeout()));
    connect(pPrinterComm, SIGNAL(BC_PrintReleaseCycleFinished()), this, SLOT(onBC_PrintReleaseCycleFinished()));
}