Skip to content

Improvement to timeout in Updater.cpp #6113

Closed
@adrian-dybwad

Description

@adrian-dybwad

Recently, when doing a deep dive into behavior in slow network environments, I can across the code in Updater.cpp that handles a timeout while an update is being streamed. Effectively, it will wait for 100ms after a timeout and then try once more. If this second attempt fails, the update fails. I would like to propose a change to this mechanism that makes the download succeed in even the slowest networks.

This change uses a call to millis() to track the start time, reseting this start time every time data is received. After 60 seconds of not receiving more data, it will timeout.

The new function is below with the new variable called "timeout":

size_t UpdaterClass::writeStream(Stream &data) {
    size_t written = 0;
    size_t toRead = 0;
    if(hasError() || !isRunning())
        return 0;

    if(!_verifyHeader(data.peek())) {
#ifdef DEBUG_UPDATER
        printError(DEBUG_UPDATER);
#endif
        _reset();
        return 0;
    }
    unsigned long timeout = millis();
    if (_progress_callback) {
        _progress_callback(0, _size);
    }
    if(_ledPin != -1) {
        pinMode(_ledPin, OUTPUT);
    }

    while(remaining()) {
        if(_ledPin != -1) {
            digitalWrite(_ledPin, _ledOn); // Switch LED on
        }
        size_t bytesToRead = _bufferSize - _bufferLen;
        if(bytesToRead > remaining()) {
            bytesToRead = remaining();
        }
        toRead = data.readBytes(_buffer + _bufferLen,  bytesToRead);
        if(toRead == 0) { //Timeout
          if (millis() - timeout > 60000) {
            _currentAddress = (_startAddress + _size);
            _setError(UPDATE_ERROR_STREAM);
            _reset();
            return written;
          }
          delay(100);
        } else {
          timeout = millis();
        }
        if(_ledPin != -1) {
            digitalWrite(_ledPin, !_ledOn); // Switch LED off
        }
        _bufferLen += toRead;
        if((_bufferLen == remaining() || _bufferLen == _bufferSize) && !_writeBuffer())
            return written;
        written += toRead;
        if(_progress_callback) {
            _progress_callback(progress(), _size);
        }
        yield();
    }
    if(_progress_callback) {
        _progress_callback(progress(), _size);
    }
    return written;
}

Also, I read another thread recently with comments thanking you all for the incredible work you do on this project. One response was it is not common to get thanks, so here is another. THANK YOU!!

Metadata

Metadata

Assignees

No one assigned

    Labels

    waiting for feedbackWaiting on additional info. If it's not received, the issue may be closed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions