From 48d398ef23a827b2cae3ca779ac14bb621494c59 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 1 Mar 2025 16:41:27 -0500 Subject: [PATCH 1/4] Create reset() function for each display type This creates a function which can be used when the screen is explicitly being reset rather than being initialized, e.g. when a relay pin is toggled --- src/ActuatorArduinoPin.cpp | 2 +- src/displays/DisplayLcd.cpp | 6 ++++++ src/displays/DisplayLcd.h | 1 + src/displays/DisplayTFT_ILI.cpp | 5 +++++ src/displays/DisplayTFT_ILI.h | 1 + src/displays/DisplayTFT_eSPI.cpp | 6 ++++++ src/displays/DisplayTFT_eSPI.h | 1 + 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ActuatorArduinoPin.cpp b/src/ActuatorArduinoPin.cpp index 6c647bd..15c8bc2 100644 --- a/src/ActuatorArduinoPin.cpp +++ b/src/ActuatorArduinoPin.cpp @@ -14,7 +14,7 @@ void DigitalPinActuator::setActive(bool active_setting) { if (oldActive != active) { // We toggled one of the pins, which can cause issues for the display. Delay slightly to let everything settle down, then reinit the display delay(100); - display.init(); + display.reset(); display.printAll(); } diff --git a/src/displays/DisplayLcd.cpp b/src/displays/DisplayLcd.cpp index 6d49871..1c106ef 100644 --- a/src/displays/DisplayLcd.cpp +++ b/src/displays/DisplayLcd.cpp @@ -89,6 +89,12 @@ void LcdDisplay::init(){ lcd.clear(); } +void LcdDisplay::reset(){ + // This is called whenever the screen is reset when a relay pin toggles. + // For now, just call init() + init(); +} + #ifndef UINT16_MAX #define UINT16_MAX 65535 #endif diff --git a/src/displays/DisplayLcd.h b/src/displays/DisplayLcd.h index 1fb6b59..0ba9684 100644 --- a/src/displays/DisplayLcd.h +++ b/src/displays/DisplayLcd.h @@ -58,6 +58,7 @@ class LcdDisplay DISPLAY_SUPERCLASS public: // initializes the lcd display DISPLAY_METHOD void init(); + DISPLAY_METHOD void reset(); /** * Print all display content diff --git a/src/displays/DisplayTFT_ILI.cpp b/src/displays/DisplayTFT_ILI.cpp index 726331b..b2f77c0 100644 --- a/src/displays/DisplayTFT_ILI.cpp +++ b/src/displays/DisplayTFT_ILI.cpp @@ -123,7 +123,12 @@ void LcdDisplay::init(){ pinMode(TFT_BACKLIGHT, OUTPUT); digitalWrite(TFT_BACKLIGHT, HIGH); #endif +} +void LcdDisplay::reset(){ + // This is called whenever the screen is reset when a relay pin toggles. + // For now, just call init() + init(); } #ifndef UINT16_MAX diff --git a/src/displays/DisplayTFT_ILI.h b/src/displays/DisplayTFT_ILI.h index 3b399f4..518d40f 100644 --- a/src/displays/DisplayTFT_ILI.h +++ b/src/displays/DisplayTFT_ILI.h @@ -99,6 +99,7 @@ class LcdDisplay ~LcdDisplay(); // initializes the lcd display void init(); + void reset(); void printAll() { diff --git a/src/displays/DisplayTFT_eSPI.cpp b/src/displays/DisplayTFT_eSPI.cpp index 998268c..f6d2296 100644 --- a/src/displays/DisplayTFT_eSPI.cpp +++ b/src/displays/DisplayTFT_eSPI.cpp @@ -125,6 +125,12 @@ void LcdDisplay::init() { } +void LcdDisplay::reset() { + // This is called whenever the screen is reset when a relay pin toggles. + // For now, just call init() + init(); +} + #ifndef UINT16_MAX #define UINT16_MAX 65535 #endif diff --git a/src/displays/DisplayTFT_eSPI.h b/src/displays/DisplayTFT_eSPI.h index 0466817..ad058b0 100644 --- a/src/displays/DisplayTFT_eSPI.h +++ b/src/displays/DisplayTFT_eSPI.h @@ -28,6 +28,7 @@ class LcdDisplay ~LcdDisplay(); // initializes the lcd display void init(); + void reset(); void printAll() { From 0df545273daf9fb02ae31d46ddd95c4d1d8c67e6 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 1 Mar 2025 16:42:53 -0500 Subject: [PATCH 2/4] Add option to enable/disable resetting on pin toggle (Closes #123) --- src/ActuatorArduinoPin.cpp | 6 ++++-- src/EepromStructs.cpp | 18 ++++++++++++++++++ src/EepromStructs.h | 2 ++ src/JsonKeys.h | 1 + src/http_server.cpp | 14 +++++++++++++- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/ActuatorArduinoPin.cpp b/src/ActuatorArduinoPin.cpp index 15c8bc2..232f211 100644 --- a/src/ActuatorArduinoPin.cpp +++ b/src/ActuatorArduinoPin.cpp @@ -3,6 +3,7 @@ #include "Pins.h" #include "ActuatorArduinoPin.h" #include "Display.h" +#include "EepromManager.h" // for extendedSettings void DigitalPinActuator::setActive(bool active_setting) { @@ -11,8 +12,9 @@ void DigitalPinActuator::setActive(bool active_setting) { this->active = active_setting; digitalWrite(pin, active_setting^invert ? HIGH : LOW); - if (oldActive != active) { - // We toggled one of the pins, which can cause issues for the display. Delay slightly to let everything settle down, then reinit the display + if (oldActive != active && extendedSettings.resetScreenOnPin) { + // We toggled one of the pins, which can cause issues for the display. + // Delay slightly to let everything settle down, then reinit the display delay(100); display.reset(); display.printAll(); diff --git a/src/EepromStructs.cpp b/src/EepromStructs.cpp index 3ff8749..0f56d5b 100644 --- a/src/EepromStructs.cpp +++ b/src/EepromStructs.cpp @@ -286,6 +286,7 @@ void ExtendedSettings::setDefaults() { invertTFT = false; glycol = false; largeTFT = false; + resetScreenOnPin = false; #ifdef HAS_BLUETOOTH tiltGravSensor = NoTiltDevice; #endif @@ -301,6 +302,7 @@ void ExtendedSettings::toJson(JsonDocument &doc) { doc[ExtendedSettingsKeys::invertTFT] = invertTFT; doc[ExtendedSettingsKeys::glycol] = glycol; doc[ExtendedSettingsKeys::largeTFT] = largeTFT; + doc[ExtendedSettingsKeys::resetScreenOnPin] = resetScreenOnPin; #ifdef HAS_BLUETOOTH doc[ExtendedSettingsKeys::tiltGravSensor] = tiltGravSensor.toString(); #endif @@ -331,6 +333,7 @@ void ExtendedSettings::loadFromFilesystem() { if(json_doc[ExtendedSettingsKeys::invertTFT].is()) invertTFT = json_doc[ExtendedSettingsKeys::invertTFT]; if(json_doc[ExtendedSettingsKeys::glycol].is()) glycol = json_doc[ExtendedSettingsKeys::glycol]; if(json_doc[ExtendedSettingsKeys::largeTFT].is()) largeTFT = json_doc[ExtendedSettingsKeys::largeTFT]; + if(json_doc[ExtendedSettingsKeys::resetScreenOnPin].is()) resetScreenOnPin = json_doc[ExtendedSettingsKeys::resetScreenOnPin]; #ifdef HAS_BLUETOOTH // Tilts use address type 1 ("random", which (correctly!) indicates they didn't buy a MAC block) if(json_doc[ExtendedSettingsKeys::tiltGravSensor].is()) tiltGravSensor = NimBLEAddress(json_doc[ExtendedSettingsKeys::tiltGravSensor].as(), 1); @@ -359,6 +362,8 @@ void ExtendedSettings::processSettingKeypair(JsonPair kv) { setGlycol(kv.value().as()); } else if (kv.key() == ExtendedSettingsKeys::largeTFT) { setLargeTFT(kv.value().as()); + } else if (kv.key() == ExtendedSettingsKeys::resetScreenOnPin) { + setResetScreenOnPin(kv.value().as()); } #ifdef HAS_BLUETOOTH else if (kv.key() == ExtendedSettingsKeys::tiltGravSensor) { @@ -409,6 +414,19 @@ void ExtendedSettings::setInvertTFT(bool setting) { display.printState(); } +/** + * \brief Set if the screen should be reset when an ArduinoActuatorPin (ie. relay) toggles + * + * \param setting - The new setting + */ +void ExtendedSettings::setResetScreenOnPin(bool setting) { + resetScreenOnPin = setting; + + // The only thing we must do here is change the setting, but we'll reinit the screen as well + // in case the user is enabling this as a result of their screen being frozen + if(setting) + display.printAll(); +} #ifdef HAS_BLUETOOTH /** diff --git a/src/EepromStructs.h b/src/EepromStructs.h index 46b780c..69ad92f 100644 --- a/src/EepromStructs.h +++ b/src/EepromStructs.h @@ -206,6 +206,7 @@ class ExtendedSettings : public JSONSaveable { bool invertTFT; //()) { + if(extendedSettings.resetScreenOnPin != json[ExtendedSettingsKeys::resetScreenOnPin].as()) { + extendedSettings.setResetScreenOnPin(json[ExtendedSettingsKeys::resetScreenOnPin].as()); + saveSettings = true; + } + } else { + Log.warning(F("Invalid [resetScreenOnPin]:(%s) received (wrong type).\r\n"), json[ExtendedSettingsKeys::resetScreenOnPin]); + failCount++; + } + #ifdef HAS_BLUETOOTH // Tilt Gravity Sensor From e65e094bd85911c1a82d1650bd7e40099905b353 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 1 Mar 2025 16:43:11 -0500 Subject: [PATCH 3/4] Clean up unused variables --- src/rest/rest_processing.cpp | 3 ++- src/rest/rest_send.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rest/rest_processing.cpp b/src/rest/rest_processing.cpp index 84e1ca3..dfcee36 100644 --- a/src/rest/rest_processing.cpp +++ b/src/rest/rest_processing.cpp @@ -247,7 +247,8 @@ void restHandler::load_devices_from_array(JsonArray &root) { // serializeJsonPretty(kv, Serial); // Print the received JSON to the console // piLink.receiveJsonMessage(doc); // Read the JSON off the line from the Pi dev = DeviceManager::readJsonIntoDeviceDef(kv); // Parse the JSON into a DeviceDefinition object - DeviceConfig print = deviceManager.updateDeviceDefinition(dev); // Save the device definition (if valid) + /*DeviceConfig print =*/ + deviceManager.updateDeviceDefinition(dev); // Save the device definition (if valid) Log.verboseln("\r\nProcessed device."); } } \ No newline at end of file diff --git a/src/rest/rest_send.cpp b/src/rest/rest_send.cpp index c348e85..a10d7ed 100644 --- a/src/rest/rest_send.cpp +++ b/src/rest/rest_send.cpp @@ -186,7 +186,6 @@ bool restHandler::send_bluetooth_crash_report() { String payload; { JsonDocument doc; - const char *url; char guid[20]; getGuid(guid); From b1ee9f08ac411108013bd5d6c79725a64b01840f Mon Sep 17 00:00:00 2001 From: John Date: Sun, 2 Mar 2025 13:57:57 -0500 Subject: [PATCH 4/4] Clean up file formatting --- src/extended_async_json_handler.h | 195 +++++++++++++++--------------- 1 file changed, 98 insertions(+), 97 deletions(-) diff --git a/src/extended_async_json_handler.h b/src/extended_async_json_handler.h index ff66436..9026de0 100644 --- a/src/extended_async_json_handler.h +++ b/src/extended_async_json_handler.h @@ -10,25 +10,26 @@ #if ASYNC_JSON_SUPPORT == 1 -/** - * @class PutAsyncCallbackJsonWebHandler - * @brief Extends AsyncCallbackJsonWebHandler to support custom JSON request handling for HTTP PUT. - * - * This class provides the ability to process incoming PUT requests in an `AsyncWebServer` - * using a user-defined handler function. The handler processes the JSON payload and returns - * a success or failure response based on its logic. - */ - class PutAsyncCallbackJsonWebHandler : public AsyncCallbackJsonWebHandler { - protected: + /** + * @class PutAsyncCallbackJsonWebHandler + * @brief Extends AsyncCallbackJsonWebHandler to support custom JSON request handling for HTTP PUT. + * + * This class provides the ability to process incoming PUT requests in an `AsyncWebServer` + * using a user-defined handler function. The handler processes the JSON payload and returns + * a success or failure response based on its logic. + */ + class PutAsyncCallbackJsonWebHandler : public AsyncCallbackJsonWebHandler + { + protected: /** * @brief Pointer to the custom handler function. * * The custom handler function processes the JSON payload and determines whether the * request should be considered successful or not. */ - bool (*_customHandler)(const JsonDocument&, bool); + bool (*_customHandler)(const JsonDocument &, bool); - public: + public: /** * @brief Constructor for PutAsyncCallbackJsonWebHandler. * @@ -41,94 +42,94 @@ * the handler is not provided or fails, an appropriate HTTP response will be sent to the client. */ PutAsyncCallbackJsonWebHandler( - const char* uri, - bool (*customHandler)(const JsonDocument&, bool) = nullptr) - : AsyncCallbackJsonWebHandler( - uri, - [customHandler](AsyncWebServerRequest* request, JsonVariant& json) { - if (!customHandler) { - request->send(500, "application/json", "{\"error\":\"No handler provided\"}"); - return; - } + const char *uri, bool (*customHandler)(const JsonDocument &, bool) = nullptr) + : AsyncCallbackJsonWebHandler( + uri, [customHandler](AsyncWebServerRequest *request, JsonVariant &json) + { + if (!customHandler) { + request->send(500, "application/json", "{\"error\":\"No handler provided\"}"); + return; + } - // Parse the JSON payload - JsonDocument doc; - doc = json.as(); + // Parse the JSON payload + JsonDocument doc; + doc = json.as(); - // Call the handler - if (customHandler(doc, true)) { - request->send(200, "application/json", "{\"status\":\"ok\"}"); - } else { - request->send(400, "application/json", "{\"status\":\"error\"}"); - } - }), - _customHandler(customHandler) { - setMethod(HTTP_PUT); - } + // Call the handler + if (customHandler(doc, true)) { + request->send(200, "application/json", "{\"status\":\"ok\"}"); + } else { + request->send(400, "application/json", "{\"status\":\"error\"}"); + } + }), + _customHandler(customHandler) + { + setMethod(HTTP_PUT); + } + }; + + /** + * @class GetAsyncCallbackJsonWebHandler + * @brief Extends AsyncCallbackJsonWebHandler to support custom JSON response handling for HTTP GET. + * + * This class provides the ability to process incoming GET requests in an `AsyncWebServer` + * using a user-defined handler function that generates and returns JSON data. + */ + class GetAsyncCallbackJsonWebHandler : public AsyncCallbackJsonWebHandler + { + protected: + /** + * @brief Pointer to the custom handler function. + * + * The custom handler function generates JSON data to be sent in the response. + * It accepts a `JsonDocument` reference which it populates with the response data. + */ + void (*_customHandler)(JsonDocument &); + + public: + /** + * @brief Constructor for GetAsyncCallbackJsonWebHandler. + * + * @param uri The URI to handle. + * @param customHandler A pointer to the custom handler function. The function must accept + * a `JsonDocument` reference and populate it with the response data. + * + * The custom handler function will be invoked for each GET request to the specified URI. + * If the handler is not provided, an appropriate HTTP response will be sent to the client. + */ + GetAsyncCallbackJsonWebHandler( + const char *uri, + void (*customHandler)(JsonDocument &) = nullptr) + : AsyncCallbackJsonWebHandler( + uri, + [customHandler](AsyncWebServerRequest *request, JsonVariant &json) + { + if (!customHandler) { + request->send(500, "application/json", "{\"error\":\"No handler provided\"}"); + return; + } + + AsyncJsonResponse *response = new AsyncJsonResponse(); + { + JsonDocument doc; + customHandler(doc); + + // // Print the contents of doc to the serial console + // Serial.println(F("Generated JSON:")); + // serializeJsonPretty(doc, Serial); // Pretty print for easier reading + // Serial.println(); // Add a newline for better formatting + + response->getRoot().set(doc); + } + + response->setLength(); + request->send(response); + }), + _customHandler(customHandler) + { + setMethod(HTTP_GET); + } }; - - -/** - * @class GetAsyncCallbackJsonWebHandler - * @brief Extends AsyncCallbackJsonWebHandler to support custom JSON response handling for HTTP GET. - * - * This class provides the ability to process incoming GET requests in an `AsyncWebServer` - * using a user-defined handler function that generates and returns JSON data. - */ -class GetAsyncCallbackJsonWebHandler : public AsyncCallbackJsonWebHandler { - protected: - /** - * @brief Pointer to the custom handler function. - * - * The custom handler function generates JSON data to be sent in the response. - * It accepts a `JsonDocument` reference which it populates with the response data. - */ - void (*_customHandler)(JsonDocument&); - - public: - /** - * @brief Constructor for GetAsyncCallbackJsonWebHandler. - * - * @param uri The URI to handle. - * @param customHandler A pointer to the custom handler function. The function must accept - * a `JsonDocument` reference and populate it with the response data. - * - * The custom handler function will be invoked for each GET request to the specified URI. - * If the handler is not provided, an appropriate HTTP response will be sent to the client. - */ - GetAsyncCallbackJsonWebHandler( - const char* uri, - void (*customHandler)(JsonDocument&) = nullptr) - : AsyncCallbackJsonWebHandler( - uri, - [customHandler](AsyncWebServerRequest* request, JsonVariant& json) { - if (!customHandler) { - request->send(500, "application/json", "{\"error\":\"No handler provided\"}"); - return; - } - - AsyncJsonResponse *response = new AsyncJsonResponse(); - { - JsonDocument doc; - customHandler(doc); - - // // Print the contents of doc to the serial console - // Serial.println(F("Generated JSON:")); - // serializeJsonPretty(doc, Serial); // Pretty print for easier reading - // Serial.println(); // Add a newline for better formatting - - response->getRoot().set(doc); - } - - response->setLength(); - request->send(response); - - }), - _customHandler(customHandler) { - setMethod(HTTP_GET); - } - - }; #endif // ASYNC_JSON_SUPPORT == 1