diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 0000000..101edae --- /dev/null +++ b/.codespellrc @@ -0,0 +1,7 @@ +# See: https://github.com/codespell-project/codespell#using-a-config-file +[codespell] +# In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: +ignore-words-list = , +check-filenames = +check-hidden = +skip = ./.git diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fa738ec --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file +version: 2 + +updates: + # Configure check for outdated GitHub Actions actions in workflows. + # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + - package-ecosystem: github-actions + directory: / # Check the repository's workflows under /.github/workflows/ + schedule: + interval: daily + labels: + - "topic: infrastructure" diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml new file mode 100644 index 0000000..3e0d26c --- /dev/null +++ b/.github/workflows/check-arduino.yml @@ -0,0 +1,28 @@ +name: Check Arduino + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows +on: + push: + pull_request: + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Arduino Lint + uses: arduino/arduino-lint-action@v1 + with: + compliance: specification + library-manager: update + # Always use this setting for official repositories. Remove for 3rd party projects. + official: true + project-type: library diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml new file mode 100644 index 0000000..b880357 --- /dev/null +++ b/.github/workflows/compile-examples.yml @@ -0,0 +1,113 @@ +name: Compile Examples + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/compile-examples.yml" + - "examples/**" + - "src/**" + pull_request: + paths: + - ".github/workflows/compile-examples.yml" + - "examples/**" + - "src/**" + schedule: + # Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms). + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + build: + name: ${{ matrix.board.fqbn }} + runs-on: ubuntu-latest + + env: + SKETCHES_REPORTS_PATH: sketches-reports + + strategy: + fail-fast: false + + matrix: + board: + - fqbn: arduino:avr:nano + platforms: | + - name: arduino:avr + softwareserial: true + - fqbn: arduino:avr:mega + platforms: | + - name: arduino:avr + softwareserial: true + - fqbn: arduino:avr:leonardo + platforms: | + - name: arduino:avr + softwareserial: true + - fqbn: arduino:megaavr:nona4809 + platforms: | + - name: arduino:megaavr + softwareserial: true + - fqbn: arduino:sam:arduino_due_x_dbg + platforms: | + - name: arduino:sam + softwareserial: false + - fqbn: arduino:samd:mkrzero + platforms: | + - name: arduino:samd + softwareserial: false + - fqbn: arduino:mbed_portenta:envie_m4 + platforms: | + - name: arduino:mbed_portenta + softwareserial: false + - fqbn: arduino:mbed_portenta:envie_m7 + platforms: | + - name: arduino:mbed_portenta + softwareserial: false + - fqbn: arduino:mbed_nano:nano33ble + platforms: | + - name: arduino:mbed_nano + softwareserial: false + - fqbn: arduino:mbed_nano:nanorp2040connect + platforms: | + - name: arduino:mbed_nano + softwareserial: false + + # Make board type-specific customizations to the matrix jobs + include: + - board: + # Boards with a SoftwareSerial library + softwareserial: true + # Compile these sketches in addition to the ones defined by env.UNIVERSAL_SKETCH_PATHS + sketch-paths: | + - examples/Arduino_Debug_Advance + - board: + softwareserial: false + sketch-paths: "" + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Compile examples + uses: arduino/compile-sketches@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fqbn: ${{ matrix.board.fqbn }} + platforms: ${{ matrix.board.platforms }} + libraries: | + # Install the library from the local path. + - source-path: ./ + # Additional library dependencies can be listed here. + # See: https://github.com/arduino/compile-sketches#libraries + sketch-paths: | + - examples/Arduino_Debug_Basic + ${{ matrix.sketch-paths }} + enable-deltas-report: true + sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} + + - name: Save sketches report as workflow artifact + uses: actions/upload-artifact@v3 + with: + if-no-files-found: error + path: ${{ env.SKETCHES_REPORTS_PATH }} + name: ${{ env.SKETCHES_REPORTS_PATH }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml new file mode 100644 index 0000000..652be5d --- /dev/null +++ b/.github/workflows/report-size-deltas.yml @@ -0,0 +1,24 @@ +name: Report Size Deltas + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/report-size-deltas.yml" + schedule: + # Run at the minimum interval allowed by GitHub Actions. + # Note: GitHub Actions periodically has outages which result in workflow failures. + # In this event, the workflows will start passing again once the service recovers. + - cron: "*/5 * * * *" + workflow_dispatch: + repository_dispatch: + +jobs: + report: + runs-on: ubuntu-latest + steps: + - name: Comment size deltas reports to PRs + uses: arduino/report-size-deltas@v1 + with: + # The name of the workflow artifact created by the sketch compilation workflow + sketches-reports-source: sketches-reports diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml new file mode 100644 index 0000000..3f6b03f --- /dev/null +++ b/.github/workflows/spell-check.yml @@ -0,0 +1,22 @@ +name: Spell Check + +# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows +on: + push: + pull_request: + schedule: + # Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates. + - cron: "0 8 * * TUE" + workflow_dispatch: + repository_dispatch: + +jobs: + spellcheck: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Spell check + uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..986bda6 --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,138 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md +name: Sync Labels + +# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + pull_request: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + schedule: + # Run daily at 8 AM UTC to sync with changes to shared label configurations. + - cron: "0 8 * * *" + workflow_dispatch: + repository_dispatch: + +env: + CONFIGURATIONS_FOLDER: .github/label-configuration-files + CONFIGURATIONS_ARTIFACT: label-configuration-files + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download JSON schema for labels configuration file + id: download-schema + uses: carlosperate/download-file-action@v1 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json + location: ${{ runner.temp }}/label-configuration-schema + + - name: Install JSON schema validator + run: | + sudo npm install \ + --global \ + ajv-cli \ + ajv-formats + + - name: Validate local labels configuration + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + ajv validate \ + --all-errors \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" + + download: + needs: check + runs-on: ubuntu-latest + + strategy: + matrix: + filename: + # Filenames of the shared configurations to apply to the repository in addition to the local configuration. + # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels + - universal.yml + + steps: + - name: Download + uses: carlosperate/download-file-action@v1 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} + + - name: Pass configuration files to next job via workflow artifact + uses: actions/upload-artifact@v3 + with: + path: | + *.yaml + *.yml + if-no-files-found: error + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + sync: + needs: download + runs-on: ubuntu-latest + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable + echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" + + - name: Determine whether to dry run + id: dry-run + if: > + github.event_name == 'pull_request' || + ( + ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' + ) && + github.ref != format('refs/heads/{0}', github.event.repository.default_branch) + ) + run: | + # Use of this flag in the github-label-sync command will cause it to only check the validity of the + # configuration. + echo "::set-output name=flag::--dry-run" + + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download configuration files artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + path: ${{ env.CONFIGURATIONS_FOLDER }} + + - name: Remove unneeded artifact + uses: geekyeggo/delete-artifact@v1 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + - name: Merge label configuration files + run: | + # Merge all configuration files + shopt -s extglob + cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" + + - name: Install github-label-sync + run: sudo npm install --global github-label-sync + + - name: Sync labels + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # See: https://github.com/Financial-Times/github-label-sync + github-label-sync \ + --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ + ${{ steps.dry-run.outputs.flag }} \ + ${{ github.repository }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8c6cbef..0000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -language: generic -env: - global: - - CLI_VERSION=latest -matrix: - include: - - env: - - BOARD="arduino:samd:mkr1000" - - env: - - BOARD="arduino:samd:mkrwifi1010" - - env: - - BOARD="arduino:samd:mkrgsm1400" - - env: - - NAME=Spell Check - language: python - python: 3.6 - # must define an empty before_install phase, otherwise the default one is used - before_install: true - install: - # https://github.com/codespell-project/codespell - - pip install codespell - script: - - codespell --skip="${TRAVIS_BUILD_DIR}/.git" --ignore-words="${TRAVIS_BUILD_DIR}/extras/codespell-ignore-words-list.txt" "${TRAVIS_BUILD_DIR}" -# default phases -before_install: - - wget http://downloads.arduino.cc/arduino-cli/arduino-cli-$CLI_VERSION-linux64.tar.bz2 - - tar xf arduino-cli-$CLI_VERSION-linux64.tar.bz2 - - mkdir -p "$HOME/bin" - - mv arduino-cli $HOME/bin - - export PATH="$PATH:$HOME/bin" - - arduino-cli core update-index - - if [[ "$BOARD" =~ "arduino:samd:" ]]; then - arduino-cli core install arduino:samd; - fi - - buildExampleSketch() { arduino-cli compile --warnings all --fqbn $BOARD $PWD/examples/$1; } -install: - - mkdir -p $HOME/Arduino/libraries - - ln -s $PWD $HOME/Arduino/libraries/. -script: - - buildExampleSketch Arduino_Debug_Basic -notifications: - webhooks: - urls: - - https://www.travisbuddy.com/ - on_success: never - on_failure: always diff --git a/README.md b/README.md index 32a5558..8f08544 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ Arduino_DebugUtils ================== +[![Check Arduino status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/check-arduino.yml) +[![Compile Examples status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/compile-examples.yml) +[![Spell Check status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/spell-check.yml) + This class provides functionality useful for debugging sketches via `printf`-style statements. # How-To-Use Basic @@ -23,7 +27,7 @@ float pi = 3.1459; Debug.print(DBG_VERBOSE, "i = %d, pi = %f", i, pi); ``` -If desired timestamps can be prefixed to the debug message. Timestamp output can be enabled and disabled via `timestampOn` and `timestampOff`. +If desired, timestamps can be prefixed to the debug message. Timestamp output can be enabled and disabled via `timestampOn` and `timestampOff`. # How-To-Use Advanced Normally all debug output is redirected to the primary serial output of each board (`Serial`). In case you want to redirect the output to another output stream you can make use of `setDebugOutputStream(&Serial2)`. @@ -74,6 +78,26 @@ Debug.timestampOff(); Debug.print(DBG_VERBOSE, "i = %d", i); //Output looks like : i = 21 ``` +### Debug.newlineOn() : +Calling this function ensures that a newline will be sent at the end of the `Debug.print()` function call; +By default, a newline is sent +Return type: void. + +Example: +``` +Debug.newlineOn(); +``` + +### Debug.newlineOff() : +Calling this function ensure that a newline will NOT be sent at the end of the `Debug.print()` function call; +By default a newline is sent. Call this to shut that functionality off. +Return type: void. + +Example: +``` +Debug.timestampOff(); +``` + ### Debug.print(int const debug_level, const char * fmt, ...); This function prints the message if parameter `debug_level` in the `Debug.print(debug_level, ...)` function call belongs to the range: DBG_ERROR <= debug_level <= ( that has been set using `setDebugLevel()` function). diff --git a/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino b/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino index 5ebbcc1..5837b52 100644 --- a/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino +++ b/examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino @@ -1,11 +1,12 @@ /* Advanced Debug can be helpful in embedded applications when - there are more that two microcontrollers connected serially + there are more than two microcontrollers connected serially or a wireless sensor like XBee is connected to the serial port - that will send data wirelessly to other XBee node. + that will send data wirelessly to other XBee nodes. - In boards like Arduino Nano, UNO, MEGA only one serial port is available, - therefore additional Software Serial ports can be made using SoftwareSerial + In boards like Arduino Nano, UNO, or MEGA only one serial port is available, + therefore additional software serial ports can be made using the + SoftwareSerial library. */ #include "Arduino_DebugUtils.h" diff --git a/extras/codespell-ignore-words-list.txt b/extras/codespell-ignore-words-list.txt deleted file mode 100644 index e69de29..0000000 diff --git a/library.properties b/library.properties index 30c17d8..8bbc786 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_DebugUtils -version=1.1.0 +version=1.2.0 author=Arduino maintainer=Arduino sentence=Debugging module with different debug levels, timestamps and printf-style output. diff --git a/src/Arduino_DebugUtils.cpp b/src/Arduino_DebugUtils.cpp index 63c9444..7111715 100644 --- a/src/Arduino_DebugUtils.cpp +++ b/src/Arduino_DebugUtils.cpp @@ -34,6 +34,7 @@ static Stream * DEFAULT_OUTPUT_STREAM = &Serial; Arduino_DebugUtils::Arduino_DebugUtils() { timestampOff(); + newlineOn(); setDebugLevel(DEFAULT_DEBUG_LEVEL); setDebugOutputStream(DEFAULT_OUTPUT_STREAM); } @@ -50,6 +51,14 @@ void Arduino_DebugUtils::setDebugOutputStream(Stream * stream) { _debug_output_stream = stream; } +void Arduino_DebugUtils::newlineOn() { + _newline_on = true; +} + +void Arduino_DebugUtils::newlineOff() { + _newline_on = false; +} + void Arduino_DebugUtils::timestampOn() { _timestamp_on = true; } @@ -83,7 +92,7 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper String fmt_str(fmt); va_list args; - va_start(args, fmt_str.c_str()); + va_start(args, fmt); vPrint(fmt_str.c_str(), args); va_end(args); } @@ -93,12 +102,27 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper ******************************************************************************/ void Arduino_DebugUtils::vPrint(char const * fmt, va_list args) { - static size_t const MSG_BUF_SIZE = 120; - char msg_buf[MSG_BUF_SIZE] = {0}; - - vsnprintf(msg_buf, MSG_BUF_SIZE, fmt, args); - - _debug_output_stream->println(msg_buf); + // calculate required buffer length + int msg_buf_size = vsnprintf(nullptr, 0, fmt, args) + 1; // add one for null terminator +#if __STDC_NO_VLA__ == 1 + // in the rare case where VLA is not allowed by compiler, fall back on heap-allocated memory + char * msg_buf = new char[msg_buf_size]; +#else + char msg_buf[msg_buf_size]; +#endif + + vsnprintf(msg_buf, msg_buf_size, fmt, args); + + if (_newline_on) { + _debug_output_stream->println(msg_buf); + } else { + _debug_output_stream->print(msg_buf); + } + +#if __STDC_NO_VLA__ == 1 + // remember to clean up memory + delete[] msg_buf; +#endif } void Arduino_DebugUtils::printTimestamp() @@ -120,4 +144,4 @@ bool Arduino_DebugUtils::shouldPrint(int const debug_level) const Arduino_DebugUtils Debug; void setDebugMessageLevel(int const debug_level) { Debug.setDebugLevel(debug_level); -} \ No newline at end of file +} diff --git a/src/Arduino_DebugUtils.h b/src/Arduino_DebugUtils.h index bfbb41d..b759534 100644 --- a/src/Arduino_DebugUtils.h +++ b/src/Arduino_DebugUtils.h @@ -56,6 +56,9 @@ class Arduino_DebugUtils { void timestampOn(); void timestampOff(); + void newlineOn(); + void newlineOff(); + void print(int const debug_level, const char * fmt, ...); void print(int const debug_level, const __FlashStringHelper * fmt, ...); @@ -63,6 +66,7 @@ class Arduino_DebugUtils { private: bool _timestamp_on; + bool _newline_on; int _debug_level; Stream * _debug_output_stream; @@ -78,4 +82,4 @@ class Arduino_DebugUtils { extern Arduino_DebugUtils Debug; -#endif /* ARDUINO_DEBUG_UTILS_H_ */ \ No newline at end of file +#endif /* ARDUINO_DEBUG_UTILS_H_ */