Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/ActuatorArduinoPin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Pins.h"
#include "ActuatorArduinoPin.h"
#include "Display.h"
#include "EepromManager.h" // for extendedSettings


void DigitalPinActuator::setActive(bool active_setting) {
Expand All @@ -11,10 +12,11 @@ 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.init();
display.reset();
display.printAll();
}

Expand Down
18 changes: 18 additions & 0 deletions src/EepromStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ void ExtendedSettings::setDefaults() {
invertTFT = false;
glycol = false;
largeTFT = false;
resetScreenOnPin = false;
#ifdef HAS_BLUETOOTH
tiltGravSensor = NoTiltDevice;
#endif
Expand All @@ -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
Expand Down Expand Up @@ -331,6 +333,7 @@ void ExtendedSettings::loadFromFilesystem() {
if(json_doc[ExtendedSettingsKeys::invertTFT].is<bool>()) invertTFT = json_doc[ExtendedSettingsKeys::invertTFT];
if(json_doc[ExtendedSettingsKeys::glycol].is<bool>()) glycol = json_doc[ExtendedSettingsKeys::glycol];
if(json_doc[ExtendedSettingsKeys::largeTFT].is<bool>()) largeTFT = json_doc[ExtendedSettingsKeys::largeTFT];
if(json_doc[ExtendedSettingsKeys::resetScreenOnPin].is<bool>()) 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<std::string>()) tiltGravSensor = NimBLEAddress(json_doc[ExtendedSettingsKeys::tiltGravSensor].as<std::string>(), 1);
Expand Down Expand Up @@ -359,6 +362,8 @@ void ExtendedSettings::processSettingKeypair(JsonPair kv) {
setGlycol(kv.value().as<bool>());
} else if (kv.key() == ExtendedSettingsKeys::largeTFT) {
setLargeTFT(kv.value().as<bool>());
} else if (kv.key() == ExtendedSettingsKeys::resetScreenOnPin) {
setResetScreenOnPin(kv.value().as<bool>());
}
#ifdef HAS_BLUETOOTH
else if (kv.key() == ExtendedSettingsKeys::tiltGravSensor) {
Expand Down Expand Up @@ -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
/**
Expand Down
2 changes: 2 additions & 0 deletions src/EepromStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class ExtendedSettings : public JSONSaveable {
bool invertTFT; //<! Whether or not to invert the TFT
bool largeTFT; //<! Whether or not to use a large TFT
bool glycol; //<! Whether or not to use glycol mode
bool resetScreenOnPin; //<! Whether or not to reset the screen when an ActuatorArduinoPin toggles

#ifdef HAS_BLUETOOTH
NimBLEAddress tiltGravSensor; //<! The color of the Tilt hydrometer used for gravity
Expand All @@ -222,6 +223,7 @@ class ExtendedSettings : public JSONSaveable {
void setGlycol(bool setting);
void setInvertTFT(bool setting);
void setLargeTFT(bool setting);
void setResetScreenOnPin(bool setting);

/**
* \brief Filename used when reading/writing data to flash
Expand Down
1 change: 1 addition & 0 deletions src/JsonKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ constexpr auto eepromReset = "confirmReset";
constexpr auto invertTFT = "invertTFT";
constexpr auto glycol = "glycol";
constexpr auto largeTFT = "largeTFT";
constexpr auto resetScreenOnPin = "resetScreenOnPin";
constexpr auto tiltGravSensor = "tiltGravSensor";
}; // namespace ExtendedSettingsKeys

Expand Down
6 changes: 6 additions & 0 deletions src/displays/DisplayLcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/displays/DisplayLcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/displays/DisplayTFT_ILI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/displays/DisplayTFT_ILI.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class LcdDisplay
~LcdDisplay();
// initializes the lcd display
void init();
void reset();

void printAll()
{
Expand Down
6 changes: 6 additions & 0 deletions src/displays/DisplayTFT_eSPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/displays/DisplayTFT_eSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class LcdDisplay
~LcdDisplay();
// initializes the lcd display
void init();
void reset();

void printAll()
{
Expand Down
195 changes: 98 additions & 97 deletions src/extended_async_json_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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<JsonObject>();
// Parse the JSON payload
JsonDocument doc;
doc = json.as<JsonObject>();

// 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

Expand Down
Loading