From e569a74cc67893f43e97c698e21e521788b84442 Mon Sep 17 00:00:00 2001 From: Holger Mueller Date: Fri, 11 Jul 2025 12:41:53 +0200 Subject: [PATCH 01/23] add defines for needed PROGMEM functions --- tests/src/lib/Arduino.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/src/lib/Arduino.h b/tests/src/lib/Arduino.h index b5903ea5..6a60a0a0 100644 --- a/tests/src/lib/Arduino.h +++ b/tests/src/lib/Arduino.h @@ -13,6 +13,7 @@ extern "C" { typedef uint8_t byte; typedef uint8_t boolean; +typedef uint8_t prog_uint8_t; /* sketch */ extern void setup(void); @@ -21,6 +22,9 @@ unsigned long millis(void); } #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) From 1a6d44b9b6410bd9983c391bfd9bcd9a45cc2987 Mon Sep 17 00:00:00 2001 From: Holger Mueller Date: Fri, 11 Jul 2025 12:44:23 +0200 Subject: [PATCH 02/23] implemented writeString(const __FlashStringHelper* ...), writeString_P() --- src/PubSubClient.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 0a17660c..7ec84083 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -489,11 +489,11 @@ bool PubSubClient::publish(const char* topic, const uint8_t* payload, size_t ple return false; } -bool PubSubClient::publish_P(const char* topic, const char* payload, bool retained) { - return publish_P(topic, (const uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, retained); +bool PubSubClient::publish_P(const char* topic, PGM_P payload, bool retained) { + return publish_P(topic, (const prog_uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, retained); } -bool PubSubClient::publish_P(const char* topic, const uint8_t* payload, size_t plength, bool retained) { +bool PubSubClient::publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, bool retained) { if (beginPublish(topic, plength, retained)) { size_t rc = 0; for (size_t i = 0; i < plength; i++) { @@ -651,6 +651,27 @@ size_t PubSubClient::writeString(const char* string, uint8_t* buf, size_t pos, s return pos; } +size_t PubSubClient::writeString(const __FlashStringHelper* fstring, uint8_t* buf, size_t pos, size_t size) { + // convert FlashStringHelper in PROGMEM-pointer + return writeString_P(reinterpret_cast(fstring), buf, pos, this->bufferSize); +} + +size_t PubSubClient::writeString_P(PGM_P string, uint8_t* buf, size_t pos, size_t size) { + if (!string) return pos; + + size_t sLen = strlen_P(string); + if ((pos + 2 + sLen) <= size && sLen <= 0xFFFF) { + buf[pos++] = (uint8_t)(sLen >> 8); + buf[pos++] = (uint8_t)(sLen & 0xFF); + memcpy_P(buf + pos, string, sLen); + pos += sLen; + } else { + ERROR_PSC_PRINTF_P("writeString_P(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, size); + } + + return pos; +} + bool PubSubClient::subscribe(const char* topic) { return subscribe(topic, 0); } From 64709f1c2633451858be1f465e176a46ad145d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 13 Jul 2025 10:47:54 +0200 Subject: [PATCH 03/23] fix merge failure --- src/PubSubClient.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 91cdbc38..32a3e814 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -531,7 +531,11 @@ bool PubSubClient::publish(const char* topic, const uint8_t* payload, size_t ple } bool PubSubClient::publish_P(const char* topic, PGM_P payload, bool retained) { - return publish_P(topic, (const prog_uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, retained); + return publish_P(topic, payload, MQTT_QOS0, retained); +} + +bool PubSubClient::publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained) { + return publish_P(topic, (const prog_uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } bool PubSubClient::publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, bool retained) { @@ -723,7 +727,7 @@ size_t PubSubClient::writeString(const char* string, uint8_t* buf, size_t pos, s size_t PubSubClient::writeString(const __FlashStringHelper* fstring, uint8_t* buf, size_t pos, size_t size) { // convert FlashStringHelper in PROGMEM-pointer - return writeString_P(reinterpret_cast(fstring), buf, pos, this->bufferSize); + return writeString_P(reinterpret_cast(fstring), buf, pos, size); } size_t PubSubClient::writeString_P(PGM_P string, uint8_t* buf, size_t pos, size_t size) { From b2fb86cf1a323192073a6d68ef6912f769477958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 13 Jul 2025 10:55:56 +0200 Subject: [PATCH 04/23] added writeString(const __FlashStringHelper* ...), writeString_P() --- src/PubSubClient.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 9a2f4dda..98131aa7 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -200,6 +200,8 @@ class PubSubClient : public Print { 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 writeString(const char* string, uint8_t* buf, size_t pos, size_t size); + size_t writeString(const __FlashStringHelper* fstring, uint8_t* buf, size_t pos, size_t size); + size_t writeString_P(PGM_P string, uint8_t* buf, size_t pos, size_t size); size_t writeNextMsgId(uint8_t* buf, size_t pos, size_t size); public: @@ -561,7 +563,7 @@ 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); + bool publish_P(const char* topic, PGM_P payload, bool retained); /** * @brief Publishes a message stored in PROGMEM to the specified topic. @@ -572,7 +574,7 @@ 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); + bool publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained); /** * @brief Publishes a message stored in PROGMEM to the specified topic using QoS 0. @@ -583,7 +585,7 @@ 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); + bool publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, bool retained); /** * @brief Publishes a message stored in PROGMEM to the specified topic. @@ -595,7 +597,7 @@ 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, uint8_t qos, bool retained); + bool publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, uint8_t qos, bool retained); /** * @brief Start to publish a message using QoS 0. From c461807d0185a75ebc9c98b018c344c51a83072e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 13 Jul 2025 10:56:16 +0200 Subject: [PATCH 05/23] added __FlashStringHelper --- tests/src/lib/Arduino.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/lib/Arduino.h b/tests/src/lib/Arduino.h index 6a60a0a0..1923ebdd 100644 --- a/tests/src/lib/Arduino.h +++ b/tests/src/lib/Arduino.h @@ -21,6 +21,7 @@ extern void loop(void); unsigned long millis(void); } +class __FlashStringHelper; #define PROGMEM #define PGM_P const char * #define memcpy_P memcpy From 07ebf85a82867794ee502849ee1f7226a4c69eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Mon, 20 Oct 2025 16:06:28 +0200 Subject: [PATCH 06/23] do not use prog_uint8_t, deprecated --- src/PubSubClient.cpp | 6 +++--- src/PubSubClient.h | 4 ++-- tests/src/lib/Arduino.h | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index e453a537..4ce0adbf 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -542,14 +542,14 @@ bool PubSubClient::publish_P(const char* topic, PGM_P payload, bool retained) { } bool PubSubClient::publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained) { - return publish_P(topic, (const prog_uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); + return publish_P(topic, (const uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } -bool PubSubClient::publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, bool retained) { +bool PubSubClient::publish_P(const char* topic, const uint8_t* payload, size_t plength, bool retained) { return publish_P(topic, payload, plength, MQTT_QOS0, retained); } -bool PubSubClient::publish_P(const char* topic, const prog_uint8_t* payload, size_t plength, uint8_t qos, bool retained) { +bool PubSubClient::publish_P(const char* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained) { if (beginPublish(topic, plength, qos, retained)) { size_t rc = write_P(payload, plength); return endPublish() && (rc == plength); diff --git a/src/PubSubClient.h b/src/PubSubClient.h index a363c49c..f1b4bc2c 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -589,7 +589,7 @@ 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 prog_uint8_t* payload, size_t plength, bool retained); + bool publish_P(const char* topic, const uint8_t* payload, size_t plength, bool retained); /** * @brief Publishes a message stored in PROGMEM to the specified topic. @@ -601,7 +601,7 @@ 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 prog_uint8_t* payload, size_t plength, uint8_t qos, bool retained); + bool publish_P(const char* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained); /** * @brief Start to publish a message using QoS 0. diff --git a/tests/src/lib/Arduino.h b/tests/src/lib/Arduino.h index 1923ebdd..d0dbfc9f 100644 --- a/tests/src/lib/Arduino.h +++ b/tests/src/lib/Arduino.h @@ -13,7 +13,6 @@ extern "C" { typedef uint8_t byte; typedef uint8_t boolean; -typedef uint8_t prog_uint8_t; /* sketch */ extern void setup(void); From 3de4409fa2dbc5aa4c00ec26bf78695df0e954b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Thu, 23 Oct 2025 21:21:23 +0200 Subject: [PATCH 07/23] removed writeString(__FlashStringHelper*), added beginPublishImpl(), beginPublish(__FlashStringHelper*) and beginPublish_P(PGM_P) --- src/PubSubClient.cpp | 58 ++++++++++++++++++++++++++++++-------------- src/PubSubClient.h | 25 +++++++++++++++++-- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 9b373899..196febba 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -564,23 +564,38 @@ bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained return beginPublish(topic, plength, MQTT_QOS0, retained); } -bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { +template +bool PubSubClient::beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, bool retained) { if (!topic) return false; - if (strlen(topic) == 0) return false; // empty topic is not allowed - if (qos > MQTT_QOS2) { // only valid QoS supported + + // get topic length depending on storage (RAM vs PROGMEM) + size_t topicLen; + if (PROGMEM_TOPIC) { + topicLen = strlen_P(topic); + } else { + topicLen = strlen(topic); + } + if (topicLen == 0) return false; // empty topic is not allowed + + if (qos > MQTT_QOS2) { // only valid QoS supported ERROR_PSC_PRINTF_P("beginPublish() called with invalid QoS %u\n", qos); return false; } + const size_t nextMsgLen = (qos > MQTT_QOS0) ? 2 : 0; // add 2 bytes for nextMsgId if QoS > 0 // check if the header, the topic (including 2 length bytes) and nextMsgId fit into the _buffer - if (connected() && (MQTT_MAX_HEADER_SIZE + strlen(topic) + 2 + nextMsgLen <= _bufferSize)) { + if (connected() && (MQTT_MAX_HEADER_SIZE + topicLen + 2 + nextMsgLen <= _bufferSize)) { // first write the topic at the end of the maximal variable header (MQTT_MAX_HEADER_SIZE) to the _buffer - size_t topicLen = writeString(topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; + if (PROGMEM_TOPIC) { + topicLen = writeString_P(topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; + } else { + topicLen = writeString(topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; + } if (qos > MQTT_QOS0) { // if QoS 1 or 2, we need to send the nextMsgId (packet identifier) after topic writeNextMsgId(MQTT_MAX_HEADER_SIZE + topicLen); } - // we now know the length of the topic string (lenght + 2 bytes signalling the length) and can build the variable header information + // we now know the length of the topic string (length + 2 bytes signalling the length) and can build the variable header information const uint8_t header = MQTTPUBLISH | MQTT_QOS_GET_HDR(qos) | (retained ? MQTTRETAINED : 0); uint8_t hdrLen = buildHeader(header, topicLen + nextMsgLen + plength); if (hdrLen == 0) return false; // exit here in case of header generation failure @@ -592,6 +607,19 @@ bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, return false; } +bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { + return beginPublishImpl(topic, plength, qos, retained); +} + +bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { + // convert FlashStringHelper in PROGMEM-pointer + return beginPublishImpl(reinterpret_cast(topic), plength, qos, retained); +} + +bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { + return beginPublishImpl(topic, plength, qos, retained); +} + bool PubSubClient::endPublish() { if (connected()) { if (_bufferWritePos > 0) { @@ -731,24 +759,18 @@ size_t PubSubClient::writeString(const char* string, size_t pos) { return pos; } -size_t PubSubClient::writeString(const __FlashStringHelper* fstring, uint8_t* buf, size_t pos, size_t size) { - // convert FlashStringHelper in PROGMEM-pointer - return writeString_P(reinterpret_cast(fstring), buf, pos, size); -} - -size_t PubSubClient::writeString_P(PGM_P string, uint8_t* buf, size_t pos, size_t size) { +size_t PubSubClient::writeString_P(PGM_P string, size_t pos) { if (!string) return pos; size_t sLen = strlen_P(string); - if ((pos + 2 + sLen) <= size && sLen <= 0xFFFF) { - buf[pos++] = (uint8_t)(sLen >> 8); - buf[pos++] = (uint8_t)(sLen & 0xFF); - memcpy_P(buf + pos, string, sLen); + if ((pos + 2 + sLen) <= _bufferSize && sLen <= 0xFFFF) { + _buffer[pos++] = (uint8_t)(sLen >> 8); + _buffer[pos++] = (uint8_t)(sLen & 0xFF); + memcpy_P(_buffer + pos, string, sLen); pos += sLen; } else { - ERROR_PSC_PRINTF_P("writeString_P(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, size); + ERROR_PSC_PRINTF_P("writeString_P(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, _bufferSize); } - return pos; } diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 72482a8b..fa2eafcd 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -200,10 +200,12 @@ class PubSubClient : public Print { bool writeControlPacket(uint8_t header, size_t length); size_t writeBuffer(size_t pos, size_t size); size_t writeString(const char* string, size_t pos); - size_t writeString(const __FlashStringHelper* fstring, uint8_t* buf, size_t pos, size_t size); - size_t writeString_P(PGM_P string, uint8_t* buf, size_t pos, size_t size); + size_t writeString_P(PGM_P string, size_t pos); size_t writeNextMsgId(size_t pos); + template + bool beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, bool retained); + // Add to buffer and flush if full (only to be used with beginPublish/endPublish) size_t appendBuffer(uint8_t data); size_t flushBuffer(); @@ -636,6 +638,25 @@ class PubSubClient : public Print { */ bool beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained); + bool beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool 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. + */ + bool beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained); + /** * @brief Finish sending a message that was started with a call to beginPublish. * @return true If the publish succeeded. From 2df1cf25e7e88ba41b45685a333778f3b00c0628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Thu, 23 Oct 2025 21:21:37 +0200 Subject: [PATCH 08/23] added F() macro --- tests/src/lib/Arduino.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/src/lib/Arduino.h b/tests/src/lib/Arduino.h index d0dbfc9f..ab830f05 100644 --- a/tests/src/lib/Arduino.h +++ b/tests/src/lib/Arduino.h @@ -22,11 +22,12 @@ unsigned long millis(void); class __FlashStringHelper; #define PROGMEM -#define PGM_P const char * +#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(x)) #define yield(x) {} From 1aec20540cf081b716ebe664d636c4a7316bc6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Fri, 24 Oct 2025 18:32:21 +0200 Subject: [PATCH 09/23] implemented writeStringImpl() using template, added __FlashStringHelper variants of publish() and publish_P() --- src/PubSubClient.cpp | 86 +++++++++++++++++++++++++++++++------------- src/PubSubClient.h | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 24 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 0c719850..cd8e87d2 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -525,6 +525,10 @@ bool PubSubClient::publish(const char* topic, const char* payload, bool retained return publish(topic, payload, MQTT_QOS0, retained); } +bool PubSubClient::publish(const __FlashStringHelper* topic, const char* payload, uint8_t qos, bool retained) { + return publish(topic, (const uint8_t*)payload, payload ? strnlen(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); +} + bool PubSubClient::publish(const char* topic, const char* payload, uint8_t qos, bool retained) { return publish(topic, (const uint8_t*)payload, payload ? strnlen(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } @@ -545,10 +549,22 @@ bool PubSubClient::publish(const char* topic, const uint8_t* payload, size_t ple return false; } +bool PubSubClient::publish(const __FlashStringHelper* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained) { + if (beginPublish(topic, plength, qos, retained)) { + size_t rc = write(payload, plength); + return endPublish() && (rc == plength); + } + return false; +} + bool PubSubClient::publish_P(const char* topic, PGM_P payload, bool retained) { return publish_P(topic, payload, MQTT_QOS0, retained); } +bool PubSubClient::publish_P(const __FlashStringHelper* topic, PGM_P payload, uint8_t qos, bool retained) { + return publish_P(topic, (const uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); +} + bool PubSubClient::publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained) { return publish_P(topic, (const uint8_t*)payload, payload ? strnlen_P(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } @@ -565,6 +581,14 @@ bool PubSubClient::publish_P(const char* topic, const uint8_t* payload, size_t p return false; } +bool PubSubClient::publish_P(const __FlashStringHelper* topic, const uint8_t* payload, size_t plength, uint8_t qos, bool retained) { + if (beginPublish(topic, plength, qos, retained)) { + size_t rc = write_P(payload, plength); + return endPublish() && (rc == plength); + } + return false; +} + bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained) { return beginPublish(topic, plength, MQTT_QOS0, retained); } @@ -740,6 +764,31 @@ size_t PubSubClient::writeBuffer(size_t pos, size_t size) { return rc; } +template +bool PubSubClient::writeStringImpl(StringT string, size_t pos) { + if (!string) return pos; + + size_t sLen; + if (PROGMEM_STRING) { + sLen = strlen_P(string); + } else { + sLen = strlen(string); + } + if ((pos + 2 + sLen <= _bufferSize) && (sLen <= 0xFFFF)) { + _buffer[pos++] = (uint8_t)(sLen >> 8); + _buffer[pos++] = (uint8_t)(sLen & 0xFF); + if (PROGMEM_STRING) { + memcpy_P(_buffer + pos, string, sLen); + } else { + memcpy(_buffer + pos, string, sLen); + } + pos += sLen; + } else { + ERROR_PSC_PRINTF_P("writeStringImpl(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, _bufferSize); + } + return pos; +} + /** * @brief Write an UTF-8 encoded string to the internal buffer at a given position. The string can have a length of 0 to 65535 bytes (depending on size of * internal buffer). The buffer is prefixed with two bytes representing the length of the string. See section 1.5.3 of MQTT v3.1.1 protocol specification. @@ -751,33 +800,22 @@ size_t PubSubClient::writeBuffer(size_t pos, size_t size) { * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. */ size_t PubSubClient::writeString(const char* string, size_t pos) { - if (!string) return pos; - - size_t sLen = strlen(string); - if ((pos + 2 + sLen <= _bufferSize) && (sLen <= 0xFFFF)) { - _buffer[pos++] = (uint8_t)(sLen >> 8); - _buffer[pos++] = (uint8_t)(sLen & 0xFF); - memcpy(_buffer + pos, string, sLen); - pos += sLen; - } else { - ERROR_PSC_PRINTF_P("writeString(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, _bufferSize); - } - return pos; + return writeStringImpl(string, pos); } +/** + * @brief Write an UTF-8 encoded PROGMEM string to the internal buffer at a given position. The string can have a length of 0 to 65535 bytes (depending on + * size of internal buffer). The buffer is prefixed with two bytes representing the length of the string. See section 1.5.3 of MQTT v3.1.1 protocol + * specification. + * @note If the string does not fit in the buffer or is longer than 65535 bytes nothing is written to the buffer and the returned position is + * unchanged. + * + * @param string PROGMEM 'C' string of the data that shall be written in the buffer. + * @param pos Position in the internal buffer to write the string. + * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. + */ size_t PubSubClient::writeString_P(PGM_P string, size_t pos) { - if (!string) return pos; - - size_t sLen = strlen_P(string); - if ((pos + 2 + sLen) <= _bufferSize && sLen <= 0xFFFF) { - _buffer[pos++] = (uint8_t)(sLen >> 8); - _buffer[pos++] = (uint8_t)(sLen & 0xFF); - memcpy_P(_buffer + pos, string, sLen); - pos += sLen; - } else { - ERROR_PSC_PRINTF_P("writeString_P(): string (%zu) does not fit into buf (%zu)\n", pos + 2 + sLen, _bufferSize); - } - return pos; + return writeStringImpl(string, pos); } /** diff --git a/src/PubSubClient.h b/src/PubSubClient.h index fa2eafcd..22c90fc9 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -199,6 +199,8 @@ class PubSubClient : public Print { 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); + template + bool writeStringImpl(StringT string, size_t pos); size_t writeString(const char* string, size_t pos); size_t writeString_P(PGM_P string, size_t pos); size_t writeNextMsgId(size_t pos); @@ -528,6 +530,17 @@ class PubSubClient : public Print { */ bool publish(const char* topic, const char* payload, 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 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 char* payload, uint8_t qos, bool retained); + /** * @brief Publishes a non retained message to the specified topic using QoS 0. * @param topic The topic to publish to. @@ -561,6 +574,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. @@ -582,6 +607,17 @@ class PubSubClient : public Print { */ bool publish_P(const char* topic, PGM_P payload, 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 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); + /** * @brief Publishes a message stored in PROGMEM to the specified topic using QoS 0. * @param topic The topic to publish to. @@ -605,6 +641,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: @@ -638,6 +686,21 @@ class PubSubClient : public Print { */ bool beginPublish(const char* topic, size_t plength, uint8_t qos, bool 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. + */ bool beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained); /** From 3ba56371f01546d73bd4f5fe4b20d1b674424bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Fri, 24 Oct 2025 19:48:46 +0200 Subject: [PATCH 10/23] fixed wrong return type of writeStringImpl() --- src/PubSubClient.cpp | 6 +++--- src/PubSubClient.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index cd8e87d2..f26b8acb 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -684,7 +684,7 @@ uint8_t PubSubClient::buildHeader(uint8_t header, size_t length) { } while ((len > 0) && (hdrLen < MQTT_MAX_HEADER_SIZE - 1)); if (len > 0) { - ERROR_PSC_PRINTF_P("buildHeader() length too big %zu, left %zu\n", length, len); + ERROR_PSC_PRINTF_P("buildHeader: header=0x%02X, length too big %zu, left %zu\n", header, length, len); return 0; } @@ -717,7 +717,7 @@ size_t PubSubClient::write_P(const uint8_t* buf, size_t size) { * * @param header Header byte, e.g. MQTTCONNECT, MQTTPUBLISH, MQTTSUBSCRIBE, MQTTUNSUBSCRIBE. * @param length Length of _buffer to write. - * @return True if successfully sent, otherwise false if buildHeader() failed or buffer could not be written. + * @return True if successfully sent, otherwise false if build header failed or buffer could not be written. */ bool PubSubClient::writeControlPacket(uint8_t header, size_t length) { uint8_t hdrLen = buildHeader(header, length); @@ -765,7 +765,7 @@ size_t PubSubClient::writeBuffer(size_t pos, size_t size) { } template -bool PubSubClient::writeStringImpl(StringT string, size_t pos) { +size_t PubSubClient::writeStringImpl(StringT string, size_t pos) { if (!string) return pos; size_t sLen; diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 22c90fc9..92df7e5d 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -200,7 +200,7 @@ class PubSubClient : public Print { bool writeControlPacket(uint8_t header, size_t length); size_t writeBuffer(size_t pos, size_t size); template - bool writeStringImpl(StringT string, size_t pos); + size_t writeStringImpl(StringT string, size_t pos); size_t writeString(const char* string, size_t pos); size_t writeString_P(PGM_P string, size_t pos); size_t writeNextMsgId(size_t pos); From 1fdd6dc11e1650d9a976d9e19dc22ed0e3245a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Fri, 24 Oct 2025 22:33:37 +0200 Subject: [PATCH 11/23] shorten source code size for getting string length --- src/PubSubClient.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index f26b8acb..15c2f241 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -598,12 +598,7 @@ bool PubSubClient::beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, b if (!topic) return false; // get topic length depending on storage (RAM vs PROGMEM) - size_t topicLen; - if (PROGMEM_TOPIC) { - topicLen = strlen_P(topic); - } else { - topicLen = strlen(topic); - } + size_t topicLen = PROGMEM_TOPIC ? strlen_P(topic) : strlen(topic); if (topicLen == 0) return false; // empty topic is not allowed if (qos > MQTT_QOS2) { // only valid QoS supported @@ -768,12 +763,7 @@ template size_t PubSubClient::writeStringImpl(StringT string, size_t pos) { if (!string) return pos; - size_t sLen; - if (PROGMEM_STRING) { - sLen = strlen_P(string); - } else { - sLen = strlen(string); - } + size_t sLen = PROGMEM_STRING ? strlen_P(string) : strlen(string); if ((pos + 2 + sLen <= _bufferSize) && (sLen <= 0xFFFF)) { _buffer[pos++] = (uint8_t)(sLen >> 8); _buffer[pos++] = (uint8_t)(sLen & 0xFF); From 541876aeca9c0df134c559359e80c81d0de50477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Wed, 29 Oct 2025 21:12:35 +0100 Subject: [PATCH 12/23] removed template implementation by classic parameter --- src/PubSubClient.cpp | 64 +++++++++++++++++++++++--------------------- src/PubSubClient.h | 7 ++--- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 15c2f241..f72f18a3 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -593,12 +593,22 @@ bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained return beginPublish(topic, plength, MQTT_QOS0, retained); } -template -bool PubSubClient::beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, bool retained) { +/** + * @brief Internal beginPublish implementation using topic stored in RAM or PROGMEM. + * + * @param progmem true if the topic is stored in PROGMEM/Flash, false if in RAM. + * @param topic The topic 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. + */ +bool PubSubClient::beginPublishImpl(bool progmem, const char* topic, size_t plength, uint8_t qos, bool retained) { if (!topic) return false; // get topic length depending on storage (RAM vs PROGMEM) - size_t topicLen = PROGMEM_TOPIC ? strlen_P(topic) : strlen(topic); + size_t topicLen = progmem ? strlen_P(topic) : strlen(topic); if (topicLen == 0) return false; // empty topic is not allowed if (qos > MQTT_QOS2) { // only valid QoS supported @@ -610,11 +620,7 @@ bool PubSubClient::beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, b // check if the header, the topic (including 2 length bytes) and nextMsgId fit into the _buffer if (connected() && (MQTT_MAX_HEADER_SIZE + topicLen + 2 + nextMsgLen <= _bufferSize)) { // first write the topic at the end of the maximal variable header (MQTT_MAX_HEADER_SIZE) to the _buffer - if (PROGMEM_TOPIC) { - topicLen = writeString_P(topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; - } else { - topicLen = writeString(topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; - } + topicLen = writeStringImpl(progmem, topic, MQTT_MAX_HEADER_SIZE) - MQTT_MAX_HEADER_SIZE; if (qos > MQTT_QOS0) { // if QoS 1 or 2, we need to send the nextMsgId (packet identifier) after topic writeNextMsgId(MQTT_MAX_HEADER_SIZE + topicLen); @@ -632,16 +638,16 @@ bool PubSubClient::beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, b } bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { - return beginPublishImpl(topic, plength, qos, retained); + return beginPublishImpl(false, topic, plength, qos, retained); } bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { // convert FlashStringHelper in PROGMEM-pointer - return beginPublishImpl(reinterpret_cast(topic), plength, qos, retained); + return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { - return beginPublishImpl(topic, plength, qos, retained); + return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } bool PubSubClient::endPublish() { @@ -759,15 +765,26 @@ size_t PubSubClient::writeBuffer(size_t pos, size_t size) { return rc; } -template -size_t PubSubClient::writeStringImpl(StringT string, size_t pos) { +/** + * @brief Internal implementation of writeString using RAM or PROGMEM string. + * Write an UTF-8 encoded string to the internal buffer at a given position. The string can have a length of 0 to 65535 bytes (depending on size of + * internal buffer). The buffer is prefixed with two bytes representing the length of the string. See section 1.5.3 of MQTT v3.1.1 protocol specification. + * @note If the string does not fit in the buffer or is longer than 65535 bytes nothing is written to the buffer and the returned position is + * unchanged. + * + * @param progmem true if the string is stored in PROGMEM, false if in RAM. + * @param string 'C' string of the data that shall be written in the buffer. + * @param pos Position in the internal buffer to write the string. + * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. + */ +size_t PubSubClient::writeStringImpl(bool progmem, const char* string, size_t pos) { if (!string) return pos; - size_t sLen = PROGMEM_STRING ? strlen_P(string) : strlen(string); + size_t sLen = progmem ? strlen_P(string) : strlen(string); if ((pos + 2 + sLen <= _bufferSize) && (sLen <= 0xFFFF)) { _buffer[pos++] = (uint8_t)(sLen >> 8); _buffer[pos++] = (uint8_t)(sLen & 0xFF); - if (PROGMEM_STRING) { + if (progmem) { memcpy_P(_buffer + pos, string, sLen); } else { memcpy(_buffer + pos, string, sLen); @@ -790,22 +807,7 @@ size_t PubSubClient::writeStringImpl(StringT string, size_t pos) { * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. */ size_t PubSubClient::writeString(const char* string, size_t pos) { - return writeStringImpl(string, pos); -} - -/** - * @brief Write an UTF-8 encoded PROGMEM string to the internal buffer at a given position. The string can have a length of 0 to 65535 bytes (depending on - * size of internal buffer). The buffer is prefixed with two bytes representing the length of the string. See section 1.5.3 of MQTT v3.1.1 protocol - * specification. - * @note If the string does not fit in the buffer or is longer than 65535 bytes nothing is written to the buffer and the returned position is - * unchanged. - * - * @param string PROGMEM 'C' string of the data that shall be written in the buffer. - * @param pos Position in the internal buffer to write the string. - * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. - */ -size_t PubSubClient::writeString_P(PGM_P string, size_t pos) { - return writeStringImpl(string, pos); + return writeStringImpl(false, string, pos); } /** diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 92df7e5d..9088c5d3 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -199,14 +199,11 @@ class PubSubClient : public Print { 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); - template - size_t writeStringImpl(StringT string, size_t pos); + size_t writeStringImpl(bool progmem, const char* string, size_t pos); size_t writeString(const char* string, size_t pos); - size_t writeString_P(PGM_P string, size_t pos); size_t writeNextMsgId(size_t pos); - template - bool beginPublishImpl(TopicT topic, size_t plength, uint8_t qos, bool retained); + bool beginPublishImpl(bool progmem, const char* topic, size_t plength, uint8_t qos, bool retained); // Add to buffer and flush if full (only to be used with beginPublish/endPublish) size_t appendBuffer(uint8_t data); From 2d7b1b29e817118d5f88168a45c1e589b4170e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Wed, 29 Oct 2025 21:44:27 +0100 Subject: [PATCH 13/23] added publish(__FlashStringHelper* topic, __FlashStringHelper* payload, ...) --- src/PubSubClient.cpp | 5 +++++ src/PubSubClient.h | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index f72f18a3..d599a930 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -529,6 +529,11 @@ bool PubSubClient::publish(const __FlashStringHelper* topic, const char* payload return publish(topic, (const uint8_t*)payload, payload ? strnlen(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } +bool PubSubClient::publish(const __FlashStringHelper* topic, const __FlashStringHelper* payload, uint8_t qos, bool retained) { + return publish_P(topic, (const uint8_t*)payload, payload ? strnlen_P(reinterpret_cast(payload), MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, + retained); +} + bool PubSubClient::publish(const char* topic, const char* payload, uint8_t qos, bool retained) { return publish(topic, (const uint8_t*)payload, payload ? strnlen(payload, MQTT_MAX_POSSIBLE_PACKET_SIZE) : 0, qos, retained); } diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 04fad5fa..21b40cd2 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -538,6 +538,17 @@ class PubSubClient : public Print { */ bool publish(const __FlashStringHelper* topic, const char* payload, uint8_t qos, bool 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. + */ + bool publish(const __FlashStringHelper* topic, const __FlashStringHelper* payload, uint8_t qos, bool retained); + /** * @brief Publishes a non retained message to the specified topic using QoS 0. * @param topic The topic to publish to. From 2fe356c02b585a01fc044038cb3bba2db7df6ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Thu, 30 Oct 2025 13:23:14 +0100 Subject: [PATCH 14/23] make all only beginPublishImpl / writeStringImpl calling functions inline --- src/PubSubClient.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index d599a930..c5bf6d0d 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -594,10 +594,6 @@ bool PubSubClient::publish_P(const __FlashStringHelper* topic, const uint8_t* pa return false; } -bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained) { - return beginPublish(topic, plength, MQTT_QOS0, retained); -} - /** * @brief Internal beginPublish implementation using topic stored in RAM or PROGMEM. * @@ -642,16 +638,20 @@ bool PubSubClient::beginPublishImpl(bool progmem, const char* topic, size_t plen return false; } -bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { +inline bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained) { + return beginPublishImpl(false, topic, plength, MQTT_QOS0, retained); +} + +inline bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { return beginPublishImpl(false, topic, plength, qos, retained); } -bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { +inline bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { // convert FlashStringHelper in PROGMEM-pointer return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } -bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { +inline bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } @@ -811,7 +811,7 @@ size_t PubSubClient::writeStringImpl(bool progmem, const char* string, size_t po * @param pos Position in the internal buffer to write the string. * @return New position in the internal buffer (pos + 2 + string length), or pos if a buffer overrun would occur or the string is a nullptr. */ -size_t PubSubClient::writeString(const char* string, size_t pos) { +inline size_t PubSubClient::writeString(const char* string, size_t pos) { return writeStringImpl(false, string, pos); } From 02f55f9439fd7271b9db13721f6eeb843f6706bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 2 Nov 2025 08:15:24 +0100 Subject: [PATCH 15/23] fix compiler error: moved public inline functions to header file --- src/PubSubClient.cpp | 17 ----------------- src/PubSubClient.h | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index c5bf6d0d..8269e1e6 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -638,23 +638,6 @@ bool PubSubClient::beginPublishImpl(bool progmem, const char* topic, size_t plen return false; } -inline bool PubSubClient::beginPublish(const char* topic, size_t plength, bool retained) { - return beginPublishImpl(false, topic, plength, MQTT_QOS0, retained); -} - -inline bool PubSubClient::beginPublish(const char* topic, size_t plength, uint8_t qos, bool retained) { - return beginPublishImpl(false, topic, plength, qos, retained); -} - -inline bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { - // convert FlashStringHelper in PROGMEM-pointer - return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); -} - -inline bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { - return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); -} - bool PubSubClient::endPublish() { if (connected()) { if (_bufferWritePos > 0) { diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 21b40cd2..069ea093 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -675,7 +675,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 PubSubClient::beginPublish(const char* topic, size_t plength, bool retained) { + return beginPublishImpl(false, topic, plength, MQTT_QOS0, retained); + } /** * @brief Start to publish a message. @@ -692,7 +694,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, uint8_t qos, bool retained); + inline bool PubSubClient::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(). @@ -709,7 +713,10 @@ 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 __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained); + inline bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { + // convert FlashStringHelper in PROGMEM-pointer + return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); + } /** * @brief Start to publish a message using a topic in PROGMEM. @@ -726,7 +733,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_P(PGM_P topic, size_t plength, uint8_t qos, bool retained); + inline bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { + return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); + } /** * @brief Finish sending a message that was started with a call to beginPublish. From ae7cd3e0a1bb1ced8996fa7dbfd04cbdcf0ee27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 2 Nov 2025 08:18:33 +0100 Subject: [PATCH 16/23] fix compiler error: moved public inline functions to header file --- src/PubSubClient.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 069ea093..35cd1e91 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -675,7 +675,7 @@ class PubSubClient : public Print { * @return true If the publish succeeded. * false If the publish failed, either connection lost or message too large. */ - inline bool PubSubClient::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); } @@ -694,7 +694,7 @@ class PubSubClient : public Print { * @return true If the publish succeeded. * false If the publish failed, either connection lost or message too large. */ - inline bool PubSubClient::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); } @@ -713,7 +713,7 @@ class PubSubClient : public Print { * @return true If the publish succeeded. * false If the publish failed, either connection lost or message too large. */ - inline bool PubSubClient::beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { + inline bool beginPublish(const __FlashStringHelper* topic, size_t plength, uint8_t qos, bool retained) { // convert FlashStringHelper in PROGMEM-pointer return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } @@ -733,7 +733,7 @@ class PubSubClient : public Print { * @return true If the publish succeeded. * false If the publish failed, either connection lost or message too large. */ - inline bool PubSubClient::beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { + inline bool beginPublish_P(PGM_P topic, size_t plength, uint8_t qos, bool retained) { return beginPublishImpl(true, reinterpret_cast(topic), plength, qos, retained); } From 5ea9b745f87fe977c02589dbfdc0a31b3672ed10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 2 Nov 2025 21:08:14 +0100 Subject: [PATCH 17/23] implement write_P(PGM_P string) --- src/PubSubClient.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 35cd1e91..e8f36b1d 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -763,6 +763,17 @@ class PubSubClient : public Print { */ 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(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, From 443097d8b2b911e1a8f877a6fc62e6112812733e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 2 Nov 2025 21:09:02 +0100 Subject: [PATCH 18/23] Initial revision --- examples/mqtt_progmem/platformio.ini | 41 ++++++++++++++++++ examples/mqtt_progmem/src/mqtt_progmem.ino | 48 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 examples/mqtt_progmem/platformio.ini create mode 100755 examples/mqtt_progmem/src/mqtt_progmem.ino diff --git a/examples/mqtt_progmem/platformio.ini b/examples/mqtt_progmem/platformio.ini new file mode 100644 index 00000000..b54f914a --- /dev/null +++ b/examples/mqtt_progmem/platformio.ini @@ -0,0 +1,41 @@ +; 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.2.1 + https://github.com/hmueller01/pubsubclient3.git#implement-fstring-topics +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 diff --git a/examples/mqtt_progmem/src/mqtt_progmem.ino b/examples/mqtt_progmem/src/mqtt_progmem.ino new file mode 100755 index 00000000..04efee1d --- /dev/null +++ b/examples/mqtt_progmem/src/mqtt_progmem.ino @@ -0,0 +1,48 @@ +/* + 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 +#include +#include + +// 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"; + +void callback(char* topic, uint8_t* payload, 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("inTopic"); + } +} + +void loop() { + client.loop(); +} From 1a3b765bee72d298c897f0b5048ec337d458a1c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 2 Nov 2025 21:46:38 +0100 Subject: [PATCH 19/23] fix arduino-cli compile error --- examples/mqtt_progmem/mqtt_progmem.ino | 3 +++ .../mqtt_progmem/src/{mqtt_progmem.ino => mqtt_progmem.cpp} | 0 2 files changed, 3 insertions(+) create mode 100644 examples/mqtt_progmem/mqtt_progmem.ino rename examples/mqtt_progmem/src/{mqtt_progmem.ino => mqtt_progmem.cpp} (100%) mode change 100755 => 100644 diff --git a/examples/mqtt_progmem/mqtt_progmem.ino b/examples/mqtt_progmem/mqtt_progmem.ino new file mode 100644 index 00000000..d75fcb9b --- /dev/null +++ b/examples/mqtt_progmem/mqtt_progmem.ino @@ -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. diff --git a/examples/mqtt_progmem/src/mqtt_progmem.ino b/examples/mqtt_progmem/src/mqtt_progmem.cpp old mode 100755 new mode 100644 similarity index 100% rename from examples/mqtt_progmem/src/mqtt_progmem.ino rename to examples/mqtt_progmem/src/mqtt_progmem.cpp From b7fe4c385d9a866d6a0951dbd53300b117e8c267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Wed, 5 Nov 2025 21:54:43 +0100 Subject: [PATCH 20/23] implemented bool subscribeImpl(bool progmem, ...) and bool unsubscribeImpl(bool progmem, ...) --- src/PubSubClient.cpp | 33 ++++++++++++------ src/PubSubClient.h | 79 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/PubSubClient.cpp b/src/PubSubClient.cpp index 8269e1e6..fc57b5be 100755 --- a/src/PubSubClient.cpp +++ b/src/PubSubClient.cpp @@ -845,15 +845,20 @@ size_t PubSubClient::flushBuffer() { return rc; } -bool PubSubClient::subscribe(const char* topic) { - return subscribe(topic, MQTT_QOS0); -} - -bool PubSubClient::subscribe(const char* topic, uint8_t qos) { +/** + * @brief Internal subscribes to messages published to the specified topic. The topic can be stored in RAM or PROGMEM. + * @param progmem true if the topic is stored in PROGMEM/Flash, false if in RAM. + * @param topic The topic 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. + */ +bool PubSubClient::subscribeImpl(bool progmem, const char* topic, uint8_t qos) { if (!topic) return false; if (qos > MQTT_QOS1) return false; // only QoS 0 and 1 supported - size_t topicLen = strnlen(topic, _bufferSize); + // get topic length depending on storage (RAM vs PROGMEM) + size_t topicLen = progmem ? strnlen_P(topic, _bufferSize) : strnlen(topic, _bufferSize); if (_bufferSize < MQTT_MAX_HEADER_SIZE + 2 + 2 + topicLen + 1) { // Too long: header + nextMsgId (2) + topic length bytes (2) + topicLen + QoS (1) return false; @@ -862,17 +867,25 @@ bool PubSubClient::subscribe(const char* topic, uint8_t qos) { // Leave room in the _buffer for header and variable length field uint16_t length = MQTT_MAX_HEADER_SIZE; length = writeNextMsgId(length); // _buffer size is checked before - length = writeString(topic, length); + length = writeStringImpl(progmem, topic, length); _buffer[length++] = qos; return writeControlPacket(MQTTSUBSCRIBE | MQTT_QOS_GET_HDR(MQTT_QOS1), length - MQTT_MAX_HEADER_SIZE); } return false; } -bool PubSubClient::unsubscribe(const char* topic) { +/** + * @brief Internal unsubscribes from messages published to the specified topic. The topic can be stored in RAM or PROGMEM. + * @param progmem true if the topic is stored in PROGMEM/Flash, false if in RAM. + * @param topic The topic to unsubscribe from. + * @return true If sending the unsubscribe succeeded. + * false If sending the unsubscribe failed, either connection lost or message too large. + */ +bool PubSubClient::unsubscribeImpl(bool progmem, const char* topic) { if (!topic) return false; - size_t topicLen = strnlen(topic, _bufferSize); + // get topic length depending on storage (RAM vs PROGMEM) + size_t topicLen = progmem ? strnlen_P(topic, _bufferSize) : strnlen(topic, _bufferSize); if (_bufferSize < MQTT_MAX_HEADER_SIZE + 2 + 2 + topicLen) { // Too long: header + nextMsgId (2) + topic length bytes (2) + topicLen return false; @@ -880,7 +893,7 @@ bool PubSubClient::unsubscribe(const char* topic) { if (connected()) { uint16_t length = MQTT_MAX_HEADER_SIZE; length = writeNextMsgId(length); // _buffer size is checked before - length = writeString(topic, length); + length = writeStringImpl(progmem, topic, length); return writeControlPacket(MQTTUNSUBSCRIBE | MQTT_QOS_GET_HDR(MQTT_QOS1), length - MQTT_MAX_HEADER_SIZE); } return false; diff --git a/src/PubSubClient.h b/src/PubSubClient.h index e8f36b1d..210e4c6e 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -204,6 +204,8 @@ class PubSubClient : public Print { 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) size_t appendBuffer(uint8_t data); @@ -790,7 +792,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(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(topic), MQTT_QOS0); + } /** * @brief Subscribes to messages published to the specified topic. @@ -799,7 +824,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(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(topic), qos); + } /** * @brief Unsubscribes from the specified topic. @@ -807,7 +857,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(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(topic)); + } /** * @brief This should be called regularly to allow the client to process incoming messages and maintain its connection to the server. From f455953a1016e89d9cfe269cb5cf2da13dd3d4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Thu, 6 Nov 2025 21:08:10 +0100 Subject: [PATCH 21/23] added subscribe examples --- examples/mqtt_progmem/src/mqtt_progmem.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/mqtt_progmem/src/mqtt_progmem.cpp b/examples/mqtt_progmem/src/mqtt_progmem.cpp index 04efee1d..b603f0a0 100644 --- a/examples/mqtt_progmem/src/mqtt_progmem.cpp +++ b/examples/mqtt_progmem/src/mqtt_progmem.cpp @@ -17,6 +17,7 @@ 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(char* topic, uint8_t* payload, size_t plength) { // handle message arrived @@ -36,10 +37,13 @@ void setup() { 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("inTopic"); + + client.subscribe(F("inTopic")); + client.subscribe_P(SUBSCRIBE_TOPIC, MQTT_QOS1); } } From 16768616c545b0c78243564ed334f98bb31f2a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Sun, 9 Nov 2025 22:14:00 +0100 Subject: [PATCH 22/23] tag unused parameter --- examples/mqtt_progmem/src/mqtt_progmem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/mqtt_progmem/src/mqtt_progmem.cpp b/examples/mqtt_progmem/src/mqtt_progmem.cpp index b603f0a0..9088c7ff 100644 --- a/examples/mqtt_progmem/src/mqtt_progmem.cpp +++ b/examples/mqtt_progmem/src/mqtt_progmem.cpp @@ -11,6 +11,8 @@ #include #include +#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); @@ -19,7 +21,7 @@ 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(char* topic, uint8_t* payload, size_t plength) { +void callback(_UNUSED_ char* topic, _UNUSED_ uint8_t* payload, _UNUSED_ size_t plength) { // handle message arrived } From 94a83dfc91200659c10f66fb43f36283547d076c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Mu=CC=88ller?= Date: Mon, 10 Nov 2025 21:50:52 +0100 Subject: [PATCH 23/23] use C++ casting --- src/PubSubClient.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PubSubClient.h b/src/PubSubClient.h index 4534693c..9677d9f4 100755 --- a/src/PubSubClient.h +++ b/src/PubSubClient.h @@ -541,7 +541,7 @@ class PubSubClient : public Print { * false If the publish failed, either connection lost or message too large. */ inline bool publish(const char* topic, const char* payload, uint8_t qos, bool retained) { - return publish(topic, (const uint8_t*)payload, payload ? strlen(payload) : 0, qos, retained); + return publish(topic, reinterpret_cast(payload), payload ? strlen(payload) : 0, qos, retained); } /** @@ -554,7 +554,7 @@ class PubSubClient : public Print { * 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, (const uint8_t*)payload, payload ? strlen(payload) : 0, qos, retained); + return publish(topic, reinterpret_cast(payload), payload ? strlen(payload) : 0, qos, retained); } /** @@ -567,7 +567,7 @@ class PubSubClient : public Print { * 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, (const uint8_t*)payload, payload ? strlen_P(reinterpret_cast(payload)) : 0, qos, retained); + return publish_P(topic, reinterpret_cast(payload), payload ? strlen_P(reinterpret_cast(payload)) : 0, qos, retained); } /** @@ -641,7 +641,7 @@ class PubSubClient : public Print { * false If the publish failed, either connection lost or message too large. */ inline bool publish_P(const char* topic, PGM_P payload, uint8_t qos, bool retained) { - return publish_P(topic, (const uint8_t*)payload, payload ? strlen_P(payload) : 0, qos, retained); + return publish_P(topic, reinterpret_cast(payload), payload ? strlen_P(payload) : 0, qos, retained); } /** @@ -654,7 +654,7 @@ class PubSubClient : public Print { * 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, (const uint8_t*)payload, payload ? strlen_P(payload) : 0, qos, retained); + return publish_P(topic, reinterpret_cast(payload), payload ? strlen_P(payload) : 0, qos, retained); } /**