Skip to content

Commit

Permalink
Merge pull request #739 from SignalK/reactesp_rename
Browse files Browse the repository at this point in the history
Rename ReactESP classes
  • Loading branch information
mairas authored Sep 9, 2024
2 parents 7369761 + 6552d67 commit 8210ba1
Show file tree
Hide file tree
Showing 59 changed files with 345 additions and 273 deletions.
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

```ini
lib_deps =
SignalK/SensESP @ >=3.0.0-beta.1,<4
SignalK/SensESP @ >=3.0.0-beta.2,<4
# https://github.com/SignalK/SensESP.git # Use this line to use the latest git version
# symlink:///Users/mairas/src/SignalK/SensESP # Use this line to use a local copy
```
Expand Down Expand Up @@ -95,10 +95,29 @@
- The `reactesp` namespace is no longer imported. If you have any references to
classes in this namespace, you will need to update them to use the namespace
explicitly. For example, `ReactESP` class should be referred to as
`reactesp::ReactESP`. In particular, this change probably needs to be made
explicitly.
Additionally, ReactESP classes have been renamed:
- `ReactESP` -> `reactesp::EventLoop`
- `*Reaction` -> `reactesp::*Event`
For example, `ReactESP` class should be referred to as
`reactesp::EventLoop`. In particular, this change probably needs to be made
in your project's `main.cpp` file.

- `ReactESP` is no longer a singleton. Earlier, you could refer to the singleton
instance of `ReactESP` using `ReactESP::app`. Now, the object pointer is
maintained by the `SensESPBaseApp` class, and you can refer to it using
`sensesp_app->get_event_loop()`. For example:

```cpp
SensESPBaseApp::get_event_loop()->onRepeat(
1000,
[]() { Serial.println("Hello, world!"); }
);
```

### Development

The frontend project is in the `frontend` directory tree. To build the frontend,
Expand Down
38 changes: 19 additions & 19 deletions docs/pages/concepts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void setup() {
// initialize the GPIO pin
pinMode(kGpioPin, OUTPUT);

// create the repeat reaction
// create the repeat event
app.onRepeat(interval, toggle_gpio);

// setup continues
Expand All @@ -47,18 +47,18 @@ void setup() {
What happens in the above example?
We define a callback function `toggle_gpio()`.
Then, we set the pin mode to OUTPUT.
And finally, we create a repeat reaction with the interval `interval`.
And finally, we create a repeat event with the interval `interval`.

Once the program is running, the repeat reaction is triggered automatically every 350 milliseconds.
Once the program is running, the repeat event is triggered automatically every 350 milliseconds.
The interval is calculated from the previous trigger time - if the callback function takes 4 milliseconds to complete, the actual interval still remains 350 ms instead of 354 ms.

Another commonly used and useful time-based reaction is `DelayReaction`.
Another commonly used and useful time-based event is `DelayEvent`.
It triggers after a certain amount of time has passed but does not repeat.
Example use cases for that would be sensor devices in which you trigger the read operation and then come back to get the value after a certain amount of time.
For example, the 1-Wire DS18B20 sensor can take up to 750 ms before the conversion is ready.
In that case, you would first trigger the call and then have something like `app.onDelay(750, read_sensor);` to come back later to read the value.

You can also use `app.onDelay(...)` with a zero delay to trigger the reaction as soon as possible, without blocking the main event loop.
You can also use `app.onDelay(...)` with a zero delay to trigger the event as soon as possible, without blocking the main event loop.

### Lambdas

Expand All @@ -77,7 +77,7 @@ void setup() {
// initialize the GPIO pin
pinMode(kGpioPin, OUTPUT);

// create the repeat reaction
// create the repeat event
app.onRepeat(
interval,
[]() {
Expand All @@ -97,25 +97,25 @@ The brackets `[]` define the start of the lambda expression.
They may also contain definitions for variable capture.
To learn more about that topic, see the [cppreference.com discussion and examples](https://en.cppreference.com/w/cpp/language/lambda).

### Reaction Types
### Event Types

ReactESP is not limited to just delays or repeating reactions.
ReactESP is not limited to just delays or repeating events.
It also supports the following:

- `StreamReaction`: a reaction that triggers when data is available on a stream, for example on a serial port
- `ISRReaction`: a reaction that is called when an interrupt is triggered (for example, when a GPIO pin is toggled)
- `TickReaction`: a reaction that is called every time the main event loop is executed
- `StreamEvent`: an event that triggers when data is available on a stream, for example on a serial port
- `ISREvent`: an event that is called when an interrupt is triggered (for example, when a GPIO pin is toggled)
- `TickEvent`: an event that is called every time the main event loop is executed

### Removing Reactions
### Removing Events

All of the `app.onXXX()` calls return a `Reaction` object.
If this object is stored, it can be used to access and manipulate the reaction later.
In practice, you can disable the reaction by calling `reaction->remove()`.
The same reaction can be re-added later by calling `reaction->add()`.
All of the `app.onXXX()` calls return a `Event` object.
If this object is stored, it can be used to access and manipulate the event later.
In practice, you can disable the event by calling `event->remove()`.
The same event can be re-added later by calling `event->add()`.

Some attention needs to be paid with `DelayReaction` objects, though.
Since they are by nature one-off operations, the corresponding object is deleted after the reaction is triggered.
You must ensure that you don't try to call the methods of an object that has been deleted, for example by setting a flag in the callback function and checking the flag value before trying to remove the reaction.
Some attention needs to be paid with `DelayEvent` objects, though.
Since they are by nature one-off operations, the corresponding object is deleted after the event is triggered.
You must ensure that you don't try to call the methods of an object that has been deleted, for example by setting a flag in the callback function and checking the flag value before trying to remove the event.

## Sensors

Expand Down
12 changes: 4 additions & 8 deletions docs/pages/tutorials/arduino_style/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ parent: Tutorials

# Mix and Match SensESP with Arduino Style Code

While the ReactESP and SensESP features such as the reactions and the producers, consumers and transforms are very powerful, they are not for everyone. This tutorial shows how to use SensESP to only deal with the Signal K networking, and use Arduino-style code to handle the rest.
While the ReactESP and SensESP features such as the events and the producers, consumers and transforms are very powerful, they are not for everyone. This tutorial shows how to use SensESP to only deal with the Signal K networking, and use Arduino-style code to handle the rest.

After reading this tutorial, you should be able to use SensESP together with existing Arduino style code examples. SensESP will take care of initializing the WiFi and the Signal K connection, and you can use the Arduino style code to read sensors and send data to Signal K.

Expand Down Expand Up @@ -176,12 +176,10 @@ First, let's add the required header file include statements to the `src/main.cp

The `sensesp_app_builder.h` file contains the `SensESPAppBuilder` class, which we'll use to build the SensESP app. The `signalk_output.h` file contains the `SKOutput` class, which we'll use to create the Signal K output objects.

We'll also need to add a namespace definition and create the ReactESP app that SensESP uses to run the code. Add the following lines after the `#define` statements:
We also need to add a namespace definition. Add the following lines after the `#include` statements:

```cpp
using namespace sensesp;

reactesp::ReactESP app;
```

Next, we'll create the SensESP application using the builder class. Add the following lines to the `setup()` function, right before the `Wire.begin()` line:
Expand All @@ -195,7 +193,7 @@ Next, we'll create the SensESP application using the builder class. Add the foll
This will create a SensESP app with the hostname `sensesp-bme280`. You can change this to whatever you want, but make sure it's unique on your network. The builder class also allows you to set the WiFi SSID and password and other settings, if needed. See the [SensESPAppBuilder](/generated/docs/classsensesp_1_1_sens_e_s_p_app_builder.html) documentation for more information.
One more thing to do is to add the `app.tick();` command to the end of the `loop()` function. This call triggers execution of any ReactESP reactions that have been scheduled.
One more thing to do is to add the `app.tick();` command to the end of the `loop()` function. This call triggers execution of any ReactESP events that have been scheduled.
Now, let's start our program. Add the line `sensesp_app->start();` at the very end of the `setup()` function. This will start the SensESP app and connect to the WiFi network.
Expand All @@ -214,7 +212,7 @@ Every time it is run, after printing the values, the software will sleep for `de

A major, fundamental rule in asynchronous programming (of which ReactESP is a simple example) is that you should never block the main loop. If you do, you'll block all the other tasks as well. So, let's remove the `delay(delayTime);` line from the `loop()` function.

Normally, we'd add an `onRepeat` reaction to call the `printValues()` function every second, but since I promised to minimise the use of ReactESP and SensESP constructs, we'll implement a simple timer using the Arduino `millis()` function. Replace the `loop()` function with the following code:
Normally, we'd add an `onRepeat` event to call the `printValues()` function every second, but since I promised to minimise the use of ReactESP and SensESP constructs, we'll implement a simple timer using the Arduino `millis()` function. Replace the `loop()` function with the following code:

```cpp
void loop() {
Expand Down Expand Up @@ -304,8 +302,6 @@ Here's the complete code for the `src/main.cpp` file:

using namespace sensesp;

reactesp::ReactESP app;

Adafruit_BME280 bme;

unsigned long delayTime = 1000;
Expand Down
13 changes: 6 additions & 7 deletions examples/analog_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@

using namespace sensesp;

// SensESP builds upon the ReactESP framework. Every ReactESP application
// must instantiate the "app" object.
reactesp::ReactESP app;

// The setup function performs one-time application initialization.
void setup() {
// Some initialization boilerplate when in debug mode...
Expand Down Expand Up @@ -91,6 +87,9 @@ void setup() {
new SKMetadata("ratio", "Indoor light")));
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
13 changes: 7 additions & 6 deletions examples/async_repeat_sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

using namespace sensesp;

reactesp::ReactESP app;

// The setup function performs one-time application initialization.
void setup() {
SetupLogging();
Expand All @@ -35,7 +33,7 @@ void setup() {
auto digital_read_callback = [](RepeatSensor<bool>* sensor) {
ESP_LOGI("Example",
"Pretend to trigger an asynchronous measurement operation here.");
app.onDelay(1000,
SensESPBaseApp::get_event_loop()->onDelay(1000,
[sensor]() { sensor->emit(digitalRead(kDigitalInputPin)); });
};

Expand All @@ -56,6 +54,9 @@ void setup() {
digital->connect_to(new SKOutputFloat(sk_path, ""));
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
11 changes: 7 additions & 4 deletions examples/chain_counter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ using namespace sensesp;
* A bi-directional chain counter is possible, but this is not one.
*/

reactesp::ReactESP app;

void setup() {
SetupLogging();

Expand Down Expand Up @@ -147,5 +145,10 @@ void setup() {
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
// It simply calls `app.tick()` which will then execute all events needed.
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
9 changes: 6 additions & 3 deletions examples/constant_sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

using namespace sensesp;

reactesp::ReactESP app;

void setup() {
SetupLogging();

Expand All @@ -37,4 +35,9 @@ void setup() {
new SKMetadata("m3", "Fresh Water Tank Capacity")));
}

void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
9 changes: 6 additions & 3 deletions examples/dual_thermocouple_sensors/max6675_signalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

using namespace sensesp;

reactesp::ReactESP app;

MAX6675 thermocouple0(thermoCLK, thermo1CS, thermoDO);
MAX6675 thermocouple1(thermoCLK, thermo2CS, thermoDO);

Expand Down Expand Up @@ -57,4 +55,9 @@ void setup() {

}

void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
9 changes: 6 additions & 3 deletions examples/dual_thermocouple_sensors/max6675_signalk_n2k.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ using namespace sensesp;

tNMEA2000* nmea2000;

reactesp::ReactESP app;

// MAX6675 setup
MAX6675 thermocouple0(thermoCLK, thermo1CS, thermoDO);
MAX6675 thermocouple1(thermoCLK, thermo2CS, thermoDO);
Expand Down Expand Up @@ -145,4 +143,9 @@ void setup() {
}

// main program loop
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
13 changes: 7 additions & 6 deletions examples/freertos_tasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ const int kTestOutputInterval = 410;

const uint8_t kDigitalInputPin = 15;

reactesp::ReactESP app;

void ToggleTestOutputPin(void *parameter) {
while (true) {
digitalWrite(kTestOutputPin, !digitalRead(kTestOutputPin));
Expand Down Expand Up @@ -90,10 +88,13 @@ void setup() {
[](float input) { ESP_LOGD("Example", "Heading: %f", input); }));

// print out free heap
app.onRepeat(
SensESPBaseApp::get_event_loop()->onRepeat(
2000, []() { ESP_LOGD("Example", "Free heap: %d", ESP.getFreeHeap()); });
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
11 changes: 6 additions & 5 deletions examples/fuel_level_sensor/fuel_level_sensor_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

using namespace sensesp;

reactesp::ReactESP app;

void setup() {
SetupLogging();

Expand Down Expand Up @@ -37,6 +35,9 @@ void setup() {
new SKOutputFloat("tanks.fuel.0.currentLevel"));
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
11 changes: 6 additions & 5 deletions examples/hysteresis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

using namespace sensesp;

reactesp::ReactESP app;

void setup() {
SetupLogging();

Expand Down Expand Up @@ -47,6 +45,9 @@ void setup() {
->connect_to(new SKOutputBool(sk_path));
}

// The loop function is called in an endless loop during program execution.
// It simply calls `app.tick()` which will then execute all reactions as needed.
void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
9 changes: 6 additions & 3 deletions examples/join_and_zip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@

using namespace sensesp;

reactesp::ReactESP app;

SensESPMinimalApp* sensesp_app;

void setup() {
Expand Down Expand Up @@ -149,4 +147,9 @@ void setup() {
}));
}

void loop() { app.tick(); }
void loop() {
// We're storing the event loop in a static variable so that it's only
// acquired once. Saves a few function calls per loop iteration.
static auto event_loop = SensESPBaseApp::get_event_loop();
event_loop->tick();
}
Loading

0 comments on commit 8210ba1

Please sign in to comment.