diff options
| -rw-r--r-- | include/mts/MTS_IO_QuectelRadio.h | 2 | ||||
| -rw-r--r-- | src/MTS_IO_QuectelRadio.cpp | 71 | 
2 files changed, 49 insertions, 24 deletions
| diff --git a/include/mts/MTS_IO_QuectelRadio.h b/include/mts/MTS_IO_QuectelRadio.h index 0f24db8..5199b40 100644 --- a/include/mts/MTS_IO_QuectelRadio.h +++ b/include/mts/MTS_IO_QuectelRadio.h @@ -73,7 +73,7 @@ namespace MTS {                  static const std::string VALUE_MTS_DELTA_NAME;                  static const std::string VALUE_MTS_DELTA_PATH; -                CODE startFileUpload(const std::string& sTargetFilename, size_t nBytes); +                CODE startFileUpload(const std::string& sTargetFilename, size_t nBytes, uint16_t uRxTimeout = 5, bool bAckEnabled = false);                  CODE abortFileUpload();                  static inline void callNextStep(UpdateCb& stepCb, const char* csMessage); diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp index 942c0f7..a41e6fc 100644 --- a/src/MTS_IO_QuectelRadio.cpp +++ b/src/MTS_IO_QuectelRadio.cpp @@ -871,6 +871,9 @@ ICellularRadio::CODE QuectelRadio::setCellularMode(CELLULAR_MODES networks) {  }  ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTargetFilename, ICellularRadio::UpdateCb& stepCb) { +    const uint16_t uFileTimeout = 2;  // s +    const int32_t iUploadResultTimeout = uFileTimeout * 2 * 1000;  // ms +      size_t dPayloadLength;      size_t nChunks;      CODE rc; @@ -888,7 +891,8 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget      printTrace("File size: %d bytes and %d chunks", dPayloadLength, nChunks);      printTrace("Starting file upload..."); -    rc = startFileUpload(sTargetFilename, dPayloadLength); +    // Start file upload, set transmission timeouts and enable ACK mode +    rc = startFileUpload(sTargetFilename, dPayloadLength, uFileTimeout, true);      if (rc != SUCCESS) {          return rc;      } @@ -900,6 +904,20 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget      size_t nChunksPerCent = (nChunks / 100) + 1;      size_t nFragmentLength = 0;      std::array<char, FILE_CHUNK_SIZE> vBuffer; +    std::string sResponse; + +    // ACK waiter callback - wait for ACK and populate result code +    IsNeedMoreData waitAck = [&rc](const std::string& iterationData, const std::string&/*allData*/)->bool { +        if (iterationData.find('A') != std::string::npos) { +            // No data needed +            rc = SUCCESS; +            return false; +        } + +        // We need more data +        rc = NO_RESPONSE; +        return true; +    };      for (size_t iChunk = 1; iChunk < (nChunks + 1); iChunk++) { @@ -914,6 +932,14 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget          rc = sendData(vBuffer.data(), nFragmentLength);          if (rc != SUCCESS) { +            // failed to send data +            break; +        } + +        // Wait for ACK for up to 1 second and populate rc variable +        sResponse = waitResponse(waitAck, 1000); +        if (rc != SUCCESS) { +            // timeout or end of execution - check later              break;          } @@ -924,38 +950,28 @@ ICellularRadio::CODE QuectelRadio::uploadFile(int fd, const std::string& sTarget      } -    if (rc != SUCCESS) { -        // cancel upload and terminate -        callNextStep(stepCb, "FILE Error: Upload failed due to internal error"); -        abortFileUpload(); -        return rc; -    } -      printTrace("Waiting for acknoledge from the radio");      std::string sExpectedResult = "+QFUPL: ";      sExpectedResult += MTS::Text::format(dPayloadLength);      sExpectedResult += ",";      sExpectedResult += MTS::Text::toLowerCase(MTS::Text::formatHex(dChecksum)); -    // "send" empty string to read acknoledge string -    std::string sResult = sendCommand("", DEFAULT_BAIL_STRINGS, 10000, 0x00); +    // Wait for confirmation of successful upload completion +    sResponse += waitResponse(DEFAULT_BAIL_STRINGS, iUploadResultTimeout); -    if (sResult.find(sExpectedResult) != std::string::npos) { -        printDebug("Radio returned: [%s]", sResult.c_str()); +    if (sResponse.find(sExpectedResult) != std::string::npos) { +        printDebug("Radio returned: [%s]", sResponse.c_str());          printTrace("Upload finished, checksum matched"); -    } else { -        printError("Upload failed: checksum mismatch. Expected: [%s], Actual: [%s]", sExpectedResult.c_str(), sResult.c_str()); -        abortFileUpload(); -        rc = FAILURE; -    } - -    if (rc == SUCCESS) {          callNextStep(stepCb, "FILE Info: Upload finished successfully"); -    } else { -        callNextStep(stepCb, "FILE Error: Upload failed due to internal error"); + +        return SUCCESS;      } -    return rc; +    printError("Upload failed: checksum mismatch. Expected: [%s], Actual: [%s]", sExpectedResult.c_str(), sResponse.c_str()); +    callNextStep(stepCb, "FILE Error: Upload failed due to internal error"); + +    abortFileUpload(); +    return FAILURE;  }  ICellularRadio::CODE QuectelRadio::removeFile(const std::string& sTargetFilename) { @@ -1159,15 +1175,24 @@ std::string QuectelRadio::getFumoEarlyErrorCode(const std::string& sRadioInput)      return sResult;  } -ICellularRadio::CODE QuectelRadio::startFileUpload(const std::string& sTargetFilename, size_t nBytes) { +ICellularRadio::CODE QuectelRadio::startFileUpload(const std::string& sTargetFilename, size_t nBytes, uint16_t uRxTimeout, bool bAckEnabled) {      const std::vector<std::string> vBailStrings{ ICellularRadio::RSP_CONNECT, ICellularRadio::RSP_ERROR };      const int dTimeout = 1000; //ms      std::string sCommand, sResult; +    // Format: AT+QFUPL=<filename>[,<file_size>[,<timeout>[,<ackmode>]] +      sCommand = "AT+QFUPL=\"";      sCommand += sTargetFilename;      sCommand += "\",";      sCommand += MTS::Text::format(nBytes); +    sCommand += ","; +    sCommand += MTS::Text::format(uRxTimeout); + +    if (bAckEnabled) { +        // ACK mode enabled +        sCommand += ",1"; +    }      sResult = sendCommand(sCommand, vBailStrings, dTimeout);      if (sResult.find(ICellularRadio::RSP_CONNECT) == std::string::npos) { | 
