mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[PubSubClient3] Update to latest MQTT Client PubSubClient3
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help improve PubSubClient3
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what happened...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Connect to '...'
|
||||
2. Publish message to '...'
|
||||
3. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Library version
|
||||
description: What version of PubSubClient3 are you running?
|
||||
placeholder: v3.3.0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: What platform are you using?
|
||||
options:
|
||||
- Arduino AVR
|
||||
- ESP32
|
||||
- ESP8266
|
||||
- Other (specify in environment)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: |
|
||||
Provide details about your hardware and software environment, including:
|
||||
- Board: (e.g., Arduino Uno, ESP12E, ESP32, NodeMCU, etc.)
|
||||
- Framework Version: (e.g., Arduino AVR 5.2.0, ESP32 Arduino 3.3.2, ESP8266 Core 3.1.2 / 3.2.0-git)
|
||||
- Development Environment: (e.g., Arduino IDE 2.3.6, PlatformIO Core 6.1.8)
|
||||
- Platform: (if Other was selected above)
|
||||
placeholder: |
|
||||
- Board:
|
||||
- Framework Version:
|
||||
- Development Environment:
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: example_code
|
||||
attributes:
|
||||
label: Minimal reproducible example (MVP)
|
||||
description: Provide the smallest code/config and exact steps that reproduce the bug. Paste complete minimal sketch or commands.
|
||||
placeholder: |
|
||||
```cpp
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
// minimal setup showing the bug
|
||||
void setup() {
|
||||
// ...
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
render: markdown
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output
|
||||
render: shell
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature for PubSubClient3
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to suggest a new feature!
|
||||
|
||||
- type: textarea
|
||||
id: reason
|
||||
attributes:
|
||||
label: Describe the reason of your feature request
|
||||
description: A clear and concise description of what the problem is.
|
||||
placeholder: I want to do [...]
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Describe the solution you'd like
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or code examples about the feature request here.
|
||||
render: markdown
|
||||
+1
-1
@@ -29,7 +29,7 @@ ln -s $GITHUB_WORKSPACE $HOME/Arduino/libraries/CI_Test_Library
|
||||
|
||||
# Compile all *.ino files for the Arduino
|
||||
for f in **/*.ino ; do
|
||||
if [[ "$f" != *mqtt_esp8266.ino && "$f" != *mqtt_large_message.ino ]]; then
|
||||
if [[ "$f" != *"mqtt_esp"* ]]; then
|
||||
echo "################################################################"
|
||||
echo "Arduino Uno compiling file ${f}"
|
||||
arduino-cli compile -b arduino:avr:uno $f
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ cd $GITHUB_WORKSPACE
|
||||
#command -v clang-format >/dev/null 2>&1 || sudo apt-get -y install clang-format
|
||||
# need Ubuntu clang-format version 19.1.1 (1ubuntu1~24.04.2)
|
||||
# default Ubuntu clang-format version 18.1.3 (1ubuntu1) is not working
|
||||
sudo apt-get -y install clang-format-19
|
||||
#sudo apt-get -y install clang-format-19
|
||||
# Check clang-format output
|
||||
for f in **/*.{h,c,hpp,cpp,ino} ; do
|
||||
#if [ -f "$f" ] && [[ "$f" != "tests/"* ]]; then
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
time: "06:00"
|
||||
@@ -0,0 +1,103 @@
|
||||
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/**'
|
||||
|
||||
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:uno
|
||||
platforms: |
|
||||
- name: arduino:avr
|
||||
libraries: ""
|
||||
artifact-name-suffix: arduino-avr-uno
|
||||
- fqbn: arduino:megaavr:uno2018
|
||||
platforms: |
|
||||
- name: arduino:megaavr
|
||||
libraries: |
|
||||
- name: WiFiNINA
|
||||
artifact-name-suffix: arduino-megaavr-uno2018
|
||||
- fqbn: arduino:samd:mkr1000
|
||||
platforms: |
|
||||
- name: arduino:samd
|
||||
libraries: |
|
||||
- name: WiFi101
|
||||
artifact-name-suffix: arduino-samd-mkr1000
|
||||
- fqbn: esp8266:esp8266:generic
|
||||
platforms: |
|
||||
- name: esp8266:esp8266
|
||||
source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
libraries: ""
|
||||
artifact-name-suffix: esp8266-esp8266-generic
|
||||
- fqbn: "esp32:esp32:esp32"
|
||||
platforms: |
|
||||
- name: esp32:esp32
|
||||
libraries: ""
|
||||
artifact-name-suffix: esp32-esp32-esp32
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download SRAM library
|
||||
run: |
|
||||
mkdir -p ./arduino-libraries
|
||||
git -C ./arduino-libraries clone https://github.com/ennui2342/arduino-sram.git
|
||||
|
||||
- name: Filter examples
|
||||
if: success()
|
||||
run: |
|
||||
if [[ "${{ matrix.board.fqbn }}" == esp32:esp32:* ]]; then
|
||||
echo "Removing non-ESP32 specific examples"
|
||||
rm -rf examples/mqtt_stream
|
||||
fi
|
||||
if [[ ! "${{ matrix.board.fqbn }}" == *:esp*:* ]]; then
|
||||
echo "Removing ESP specific examples"
|
||||
rm -rf examples/mqtt_esp*
|
||||
fi
|
||||
|
||||
- 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: ./
|
||||
- source-path: ./arduino-libraries/arduino-sram
|
||||
# Install libraries from GitHub
|
||||
#- source-url: https://github.com/ennui2342/arduino-sram
|
||||
- name: Ethernet
|
||||
${{ matrix.board.libraries }}
|
||||
sketch-paths: |
|
||||
- examples
|
||||
enable-deltas-report: true
|
||||
sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
|
||||
- name: Save sketches report as workflow artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
if-no-files-found: error
|
||||
path: ${{ env.SKETCHES_REPORTS_PATH }}
|
||||
name: sketches-report-${{ matrix.board.artifact-name-suffix }}
|
||||
+6
-7
@@ -7,7 +7,7 @@ name: Generate Doxygen API and deploy content to GitHub Pages
|
||||
on:
|
||||
# Runs on pushes targeting the default branch
|
||||
push:
|
||||
branches: ["master"]
|
||||
branches: ["release"]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
@@ -34,12 +34,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Update Doxyfile PROJECT_NUMBER
|
||||
run: bash .github/doxygen-update-version.sh
|
||||
- name: Doxygenize
|
||||
#uses: langroodi/doxygenize@v1.7.1 # waiting for update ...
|
||||
uses: langroodi/doxygenize@6e920681c5d838e9a1b5cd273b814d1e4023b63d
|
||||
uses: langroodi/doxygenize@v1.7.1
|
||||
#uses: hmueller01/doxygenize@update-alpine-linux+patches
|
||||
with:
|
||||
# Doxygen configuration file path
|
||||
@@ -54,12 +53,12 @@ jobs:
|
||||
# run: |
|
||||
# find ./site
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
uses: actions/configure-pages@v6
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
#path: '.' # Upload entire repository
|
||||
path: './site'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
uses: actions/deploy-pages@v5
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
paths:
|
||||
- 'examples/**'
|
||||
- 'src/**'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
run-checks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install deps
|
||||
# need Ubuntu clang-format version 19.1.1 (1ubuntu1~24.04.2)
|
||||
# default Ubuntu clang-format version 18.1.3 (1ubuntu1) is not working
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang-format-19
|
||||
|
||||
- name: Check clang-format conformity
|
||||
run: bash .github/clang-lint.sh
|
||||
@@ -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:
|
||||
# Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow
|
||||
sketches-reports-source: ^sketches-report-.+
|
||||
Vendored
+5
-8
@@ -1,4 +1,4 @@
|
||||
name: build
|
||||
name: Unit tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -11,14 +11,11 @@ on:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check clang-format conformity
|
||||
run: bash .github/clang-lint.sh
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Build tests
|
||||
# Build / Execute tests defined in tests folder
|
||||
@@ -31,5 +28,5 @@ jobs:
|
||||
#run: make test
|
||||
run: bin/connect_spec && bin/publish_spec && bin/receive_spec && bin/subscribe_spec
|
||||
|
||||
- name: Build on Arduino CLI
|
||||
run: bash .github/build-arduino.sh
|
||||
# - name: Build on Arduino CLI
|
||||
# run: bash .github/build-arduino.sh
|
||||
@@ -1,6 +1,8 @@
|
||||
tests/bin
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.pio/
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.vscode/
|
||||
site/api
|
||||
tests/bin
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
|
||||
[Semantic Versioning](https://semver.org/).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
* Improved test coverage for all QoS levels (0, 1, 2)
|
||||
* Increased robustness and correctness in client-side handling of QoS 1 and QoS 2 messages (proper handling of PUBACK, PUBREC, PUBREL, PUBCOMP sequences)
|
||||
* Merged and cleaned up tests to ensure MQTT protocol compliance for all QoS scenarios
|
||||
|
||||
## [3.3.0] - 2025-12-14
|
||||
|
||||
### Added
|
||||
|
||||
* Speedup publish large messages by using a buffer by @TD-er in [#59](https://github.com/hmueller01/pubsubclient3/pull/59)
|
||||
* Support `PROGMEM` and `__FlashStringHelper` topics by @hmueller01 in [#72](https://github.com/hmueller01/pubsubclient3/pull/72)
|
||||
* Added issue template by @hmueller01 in [#76](https://github.com/hmueller01/pubsubclient3/pull/76)
|
||||
* Report delta sizes in pull requests by @hmueller01 in [#77](https://github.com/hmueller01/pubsubclient3/pull/77)
|
||||
|
||||
### Changed
|
||||
|
||||
* Refactored private members by @hmueller01 in [#68](https://github.com/hmueller01/pubsubclient3/pull/68)
|
||||
* Refactored private functions by @hmueller01 in [#70](https://github.com/hmueller01/pubsubclient3/pull/70)
|
||||
* Do not crash if `_client` not set by @hmueller01 in [#69](https://github.com/hmueller01/pubsubclient3/pull/69)
|
||||
* Minor updates that come across by @hmueller01 in [#73](https://github.com/hmueller01/pubsubclient3/pull/73)
|
||||
* Inline optimisation by @hmueller01 in [#75](https://github.com/hmueller01/pubsubclient3/pull/75)
|
||||
* Bump actions/upload-pages-artifact from 3 to 4 by @dependabot[bot] in [#78](https://github.com/hmueller01/pubsubclient3/pull/78)
|
||||
* Bump actions/checkout from 2 to 5 by @dependabot[bot] in [#79](https://github.com/hmueller01/pubsubclient3/pull/79)
|
||||
* Tag unused parameter to avoid warnings by @hmueller01 in [#82](https://github.com/hmueller01/pubsubclient3/pull/82)
|
||||
* Fix compile warning at strnlen bound by @hmueller01 in [#83](https://github.com/hmueller01/pubsubclient3/pull/83)
|
||||
* Fix deprecated `BUILTIN_LED` by @hmueller01 in [#84](https://github.com/hmueller01/pubsubclient3/pull/84)
|
||||
* Bump actions/checkout from 5 to 6 by @dependabot[bot] in [#85](https://github.com/hmueller01/pubsubclient3/pull/85)
|
||||
* Update workflows by @hmueller01 in [#86](https://github.com/hmueller01/pubsubclient3/pull/86)
|
||||
|
||||
## [3.2.1] - 2025-09-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed bug introduced with QoS > 0 support (#65)
|
||||
|
||||
## [3.2.0] - 2025-07-20
|
||||
|
||||
### Added
|
||||
|
||||
- Support publish at QoS 1 and 2 (by @hmueller01) (#49)
|
||||
- Doxygen API documentation on gh-pages (by @hmueller01) (#51)
|
||||
|
||||
### Changed
|
||||
|
||||
- Add check for nullptr in `CHECK_STRING_LENGTH` (by @TD-er) (#48)
|
||||
- Move `CHECK_STRING_LENGTH` to `PubSubClient.cpp` (by @hmueller01) (#50)
|
||||
- Get rid of lazy calling parameter (by @hmueller01) (#53)
|
||||
- Implemented `writeNextMsgId()` (by @hmueller01) (#54)
|
||||
- Cleanup `writeString()` (by @hmueller01) (#55)
|
||||
|
||||
## [3.1.0] - 2025-03-20
|
||||
|
||||
### Added
|
||||
|
||||
- Added `ERROR_PSC_PRINTF` and `ERROR_PSC_PRINTF_P` outputs (#25)
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix `setServer(domain, ...)` by copying domain string to an internal buffer (prevent potential dangling pointer) (#10)
|
||||
- Connect to broker only if port != 0 (protect against incorrect initialization) (#10)
|
||||
- Refactored buffer length types to `size_t` (#11)
|
||||
- Added warnings and `-Werror` to tests Makefile (#11)
|
||||
- Reformatted tests code using Google style (see `.clang-format`) (#11)
|
||||
- Fix keepalive handling (thanks to @uschnindler) (#14)
|
||||
- Use initializer lists for constructors (#15)
|
||||
- Fix `DEBUG_PSC_PRINTF` outputs (#18)
|
||||
- Introduce `MQTTRETAINED` flag (#21)
|
||||
- Added documentation on `readByte()` and `readPacket()` (#23)
|
||||
- Refactored `buildHeader()`, `readPacket()`, `readByte()`, `beginPublish()`/`endPublish()`, `publish()`/`publish_P()`, `connect()`, `connected()`, `subscribe()`/`unsubscribe()` and internal timing handling (#22, #23, #28, #30, #31, #33, #34, #37, #38, #39, #40, #44)
|
||||
- Fixed potential memory corruption in `MQTTPUBLISH` callback preparation (#25)
|
||||
- Fixed a missing failure test on `_client->read()` in `readByte()` (#32)
|
||||
- Switch from constructor init-lists to class member initialization (C++ core guideline C.45) (#42)
|
||||
|
||||
## [3.0.2] - 2025-02-27
|
||||
|
||||
### Added
|
||||
|
||||
- GitHub workflow to execute tests
|
||||
- GitHub workflow to compile examples using Arduino CLI
|
||||
- Examples: Use a better source of randomness (#9)
|
||||
- Optionally deactivate `std::function` usage (#7)
|
||||
|
||||
## [3.0.1] - 2025-02-20
|
||||
|
||||
### Added
|
||||
|
||||
- Added `.editorconfig`
|
||||
- Added GitHub workflow to check code style on push/PR
|
||||
|
||||
### Changed
|
||||
|
||||
- Reformatted code using Google style
|
||||
- Fixes for tests: missing def for `strlen_P` & Python libs
|
||||
|
||||
## [3.0] - 2025-02-17
|
||||
|
||||
Maintenance taken over by Holger Mueller
|
||||
|
||||
### Added
|
||||
|
||||
- In-source documentation added to `PubSubClient` header
|
||||
- Add flag for enabling debugging of library
|
||||
|
||||
### Changed
|
||||
|
||||
- Always use `PubSubClient()` constructor
|
||||
- Use `bool` instead of `boolean`
|
||||
- Add `yield()` calls in `connect()` and `write()` to avoid watchdog resets
|
||||
- Fix bug in `publish_P` handling of PROGMEM payload length
|
||||
- Fix increase `bytesToWrite` to `uint16_t` to prevent overflow
|
||||
- Remove compiler warning about unsigned `expectedLength`
|
||||
- Extend usage of `std::function` where available
|
||||
- Fix for keep alive zero
|
||||
|
||||
## [2.8] - 2020-05-20
|
||||
|
||||
### Added
|
||||
|
||||
- `setBufferSize()` to override `MQTT_MAX_PACKET_SIZE`
|
||||
- `setKeepAlive()` to override `MQTT_KEEPALIVE`
|
||||
- `setSocketTimeout()` to override `MQTT_SOCKET_TIMEOUT`
|
||||
- Check to prevent subscribe/unsubscribe to empty topics
|
||||
- Declare WiFi mode prior to connect in ESP example
|
||||
- Use `strnlen` to avoid overruns
|
||||
- Support pre-connected `Client` objects
|
||||
|
||||
## [2.7] - 2018-11-02
|
||||
|
||||
### Added
|
||||
|
||||
- Added large-payload API: `beginPublish`/`write`/`publish`/`endPublish`
|
||||
- Added `yield` calls to improve reliability on ESP
|
||||
- Added Clean Session flag to connect options
|
||||
- Added ESP32 support for functional callback signature
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed remaining-length handling to prevent buffer overrun
|
||||
|
||||
## [2.4] - 2015-11-21
|
||||
|
||||
### Added
|
||||
|
||||
- `MQTT_SOCKET_TIMEOUT` to avoid blocking indefinitely while waiting for inbound data
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed return code when publishing >256 bytes
|
||||
|
||||
## [2.3] - 2015-09-11
|
||||
|
||||
### Added
|
||||
|
||||
- `publish(topic,payload,retained)` convenience overload
|
||||
|
||||
## [2.2] - 2015-09-07
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed code layout to match Arduino Library requirements
|
||||
|
||||
## [2.1] - 2015-09-07
|
||||
|
||||
### Added
|
||||
|
||||
- `MAX_TRANSFER_SIZE` to chunk messages if needed
|
||||
- Reject topic/payloads that exceed `MQTT_MAX_PACKET_SIZE`
|
||||
|
||||
## [2.0] - 2015-08-28
|
||||
|
||||
### Added
|
||||
|
||||
- MQTT 3.1.1 support
|
||||
- Fix PROGMEM handling for Intel Galileo/ESP8266
|
||||
- Overloaded constructors for convenience
|
||||
- Chainable setters for server/callback/client/stream
|
||||
- `state()` function to return CONNACK code
|
||||
|
||||
## [1.0] - 2009-02-02
|
||||
|
||||
- Initial release notes: QoS 0 only, 128 byte max message size, keepalive 30s, no Will messages
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
3.1.0
|
||||
* Fix setServer(domain, ...) by copy domain string to own buffer (prevent potential dangling string pointer) #10
|
||||
* Connect to broker only if port != 0 (e.g. in case of incorrect PubSubClient initialization) #10
|
||||
* Refactored different buffer length types to size_t #11
|
||||
* Added a bunch of warnings and -Werror to tests Makefile #11
|
||||
* Reformatted tests code using Google sytle (see .clang-format) #11
|
||||
* Fix keepalive handling, thanks to @uschnindler providing this to thingsboard #14
|
||||
* Use initializer lists instead of assigning global members in constructor #15
|
||||
* Fix DEBUG_PSC_PRINTF outputs #18
|
||||
* Added ERROR_PSC_PRINTF and ERROR_PSC_PRINTF_P outputs #25
|
||||
* Introduce MQTTRETAINED flag instead of hard coding #21
|
||||
* Added documentation on readByte() and readPacket() functions #23
|
||||
* Refactored buildHeader() (change return type, use MQTT_MAX_HEADER_SIZE, locals) #22, #34, #37
|
||||
* Refactored readPacket() (changed return type to size_t, used MQTT_MAX_HEADER_SIZE, locals) #23
|
||||
* Refactored readByte() #23
|
||||
* Refactored beginPublish() and endPublish() #28
|
||||
* Refactored publish() #31
|
||||
* Refactored publish_P() #30
|
||||
* Refactored connect() #40
|
||||
* Refactored connected() (mostly rewritten and simplified, added setting pingOutstanding, don't need flush()) #44
|
||||
* Refactored subscribe() and unsubscribe() #44
|
||||
* Refactored internal socketTimeout and keepAlive to millis to improve performance #33, #38, #39
|
||||
* Fix potential memory corruption in MQTTPUBLISH callback preparation #25
|
||||
* Fix potential error in readByte() (missing failure test on _client->read()) #32
|
||||
* Switch from constructor init-lists to class member initialization, see C++ core guideline C.45 #42
|
||||
|
||||
3.0.2
|
||||
* Added github workflow to execute tests
|
||||
* Added github workflow to compile examples using arduino-cli
|
||||
* Examples: Use a better source of random #9
|
||||
* Deactivate use of std::function on demand #7
|
||||
|
||||
3.0.1
|
||||
* Reformatted code using Google sytle (see .clang-format)
|
||||
* Added .editorconfig
|
||||
* Added github workflow to check code sytle on push and pull request
|
||||
* Fix-tests: missing def for strlen_P & Python libs
|
||||
|
||||
3.0
|
||||
* Maintenance taken over by Holger Mueller
|
||||
* Adds in-source documentation to PubSubClient header.
|
||||
* Add flag for enabling debugging of library
|
||||
* Always use PubSubClient() constructor
|
||||
* Use bool instead of boolean
|
||||
* Add yield() calls in connect() and write() to avoid wdt resets if either blocks for too long
|
||||
* Fix bug in publish_P which will always treat the payload length as 0 when used with PROGMEM
|
||||
* Fix increase `bytesToWrite` to uint16_t to prevent overflow
|
||||
* Remove compiler warning `expectedLength` should be unsigned
|
||||
* Extend usage of std::function on all the platforms where it's available
|
||||
* Fix for keep alive zero
|
||||
|
||||
2.8
|
||||
* Add setBufferSize() to override MQTT_MAX_PACKET_SIZE
|
||||
* Add setKeepAlive() to override MQTT_KEEPALIVE
|
||||
* Add setSocketTimeout() to overide MQTT_SOCKET_TIMEOUT
|
||||
* Added check to prevent subscribe/unsubscribe to empty topics
|
||||
* Declare wifi mode prior to connect in ESP example
|
||||
* Use `strnlen` to avoid overruns
|
||||
* Support pre-connected Client objects
|
||||
|
||||
2.7
|
||||
* Fix remaining-length handling to prevent buffer overrun
|
||||
* Add large-payload API - beginPublish/write/publish/endPublish
|
||||
* Add yield call to improve reliability on ESP
|
||||
* Add Clean Session flag to connect options
|
||||
* Add ESP32 support for functional callback signature
|
||||
* Various other fixes
|
||||
|
||||
2.4
|
||||
* Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely
|
||||
whilst waiting for inbound data
|
||||
* Fixed return code when publishing >256 bytes
|
||||
|
||||
2.3
|
||||
* Add publish(topic,payload,retained) function
|
||||
|
||||
2.2
|
||||
* Change code layout to match Arduino Library reqs
|
||||
|
||||
2.1
|
||||
* Add MAX_TRANSFER_SIZE def to chunk messages if needed
|
||||
* Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE
|
||||
|
||||
2.0
|
||||
* Add (and default to) MQTT 3.1.1 support
|
||||
* Fix PROGMEM handling for Intel Galileo/ESP8266
|
||||
* Add overloaded constructors for convenience
|
||||
* Add chainable setters for server/callback/client/stream
|
||||
* Add state function to return connack return code
|
||||
|
||||
1.9
|
||||
* Do not split MQTT packets over multiple calls to _client->write()
|
||||
* API change: All constructors now require an instance of Client
|
||||
to be passed in.
|
||||
* Fixed example to match 1.8 api changes - dpslwk
|
||||
* Added username/password support - WilHall
|
||||
* Added publish_P - publishes messages from PROGMEM - jobytaffey
|
||||
|
||||
1.8
|
||||
* KeepAlive interval is configurable in PubSubClient.h
|
||||
* Maximum packet size is configurable in PubSubClient.h
|
||||
* API change: Return boolean rather than int from various functions
|
||||
* API change: Length parameter in message callback changed
|
||||
from int to unsigned int
|
||||
* Various internal tidy-ups around types
|
||||
|
||||
1.7
|
||||
* Improved keepalive handling
|
||||
* Updated to the Arduino-1.0 API
|
||||
|
||||
1.6
|
||||
* Added the ability to publish a retained message
|
||||
|
||||
1.5
|
||||
* Added default constructor
|
||||
* Fixed compile error when used with arduino-0021 or later
|
||||
|
||||
1.4
|
||||
* Fixed connection lost handling
|
||||
|
||||
1.3
|
||||
* Fixed packet reading bug in PubSubClient.readPacket
|
||||
|
||||
1.2
|
||||
* Fixed compile error when used with arduino-0016 or later
|
||||
|
||||
1.1
|
||||
* Reduced size of library
|
||||
* Added support for Will messages
|
||||
* Clarified licensing - see LICENSE.txt
|
||||
|
||||
1.0
|
||||
* Only Quality of Service (QOS) 0 messaging is supported
|
||||
* The maximum message size, including header, is 128 bytes
|
||||
* The keepalive interval is set to 30 seconds
|
||||
* No support for Will messages
|
||||
Regular → Executable
@@ -29,7 +29,7 @@ Full API documentation is available here: https://hmueller01.github.io/pubsubcli
|
||||
## Limitations
|
||||
|
||||
- The client is based on the [MQTT Version 3.1.1 specification](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) with some limitations.
|
||||
- It can publish at QoS 0, 1 or 2.
|
||||
- It can publish at QoS 0 and since [v3.2.0](https://github.com/hmueller01/pubsubclient3/releases/tag/v3.2.0) also at QoS 1 or 2.
|
||||
|
||||
**WARNING:** No retransmission is supported to keep the library as much memory friendly as possible.
|
||||
|
||||
@@ -45,7 +45,17 @@ Full API documentation is available here: https://hmueller01.github.io/pubsubcli
|
||||
`PubSubClient::setKeepAlive(keepAlive)`.
|
||||
- The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by
|
||||
changing value of `MQTT_VERSION` in `PubSubClient.h`.
|
||||
|
||||
- Since [v3.3.0](https://github.com/hmueller01/pubsubclient3/releases/tag/v3.3.0) it can publish and subscribe to `PROGMEM` or `__FlashStringHelper` topics.
|
||||
Details see [mqtt_progmem](https://github.com/hmueller01/pubsubclient3/blob/aae84e4d1aa65e752e19e30239b5796b4fe2705b/examples/mqtt_progmem/src/mqtt_progmem.cpp#L39-L48) example.
|
||||
But if you like to publish `PROGMEM` topics you have to use
|
||||
```c
|
||||
const char TOPIC[] PROGMEM = "test";
|
||||
const char HELLO_WORLD[] PROGMEM = "hello world";
|
||||
client.beginPublish_P(TOPIC, strlen_P(HELLO_WORLD), MQTT_QOS0, false);
|
||||
client.write_P(HELLO_WORLD);
|
||||
client.endPublish();
|
||||
```
|
||||
as `client.publish_P(...)` is already used for `PROGMEM` payloads.
|
||||
|
||||
## Compatible Hardware
|
||||
|
||||
@@ -69,6 +79,10 @@ The library cannot currently be used with hardware based on the ENC28J60 chip
|
||||
such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an
|
||||
[alternative library](https://github.com/njh/NanodeMQTT) available.
|
||||
|
||||
## Changelog
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md)
|
||||
|
||||
## License
|
||||
|
||||
This code is released under the MIT License.
|
||||
This code is released under the [MIT License](LICENSE.txt).
|
||||
|
||||
Regular → Executable
+3
-1
@@ -11,12 +11,14 @@
|
||||
#include <PubSubClient.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
// Update these with values suitable for your network.
|
||||
byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED};
|
||||
IPAddress ip(172, 16, 0, 100);
|
||||
IPAddress server(172, 16, 0, 2);
|
||||
|
||||
void callback(char* topic, uint8_t* payload, size_t plength) {
|
||||
void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, _UNUSED_ size_t plength) {
|
||||
// handle message arrived
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+5
-5
@@ -23,7 +23,7 @@
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <esp_random.h>
|
||||
#define BUILTIN_LED A0
|
||||
#define LED_BUILTIN A0
|
||||
#define RANDOM_REG32 esp_random()
|
||||
#else
|
||||
#error Platform not supported.
|
||||
@@ -77,11 +77,11 @@ void callback(char* topic, uint8_t* payload, size_t plength) {
|
||||
|
||||
// Switch on the LED if an 1 was received as first character
|
||||
if ((char)payload[0] == '1') {
|
||||
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
|
||||
// but actually the LED is on; this is because
|
||||
// it is active low on the ESP-01)
|
||||
} else {
|
||||
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ void reconnect() {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||
Serial.begin(115200);
|
||||
setup_wifi();
|
||||
client.setServer(mqtt_server, 1883);
|
||||
@@ -127,7 +127,7 @@ void loop() {
|
||||
if (now - lastMsg > 2000) {
|
||||
lastMsg = now;
|
||||
++value;
|
||||
snprintf(msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
|
||||
snprintf(msg, MSG_BUFFER_SIZE, "hello world #%d", value);
|
||||
Serial.print("Publish message: ");
|
||||
Serial.println(msg);
|
||||
client.publish("outTopic", msg);
|
||||
-2
@@ -28,7 +28,6 @@
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <esp_random.h>
|
||||
#define BUILTIN_LED A0
|
||||
#define RANDOM_REG32 esp_random()
|
||||
#else
|
||||
#error Platform not supported.
|
||||
@@ -170,7 +169,6 @@ void reconnect() {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
|
||||
Serial.begin(115200);
|
||||
setup_wifi();
|
||||
client.setServer(mqtt_server, 1883);
|
||||
@@ -0,0 +1,3 @@
|
||||
// Example sketch showing how to use PubSubClient with strings stored in PROGMEM.
|
||||
// This needs to be an empty file to satisfy the arduino-cli build system.
|
||||
// See src/mqtt_progmem.cpp for the actual example code.
|
||||
@@ -0,0 +1,40 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
; https://docs.platformio.org/en/latest/boards/atmelavr/uno.html
|
||||
|
||||
[platformio]
|
||||
description = Basic MQTT example with Authentication and Progmem strings
|
||||
|
||||
[env]
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
arduino-libraries/Ethernet @ ^2.0.2
|
||||
hmueller01/PubSubClient3 @ ^3.3.0
|
||||
build_flags =
|
||||
; -D DEBUG_ESP_PORT=Serial
|
||||
; -D DEBUG_PUBSUBCLIENT
|
||||
; -D MQTT_MAX_PACKET_SIZE=512
|
||||
; -D MQTT_KEEPALIVE=120
|
||||
|
||||
[env:uno]
|
||||
platform = atmelavr
|
||||
board = uno
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266
|
||||
platform_packages = platformio/framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||
board = esp12e
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Basic MQTT example with Authentication
|
||||
|
||||
- connects to an MQTT server, providing username
|
||||
and password
|
||||
- publishes "hello world" to the topic "outTopic"
|
||||
- subscribes to the topic "inTopic"
|
||||
*/
|
||||
|
||||
#include <Ethernet.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
// Update these with values suitable for your network.
|
||||
byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED};
|
||||
IPAddress ip(172, 16, 0, 100);
|
||||
IPAddress server(172, 16, 0, 2);
|
||||
const char HELLO_WORLD_3[] PROGMEM = "hello world 3";
|
||||
const char HELLO_WORLD_4[] PROGMEM = "hello world 4";
|
||||
const char SUBSCRIBE_TOPIC[] PROGMEM = "inTopic1";
|
||||
|
||||
void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, _UNUSED_ size_t plength) {
|
||||
// handle message arrived
|
||||
}
|
||||
|
||||
EthernetClient ethClient;
|
||||
PubSubClient client(server, 1883, callback, ethClient);
|
||||
|
||||
void setup() {
|
||||
Ethernet.begin(mac, ip);
|
||||
// Note - the default maximum packet size is 128 bytes. If the
|
||||
// combined length of clientId, username and password exceed this use the
|
||||
// following to increase the buffer size:
|
||||
// client.setBufferSize(255);
|
||||
|
||||
if (client.connect("arduinoClient", "testuser", "testpass")) {
|
||||
client.publish(F("outTopic"), "hello world 1", MQTT_QOS0, false);
|
||||
client.publish(F("outTopic"), F("hello world 2"), MQTT_QOS1, false);
|
||||
client.publish_P(F("outTopic"), HELLO_WORLD_3, MQTT_QOS2, false);
|
||||
|
||||
client.beginPublish(F("outTopic"), strlen_P(HELLO_WORLD_4), MQTT_QOS1, false);
|
||||
client.write_P(HELLO_WORLD_4);
|
||||
client.endPublish();
|
||||
|
||||
client.subscribe(F("inTopic"));
|
||||
client.subscribe_P(SUBSCRIBE_TOPIC, MQTT_QOS1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <PubSubClient.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
// Update these with values suitable for your network.
|
||||
byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED};
|
||||
IPAddress ip(172, 16, 0, 100);
|
||||
@@ -29,7 +31,7 @@ EthernetClient ethClient;
|
||||
PubSubClient client(server, 1883, callback, ethClient);
|
||||
|
||||
// Callback function
|
||||
void callback(char* topic, uint8_t* payload, size_t plength) {
|
||||
void callback(_UNUSED_ char* topic, uint8_t* payload, size_t plength) {
|
||||
// In order to republish this payload, a copy must be made
|
||||
// as the orignal payload buffer will be overwritten whilst
|
||||
// constructing the PUBLISH packet.
|
||||
|
||||
+3
-1
@@ -11,12 +11,14 @@
|
||||
#include <PubSubClient.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
// Update these with values suitable for your hardware/network.
|
||||
byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED};
|
||||
IPAddress ip(172, 16, 0, 100);
|
||||
IPAddress server(172, 16, 0, 2);
|
||||
|
||||
void callback(char* topic, uint8_t* payload, size_t plength) {
|
||||
void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, _UNUSED_ size_t plength) {
|
||||
// handle message arrived
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <SPI.h>
|
||||
#include <SRAM.h>
|
||||
|
||||
#define _UNUSED_ __attribute__((unused))
|
||||
|
||||
// Update these with values suitable for your network.
|
||||
byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED};
|
||||
IPAddress ip(172, 16, 0, 100);
|
||||
@@ -21,7 +23,7 @@ IPAddress server(172, 16, 0, 2);
|
||||
|
||||
SRAM sram(4, SRAM_1024);
|
||||
|
||||
void callback(char* topic, uint8_t* payload, size_t plength) {
|
||||
void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, size_t plength) {
|
||||
sram.seek(1);
|
||||
|
||||
// do something with the message
|
||||
|
||||
Regular → Executable
+3
@@ -17,9 +17,12 @@ disconnect KEYWORD2
|
||||
publish KEYWORD2
|
||||
publish_P KEYWORD2
|
||||
beginPublish KEYWORD2
|
||||
beginPublish_P KEYWORD2
|
||||
endPublish KEYWORD2
|
||||
write KEYWORD2
|
||||
write_P KEYWORD2
|
||||
subscribe KEYWORD2
|
||||
subscribe_P KEYWORD2
|
||||
unsubscribe KEYWORD2
|
||||
loop KEYWORD2
|
||||
connected KEYWORD2
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/hmueller01/pubsubclient3.git"
|
||||
},
|
||||
"version": "3.1.0",
|
||||
"version": "3.3.0",
|
||||
"license": "MIT",
|
||||
"exclude": "tests",
|
||||
"examples": "examples/*/*.ino",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"atmelsam",
|
||||
"atmelmegaavr",
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=PubSubClient3
|
||||
version=3.1.0
|
||||
version=3.3.0
|
||||
author=Nick O'Leary <nick.oleary@gmail.com>
|
||||
maintainer=Holger Mueller <github@euhm.de>
|
||||
license=MIT
|
||||
|
||||
Regular → Executable
+359
-312
File diff suppressed because it is too large
Load Diff
Regular → Executable
+270
-43
@@ -34,7 +34,7 @@
|
||||
* @brief Maximum packet size defined by MQTT protocol.
|
||||
*/
|
||||
#ifndef MQTT_MAX_POSSIBLE_PACKET_SIZE
|
||||
#define MQTT_MAX_POSSIBLE_PACKET_SIZE 268435455
|
||||
#define MQTT_MAX_POSSIBLE_PACKET_SIZE ((size_t)268435455) // might be limited to 65535 if size_t is 16-bit (unsigned int)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -176,36 +176,39 @@
|
||||
class PubSubClient : public Print {
|
||||
private:
|
||||
Client* _client{};
|
||||
uint8_t* buffer{};
|
||||
size_t bufferSize{};
|
||||
unsigned long keepAliveMillis{};
|
||||
unsigned long socketTimeoutMillis{};
|
||||
uint16_t nextMsgId{};
|
||||
unsigned long lastOutActivity{};
|
||||
unsigned long lastInActivity{};
|
||||
bool pingOutstanding{};
|
||||
MQTT_CALLBACK_SIGNATURE{};
|
||||
IPAddress ip{};
|
||||
char* domain{};
|
||||
uint16_t port{};
|
||||
Stream* stream{};
|
||||
int _state{MQTT_DISCONNECTED};
|
||||
uint8_t* _buffer{};
|
||||
size_t _bufferSize{};
|
||||
size_t _bufferWritePos{};
|
||||
uint8_t _qos{MQTT_QOS0};
|
||||
unsigned long _keepAliveMillis{};
|
||||
unsigned long _socketTimeoutMillis{};
|
||||
uint16_t _nextMsgId{};
|
||||
unsigned long _lastOutActivity{};
|
||||
unsigned long _lastInActivity{};
|
||||
bool _pingOutstanding{};
|
||||
MQTT_CALLBACK_SIGNATURE{};
|
||||
IPAddress _ip{};
|
||||
char* _domain{};
|
||||
uint16_t _port{};
|
||||
Stream* _stream{};
|
||||
int _state{MQTT_DISCONNECTED};
|
||||
|
||||
size_t readPacket(uint8_t* hdrLen);
|
||||
bool handlePacket(uint8_t hdrLen, size_t len);
|
||||
bool readByte(uint8_t* result);
|
||||
bool readByte(uint8_t* result, size_t* pos);
|
||||
uint8_t buildHeader(uint8_t header, uint8_t* buf, size_t length);
|
||||
bool write(uint8_t header, uint8_t* buf, size_t length);
|
||||
size_t writeString(const char* string, uint8_t* buf, size_t pos, size_t size);
|
||||
size_t writeNextMsgId(uint8_t* buf, size_t pos, size_t size);
|
||||
uint8_t buildHeader(uint8_t header, size_t length);
|
||||
bool writeControlPacket(uint8_t header, size_t length);
|
||||
size_t writeBuffer(size_t pos, size_t size);
|
||||
size_t writeStringImpl(bool progmem, const char* string, size_t pos);
|
||||
size_t writeString(const char* string, size_t pos);
|
||||
size_t writeNextMsgId(size_t pos);
|
||||
|
||||
bool beginPublishImpl(bool progmem, const char* topic, size_t plength, uint8_t qos, bool retained);
|
||||
bool subscribeImpl(bool progmem, const char* topic, uint8_t qos);
|
||||
bool unsubscribeImpl(bool progmem, const char* topic);
|
||||
|
||||
// Add to buffer and flush if full (only to be used with beginPublish/endPublish)Add commentMore actions
|
||||
// Add to buffer and flush if full (only to be used with beginPublish/endPublish)
|
||||
size_t appendBuffer(uint8_t data);
|
||||
size_t appendBuffer(const uint8_t *data, size_t size);
|
||||
size_t flushBuffer();
|
||||
|
||||
public:
|
||||
@@ -428,7 +431,9 @@ class PubSubClient : public Print {
|
||||
* @return true If client succeeded in establishing a connection to the broker.
|
||||
* false If client failed to establish a connection to the broker.
|
||||
*/
|
||||
bool connect(const char* id);
|
||||
inline bool connect(const char* id) {
|
||||
return connect(id, nullptr, nullptr, nullptr, MQTT_QOS0, false, nullptr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the client using a clean session with username and password.
|
||||
@@ -440,7 +445,9 @@ class PubSubClient : public Print {
|
||||
* @return true If client succeeded in establishing a connection to the broker.
|
||||
* false If client failed to establish a connection to the broker.
|
||||
*/
|
||||
bool connect(const char* id, const char* user, const char* pass);
|
||||
inline bool connect(const char* id, const char* user, const char* pass) {
|
||||
return connect(id, user, pass, nullptr, MQTT_QOS0, false, nullptr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the client using a clean session and will.
|
||||
@@ -453,7 +460,9 @@ class PubSubClient : public Print {
|
||||
* @return true If client succeeded in establishing a connection to the broker.
|
||||
* false If client failed to establish a connection to the broker.
|
||||
*/
|
||||
bool connect(const char* id, const char* willTopic, uint8_t willQos, bool willRetain, const char* willMessage);
|
||||
inline bool connect(const char* id, const char* willTopic, uint8_t willQos, bool willRetain, const char* willMessage) {
|
||||
return connect(id, nullptr, nullptr, willTopic, willQos, willRetain, willMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the client using a clean session with username, password and will.
|
||||
@@ -470,7 +479,10 @@ class PubSubClient : public Print {
|
||||
* @return true If client succeeded in establishing a connection to the broker.
|
||||
* false If client failed to establish a connection to the broker.
|
||||
*/
|
||||
bool connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, bool willRetain, const char* willMessage);
|
||||
inline bool connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, bool willRetain,
|
||||
const char* willMessage) {
|
||||
return connect(id, user, pass, willTopic, willQos, willRetain, willMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connects the client with all possible parameters (user, password, will and session).
|
||||
@@ -503,7 +515,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const char* topic, const char* payload);
|
||||
inline bool publish(const char* topic, const char* payload) {
|
||||
return publish(topic, payload, MQTT_QOS0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic using QoS 0.
|
||||
@@ -513,7 +527,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const char* topic, const char* payload, bool retained);
|
||||
inline bool publish(const char* topic, const char* payload, bool retained) {
|
||||
return publish(topic, payload, MQTT_QOS0, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic.
|
||||
@@ -524,7 +540,35 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const char* topic, const char* payload, uint8_t qos, bool retained);
|
||||
inline bool publish(const char* topic, const char* payload, uint8_t qos, bool retained) {
|
||||
return publish(topic, reinterpret_cast<const uint8_t*>(payload), payload ? strlen(payload) : 0, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic.
|
||||
* @param topic The topic from __FlashStringHelper to publish to.
|
||||
* @param payload The message to publish.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool publish(const __FlashStringHelper* topic, const char* payload, uint8_t qos, bool retained) {
|
||||
return publish(topic, reinterpret_cast<const uint8_t*>(payload), payload ? strlen(payload) : 0, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message from __FlashStringHelper to the specified topic from __FlashStringHelper.
|
||||
* @param topic The topic to publish to.
|
||||
* @param payload The message to publish.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool publish(const __FlashStringHelper* topic, const __FlashStringHelper* payload, uint8_t qos, bool retained) {
|
||||
return publish_P(topic, reinterpret_cast<const uint8_t*>(payload), payload ? strlen_P(reinterpret_cast<const char*>(payload)) : 0, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a non retained message to the specified topic using QoS 0.
|
||||
@@ -534,7 +578,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const char* topic, const uint8_t* payload, size_t plength);
|
||||
inline bool publish(const char* topic, const uint8_t* payload, size_t plength) {
|
||||
return publish(topic, payload, plength, MQTT_QOS0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic using QoS 0.
|
||||
@@ -545,7 +591,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const char* topic, const uint8_t* payload, size_t plength, bool retained);
|
||||
inline bool publish(const char* topic, const uint8_t* payload, size_t plength, bool retained) {
|
||||
return publish(topic, payload, plength, MQTT_QOS0, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic.
|
||||
@@ -559,6 +607,18 @@ class PubSubClient : public Print {
|
||||
*/
|
||||
bool publish(const char* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained);
|
||||
|
||||
/**
|
||||
* @brief Publishes a message to the specified topic.
|
||||
* @param topic The topic from __FlashStringHelper to publish to.
|
||||
* @param payload The message to publish.
|
||||
* @param plength The length of the payload.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish(const __FlashStringHelper* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained);
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic using QoS 0.
|
||||
* @param topic The topic to publish to.
|
||||
@@ -567,7 +627,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish_P(const char* topic, const char* payload, bool retained);
|
||||
inline bool publish_P(const char* topic, PGM_P payload, bool retained) {
|
||||
return publish_P(topic, payload, MQTT_QOS0, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic.
|
||||
@@ -578,7 +640,22 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish_P(const char* topic, const char* payload, uint8_t qos, bool retained);
|
||||
inline bool publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained) {
|
||||
return publish_P(topic, reinterpret_cast<const uint8_t*>(payload), payload ? strlen_P(payload) : 0, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic.
|
||||
* @param topic The topic from __FlashStringHelper to publish to.
|
||||
* @param payload The message to publish.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish_P(const __FlashStringHelper* topic, PGM_P payload, uint8_t qos, bool retained) {
|
||||
return publish_P(topic, reinterpret_cast<const uint8_t*>(payload), payload ? strlen_P(payload) : 0, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic using QoS 0.
|
||||
@@ -589,7 +666,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish_P(const char* topic, const uint8_t* payload, size_t plength, bool retained);
|
||||
inline bool publish_P(const char* topic, const uint8_t* payload, size_t plength, bool retained) {
|
||||
return publish_P(topic, payload, plength, MQTT_QOS0, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic.
|
||||
@@ -603,6 +682,18 @@ class PubSubClient : public Print {
|
||||
*/
|
||||
bool publish_P(const char* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained);
|
||||
|
||||
/**
|
||||
* @brief Publishes a message stored in PROGMEM to the specified topic.
|
||||
* @param topic The topic from __FlashStringHelper to publish to.
|
||||
* @param payload The message from PROGMEM to publish.
|
||||
* @param plength The length of the payload.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool publish_P(const __FlashStringHelper* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained);
|
||||
|
||||
/**
|
||||
* @brief Start to publish a message using QoS 0.
|
||||
* This API:
|
||||
@@ -617,7 +708,9 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool beginPublish(const char* topic, size_t plength, bool retained);
|
||||
inline bool beginPublish(const char* topic, size_t plength, bool retained) {
|
||||
return beginPublishImpl(false, topic, plength, MQTT_QOS0, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start to publish a message.
|
||||
@@ -634,7 +727,48 @@ class PubSubClient : public Print {
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
bool beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained);
|
||||
inline bool beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) {
|
||||
return beginPublishImpl(false, topic, plength, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start to publish a message using a topic from __FlashStringHelper F().
|
||||
* This API:
|
||||
* beginPublish(...)
|
||||
* one or more calls to write(...)
|
||||
* endPublish()
|
||||
* Allows for arbitrarily large payloads to be sent without them having to be copied into
|
||||
* a new buffer and held in memory at one time.
|
||||
* @param topic The topic from __FlashStringHelper to publish to.
|
||||
* @param plength The length of the payload.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) {
|
||||
// convert FlashStringHelper in PROGMEM-pointer
|
||||
return beginPublishImpl(true, reinterpret_cast<const char*>(topic), plength, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start to publish a message using a topic in PROGMEM.
|
||||
* This API:
|
||||
* beginPublish_P(...)
|
||||
* one or more calls to write(...)
|
||||
* endPublish()
|
||||
* Allows for arbitrarily large payloads to be sent without them having to be copied into
|
||||
* a new buffer and held in memory at one time.
|
||||
* @param topic The topic in PROGMEM to publish to.
|
||||
* @param plength The length of the payload.
|
||||
* @param qos The quality of service (\ref group_qos) to publish at. [0, 1, 2].
|
||||
* @param retained Publish the message with the retain flag.
|
||||
* @return true If the publish succeeded.
|
||||
* false If the publish failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) {
|
||||
return beginPublishImpl(true, reinterpret_cast<const char*>(topic), plength, qos, retained);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finish sending a message that was started with a call to beginPublish.
|
||||
@@ -648,18 +782,40 @@ class PubSubClient : public Print {
|
||||
* For performance reasons, this will be appended to the internal buffer,
|
||||
* which will be flushed when full or on a call to endPublish().
|
||||
* @param data A byte to write to the publish payload.
|
||||
* @return The number of bytes written.
|
||||
* @return The number of bytes written (0 or 1). If 0 is returned a write error occurred.
|
||||
*/
|
||||
virtual size_t write(uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief Writes an array of bytes as a component of a publish started with a call to beginPublish.
|
||||
* For performance reasons, this will be appended to the internal buffer,
|
||||
* which will be flushed when full or on a call to endPublish(). * @param buffer The bytes to write.
|
||||
* which will be flushed when full or on a call to endPublish().
|
||||
* @param buf The bytes to write.
|
||||
* @param size The length of the payload to be sent.
|
||||
* @return The number of bytes written.
|
||||
* @return The number of bytes written. If return value is != size a write error occurred.
|
||||
*/
|
||||
virtual size_t write(const uint8_t* buffer, size_t size);
|
||||
virtual size_t write(const uint8_t* buf, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Writes a string in PROGMEM as a component of a publish started with a call to beginPublish.
|
||||
* For performance reasons, this will be appended to the internal buffer,
|
||||
* which will be flushed when full or on a call to endPublish().
|
||||
* @param string The message to write.
|
||||
* @return The number of bytes written. If return value is != string length a write error occurred.
|
||||
*/
|
||||
inline size_t write_P(PGM_P string) {
|
||||
return write_P(reinterpret_cast<const uint8_t*>(string), strlen_P(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes an array of progmem bytes as a component of a publish started with a call to beginPublish.
|
||||
* For performance reasons, this will be appended to the internal buffer,
|
||||
* which will be flushed when full or on a call to endPublish().
|
||||
* @param buf The bytes to write.
|
||||
* @param size The length of the payload to be sent.
|
||||
* @return The number of bytes written. If return value is != size a write error occurred.
|
||||
*/
|
||||
size_t write_P(const uint8_t* buf, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic using QoS 0.
|
||||
@@ -667,7 +823,30 @@ class PubSubClient : public Print {
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
bool subscribe(const char* topic);
|
||||
inline bool subscribe(const char* topic) {
|
||||
return subscribeImpl(false, topic, MQTT_QOS0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic from __FlashStringHelper using QoS 0.
|
||||
* @param topic The topic from __FlashStringHelper to subscribe to.
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool subscribe(const __FlashStringHelper* topic) {
|
||||
// convert FlashStringHelper in PROGMEM-pointer
|
||||
return subscribeImpl(true, reinterpret_cast<const char*>(topic), MQTT_QOS0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic in PROGMEM using QoS 0.
|
||||
* @param topic The topic in PROGMEM to subscribe to.
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool subscribe_P(PGM_P topic) {
|
||||
return subscribeImpl(true, reinterpret_cast<const char*>(topic), MQTT_QOS0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic.
|
||||
@@ -676,7 +855,32 @@ class PubSubClient : public Print {
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
bool subscribe(const char* topic, uint8_t qos);
|
||||
inline bool subscribe(const char* topic, uint8_t qos) {
|
||||
return subscribeImpl(false, topic, qos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic from __FlashStringHelper.
|
||||
* @param topic The topic from __FlashStringHelper to subscribe to.
|
||||
* @param qos The qos to subscribe at. [0, 1].
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool subscribe(const __FlashStringHelper* topic, uint8_t qos) {
|
||||
// convert FlashStringHelper in PROGMEM-pointer
|
||||
return subscribeImpl(true, reinterpret_cast<const char*>(topic), qos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribes to messages published to the specified topic in PROGMEM.
|
||||
* @param topic The topic in PROGMEM to subscribe to.
|
||||
* @param qos The qos to subscribe at. [0, 1].
|
||||
* @return true If sending the subscribe succeeded.
|
||||
* false If sending the subscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool subscribe_P(PGM_P topic, uint8_t qos) {
|
||||
return subscribeImpl(true, reinterpret_cast<const char*>(topic), qos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes from the specified topic.
|
||||
@@ -684,7 +888,30 @@ class PubSubClient : public Print {
|
||||
* @return true If sending the unsubscribe succeeded.
|
||||
* false If sending the unsubscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
bool unsubscribe(const char* topic);
|
||||
inline bool unsubscribe(const char* topic) {
|
||||
return unsubscribeImpl(false, topic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes from the specified topic from __FlashStringHelper.
|
||||
* @param topic The topic from __FlashStringHelper to unsubscribe from.
|
||||
* @return true If sending the unsubscribe succeeded.
|
||||
* false If sending the unsubscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool unsubscribe(const __FlashStringHelper* topic) {
|
||||
// convert FlashStringHelper in PROGMEM-pointer
|
||||
return unsubscribeImpl(true, reinterpret_cast<const char*>(topic));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unsubscribes from the specified topic in PROGMEM.
|
||||
* @param topic The topic in PROGMEM to unsubscribe from.
|
||||
* @return true If sending the unsubscribe succeeded.
|
||||
* false If sending the unsubscribe failed, either connection lost or message too large.
|
||||
*/
|
||||
inline bool unsubscribe_P(PGM_P topic) {
|
||||
return unsubscribeImpl(true, reinterpret_cast<const char*>(topic));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This should be called regularly to allow the client to process incoming messages and maintain its connection to the server.
|
||||
|
||||
@@ -20,9 +20,14 @@ extern void loop(void);
|
||||
unsigned long millis(void);
|
||||
}
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define PROGMEM
|
||||
#define PGM_P const char*
|
||||
#define memcpy_P memcpy
|
||||
#define strlen_P strlen
|
||||
#define strnlen_P strnlen
|
||||
#define pgm_read_byte_near(x) *(x)
|
||||
#define F(x) (reinterpret_cast<const __FlashStringHelper*>(x))
|
||||
|
||||
#define yield(x) {}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ int test_publish_bytes();
|
||||
int test_publish_retained();
|
||||
int test_publish_retained_2();
|
||||
int test_publish_not_connected();
|
||||
int test_publish_long();
|
||||
int test_publish_too_long();
|
||||
int test_publish_P();
|
||||
int test_publish_P_too_long();
|
||||
@@ -22,6 +23,10 @@ int test_publish_qos1();
|
||||
int test_publish_qos2();
|
||||
int test_publish_P_qos1();
|
||||
int test_publish_P_qos2();
|
||||
int test_publish_FlashStringHelper();
|
||||
int test_publish_FlashStringHelper2();
|
||||
int test_publish_P_FlashStringHelper();
|
||||
int test_publish_P_P();
|
||||
|
||||
void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, _UNUSED_ size_t plength) {
|
||||
// handle message arrived
|
||||
@@ -139,6 +144,49 @@ int test_publish_not_connected() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_long() {
|
||||
IT("publishes with long payload message (> buffer size)");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
// buffer size 64 bytes - 5 bytes header - 2 bytes topic length = max. 57 bytes topic
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
char topic[] = "123456789012345678901234567890123456789012345678901234567";
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
char payload[] = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
|
||||
size_t plength = strlen(payload);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
client.setBufferSize(64);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[256];
|
||||
publish[0] = 0x30; // PUBLISH, QoS 0, no retain
|
||||
publish[1] = 0xb3; // Remaining length byte 1: 2 + 57 + 120 bytes (topic length bytes + topic length + payload length = 179)
|
||||
publish[2] = 0x01; // Remaining length byte 2
|
||||
publish[3] = 0x00; // Topic length MSB
|
||||
publish[4] = 0x39; // Topic length LSB (57 bytes)
|
||||
memcpy(&publish[5], topic, sizeof(topic) - 1);
|
||||
memcpy(&publish[5 + sizeof(topic) - 1], payload, sizeof(payload) - 1);
|
||||
shimClient.expect(publish, 5 + sizeof(topic) - 1 + sizeof(payload) - 1);
|
||||
|
||||
rc = client.beginPublish(topic, plength, 0, false);
|
||||
IS_TRUE(rc);
|
||||
plength = client.write((uint8_t*)payload, plength);
|
||||
IS_EQUAL(plength, strlen(payload));
|
||||
rc = client.endPublish();
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_too_long() {
|
||||
IT("publish fails when topic/payload are too long");
|
||||
ShimClient shimClient;
|
||||
@@ -167,7 +215,7 @@ int test_publish_too_long() {
|
||||
}
|
||||
|
||||
int test_publish_P() {
|
||||
IT("publishes using PROGMEM");
|
||||
IT("publishes using PROGMEM payload");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
@@ -193,7 +241,7 @@ int test_publish_P() {
|
||||
}
|
||||
|
||||
int test_publish_P_too_long() {
|
||||
IT("publish using PROGMEM fails when topic is too long");
|
||||
IT("publish using PROGMEM payload fails when topic is too long");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
@@ -219,6 +267,112 @@ int test_publish_P_too_long() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_FlashStringHelper() {
|
||||
IT("publishes using FlashStringHelper topic");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
char payload[] = "12345";
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, sizeof(connack));
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x31, 0x0c, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', '1', '2', '3', '4', '5'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish(F("topic"), payload, MQTT_QOS0, true);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_FlashStringHelper2() {
|
||||
IT("publishes using FlashStringHelper topic and payload");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
char payload[] = "12345";
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, sizeof(connack));
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x31, 0x0c, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', '1', '2', '3', '4', '5'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish(F("topic"), F(payload), MQTT_QOS0, true);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_P_FlashStringHelper() {
|
||||
IT("publishes using FlashStringHelper topic and PROGMEM payload");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
char payload[] PROGMEM = "12345";
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, sizeof(connack));
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x31, 0x0c, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', '1', '2', '3', '4', '5'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish_P(F("topic"), payload, MQTT_QOS0, true);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_P_P() {
|
||||
IT("publishes using PROGMEM topic and PROGMEM payload");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
char topic[] PROGMEM = "topic";
|
||||
char payload[] PROGMEM = "12345";
|
||||
size_t length = strlen_P(payload);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, sizeof(connack));
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x31, 0x0c, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', '1', '2', '3', '4', '5'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.beginPublish_P(topic, length, MQTT_QOS0, true);
|
||||
IS_TRUE(rc);
|
||||
length = client.write_P(payload);
|
||||
IS_EQUAL(length, strlen_P(payload));
|
||||
rc = client.endPublish();
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_publish_empty_topic() {
|
||||
IT("publish fails when topic is empty");
|
||||
ShimClient shimClient;
|
||||
@@ -275,7 +429,7 @@ int test_publish_qos1() {
|
||||
IS_TRUE(rc);
|
||||
|
||||
// Example publish packet for QoS 1 (0x32)
|
||||
byte publish[] = {0x32, 0x10, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00, 0x02};
|
||||
byte publish[] = {0x32, 0x10, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x00, 0x02, 'p', 'a', 'y', 'l', 'o', 'a', 'd'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish("topic", "payload", MQTT_QOS1, false);
|
||||
@@ -299,7 +453,7 @@ int test_publish_qos2() {
|
||||
IS_TRUE(rc);
|
||||
|
||||
// Example publish packet for QoS 2 (0x34)
|
||||
byte publish[] = {0x34, 0x10, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 'p', 'a', 'y', 'l', 'o', 'a', 'd', 0x00, 0x02};
|
||||
byte publish[] = {0x34, 0x10, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x00, 0x02, 'p', 'a', 'y', 'l', 'o', 'a', 'd'};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish("topic", "payload", MQTT_QOS2, false);
|
||||
@@ -311,7 +465,7 @@ int test_publish_qos2() {
|
||||
}
|
||||
|
||||
int test_publish_P_qos1() {
|
||||
IT("publishes using PROGMEM with QoS 1 retained");
|
||||
IT("publishes using PROGMEM payload with QoS 1 retained");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
@@ -325,7 +479,7 @@ int test_publish_P_qos1() {
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x33, 0x0e, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x02};
|
||||
byte publish[] = {0x33, 0x0e, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish_P("topic", payload, length, MQTT_QOS1, true);
|
||||
@@ -337,7 +491,7 @@ int test_publish_P_qos1() {
|
||||
}
|
||||
|
||||
int test_publish_P_qos2() {
|
||||
IT("publishes using PROGMEM with QoS 2 retained");
|
||||
IT("publishes using PROGMEM payload with QoS 2 retained");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
@@ -351,7 +505,7 @@ int test_publish_P_qos2() {
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x35, 0x0e, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x02};
|
||||
byte publish[] = {0x35, 0x0e, 0x00, 0x05, 't', 'o', 'p', 'i', 'c', 0x00, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
shimClient.expect(publish, sizeof(publish));
|
||||
|
||||
rc = client.publish_P("topic", payload, length, MQTT_QOS2, true);
|
||||
@@ -371,6 +525,7 @@ int main() {
|
||||
test_publish_qos1();
|
||||
test_publish_qos2();
|
||||
test_publish_null_payload();
|
||||
test_publish_long();
|
||||
test_publish_not_connected();
|
||||
test_publish_empty_topic();
|
||||
test_publish_too_long();
|
||||
@@ -378,6 +533,10 @@ int main() {
|
||||
test_publish_P_qos1();
|
||||
test_publish_P_qos2();
|
||||
test_publish_P_too_long();
|
||||
test_publish_FlashStringHelper();
|
||||
test_publish_FlashStringHelper2();
|
||||
test_publish_P_FlashStringHelper();
|
||||
test_publish_P_P();
|
||||
|
||||
FINISH
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ int test_receive_oversized_message();
|
||||
int test_resize_buffer();
|
||||
int test_receive_oversized_stream_message();
|
||||
int test_receive_qos1();
|
||||
int test_receive_qos2();
|
||||
|
||||
void reset_callback() {
|
||||
callback_called = false;
|
||||
@@ -330,6 +331,57 @@ int test_receive_qos1() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_receive_qos2() {
|
||||
IT("receives a qos2 message - responds PUBREC then PUBCOMP");
|
||||
reset_callback();
|
||||
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
// QoS 2 PUBLISH from broker (0x34 = MQTTPUBLISH | QoS2 bits)
|
||||
// Fixed header 0x34, remaining length 0x10 (16), topic len 0x0005, topic "topic",
|
||||
// msgId 0x1234, payload "payload"
|
||||
byte publish[] = {0x34, 0x10, 0x0, 0x5, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x34, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64};
|
||||
shimClient.respond(publish, 18);
|
||||
|
||||
// Client must respond with PUBREC (0x50), remaining length 2, msgId 0x1234
|
||||
byte pubrec[] = {0x50, 0x02, 0x12, 0x34};
|
||||
shimClient.expect(pubrec, 4);
|
||||
|
||||
rc = client.loop();
|
||||
IS_TRUE(rc);
|
||||
IS_TRUE(callback_called);
|
||||
IS_TRUE(strcmp(lastTopic, "topic") == 0);
|
||||
IS_TRUE(memcmp(lastPayload, "payload", 7) == 0);
|
||||
IS_TRUE(lastLength == 7);
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
reset_callback();
|
||||
|
||||
// Broker sends PUBREL (0x62 = MQTTPUBREL | bit1), remaining length 2, msgId 0x1234
|
||||
byte pubrel[] = {0x62, 0x02, 0x12, 0x34};
|
||||
shimClient.respond(pubrel, 4);
|
||||
|
||||
// Client must respond with PUBCOMP (0x70), remaining length 2, msgId 0x1234
|
||||
byte pubcomp[] = {0x70, 0x02, 0x12, 0x34};
|
||||
shimClient.expect(pubcomp, 4);
|
||||
|
||||
rc = client.loop();
|
||||
IS_TRUE(rc);
|
||||
IS_FALSE(callback_called); // callback must NOT fire again on PUBREL
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int main() {
|
||||
SUITE("Receive");
|
||||
test_receive_callback();
|
||||
@@ -340,6 +392,7 @@ int main() {
|
||||
test_resize_buffer();
|
||||
test_receive_oversized_stream_message();
|
||||
test_receive_qos1();
|
||||
test_receive_qos2();
|
||||
|
||||
FINISH
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ byte server[] = {172, 16, 0, 2};
|
||||
void callback(char* topic, uint8_t* payload, size_t plength);
|
||||
int test_subscribe_no_qos();
|
||||
int test_subscribe_qos_1();
|
||||
int test_subscribe_P();
|
||||
int test_subscribe_P_qos_1();
|
||||
int test_subscribe_FlashStringHelper();
|
||||
int test_subscribe_FlashStringHelper_qos_1();
|
||||
int test_subscribe_not_connected();
|
||||
int test_subscribe_invalid_qos();
|
||||
int test_subscribe_too_long();
|
||||
@@ -70,6 +74,108 @@ int test_subscribe_qos_1() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_subscribe_P() {
|
||||
IT("subscribe using PROGMEM");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte subscribe[] = {0x82, 0xa, 0x0, 0x2, 0x0, 0x5, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x0};
|
||||
shimClient.expect(subscribe, 12);
|
||||
byte suback[] = {0x90, 0x3, 0x0, 0x2, 0x0};
|
||||
shimClient.respond(suback, 5);
|
||||
|
||||
char topic[] PROGMEM = "topic";
|
||||
rc = client.subscribe_P(topic);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_subscribe_P_qos_1() {
|
||||
IT("subscribe using PROGMEM with QoS 1");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte subscribe[] = {0x82, 0xa, 0x0, 0x2, 0x0, 0x5, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x1};
|
||||
shimClient.expect(subscribe, 12);
|
||||
byte suback[] = {0x90, 0x3, 0x0, 0x2, 0x1};
|
||||
shimClient.respond(suback, 5);
|
||||
|
||||
char topic[] PROGMEM = "topic";
|
||||
rc = client.subscribe_P(topic, MQTT_QOS1);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_subscribe_FlashStringHelper() {
|
||||
IT("subscribe using FlashStringHelper");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte subscribe[] = {0x82, 0xa, 0x0, 0x2, 0x0, 0x5, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x0};
|
||||
shimClient.expect(subscribe, 12);
|
||||
byte suback[] = {0x90, 0x3, 0x0, 0x2, 0x0};
|
||||
shimClient.respond(suback, 5);
|
||||
|
||||
rc = client.subscribe(F("topic"));
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_subscribe_FlashStringHelper_qos_1() {
|
||||
IT("subscribe using FlashStringHelper with QoS 1");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = {0x20, 0x02, 0x00, 0x00};
|
||||
shimClient.respond(connack, 4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
bool rc = client.connect("client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte subscribe[] = {0x82, 0xa, 0x0, 0x2, 0x0, 0x5, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x1};
|
||||
shimClient.expect(subscribe, 12);
|
||||
byte suback[] = {0x90, 0x3, 0x0, 0x2, 0x1};
|
||||
shimClient.respond(suback, 5);
|
||||
|
||||
rc = client.subscribe(F("topic"), MQTT_QOS1);
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_subscribe_not_connected() {
|
||||
IT("subscribe fails when not connected");
|
||||
ShimClient shimClient;
|
||||
@@ -176,6 +282,10 @@ int main() {
|
||||
SUITE("Subscribe");
|
||||
test_subscribe_no_qos();
|
||||
test_subscribe_qos_1();
|
||||
test_subscribe_P();
|
||||
test_subscribe_P_qos_1();
|
||||
test_subscribe_FlashStringHelper();
|
||||
test_subscribe_FlashStringHelper_qos_1();
|
||||
test_subscribe_not_connected();
|
||||
test_subscribe_invalid_qos();
|
||||
test_subscribe_too_long();
|
||||
|
||||
Reference in New Issue
Block a user