Skip to content

Commit

Permalink
Merge pull request #655 from SignalK/button_ui
Browse files Browse the repository at this point in the history
Button Handler
  • Loading branch information
mairas authored Jun 18, 2023
2 parents 1fd7cec + 5782227 commit 6e9d775
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 1 deletion.
23 changes: 23 additions & 0 deletions docs/pages/features/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ nav_order: 40

# Features

## Button Handling

Commonly used ESP32 devices such as the [SH-ESP32](https://docs.hatlabs.fi/sh-esp32/) or the DevKitC variants have a press button on the GPIO pin 0. SensESP by default recognizes the following button presses:

- Short press (less than 1 second): Restart the device
- Long press (more than 1 second): Reset the network settings
- Very long press (more than 5 seconds): Reset the device to factory settings

If you want to use a different pin for the button, add the following line to the Builder section in main.cpp, before the `->get_app()` instruction:

```c++
->set_button_pin(15)
```
where the new button GPIO would be 15 in this example.
If you want to disable the button handling completely, add the following line to the Builder section in main.cpp, before the `->get_app()` instruction:
```c++
->set_button_pin(-1)
```

It is also possible to define completely custom button behavior by disabling the default button as above and then adding your own button handler class that inherits from `BaseButtonHandler` or `MinimalButtonHandler`.

## OTA updates

Activating Over The Air (OTA) updates, requires a 2 Step setup:
Expand Down
5 changes: 5 additions & 0 deletions library.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
{
"name": "RemoteDebug",
"version": "https://github.com/JoaoLopesF/RemoteDebug.git#0b5a9c1a49fd2ade0e3cadc3a3707781e819359a"
},
{
"owner": "bxparks",
"name": "AceButton",
"version": "^1.10.1"
}
],
"version": "2.6.1-alpha",
Expand Down
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ lib_deps =
bblanchon/ArduinoJson
links2004/WebSockets
pfeerick/elapsedMillis
bxparks/AceButton @ ^1.10.1
https://github.com/JoaoLopesF/RemoteDebug.git#0b5a9c1a49fd2ade0e3cadc3a3707781e819359a

[espressif32_base]
Expand Down
47 changes: 47 additions & 0 deletions src/sensesp/system/base_button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef SENSESP_SRC_SENSESP_SYSTEM_BASE_BUTTON_H_
#define SENSESP_SRC_SENSESP_SYSTEM_BASE_BUTTON_H_

#include "AceButton.h"
#include "elapsedMillis.h"
#include "sensesp.h"
#include "sensesp/system/configurable.h"
#include "sensesp/system/startable.h"
#include "sensesp_base_app.h"

namespace sensesp {

using namespace ace_button;

/**
* @brief Base class for button handlers.
*
* Button handlers are used to handle button presses. This is an abstract base
* class that should be extended to implement a specific button handler.
*/
class BaseButtonHandler : public Configurable, public Startable, public IEventHandler {
public:
BaseButtonHandler(int pin, String config_path = "")
: Configurable{config_path}, Startable(20) {
button_ = new AceButton(pin);
pinMode(pin, INPUT_PULLUP);
}

virtual void start() override {
ButtonConfig* button_config = button_->getButtonConfig();
button_config->setIEventHandler(this);
button_config->setFeature(ButtonConfig::kFeatureLongPress);
button_config->setFeature(ButtonConfig::kFeatureSuppressAfterLongPress);

debugD("Button handler started");

ReactESP::app->onRepeat(4, [this]() { this->button_->check(); });
}

protected:
AceButton* button_;
};


} // namespace sensesp

#endif // SENSESP_SRC_SENSESP_SYSTEM_BASE_BUTTON_H_
13 changes: 13 additions & 0 deletions src/sensesp/system/button.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "sensesp/system/button.h"

#include "sensesp.h"
#include "sensesp_app.h"

namespace sensesp {

void ButtonHandler::handle_long_press() {
debugD("Resetting network settings");
SensESPApp::get()->get_networking()->reset();
}

} // namespace sensesp
34 changes: 34 additions & 0 deletions src/sensesp/system/button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef SENSESP_SRC_SENSESP_SYSTEM_BUTTON_H_
#define SENSESP_SRC_SENSESP_SYSTEM_BUTTON_H_

#define DEFAULT_BUTTON_PIN 2

#include "AceButton.h"
#include "elapsedMillis.h"
#include "sensesp.h"
#include "sensesp/system/configurable.h"
#include "sensesp/system/minimal_button.h"
#include "sensesp/system/startable.h"

namespace sensesp {

using namespace ace_button;

/**
* @brief Default Button Handler for SensESPApp applications.
*
* This button handler implements restart on short press, network settings reset
* on a long press, and factory reset on a very long press.
*/
class ButtonHandler : public MinimalButtonHandler {
public:
ButtonHandler(int pin, String config_path = "")
: MinimalButtonHandler(pin, config_path) {}

protected:
virtual void handle_long_press() override;
};

} // namespace sensesp

#endif // SENSESP_SRC_SENSESP_SYSTEM_BUTTON_H_
84 changes: 84 additions & 0 deletions src/sensesp/system/minimal_button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#ifndef SENSESP_SRC_SENSESP_SYSTEM_MINIMAL_BUTTON_H_
#define SENSESP_SRC_SENSESP_SYSTEM_MINIMAL_BUTTON_H_

#include "AceButton.h"
#include "elapsedMillis.h"
#include "sensesp.h"
#include "sensesp/system/base_button.h"
#include "sensesp/system/configurable.h"
#include "sensesp/system/startable.h"
#include "sensesp_base_app.h"

namespace sensesp {

using namespace ace_button;

/**
* @brief Minimal Button Handler
*
* This is a minimal button handler that implements restart on short press and
* factory reset on a very long press.
*
* This class may be extended to implement more complex button handlers.
*/
class MinimalButtonHandler : public BaseButtonHandler {
public:
MinimalButtonHandler(int pin, String config_path = "")
: BaseButtonHandler(pin, config_path) {}

virtual void handleEvent(AceButton* button, uint8_t event_type,
uint8_t button_state) override {
debugD("Button event: %d", event_type);
switch (event_type) {
case AceButton::kEventPressed:
time_since_press_event = 0;
debugD("Press");
break;
case AceButton::kEventLongReleased:
debugD("Long release, duration: %d", time_since_press_event);
if (time_since_press_event > 5000) {
this->handle_very_long_press();
} else if (time_since_press_event > 1000) {
this->handle_long_press();
}
break;
case AceButton::kEventReleased:
this->handle_button_press();
break;
default:
break;
}
}

protected:
elapsedMillis time_since_press_event;
/**
* @brief Handle a brief button press (less than one second).
*
*/
virtual void handle_button_press() {
debugD("Short release, duration: %d", time_since_press_event);
debugD("Restarting");
ESP.restart();
}
/**
* @brief Handle a long button press (over 1 second).
*
*/
virtual void handle_long_press() {
handle_button_press();
}
/**
* @brief Handle a very long button press (over 5 seconds).
*
*/
virtual void handle_very_long_press() {
debugD("Performing a factory reset");
SensESPBaseApp::get()->reset();
}
};


} // namespace sensesp

#endif // SENSESP_SRC_SENSESP_SYSTEM_BASE_BUTTON_H_
6 changes: 6 additions & 0 deletions src/sensesp_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "sensesp/net/discovery.h"
#include "sensesp/net/networking.h"
#include "sensesp/net/ota.h"
#include "sensesp/system/button.h"
#include "sensesp/system/system_status_led.h"
#include "sensesp/transforms/debounce.h"

Expand Down Expand Up @@ -74,6 +75,11 @@ void SensESPApp::setup() {
}
this->system_status_controller_.connect_to(system_status_led_);
this->ws_client_->get_delta_count_producer().connect_to(system_status_led_);

// create the button handler
if (button_gpio_pin_ != -1) {
button_handler_ = new ButtonHandler(button_gpio_pin_);
}
}

ObservableValue<String>* SensESPApp::get_hostname_observable() {
Expand Down
10 changes: 9 additions & 1 deletion src/sensesp_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "sensesp/sensors/sensor.h"
#include "sensesp/signalk/signalk_delta_queue.h"
#include "sensesp/system/system_status_led.h"
#include "sensesp/system/button.h"
#include "sensesp/ui/ui_output.h"
#include "sensesp_base_app.h"

Expand Down Expand Up @@ -99,6 +100,10 @@ class SensESPApp : public SensESPBaseApp {
ota_password_ = password;
return this;
}
const SensESPApp* set_button_pin(int pin) {
button_gpio_pin_ = pin;
return this;
}
const SensESPApp* set_wifi_manager_password(const char* password) {
wifi_manager_password_ = password;
return this;
Expand All @@ -119,7 +124,10 @@ class SensESPApp : public SensESPBaseApp {
HTTPServer* http_server_;
SystemStatusLed* system_status_led_ = NULL;
SystemStatusController system_status_controller_;
Networking* networking_;
int button_gpio_pin_ = SENSESP_BUTTON_PIN;
ButtonHandler* button_handler_ = nullptr;

Networking* networking_ = NULL;
OTA* ota_;
SKDeltaQueue* sk_delta_queue_;
WSClient* ws_client_;
Expand Down
10 changes: 10 additions & 0 deletions src/sensesp_app_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ class SensESPAppBuilder : public SensESPBaseAppBuilder {
return this;
}

/**
* @brief Set the button GPIO pin.
*
* @return SensESPAppBuilder*
*/
SensESPAppBuilder* set_button_pin(int pin) {
app_->set_button_pin(pin);
return this;
}

/**
* @brief Enable all built-in system info sensors.
*
Expand Down
5 changes: 5 additions & 0 deletions src/sensesp_base_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
// Required for RemoteDebug
#define USE_LIB_WEBSOCKET true

#ifndef SENSESP_BUTTON_PIN
// Default button pin is 0 (GPIO0), normally connected to the BOOT button
#define SENSESP_BUTTON_PIN 0
#endif

#include "sensesp.h"
#include "sensesp/net/debug_output.h"
#include "sensesp/system/filesystem.h"
Expand Down

0 comments on commit 6e9d775

Please sign in to comment.