From 2dfec2ec4d8c0bb4bd806cc2bf9a57f56b0faf60 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Tue, 16 Mar 2021 22:28:39 +0100 Subject: [PATCH 1/5] don't keep 0xFFFFFFFF as a valid addres in case of DNS fail --- tasmota/support.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index b1653ff2a..ff6a0aecf 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -2137,8 +2137,11 @@ void SyslogAsync(bool refresh) { if (mxtime > 0) { uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); if (syslog_host_hash != current_hash) { + IPAddress temp_syslog_host_addr; + int ret = WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), temp_syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash + if (!ret) return; syslog_host_hash = current_hash; - WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash + syslog_host_addr = temp_syslog_host_addr; } if (!PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { TasmotaGlobal.syslog_level = 0; From 74da6eb0571ba204cfa435f6be6b439e1af927b1 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Wed, 17 Mar 2021 19:45:29 +0100 Subject: [PATCH 2/5] check on hostByName + disable syslog --- tasmota/support.ino | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index ff6a0aecf..800c0a1ca 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -2138,8 +2138,13 @@ void SyslogAsync(bool refresh) { uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); if (syslog_host_hash != current_hash) { IPAddress temp_syslog_host_addr; - int ret = WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), temp_syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash - if (!ret) return; + int ok = WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), temp_syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash + if (!ok || (0xFFFFFFFF == (uint32_t)temp_syslog_host_addr)) { // 255.255.255.255 is assumed a DNS problem + TasmotaGlobal.syslog_level = 0; + TasmotaGlobal.syslog_timer = SYSLOG_TIMER; + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Loghost DNS resolve failed (%s). " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_SYSLOG_HOST), SYSLOG_TIMER); + return; + } syslog_host_hash = current_hash; syslog_host_addr = temp_syslog_host_addr; } From f31bdfdfb34edb36bc7c1498d6fbc4f4001cde7b Mon Sep 17 00:00:00 2001 From: Alex Brown <100519+alexpbrown@users.noreply.github.com> Date: Wed, 17 Mar 2021 22:26:24 -0400 Subject: [PATCH 3/5] Add period char replacement for prometheus This was a problem for me when trying to get output from an SDS011 Nova PM sensor. When parsed by the pometheus code it returns labels / metrics like: ```# TYPE tasmota_sensors_pm2.5_ gauge tasmota_sensors_pm2.5_{sensor="sds0x1"} 2.2``` The error from prometheus was: ```"append failed" err="invalid metric type \\"5_ gauge\\"``` --- tasmota/xsns_75_prometheus.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index bbdb303c5..0b0251229 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -57,6 +57,7 @@ String FormatMetricName(const char *metric) { // cleanup spaces and uppercases String formatted = metric; formatted.toLowerCase(); formatted.replace(" ", "_"); + formatted.replace(".", "_"); return formatted; } From ff7a911e4572d56846a51a23fcce0836b8593757 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Mar 2021 09:27:46 +0100 Subject: [PATCH 4/5] Fix logging if network down (#11373) --- tasmota/support.ino | 2 +- tasmota/xdrv_02_mqtt.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 800c0a1ca..63ebc371e 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -2125,7 +2125,7 @@ void SyslogAsync(bool refresh) { static uint32_t syslog_host_hash = 0; // Syslog host name hash static uint32_t index = 1; - if (!TasmotaGlobal.syslog_level) { return; } + if (!TasmotaGlobal.syslog_level || TasmotaGlobal.global_state.network_down) { return; } if (refresh && !NeedLogRefresh(TasmotaGlobal.syslog_level, index)) { return; } char* line; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 02fe422f1..3ef1ec84b 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -311,7 +311,7 @@ void MqttUnsubscribe(const char *topic) { void MqttPublishLoggingAsync(bool refresh) { static uint32_t index = 1; - if (!Settings.mqttlog_level || !Settings.flag.mqtt_enabled) { return; } // SetOption3 - Enable MQTT + if (!Settings.mqttlog_level || !Settings.flag.mqtt_enabled || !Mqtt.connected) { return; } // SetOption3 - Enable MQTT if (refresh && !NeedLogRefresh(Settings.mqttlog_level, index)) { return; } char* line; From d5ca2994ee94532405b002e28b0aca194958790f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 18 Mar 2021 17:44:10 +0100 Subject: [PATCH 5/5] Add commands MqttKeepAlive and MqttTimeout - Add commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) (#5341) - Changed PubSubClient library from EspEasy v2.7.12 to Tasmota v2.8.12 - Bump version to 9.3.1.2 --- CHANGELOG.md | 10 +- RELEASENOTES.md | 4 +- .../PubSubClient-EspEasy-2.7.12/.gitignore | 1 - lib/default/pubsubclient-2.8.12/.gitignore | 5 + .../.travis.yml | 0 .../CHANGES.txt | 9 + .../LICENSE.txt | 2 +- .../README.md | 8 +- .../examples/mqtt_auth/mqtt_auth.ino | 6 +- .../examples/mqtt_basic/mqtt_basic.ino | 0 .../examples/mqtt_esp8266/mqtt_esp8266.ino | 15 +- .../mqtt_large_message/mqtt_large_message.ino | 0 .../mqtt_publish_in_callback.ino | 0 .../mqtt_reconnect_nonblocking.ino | 0 .../examples/mqtt_stream/mqtt_stream.ino | 0 .../keywords.txt | 3 + .../library.json | 8 +- .../library.properties | 2 +- .../src/PubSubClient.cpp | 410 +++++++++++++----- .../src/PubSubClient.h | 46 +- .../tests/.gitignore | 0 .../tests/Makefile | 0 .../tests/README.md | 0 .../tests/src/connect_spec.cpp | 34 ++ .../tests/src/keepalive_spec.cpp | 0 .../tests/src/lib/Arduino.h | 0 .../tests/src/lib/BDDTest.cpp | 0 .../tests/src/lib/BDDTest.h | 0 .../tests/src/lib/Buffer.cpp | 0 .../tests/src/lib/Buffer.h | 8 +- .../tests/src/lib/Client.h | 0 .../tests/src/lib/IPAddress.cpp | 0 .../tests/src/lib/IPAddress.h | 0 .../tests/src/lib/Print.h | 0 .../tests/src/lib/ShimClient.cpp | 0 .../tests/src/lib/ShimClient.h | 0 .../tests/src/lib/Stream.cpp | 0 .../tests/src/lib/Stream.h | 0 .../tests/src/lib/trace.h | 0 .../tests/src/publish_spec.cpp | 1 + .../tests/src/receive_spec.cpp | 71 ++- .../tests/src/subscribe_spec.cpp | 1 + .../tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 0 .../testcases/mqtt_publish_in_callback.py | 0 .../tests/testcases/settings.py | 0 .../tests/testsuite.py | 0 tasmota/i18n.h | 2 + tasmota/my_user_config.h | 3 + tasmota/settings.h | 7 +- tasmota/settings.ino | 6 + tasmota/support_command.ino | 4 +- tasmota/tasmota_globals.h | 4 +- tasmota/tasmota_version.h | 2 +- tasmota/xdrv_02_mqtt.ino | 29 +- 55 files changed, 543 insertions(+), 158 deletions(-) delete mode 100644 lib/default/PubSubClient-EspEasy-2.7.12/.gitignore create mode 100644 lib/default/pubsubclient-2.8.12/.gitignore rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/.travis.yml (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/CHANGES.txt (86%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/LICENSE.txt (96%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/README.md (87%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_auth/mqtt_auth.ino (91%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_basic/mqtt_basic.ino (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_esp8266/mqtt_esp8266.ino (94%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_large_message/mqtt_large_message.ino (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/examples/mqtt_stream/mqtt_stream.ino (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/keywords.txt (91%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/library.json (85%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/library.properties (98%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/src/PubSubClient.cpp (61%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/src/PubSubClient.h (88%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/.gitignore (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/Makefile (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/README.md (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/connect_spec.cpp (90%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/keepalive_spec.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Arduino.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/BDDTest.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/BDDTest.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Buffer.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Buffer.h (88%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Client.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/IPAddress.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/IPAddress.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Print.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/ShimClient.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/ShimClient.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Stream.cpp (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/Stream.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/lib/trace.h (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/publish_spec.cpp (99%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/receive_spec.cpp (75%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/src/subscribe_spec.cpp (99%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/testcases/__init__.py (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/testcases/mqtt_basic.py (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/testcases/mqtt_publish_in_callback.py (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/testcases/settings.py (100%) rename lib/default/{PubSubClient-EspEasy-2.7.12 => pubsubclient-2.8.12}/tests/testsuite.py (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c3c9ca0f..0d3c637bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development +## [9.3.1.2] +### Added +- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) (#5341) + +### Changed +- PubSubClient library from EspEasy v2.7.12 to Tasmota v2.8.12 + ## [9.3.1.1] ### Added - Support for CSE7761 energy monitor as used in ESP32 based Sonoff Dual R3 Pow (#10793) @@ -18,8 +25,7 @@ All notable changes to this project will be documented in this file. - ESP32 Extent BLE (#11212) - ESP32 support for WS2812 hardware driver via RMT or I2S - ESP32 support for secondary I2C controller -- Add support for MPU6686 on primary or secondary I2C bus - +- Support for MPU6686 on primary or secondary I2C bus ### Changed - ESP32 core library from v1.0.5-rc6 to v1.0.5 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c5ad1ba9e..cdb71c52e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -78,8 +78,9 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v9.3.1.1 +## Changelog v9.3.1.2 ### Added +- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) [#5341](https://github.com/arendst/Tasmota/issues/5341) - Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073) - Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125) - Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan BubĂ­k [#11145](https://github.com/arendst/Tasmota/issues/11145) @@ -93,6 +94,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota ### Changed - TasmotaSerial library from v3.2.0 to v3.3.0 +- PubSubClient library from EspEasy v2.7.12 to Tasmota v2.8.12 - ESP32 core library from v1.0.5-rc6 to v1.0.5 - TuyaMcu dimmer timeout [#11121](https://github.com/arendst/Tasmota/issues/11121) - Rename epaper 42 commands [#11222](https://github.com/arendst/Tasmota/issues/11222) diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/.gitignore b/lib/default/PubSubClient-EspEasy-2.7.12/.gitignore deleted file mode 100644 index 1c3ba189b..000000000 --- a/lib/default/PubSubClient-EspEasy-2.7.12/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tests/bin diff --git a/lib/default/pubsubclient-2.8.12/.gitignore b/lib/default/pubsubclient-2.8.12/.gitignore new file mode 100644 index 000000000..a42cc406e --- /dev/null +++ b/lib/default/pubsubclient-2.8.12/.gitignore @@ -0,0 +1,5 @@ +tests/bin +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/.travis.yml b/lib/default/pubsubclient-2.8.12/.travis.yml similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/.travis.yml rename to lib/default/pubsubclient-2.8.12/.travis.yml diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/CHANGES.txt b/lib/default/pubsubclient-2.8.12/CHANGES.txt similarity index 86% rename from lib/default/PubSubClient-EspEasy-2.7.12/CHANGES.txt rename to lib/default/pubsubclient-2.8.12/CHANGES.txt index ff4da62ab..e23d5315f 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/CHANGES.txt +++ b/lib/default/pubsubclient-2.8.12/CHANGES.txt @@ -1,3 +1,12 @@ +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 diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/LICENSE.txt b/lib/default/pubsubclient-2.8.12/LICENSE.txt similarity index 96% rename from lib/default/PubSubClient-EspEasy-2.7.12/LICENSE.txt rename to lib/default/pubsubclient-2.8.12/LICENSE.txt index 217df35cc..12c1689e6 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/LICENSE.txt +++ b/lib/default/pubsubclient-2.8.12/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2008-2015 Nicholas O'Leary +Copyright (c) 2008-2020 Nicholas O'Leary Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/README.md b/lib/default/pubsubclient-2.8.12/README.md similarity index 87% rename from lib/default/PubSubClient-EspEasy-2.7.12/README.md rename to lib/default/pubsubclient-2.8.12/README.md index 69cbb8f0c..2e1317185 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/README.md +++ b/lib/default/pubsubclient-2.8.12/README.md @@ -13,10 +13,12 @@ Full API documentation is available here: https://pubsubclient.knolleary.net ## Limitations - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. - - The maximum message size, including header, is **128 bytes** by default. This - is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`. + - The maximum message size, including header, is **256 bytes** by default. This + is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h` or can be changed + by calling `PubSubClient::setBufferSize(size)`. - The keepalive interval is set to 15 seconds by default. This is configurable - via `MQTT_KEEPALIVE` in `PubSubClient.h`. + via `MQTT_KEEPALIVE` in `PubSubClient.h` or can be changed by calling + `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`. diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_auth/mqtt_auth.ino similarity index 91% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_auth/mqtt_auth.ino index e9f7b180f..04bd7bb29 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_auth/mqtt_auth.ino +++ b/lib/default/pubsubclient-2.8.12/examples/mqtt_auth/mqtt_auth.ino @@ -27,9 +27,9 @@ 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, - // you will need to increase the value of MQTT_MAX_PACKET_SIZE in - // PubSubClient.h + // 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("outTopic","hello world"); diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_basic/mqtt_basic.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 94% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_esp8266/mqtt_esp8266.ino index e7357b507..7e6effd24 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_esp8266/mqtt_esp8266.ino +++ b/lib/default/pubsubclient-2.8.12/examples/mqtt_esp8266/mqtt_esp8266.ino @@ -1,26 +1,21 @@ /* Basic ESP8266 MQTT example - This sketch demonstrates the capabilities of the pubsub library in combination with the ESP8266 board/library. - It connects to an MQTT server then: - publishes "hello world" to the topic "outTopic" every two seconds - subscribes to the topic "inTopic", printing out any messages it receives. NB - it assumes the received payloads are strings not binary - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led, else switch it off - It will reconnect to the server if the connection is lost using a blocking reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to achieve the same result without blocking the main loop. - To install the ESP8266 board, (using Arduino 1.6.4+): - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": http://arduino.esp8266.com/stable/package_esp8266com_index.json - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" - Select your ESP8266 in "Tools -> Board" - */ #include @@ -34,8 +29,9 @@ const char* mqtt_server = "broker.mqtt-dashboard.com"; WiFiClient espClient; PubSubClient client(espClient); -long lastMsg = 0; -char msg[50]; +unsigned long lastMsg = 0; +#define MSG_BUFFER_SIZE (50) +char msg[MSG_BUFFER_SIZE]; int value = 0; void setup_wifi() { @@ -46,6 +42,7 @@ void setup_wifi() { Serial.print("Connecting to "); Serial.println(ssid); + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { @@ -120,11 +117,11 @@ void loop() { } client.loop(); - long now = millis(); + unsigned long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; ++value; - snprintf (msg, 50, "hello world #%ld", value); + snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("outTopic", msg); diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_large_message/mqtt_large_message.ino similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_large_message/mqtt_large_message.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_large_message/mqtt_large_message.ino diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino b/lib/default/pubsubclient-2.8.12/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/examples/mqtt_stream/mqtt_stream.ino rename to lib/default/pubsubclient-2.8.12/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/keywords.txt b/lib/default/pubsubclient-2.8.12/keywords.txt similarity index 91% rename from lib/default/PubSubClient-EspEasy-2.7.12/keywords.txt rename to lib/default/pubsubclient-2.8.12/keywords.txt index 1ee23d0fa..960a033f9 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/keywords.txt +++ b/lib/default/pubsubclient-2.8.12/keywords.txt @@ -27,6 +27,9 @@ setServer KEYWORD2 setCallback KEYWORD2 setClient KEYWORD2 setStream KEYWORD2 +setKeepAlive KEYWORD2 +setBufferSize KEYWORD2 +setSocketTimeout KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/library.json b/lib/default/pubsubclient-2.8.12/library.json similarity index 85% rename from lib/default/PubSubClient-EspEasy-2.7.12/library.json rename to lib/default/pubsubclient-2.8.12/library.json index e675ecff3..c0d7bae2d 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/library.json +++ b/lib/default/pubsubclient-2.8.12/library.json @@ -6,9 +6,13 @@ "type": "git", "url": "https://github.com/knolleary/pubsubclient.git" }, - "version": "2.7", + "version": "2.8", "exclude": "tests", "examples": "examples/*/*.ino", "frameworks": "arduino", - "platforms": ["espressif8266", "espressif32"] + "platforms": [ + "atmelavr", + "espressif8266", + "espressif32" + ] } diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/library.properties b/lib/default/pubsubclient-2.8.12/library.properties similarity index 98% rename from lib/default/PubSubClient-EspEasy-2.7.12/library.properties rename to lib/default/pubsubclient-2.8.12/library.properties index 7df4daf80..732331bf9 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/library.properties +++ b/lib/default/pubsubclient-2.8.12/library.properties @@ -1,5 +1,5 @@ name=PubSubClient -version=2.7 +version=2.8 author=Nick O'Leary maintainer=Nick O'Leary sentence=A client library for MQTT messaging. diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp b/lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp similarity index 61% rename from lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp rename to lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp index 0748fdc4a..acd0fab9b 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp +++ b/lib/default/pubsubclient-2.8.12/src/PubSubClient.cpp @@ -12,12 +12,20 @@ PubSubClient::PubSubClient() { this->_client = NULL; this->stream = NULL; setCallback(NULL); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(Client& client) { this->_state = MQTT_DISCONNECTED; setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { @@ -25,12 +33,20 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { setServer(addr, port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(addr,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -38,6 +54,10 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -45,6 +65,10 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { @@ -52,12 +76,20 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { setServer(ip, port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(ip,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -65,6 +97,10 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -72,6 +108,10 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { @@ -79,12 +119,20 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { setServer(domain,port); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; setServer(domain,port); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { this->_state = MQTT_DISCONNECTED; @@ -92,6 +140,10 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN setCallback(callback); setClient(client); this->stream = NULL; + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); } PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { this->_state = MQTT_DISCONNECTED; @@ -99,6 +151,14 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN setCallback(callback); setClient(client); setStream(stream); + this->bufferSize = 0; + setBufferSize(MQTT_MAX_PACKET_SIZE); + setKeepAlive(MQTT_KEEPALIVE); + setSocketTimeout(MQTT_SOCKET_TIMEOUT); +} + +PubSubClient::~PubSubClient() { + free(this->buffer); } boolean PubSubClient::connect(const char *id) { @@ -121,18 +181,29 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass if (!connected()) { int result = 0; +// Start Tasmota patch if (_client == nullptr) { return false; } - if (_client->connected()) { +// End Tasmota patch + + if(_client->connected()) { result = 1; } else { + +// Start Tasmota patch +// if (domain != NULL) { +// result = _client->connect(this->domain, this->port); + if (domain.length() != 0) { result = _client->connect(this->domain.c_str(), this->port); +// End Tasmota patch + } else { result = _client->connect(this->ip, this->port); } } + if (result == 1) { nextMsgId = 1; // Leave room in the buffer for header and variable length field @@ -147,7 +218,7 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass #define MQTT_HEADER_VERSION_LENGTH 7 #endif for (j = 0;jbuffer[length++] = d[j]; } uint8_t v; @@ -167,45 +238,48 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass v = v|(0x80>>1); } } + this->buffer[length++] = v; - buffer[length++] = v; - - buffer[length++] = ((MQTT_KEEPALIVE) >> 8); - buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + this->buffer[length++] = ((this->keepAlive) >> 8); + this->buffer[length++] = ((this->keepAlive) & 0xFF); CHECK_STRING_LENGTH(length,id) - length = writeString(id,buffer,length); + length = writeString(id,this->buffer,length); if (willTopic) { CHECK_STRING_LENGTH(length,willTopic) - length = writeString(willTopic,buffer,length); + length = writeString(willTopic,this->buffer,length); CHECK_STRING_LENGTH(length,willMessage) - length = writeString(willMessage,buffer,length); + length = writeString(willMessage,this->buffer,length); } if(user != NULL) { CHECK_STRING_LENGTH(length,user) - length = writeString(user,buffer,length); + length = writeString(user,this->buffer,length); if(pass != NULL) { CHECK_STRING_LENGTH(length,pass) - length = writeString(pass,buffer,length); + length = writeString(pass,this->buffer,length); } } - write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE); + write(MQTTCONNECT,this->buffer,length-MQTT_MAX_HEADER_SIZE); lastInActivity = lastOutActivity = millis(); while (!_client->available()) { + +// Start Tasmota patch delay(0); // Prevent watchdog crashes +// End Tasmota patch + unsigned long t = millis(); - if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { + if (t-lastInActivity >= ((int32_t) this->socketTimeout*1000UL)) { _state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } } uint8_t llen; - uint16_t len = readPacket(&llen); + uint32_t len = readPacket(&llen); if (len == 4) { if (buffer[3] == 0) { @@ -228,14 +302,24 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass // reads a byte into result boolean PubSubClient::readByte(uint8_t * result) { + +// Start Tasmota patch if (_client == nullptr) { return false; } +// End Tasmota patch + uint32_t previousMillis = millis(); while(!_client->available()) { + +// Start Tasmota patch +// yield(); + delay(1); // Prevent watchdog crashes +// End Tasmota patch + uint32_t currentMillis = millis(); - if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ + if(currentMillis - previousMillis >= ((int32_t) this->socketTimeout * 1000)){ return false; } } @@ -254,15 +338,15 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){ return false; } -uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { +uint32_t PubSubClient::readPacket(uint8_t* lengthLength) { uint16_t len = 0; - if(!readByte(buffer, &len)) return 0; - bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + if(!readByte(this->buffer, &len)) return 0; + bool isPublish = (this->buffer[0]&0xF0) == MQTTPUBLISH; uint32_t multiplier = 1; - uint16_t length = 0; + uint32_t length = 0; uint8_t digit = 0; uint16_t skip = 0; - uint8_t start = 0; + uint32_t start = 0; do { if (len == 5) { @@ -272,59 +356,75 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { return 0; } if(!readByte(&digit)) return 0; - buffer[len++] = digit; + this->buffer[len++] = digit; length += (digit & 127) * multiplier; - multiplier *= 128; - } while ((digit & 128) != 0 && len < (MQTT_MAX_PACKET_SIZE -2)); + multiplier <<=7; //multiplier *= 128 + +// Start Tasmota patch +// } while ((digit & 128) != 0); + + } while ((digit & 128) != 0 && len < (this->bufferSize -2)); +// End Tasmota patch + *lengthLength = len-1; if (isPublish) { // Read in topic length to calculate bytes to skip over for Stream writing - if(!readByte(buffer, &len)) return 0; - if(!readByte(buffer, &len)) return 0; - skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + if(!readByte(this->buffer, &len)) return 0; + if(!readByte(this->buffer, &len)) return 0; + skip = (this->buffer[*lengthLength+1]<<8)+this->buffer[*lengthLength+2]; start = 2; - if (buffer[0]&MQTTQOS1) { + if (this->buffer[0]&MQTTQOS1) { // skip message id skip += 2; } } + uint32_t idx = len; - for (uint16_t i = start;istream) { - if (isPublish && len-*lengthLength-2>skip) { + if (isPublish && idx-*lengthLength-2>skip) { this->stream->write(digit); } } - if (len < MQTT_MAX_PACKET_SIZE) { - buffer[len] = digit; + + if (len < this->bufferSize) { + this->buffer[len] = digit; + len++; } - len++; + idx++; } - if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + if (!this->stream && idx > this->bufferSize) { len = 0; // This will cause the packet to be ignored. } - return len; } boolean PubSubClient::loop() { if (connected()) { unsigned long t = millis(); - if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if ((t - lastInActivity > this->keepAlive*1000UL) || (t - lastOutActivity > this->keepAlive*1000UL)) { if (pingOutstanding) { this->_state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } else { - buffer[0] = MQTTPINGREQ; - buffer[1] = 0; - if (_client->write(buffer,2) != 0) { + this->buffer[0] = MQTTPINGREQ; + this->buffer[1] = 0; + +// Start Tasmota patch +// _client->write(this->buffer,2); +// lastOutActivity = t; +// lastInActivity = t; + + if (_client->write(this->buffer,2) != 0) { lastOutActivity = t; lastInActivity = t; } +// End Tasmota patch + pingOutstanding = true; } } @@ -335,35 +435,42 @@ boolean PubSubClient::loop() { uint8_t *payload; if (len > 0) { lastInActivity = t; - uint8_t type = buffer[0]&0xF0; + uint8_t type = this->buffer[0]&0xF0; if (type == MQTTPUBLISH) { if (callback) { - uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */ - memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ - buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ - char *topic = (char*) buffer+llen+2; + uint16_t tl = (this->buffer[llen+1]<<8)+this->buffer[llen+2]; /* topic length in bytes */ + memmove(this->buffer+llen+2,this->buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ + this->buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ + char *topic = (char*) this->buffer+llen+2; // msgId only present for QOS>0 - if ((buffer[0]&0x06) == MQTTQOS1) { - msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; - payload = buffer+llen+3+tl+2; + if ((this->buffer[0]&0x06) == MQTTQOS1) { + msgId = (this->buffer[llen+3+tl]<<8)+this->buffer[llen+3+tl+1]; + payload = this->buffer+llen+3+tl+2; callback(topic,payload,len-llen-3-tl-2); - buffer[0] = MQTTPUBACK; - buffer[1] = 2; - buffer[2] = (msgId >> 8); - buffer[3] = (msgId & 0xFF); - if (_client->write(buffer,4) != 0) { + this->buffer[0] = MQTTPUBACK; + this->buffer[1] = 2; + this->buffer[2] = (msgId >> 8); + this->buffer[3] = (msgId & 0xFF); + +// Start Tasmota patch +// _client->write(this->buffer,4); +// lastOutActivity = t; + + if (_client->write(this->buffer,4) != 0) { lastOutActivity = t; } +// End Tasmota patch + } else { - payload = buffer+llen+3+tl; + payload = this->buffer+llen+3+tl; callback(topic,payload,len-llen-3-tl); } } } else if (type == MQTTPINGREQ) { - buffer[0] = MQTTPINGRESP; - buffer[1] = 0; - _client->write(buffer,2); + this->buffer[0] = MQTTPINGRESP; + this->buffer[1] = 0; + _client->write(this->buffer,2); } else if (type == MQTTPINGRESP) { pingOutstanding = false; } @@ -378,13 +485,11 @@ boolean PubSubClient::loop() { } boolean PubSubClient::publish(const char* topic, const char* payload) { - size_t plength = (payload != nullptr) ? strlen(payload) : 0; - return publish(topic,(const uint8_t*)payload,plength,false); + return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,false); } boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { - size_t plength = (payload != nullptr) ? strlen(payload) : 0; - return publish(topic,(const uint8_t*)payload,plength,retained); + return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,retained); } boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { @@ -393,29 +498,32 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { if (connected()) { - if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) { + if (this->bufferSize < MQTT_MAX_HEADER_SIZE + 2+strnlen(topic, this->bufferSize) + plength) { // Too long return false; } // Leave room in the buffer for header and variable length field uint16_t length = MQTT_MAX_HEADER_SIZE; - length = writeString(topic,buffer,length); + length = writeString(topic,this->buffer,length); + + // Add payload uint16_t i; for (i=0;ibuffer[length++] = payload[i]; } + + // Write the header uint8_t header = MQTTPUBLISH; if (retained) { header |= 1; } - return write(header,buffer,length-MQTT_MAX_HEADER_SIZE); + return write(header,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } boolean PubSubClient::publish_P(const char* topic, const char* payload, boolean retained) { - size_t plength = (payload != nullptr) ? strlen(payload) : 0; - return publish_P(topic, (const uint8_t*)payload, plength, retained); + return publish_P(topic, (const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0, retained); } boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { @@ -427,42 +535,48 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig unsigned int i; uint8_t header; unsigned int len; + int expectedLength; if (!connected()) { return false; } - tlen = strlen(topic); + tlen = strnlen(topic, this->bufferSize); header = MQTTPUBLISH; if (retained) { header |= 1; } - buffer[pos++] = header; + this->buffer[pos++] = header; len = plength + 2 + tlen; do { - digit = len % 128; - len = len / 128; + digit = len & 127; //digit = len %128 + len >>= 7; //len = len / 128 if (len > 0) { digit |= 0x80; } - buffer[pos++] = digit; + this->buffer[pos++] = digit; llen++; } while(len>0); - pos = writeString(topic,buffer,pos); + pos = writeString(topic,this->buffer,pos); - rc += _client->write(buffer,pos); + rc += _client->write(this->buffer,pos); for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); } + +// Start Tasmota patch +// lastOutActivity = millis(); + if (rc > 0) { lastOutActivity = millis(); } +// End Tasmota patch + + expectedLength = 1 + llen + 2 + tlen + plength; - // Header (1 byte) + llen + identifier (2 bytes) + topic len + payload len - const unsigned int expectedLength = 1 + llen + 2 + tlen + plength; return (rc == expectedLength); } @@ -470,16 +584,22 @@ boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, bool if (connected()) { // Send the header and variable length field uint16_t length = MQTT_MAX_HEADER_SIZE; - length = writeString(topic,buffer,length); + length = writeString(topic,this->buffer,length); uint8_t header = MQTTPUBLISH; if (retained) { header |= 1; } - size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE); - uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen)); + size_t hlen = buildHeader(header, this->buffer, plength+length-MQTT_MAX_HEADER_SIZE); + uint16_t rc = _client->write(this->buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen)); + +// Start Tasmota patch +// lastOutActivity = millis(); + if (rc > 0) { lastOutActivity = millis(); } +// End Tasmota patch + return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen))); } return false; @@ -490,6 +610,11 @@ int PubSubClient::endPublish() { } size_t PubSubClient::write(uint8_t data) { + +// Start Tasmota patch +// lastOutActivity = millis(); +// return _client->write(data); + if (_client == nullptr) { lastOutActivity = millis(); return 0; @@ -499,9 +624,16 @@ size_t PubSubClient::write(uint8_t data) { lastOutActivity = millis(); } return rc; +// End Tasmota patch + } size_t PubSubClient::write(const uint8_t *buffer, size_t size) { + +// Start Tasmota patch +// lastOutActivity = millis(); +// return _client->write(buffer,size); + if (_client == nullptr) { lastOutActivity = millis(); return 0; @@ -511,6 +643,8 @@ size_t PubSubClient::write(const uint8_t *buffer, size_t size) { lastOutActivity = millis(); } return rc; +// End Tasmota patch + } size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) { @@ -520,8 +654,9 @@ size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) uint8_t pos = 0; uint16_t len = length; do { - digit = len % 128; - len = len / 128; + + digit = len & 127; //digit = len %128 + len >>= 7; //len = len / 128 if (len > 0) { digit |= 0x80; } @@ -546,7 +681,6 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { uint8_t bytesToWrite; boolean result = true; while((bytesRemaining > 0) && result) { - delay(0); // Prevent watchdog crashes bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; rc = _client->write(writeBuf,bytesToWrite); result = (rc == bytesToWrite); @@ -556,9 +690,15 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { return result; #else rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen); + +// Start Tasmota patch +// lastOutActivity = millis(); + if (rc != 0) { lastOutActivity = millis(); } +// End Tasmota patch + return (rc == hlen+length); #endif } @@ -568,10 +708,14 @@ boolean PubSubClient::subscribe(const char* topic) { } boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { + size_t topicLength = strnlen(topic, this->bufferSize); + if (topic == 0) { + return false; + } if (qos > 1) { return false; } - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + if (this->bufferSize < 9 + topicLength) { // Too long return false; } @@ -582,17 +726,21 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { if (nextMsgId == 0) { nextMsgId = 1; } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString((char*)topic, buffer,length); - buffer[length++] = qos; - return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); + this->buffer[length++] = (nextMsgId >> 8); + this->buffer[length++] = (nextMsgId & 0xFF); + length = writeString((char*)topic, this->buffer,length); + this->buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } boolean PubSubClient::unsubscribe(const char* topic) { - if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + size_t topicLength = strnlen(topic, this->bufferSize); + if (topic == 0) { + return false; + } + if (this->bufferSize < 9 + topicLength) { // Too long return false; } @@ -602,25 +750,34 @@ boolean PubSubClient::unsubscribe(const char* topic) { if (nextMsgId == 0) { nextMsgId = 1; } - buffer[length++] = (nextMsgId >> 8); - buffer[length++] = (nextMsgId & 0xFF); - length = writeString(topic, buffer,length); - return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE); + this->buffer[length++] = (nextMsgId >> 8); + this->buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, this->buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE); } return false; } void PubSubClient::disconnect(bool disconnect_package) { - buffer[0] = MQTTDISCONNECT; - buffer[1] = 0; + this->buffer[0] = MQTTDISCONNECT; + this->buffer[1] = 0; + +// Start Tasmota patch +// _client->write(this->buffer,2); +// _state = MQTT_DISCONNECTED; +// _client->flush(); +// _client->stop(); + if (_client != nullptr) { if (disconnect_package) { - _client->write(buffer,2); + _client->write(this->buffer,2); } _client->flush(); _client->stop(); } _state = MQTT_DISCONNECTED; +// End Tasmota patch + lastInActivity = lastOutActivity = millis(); } @@ -628,7 +785,7 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po const char* idp = string; uint16_t i = 0; pos += 2; - while (*idp && pos < (MQTT_MAX_PACKET_SIZE - 2)) { + while (*idp) { buf[pos++] = *idp++; i++; } @@ -639,19 +796,27 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po boolean PubSubClient::connected() { + boolean rc; if (_client == NULL ) { + +// Start Tasmota patch this->_state = MQTT_DISCONNECTED; - return false; - } - if (_client->connected() == 0) { - bool lastStateConnected = this->_state == MQTT_CONNECTED; - this->disconnect(); - if (lastStateConnected) { - this->_state = MQTT_CONNECTION_LOST; +// End Tasmota patch + + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) { + if (this->_state == MQTT_CONNECTED) { + this->_state = MQTT_CONNECTION_LOST; + _client->flush(); + _client->stop(); + } + } else { + return this->_state == MQTT_CONNECTED; } - return false; } - return this->_state == MQTT_CONNECTED; + return rc; } PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { @@ -662,7 +827,13 @@ PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { this->ip = ip; this->port = port; + +// Start Tasmota patch +// this->domain = NULL; + this->domain = ""; +// End Tasmota patch + return *this; } @@ -690,3 +861,34 @@ PubSubClient& PubSubClient::setStream(Stream& stream){ int PubSubClient::state() { return this->_state; } + +boolean PubSubClient::setBufferSize(uint16_t size) { + if (size == 0) { + // Cannot set it back to 0 + return false; + } + if (this->bufferSize == 0) { + this->buffer = (uint8_t*)malloc(size); + } else { + uint8_t* newBuffer = (uint8_t*)realloc(this->buffer, size); + if (newBuffer != NULL) { + this->buffer = newBuffer; + } else { + return false; + } + } + this->bufferSize = size; + return (this->buffer != NULL); +} + +uint16_t PubSubClient::getBufferSize() { + return this->bufferSize; +} +PubSubClient& PubSubClient::setKeepAlive(uint16_t keepAlive) { + this->keepAlive = keepAlive; + return *this; +} +PubSubClient& PubSubClient::setSocketTimeout(uint16_t timeout) { + this->socketTimeout = timeout; + return *this; +} diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h b/lib/default/pubsubclient-2.8.12/src/PubSubClient.h similarity index 88% rename from lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h rename to lib/default/pubsubclient-2.8.12/src/PubSubClient.h index 19b35160a..4edf5ec57 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h +++ b/lib/default/pubsubclient-2.8.12/src/PubSubClient.h @@ -21,24 +21,20 @@ #define MQTT_VERSION MQTT_VERSION_3_1_1 #endif -// MQTT_MAX_PACKET_SIZE : Maximum packet size +// MQTT_MAX_PACKET_SIZE : Maximum packet size. Override with setBufferSize(). #ifndef MQTT_MAX_PACKET_SIZE -//#define MQTT_MAX_PACKET_SIZE 128 -//#define MQTT_MAX_PACKET_SIZE 1000 // Tasmota v5.11.1c +//#define MQTT_MAX_PACKET_SIZE 256 #define MQTT_MAX_PACKET_SIZE 1200 // Tasmota v8.1.0.8 #endif -// MQTT_KEEPALIVE : keepAlive interval in Seconds -// Keepalive timeout for default MQTT Broker is 10s +// MQTT_KEEPALIVE : keepAlive interval in Seconds. Override with setKeepAlive() #ifndef MQTT_KEEPALIVE -//#define MQTT_KEEPALIVE 10 -#define MQTT_KEEPALIVE 30 // Tasmota v6.5.0.14 enabling AWS-iot +#define MQTT_KEEPALIVE 15 #endif -// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds +// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds. Override with setSocketTimeout() #ifndef MQTT_SOCKET_TIMEOUT -//#define MQTT_SOCKET_TIMEOUT 15 -#define MQTT_SOCKET_TIMEOUT 4 // Tasmota 20210120 +#define MQTT_SOCKET_TIMEOUT 15 #endif // MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client @@ -88,18 +84,21 @@ #define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) #endif -#define CHECK_STRING_LENGTH(l,s) if (l+2+strlen(s) > MQTT_MAX_PACKET_SIZE) {_client->stop();return false;} +#define CHECK_STRING_LENGTH(l,s) if (l+2+strnlen(s, this->bufferSize) > this->bufferSize) {_client->stop();return false;} class PubSubClient : public Print { private: Client* _client; - uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint8_t* buffer; + uint16_t bufferSize; + uint16_t keepAlive; + uint16_t socketTimeout; uint16_t nextMsgId; unsigned long lastOutActivity; unsigned long lastInActivity; bool pingOutstanding; MQTT_CALLBACK_SIGNATURE; - uint16_t readPacket(uint8_t*); + uint32_t readPacket(uint8_t*); boolean readByte(uint8_t * result); boolean readByte(uint8_t * result, uint16_t * index); boolean write(uint8_t header, uint8_t* buf, uint16_t length); @@ -110,7 +109,13 @@ private: // (MQTT_MAX_HEADER_SIZE - ) bytes into the buffer size_t buildHeader(uint8_t header, uint8_t* buf, uint16_t length); IPAddress ip; + +// Start Tasmota patch +// const char* domain; + String domain; +// End Tasmota patch + uint16_t port; Stream* stream; int _state; @@ -129,7 +134,8 @@ public: PubSubClient(const char*, uint16_t, Client& client, Stream&); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); - virtual ~PubSubClient() {} + + ~PubSubClient(); PubSubClient& setServer(IPAddress ip, uint16_t port); PubSubClient& setServer(uint8_t * ip, uint16_t port); @@ -137,13 +143,24 @@ public: PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); PubSubClient& setClient(Client& client); PubSubClient& setStream(Stream& stream); + PubSubClient& setKeepAlive(uint16_t keepAlive); + PubSubClient& setSocketTimeout(uint16_t timeout); + + boolean setBufferSize(uint16_t size); + uint16_t getBufferSize(); boolean connect(const char* id); boolean connect(const char* id, const char* user, const char* pass); boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); + +// Start Tasmota patch +// void disconnect(); + void disconnect(bool disconnect_package = false); +// End Tasmota patch + boolean publish(const char* topic, const char* payload); boolean publish(const char* topic, const char* payload, boolean retained); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); @@ -173,6 +190,7 @@ public: boolean loop(); boolean connected(); int state(); + }; diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/.gitignore b/lib/default/pubsubclient-2.8.12/tests/.gitignore similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/.gitignore rename to lib/default/pubsubclient-2.8.12/tests/.gitignore diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/Makefile b/lib/default/pubsubclient-2.8.12/tests/Makefile similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/Makefile rename to lib/default/pubsubclient-2.8.12/tests/Makefile diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/README.md b/lib/default/pubsubclient-2.8.12/tests/README.md similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/README.md rename to lib/default/pubsubclient-2.8.12/tests/README.md diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp b/lib/default/pubsubclient-2.8.12/tests/src/connect_spec.cpp similarity index 90% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/connect_spec.cpp index e27a1f59f..e8545c49d 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/connect_spec.cpp +++ b/lib/default/pubsubclient-2.8.12/tests/src/connect_spec.cpp @@ -280,6 +280,38 @@ int test_connect_disconnect_connect() { END_IT } +int test_connect_custom_keepalive() { + IT("sends a properly formatted connect packet with custom keepalive value"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + + // Set keepalive to 300secs == 0x01 0x2c + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x01,0x2c,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + client.setKeepAlive(300); + + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + + int main() { SUITE("Connect"); @@ -298,5 +330,7 @@ int main() test_connect_with_will(); test_connect_with_will_username_password(); test_connect_disconnect_connect(); + + test_connect_custom_keepalive(); FINISH } diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp b/lib/default/pubsubclient-2.8.12/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/keepalive_spec.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/keepalive_spec.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/Arduino.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Arduino.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Arduino.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp b/lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/BDDTest.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/BDDTest.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp b/lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.h similarity index 88% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.h index f448cade8..c6a2cb584 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Buffer.h +++ b/lib/default/pubsubclient-2.8.12/tests/src/lib/Buffer.h @@ -5,18 +5,18 @@ class Buffer { private: - uint8_t buffer[1024]; + uint8_t buffer[2048]; uint16_t pos; uint16_t length; - + public: Buffer(); Buffer(uint8_t* buf, size_t size); - + virtual bool available(); virtual uint8_t next(); virtual void reset(); - + virtual void add(uint8_t* buf, size_t size); }; diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/Client.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Client.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Client.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp b/lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/IPAddress.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/IPAddress.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/Print.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Print.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Print.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp b/lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/ShimClient.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/ShimClient.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp b/lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.cpp similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.cpp diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/Stream.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/Stream.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h b/lib/default/pubsubclient-2.8.12/tests/src/lib/trace.h similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/lib/trace.h rename to lib/default/pubsubclient-2.8.12/tests/src/lib/trace.h diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp b/lib/default/pubsubclient-2.8.12/tests/src/publish_spec.cpp similarity index 99% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/publish_spec.cpp index 232df0d37..ee3d3bedb 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/publish_spec.cpp +++ b/lib/default/pubsubclient-2.8.12/tests/src/publish_spec.cpp @@ -134,6 +134,7 @@ int test_publish_too_long() { shimClient.respond(connack,4); PubSubClient client(server, 1883, callback, shimClient); + client.setBufferSize(128); int rc = client.connect((char*)"client_test1"); IS_TRUE(rc); diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp b/lib/default/pubsubclient-2.8.12/tests/src/receive_spec.cpp similarity index 75% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/receive_spec.cpp index 9a18af042..93e909aeb 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/receive_spec.cpp +++ b/lib/default/pubsubclient-2.8.12/tests/src/receive_spec.cpp @@ -20,6 +20,7 @@ void reset_callback() { } void callback(char* topic, byte* payload, unsigned int length) { + TRACE("Callback received topic=[" << topic << "] length=" << length << "\n") callback_called = true; strcpy(lastTopic,topic); memcpy(lastPayload,payload,length); @@ -102,10 +103,15 @@ int test_receive_max_sized_message() { shimClient.respond(connack,4); PubSubClient client(server, 1883, callback, shimClient); + int length = 80; // If this is changed to > 128 then the publish packet below + // is no longer valid as it assumes the remaining length + // is a single-byte. Don't make that mistake like I just + // did and lose a whole evening tracking down the issue. + client.setBufferSize(length); int rc = client.connect((char*)"client_test1"); IS_TRUE(rc); - int length = MQTT_MAX_PACKET_SIZE; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; byte bigPublish[length]; memset(bigPublish,'A',length); @@ -137,11 +143,13 @@ int test_receive_oversized_message() { byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; shimClient.respond(connack,4); + int length = 80; // See comment in test_receive_max_sized_message before changing this value + PubSubClient client(server, 1883, callback, shimClient); + client.setBufferSize(length-1); int rc = client.connect((char*)"client_test1"); IS_TRUE(rc); - int length = MQTT_MAX_PACKET_SIZE+1; byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; byte bigPublish[length]; memset(bigPublish,'A',length); @@ -188,9 +196,58 @@ int test_drop_invalid_remaining_length_message() { END_IT } +int test_resize_buffer() { + IT("receives a message larger than the default maximum"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + int length = 80; // See comment in test_receive_max_sized_message before changing this value + + PubSubClient client(server, 1883, callback, shimClient); + client.setBufferSize(length-1); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + // Send it twice + shimClient.respond(bigPublish,length); + shimClient.respond(bigPublish,length); + + rc = client.loop(); + IS_TRUE(rc); + + // First message fails as it is too big + IS_FALSE(callback_called); + + // Resize the buffer + client.setBufferSize(length); + + rc = client.loop(); + IS_TRUE(rc); + + IS_TRUE(callback_called); + + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == length-9); + IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0); + + IS_FALSE(shimClient.error()); + + END_IT +} + int test_receive_oversized_stream_message() { - IT("drops an oversized message"); + IT("receive an oversized streamed message"); reset_callback(); Stream stream; @@ -201,11 +258,13 @@ int test_receive_oversized_stream_message() { byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; shimClient.respond(connack,4); + int length = 80; // See comment in test_receive_max_sized_message before changing this value + PubSubClient client(server, 1883, callback, shimClient, stream); + client.setBufferSize(length-1); int rc = client.connect((char*)"client_test1"); IS_TRUE(rc); - int length = MQTT_MAX_PACKET_SIZE+1; byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; byte bigPublish[length]; @@ -222,7 +281,8 @@ int test_receive_oversized_stream_message() { IS_TRUE(callback_called); IS_TRUE(strcmp(lastTopic,"topic")==0); - IS_TRUE(lastLength == length-9); + + IS_TRUE(lastLength == length-10); IS_FALSE(stream.error()); IS_FALSE(shimClient.error()); @@ -272,6 +332,7 @@ int main() test_receive_max_sized_message(); test_drop_invalid_remaining_length_message(); test_receive_oversized_message(); + test_resize_buffer(); test_receive_oversized_stream_message(); test_receive_qos1(); diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp b/lib/default/pubsubclient-2.8.12/tests/src/subscribe_spec.cpp similarity index 99% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp rename to lib/default/pubsubclient-2.8.12/tests/src/subscribe_spec.cpp index a41982355..22dc8a443 100644 --- a/lib/default/PubSubClient-EspEasy-2.7.12/tests/src/subscribe_spec.cpp +++ b/lib/default/pubsubclient-2.8.12/tests/src/subscribe_spec.cpp @@ -106,6 +106,7 @@ int test_subscribe_too_long() { shimClient.respond(connack,4); PubSubClient client(server, 1883, callback, shimClient); + client.setBufferSize(128); int rc = client.connect((char*)"client_test1"); IS_TRUE(rc); diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py b/lib/default/pubsubclient-2.8.12/tests/testcases/__init__.py similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/__init__.py rename to lib/default/pubsubclient-2.8.12/tests/testcases/__init__.py diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py b/lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_basic.py similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_basic.py rename to lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_basic.py diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py b/lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_publish_in_callback.py similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/mqtt_publish_in_callback.py rename to lib/default/pubsubclient-2.8.12/tests/testcases/mqtt_publish_in_callback.py diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py b/lib/default/pubsubclient-2.8.12/tests/testcases/settings.py similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/testcases/settings.py rename to lib/default/pubsubclient-2.8.12/tests/testcases/settings.py diff --git a/lib/default/PubSubClient-EspEasy-2.7.12/tests/testsuite.py b/lib/default/pubsubclient-2.8.12/tests/testsuite.py similarity index 100% rename from lib/default/PubSubClient-EspEasy-2.7.12/tests/testsuite.py rename to lib/default/pubsubclient-2.8.12/tests/testsuite.py diff --git a/tasmota/i18n.h b/tasmota/i18n.h index da0893f89..accb88938 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -366,6 +366,8 @@ #define D_CMND_MQTTCLIENT "MqttClient" #define D_CMND_MQTTUSER "MqttUser" #define D_CMND_MQTTPASSWORD "MqttPassword" +#define D_CMND_MQTTKEEPALIVE "MqttKeepAlive" +#define D_CMND_MQTTTIMEOUT "MqttTimeout" #define D_CMND_TLSKEY "TLSKey" #define D_CMND_FULLTOPIC "FullTopic" #define D_CMND_PREFIX "Prefix" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index e33e5bf3c..3943ab4db 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -101,6 +101,9 @@ // -- MQTT ---------------------------------------- #define MQTT_USE true // [SetOption3] Select default MQTT use (false = Off, true = On) +#define MQTT_KEEPALIVE 30 // [MqttKeepAlive] +#define MQTT_SOCKET_TIMEOUT 4 // [MqttTimeout] + #define MQTT_HOST "" // [MqttHost] #define MQTT_FINGERPRINT1 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // [MqttFingerprint1] (auto-learn) #define MQTT_FINGERPRINT2 0xDA,0x39,0xA3,0xEE,0x5E,0x6B,0x4B,0x0D,0x32,0x55,0xBF,0xEF,0x95,0x60,0x18,0x90,0xAF,0xD8,0x07,0x09 // [MqttFingerprint2] (invalid) diff --git a/tasmota/settings.h b/tasmota/settings.h index 7dd8dbc29..8ce77b4d4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -488,7 +488,12 @@ struct { power_t interlock[MAX_INTERLOCKS_SET]; // 4D0 MAX_INTERLOCKS = MAX_RELAYS / 2 - uint8_t free_508[41]; // 508 + uint8_t free_508[36]; // 508 + + uint16_t mqtt_keepalive; // 52C + uint16_t mqtt_socket_timeout; // 52E + + uint8_t free_530[1]; // 530 uint8_t ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c1996da99..11f835592 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -864,6 +864,8 @@ void SettingsDefaultSet2(void) { memcpy_P(Settings.mqtt_fingerprint[1], default_fingerprint2, sizeof(default_fingerprint2)); Settings.tele_period = TELE_PERIOD; Settings.mqttlog_level = MQTT_LOG_LEVEL; + Settings.mqtt_keepalive = MQTT_KEEPALIVE; + Settings.mqtt_socket_timeout = MQTT_SOCKET_TIMEOUT; // Energy flag.no_power_on_check |= ENERGY_VOLTAGE_ALWAYS; @@ -1244,6 +1246,10 @@ void SettingsDelta(void) { if (Settings.version < 0x09020007) { *(uint32_t *)&Settings.device_group_tie = 0x04030201; } + if (Settings.version < 0x09030102) { + Settings.mqtt_keepalive = MQTT_KEEPALIVE; + Settings.mqtt_socket_timeout = MQTT_SOCKET_TIMEOUT; + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index de6879f16..d782f385f 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -529,9 +529,9 @@ void CmndStatus(void) if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d,\"SOCKET_TIMEOUT\":%d}}"), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, EscapeJSONString(SettingsText(SET_MQTT_CLIENT)).c_str(), - TasmotaGlobal.mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + TasmotaGlobal.mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, Settings.mqtt_keepalive, Settings.mqtt_socket_timeout); MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "6")); } diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index 52149943c..110277cc2 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -270,8 +270,8 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo #ifndef MQTT_KEEPALIVE #define MQTT_KEEPALIVE 30 // Seconds #endif -#ifndef MQTT_TIMEOUT -#define MQTT_TIMEOUT 10000 // milli seconds +#ifndef MQTT_SOCKET_TIMEOUT +#define MQTT_SOCKET_TIMEOUT 4 // Seconds #endif #ifndef MQTT_CLEAN_SESSION #define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session (default) diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 26807fb8f..e26ffc875 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x09030101; +const uint32_t VERSION = 0x09030102; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 3ef1ec84b..c31b2f4a7 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -23,6 +23,8 @@ #define MQTT_WIFI_CLIENT_TIMEOUT 200 // Wifi TCP connection timeout (default is 5000 mSec) #endif +#define USE_MQTT_NEW_PUBSUBCLIENT + // #define DEBUG_DUMP_TLS // allow dumping of TLS Flash keys #ifdef USE_MQTT_TLS @@ -42,7 +44,7 @@ const char kMqttCommands[] PROGMEM = "|" // No prefix #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) D_CMND_MQTTFINGERPRINT "|" #endif - D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" + D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_MQTTKEEPALIVE "|" D_CMND_MQTTTIMEOUT "|" #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) D_CMND_TLSKEY "|" #endif @@ -68,7 +70,7 @@ void (* const MqttCommand[])(void) PROGMEM = { #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) &CmndMqttFingerprint, #endif - &CmndMqttUser, &CmndMqttPassword, + &CmndMqttUser, &CmndMqttPassword, &CmndMqttKeepAlive, &CmndMqttTimeout, #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) &CmndTlsKey, #endif @@ -209,6 +211,9 @@ void MqttInit(void) { #else // USE_MQTT_TLS MqttClient.setClient(EspClient); #endif // USE_MQTT_TLS + + MqttClient.setKeepAlive(Settings.mqtt_keepalive); + MqttClient.setSocketTimeout(Settings.mqtt_socket_timeout); } bool MqttIsConnected(void) { @@ -829,6 +834,26 @@ void CmndMqttPassword(void) { } } +void CmndMqttKeepAlive(void) { + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 100)) { + Settings.mqtt_keepalive = XdrvMailbox.payload; +#ifdef USE_MQTT_NEW_PUBSUBCLIENT + MqttClient.setKeepAlive(Settings.mqtt_keepalive); +#endif + } + ResponseCmndNumber(Settings.mqtt_keepalive); +} + +void CmndMqttTimeout(void) { + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 100)) { + Settings.mqtt_socket_timeout = XdrvMailbox.payload; +#ifdef USE_MQTT_NEW_PUBSUBCLIENT + MqttClient.setSocketTimeout(Settings.mqtt_socket_timeout); +#endif + } + ResponseCmndNumber(Settings.mqtt_socket_timeout); +} + void CmndMqttlog(void) { if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { Settings.mqttlog_level = XdrvMailbox.payload;