From a509ceaf81c5a795f786b0b0842a642f9654dba4 Mon Sep 17 00:00:00 2001
From: tyeth <tyethgundry@googlemail.com>
Date: Mon, 27 Jan 2025 16:45:40 +0000
Subject: [PATCH 1/3] Change WS.publish to return bool

---
 platformio.ini                           |  2 +-
 src/Wippersnapper.cpp                    | 43 ++++++++++++++++++------
 src/Wippersnapper.h                      |  2 +-
 src/components/ds18x20/ws_ds18x20.cpp    | 14 +++++---
 src/components/i2c/WipperSnapper_I2C.cpp |  2 +-
 src/components/pixels/ws_pixels.cpp      | 13 +++++--
 6 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/platformio.ini b/platformio.ini
index a9bc5e7e0..421090de2 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -94,7 +94,7 @@ lib_deps =
 
 ; Common build environment for ESP32 platform
 [common:esp32]
-platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
+platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip
 ; This is needed for occasional new features and bug fixes
 ; platform = https://github.com/pioarduino/platform-espressif32#develop
 lib_ignore = WiFiNINA, WiFi101, OneWire
diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp
index 71c525a77..992ff106f 100644
--- a/src/Wippersnapper.cpp
+++ b/src/Wippersnapper.cpp
@@ -558,7 +558,7 @@ void publishI2CResponse(wippersnapper_signal_v1_I2CResponse *msgi2cResponse) {
   pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_I2CResponse_fields,
                       msgi2cResponse);
   WS_DEBUG_PRINT("Publishing Message: I2CResponse...");
-  if (!WS._mqtt->publish(WS._topic_signal_i2c_device, WS._buffer_outgoing,
+  if (!WS.publish(WS._topic_signal_i2c_device, WS._buffer_outgoing,
                          msgSz, 1)) {
     WS_DEBUG_PRINTLN("ERROR: Failed to publish I2C Response!");
   } else {
@@ -995,9 +995,16 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field,
     pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_ServoResponse_fields,
                         &msgServoResp);
     WS_DEBUG_PRINT("-> Servo Attach Response...");
-    WS._mqtt->publish(WS._topic_signal_servo_device, WS._buffer_outgoing, msgSz,
-                      1);
-    WS_DEBUG_PRINTLN("Published!");
+    if (!WS.publish(WS._topic_signal_servo_device, WS._buffer_outgoing, msgSz,
+                           1))
+    {
+      WS_DEBUG_PRINTLN("ERROR: Failed to publish Servo Attach Response!");
+      return false;
+    }
+    else
+    {
+      WS_DEBUG_PRINTLN("Published!");
+    }
   } else if (field->tag ==
              wippersnapper_signal_v1_ServoRequest_servo_write_tag) {
     WS_DEBUG_PRINTLN("GOT: Servo Write");
@@ -1161,12 +1168,12 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) {
     pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_PWMResponse_fields,
                         &msgPWMResponse);
     WS_DEBUG_PRINT("PUBLISHING: PWM Attach Response...");
-    if (!WS._mqtt->publish(WS._topic_signal_pwm_device, WS._buffer_outgoing,
+    if (!WS.publish(WS._topic_signal_pwm_device, WS._buffer_outgoing,
                            msgSz, 1)) {
       WS_DEBUG_PRINTLN("ERROR: Failed to publish PWM Attach Response!");
       return false;
     }
-    WS_DEBUG_PRINTLN("Published!");
+    WS_DEBUG_PRINTLN("Published! (PWM Attach Response)");
 
 #ifdef USE_DISPLAY
     char buffer[100];
@@ -1571,12 +1578,12 @@ bool cbDecodeUARTMessage(pb_istream_t *stream, const pb_field_t *field,
     pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_UARTResponse_fields,
                         &msgUARTResponse);
     WS_DEBUG_PRINT("PUBLISHING: UART Attach Response...");
-    if (!WS._mqtt->publish(WS._topic_signal_uart_device, WS._buffer_outgoing,
+    if (!WS.publish(WS._topic_signal_uart_device, WS._buffer_outgoing,
                            msgSz, 1)) {
       WS_DEBUG_PRINTLN("ERROR: Failed to publish UART Attach Response!");
       return false;
     }
-    WS_DEBUG_PRINTLN("Published!");
+    WS_DEBUG_PRINTLN("Published! (UART Device Attached)");
 
   } else if (field->tag ==
              wippersnapper_signal_v1_UARTRequest_req_uart_device_detach_tag) {
@@ -2653,14 +2660,27 @@ void Wippersnapper::processPackets() {
             The Quality of Service to publish with.
 */
 /*******************************************************/
-void Wippersnapper::publish(const char *topic, uint8_t *payload, uint16_t bLen,
+bool Wippersnapper::publish(const char *topic, uint8_t *payload, uint16_t bLen,
                             uint8_t qos) {
   // runNetFSM(); // NOTE: Removed for now, causes error with virtual _connect
   // method when caused with WS object in another file.
   WS.feedWDT();
-  if (!WS._mqtt->publish(topic, payload, bLen, qos)) {
-    WS_DEBUG_PRINTLN("Failed to publish MQTT message!");
+  bool response = WS._mqtt->publish(topic, payload, bLen, qos);
+  if (!response) {
+    WS_DEBUG_PRINTLN("Failed to publish MQTT message (t: ");
+    WS_DEBUG_PRINT(topic);
+    WS_DEBUG_PRINT(" q: ");
+    WS_DEBUG_PRINT(qos);
+    WS_DEBUG_PRINT(" l: ");
+    WS_DEBUG_PRINT(bLen);
+    WS_DEBUG_PRINT(" hex: ");
+    for (uint16_t i = 0; i < bLen; i++) {
+      WS_DEBUG_PRINTHEX(payload[i]);
+      WS_DEBUG_PRINT(" ");
+    }
+    WS_DEBUG_PRINTLN(")\n");
   }
+  return response;
 }
 
 /**************************************************************/
@@ -2863,6 +2883,7 @@ void Wippersnapper::publishPinConfigComplete() {
   WS_DEBUG_PRINTLN("Publishing to pin config complete...");
   WS.publish(WS._topic_device_pin_config_complete, _message_buffer,
              _message_len, 1);
+  WS_DEBUG_PRINTLN("Published! (pin config complete)");
 }
 
 /**************************************************************************/
diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h
index 7ffe02320..e1b146e9b 100644
--- a/src/Wippersnapper.h
+++ b/src/Wippersnapper.h
@@ -298,7 +298,7 @@ class Wippersnapper {
   // run() loop
   ws_status_t run();
   void processPackets();
-  void publish(const char *topic, uint8_t *payload, uint16_t bLen,
+  bool publish(const char *topic, uint8_t *payload, uint16_t bLen,
                uint8_t qos = 0);
 
   // Networking helpers
diff --git a/src/components/ds18x20/ws_ds18x20.cpp b/src/components/ds18x20/ws_ds18x20.cpp
index 0cfa6e0c5..5752a09ea 100644
--- a/src/components/ds18x20/ws_ds18x20.cpp
+++ b/src/components/ds18x20/ws_ds18x20.cpp
@@ -116,9 +116,15 @@ bool ws_ds18x20::addDS18x20(
   pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_Ds18x20Response_fields,
                       &msgInitResp);
   WS_DEBUG_PRINT("-> DS18x Init Response...");
-  WS._mqtt->publish(WS._topic_signal_ds18_device, WS._buffer_outgoing, msgSz,
-                    1);
-  WS_DEBUG_PRINTLN("Published!");
+  if (!WS.publish(WS._topic_signal_ds18_device, WS._buffer_outgoing, msgSz,
+                         1))
+  {
+    WS_DEBUG_PRINTLN("ERROR: Unable to publish DS18x20 init response message - check MQTT connection!");
+  }
+  else
+  {
+    WS_DEBUG_PRINTLN("Published! (Ds18x20 Init Response)");
+  }
 
   return is_success;
 }
@@ -294,7 +300,7 @@ void ws_ds18x20::update() {
                               wippersnapper_signal_v1_Ds18x20Response_fields,
                               &msgDS18x20Response);
           WS_DEBUG_PRINT("PUBLISHING -> msgDS18x20Response Event Message...");
-          if (!WS._mqtt->publish(WS._topic_signal_ds18_device,
+          if (!WS.publish(WS._topic_signal_ds18_device,
                                  WS._buffer_outgoing, msgSz, 1)) {
             WS_DEBUG_PRINTLN("ERROR: Unable to publish DS18x20 event message - "
                              "MQTT Publish failed!");
diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp
index dfae4db42..376c3a108 100644
--- a/src/components/i2c/WipperSnapper_I2C.cpp
+++ b/src/components/i2c/WipperSnapper_I2C.cpp
@@ -910,7 +910,7 @@ bool WipperSnapper_Component_I2C::encodePublishI2CDeviceEventMsg(
   pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_I2CResponse_fields,
                       msgi2cResponse);
   WS_DEBUG_PRINT("PUBLISHING -> I2C Device Sensor Event Message...");
-  if (!WS._mqtt->publish(WS._topic_signal_i2c_device, WS._buffer_outgoing,
+  if (!WS.publish(WS._topic_signal_i2c_device, WS._buffer_outgoing,
                          msgSz, 1)) {
     WS_DEBUG_PRINTLN("ERROR: MQTT Publish failed!");
     return false;
diff --git a/src/components/pixels/ws_pixels.cpp b/src/components/pixels/ws_pixels.cpp
index a35eb6e42..180d0b426 100644
--- a/src/components/pixels/ws_pixels.cpp
+++ b/src/components/pixels/ws_pixels.cpp
@@ -182,9 +182,16 @@ void ws_pixels::publishAddStrandResponse(bool is_success,
   pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_PixelsResponse_fields,
                       &msgInitResp);
   WS_DEBUG_PRINT("-> wippersnapper_signal_v1_PixelsResponse...");
-  WS._mqtt->publish(WS._topic_signal_pixels_device, WS._buffer_outgoing, msgSz,
-                    1);
-  WS_DEBUG_PRINTLN("Published!");
+  if (!WS.publish(WS._topic_signal_pixels_device, WS._buffer_outgoing, msgSz,
+                         1))
+  {
+    WS_DEBUG_PRINTLN("ERROR: Unable to publish PixelsResponse message - "
+                     "check MQTT connection!");
+  }
+  else
+  {
+    WS_DEBUG_PRINTLN("Published! (PixelsResponse)");
+  }
 }
 
 /**************************************************************************/

From ad1e7e18ef767d0b0ea96ee67542574a1ce2ec09 Mon Sep 17 00:00:00 2001
From: tyeth <tyethgundry@googlemail.com>
Date: Mon, 27 Jan 2025 17:05:26 +0000
Subject: [PATCH 2/3] WIP: print info on publishes

---
 src/Wippersnapper.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp
index 992ff106f..b74c7e6c0 100644
--- a/src/Wippersnapper.cpp
+++ b/src/Wippersnapper.cpp
@@ -2664,6 +2664,19 @@ bool Wippersnapper::publish(const char *topic, uint8_t *payload, uint16_t bLen,
                             uint8_t qos) {
   // runNetFSM(); // NOTE: Removed for now, causes error with virtual _connect
   // method when caused with WS object in another file.
+#ifdef ARDUINO_ARCH_ESP32
+// print stack and heap usage
+  WS_DEBUG_PRINT("Free Heap: ");
+  WS_DEBUG_PRINTLN(ESP.getFreeHeap());
+  WS_DEBUG_PRINT("Min Free Heap: ");
+  WS_DEBUG_PRINTLN(ESP.getMinFreeHeap());
+  WS_DEBUG_PRINT("Max Alloc Heap: ");
+  WS_DEBUG_PRINTLN(ESP.getMaxAllocHeap());
+  WS_DEBUG_PRINT("Heap Size: ");
+  WS_DEBUG_PRINTLN(ESP.getHeapSize());
+  WS_DEBUG_PRINT("Free Stack: ");
+  WS_DEBUG_PRINTLN(uxTaskGetStackHighWaterMark(NULL));
+#endif
   WS.feedWDT();
   bool response = WS._mqtt->publish(topic, payload, bLen, qos);
   if (!response) {

From 13628f771ad9b8ec2c52e5cb01296027b8792d12 Mon Sep 17 00:00:00 2001
From: tyeth <tyethgundry@googlemail.com>
Date: Mon, 27 Jan 2025 17:31:31 +0000
Subject: [PATCH 3/3] WIP: Log all publish failures

---
 src/Wippersnapper.cpp                         | 14 +++++++++----
 .../analogIO/Wippersnapper_AnalogIO.cpp       |  5 ++++-
 .../digitalIO/Wippersnapper_DigitalGPIO.cpp   | 17 ++++++++++++----
 .../register/Wippersnapper_Register.cpp       | 20 +++++++++++++------
 4 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp
index b74c7e6c0..07b54404f 100644
--- a/src/Wippersnapper.cpp
+++ b/src/Wippersnapper.cpp
@@ -2666,7 +2666,7 @@ bool Wippersnapper::publish(const char *topic, uint8_t *payload, uint16_t bLen,
   // method when caused with WS object in another file.
 #ifdef ARDUINO_ARCH_ESP32
 // print stack and heap usage
-  WS_DEBUG_PRINT("Free Heap: ");
+  WS_DEBUG_PRINT("\nFree Heap: ");
   WS_DEBUG_PRINTLN(ESP.getFreeHeap());
   WS_DEBUG_PRINT("Min Free Heap: ");
   WS_DEBUG_PRINTLN(ESP.getMinFreeHeap());
@@ -2894,9 +2894,15 @@ void Wippersnapper::publishPinConfigComplete() {
 
   // Publish message
   WS_DEBUG_PRINTLN("Publishing to pin config complete...");
-  WS.publish(WS._topic_device_pin_config_complete, _message_buffer,
-             _message_len, 1);
-  WS_DEBUG_PRINTLN("Published! (pin config complete)");
+  if (WS.publish(WS._topic_device_pin_config_complete, _message_buffer,
+                 _message_len, 1))
+  {
+    WS_DEBUG_PRINTLN("Published! (pin config complete)");
+  }
+  else
+  {
+    WS_DEBUG_PRINTLN("Failed to publish! (pin config complete)");
+  }
 }
 
 /**************************************************************************/
diff --git a/src/components/analogIO/Wippersnapper_AnalogIO.cpp b/src/components/analogIO/Wippersnapper_AnalogIO.cpp
index 0a887558d..8f4ebb22e 100644
--- a/src/components/analogIO/Wippersnapper_AnalogIO.cpp
+++ b/src/components/analogIO/Wippersnapper_AnalogIO.cpp
@@ -305,7 +305,10 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
                       wippersnapper_signal_v1_CreateSignalRequest_fields,
                       &outgoingSignalMsg);
   WS_DEBUG_PRINT("Publishing pinEvent...");
-  WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1);
+  if(!WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1)) {
+    WS_DEBUG_PRINTLN("ERROR: Unable to publish analogIO pin event message");
+    return false;
+  }
   WS_DEBUG_PRINTLN("Published!");
 
   return true;
diff --git a/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp b/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp
index f3ab478d9..83e5fef0c 100644
--- a/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp
+++ b/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp
@@ -276,8 +276,11 @@ void Wippersnapper_DigitalGPIO::processDigitalInputs() {
                             &_outgoingSignalMsg);
 
         WS_DEBUG_PRINT("Publishing pinEvent...");
-        WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1);
-        WS_DEBUG_PRINTLN("Published!");
+        if (!WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1)){
+          WS_DEBUG_PRINTLN("ERROR: Unable to publish DigitalIO pinEvent");
+        } else {
+          WS_DEBUG_PRINTLN("Published! (DigitalIO PinEvent)");
+        }
 
         // reset the digital pin
         _digital_input_pins[i].prvPeriod = curTime;
@@ -315,8 +318,14 @@ void Wippersnapper_DigitalGPIO::processDigitalInputs() {
               &msgSz, wippersnapper_signal_v1_CreateSignalRequest_fields,
               &_outgoingSignalMsg);
           WS_DEBUG_PRINT("Publishing pinEvent...");
-          WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1);
-          WS_DEBUG_PRINTLN("Published!");
+          if (!WS.publish(WS._topic_signal_device, WS._buffer_outgoing, msgSz, 1))
+          {
+            WS_DEBUG_PRINTLN("ERROR: Unable to publish DigitalIO pinEvent");
+          }
+          else
+          {
+            WS_DEBUG_PRINTLN("Published! (DigitalIO PinEvent)");
+          }
 
           // set the pin value in the digital pin object for comparison on next
           // run
diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp
index 522818997..ad64bcdba 100644
--- a/src/components/register/Wippersnapper_Register.cpp
+++ b/src/components/register/Wippersnapper_Register.cpp
@@ -56,8 +56,11 @@ bool Wippersnapper::encodePubRegistrationReq() {
     return _status;
 
   // pubish message
-  WS.publish(WS._topic_description, _message_buffer, _message_len, 1);
-  WS_DEBUG_PRINTLN("Published!");
+  if (!WS.publish(WS._topic_description, _message_buffer, _message_len, 1)){
+    WS_DEBUG_PRINTLN("ERROR: Unable to publish registration message");
+  } else {
+    WS_DEBUG_PRINTLN("Published! (Registration)");
+  }
   WS._boardStatus = WS_BOARD_DEF_SENT;
 
   return _status;
@@ -153,10 +156,15 @@ void Wippersnapper::decodeRegistrationResp(char *data, uint16_t len) {
     }
 
     // Publish message
-    WS.publish(_topic_description_status_complete, _message_buffer,
-               _message_len, 1);
-    WS_DEBUG_PRINTLN("Completed registration process, configuration next!");
-
+    if (WS.publish(_topic_description_status_complete, _message_buffer,
+                   _message_len, 1))
+    {
+      WS_DEBUG_PRINTLN("Completed registration process, configuration next!");
+    }
+    else
+    {
+      WS_DEBUG_PRINTLN("ERROR: Unable to publish registration complete message");
+    }
   } else {
     WS._boardStatus = WS_BOARD_DEF_INVALID;
   }