Dependency Graph Example

examples/Utilities/DependencyGraph/DependencyGraph.ino
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
 * SPDX-FileCopyrightText: 2026 Maximiliano Ramirez <maximiliano.ramirezbravo@gmail.com>
 *
 * SPDX-License-Identifier: MIT
 */

/**
 * ReactiveESP32 Example Overview:
 * - This example demonstrates the usage of the Dependency Graph feature in ReactiveESP32.
 * - Various nodes are created: a Signal, two Computeds, and two Effects.
 * - The nodes are named for easier identification in the dependency graph.
 * - Pressing 'p' in the Serial monitor will print the current dependency graph in mermaid format.
 *   You can visualize it using online tools like https://mermaid.live/.
 *
 * - It's necessary to have RXESP32_ENABLE_DEPENDENCY_GRAPH enabled in the configuration.
 *
 * - The Serial interface is used to interact with the program:
 *   - 's': Set the signal to a new value.
 *   - 'p': Print the current dependency graph in mermaid format.
 *
 * - Pressing '0' restarts the ESP32.
 */

#include <ReactiveESP32.h>
using namespace RxESP32;

#if RXESP32_ENABLE_DEPENDENCY_GRAPH == 0
#error "This example requires RXESP32_ENABLE_DEPENDENCY_GRAPH to be enabled"
#else

/* ---------------------------------------------------------------------------------------------- */
// Define a simple signal
Signal<uint8_t> number(0, {.name = "Number Signal"});

// Define a computed value that doubles the signal
Computed<uint16_t> doubled(
  []() {
    uint16_t value = number.get() * 2;
    return value;
  },
  {.name = "Doubled Computed"});

// Define a computed value that prints whenever 'doubled' changes
Effect<> print_doubled_effect(
  []() {
    uint16_t value = doubled.get();
    Serial.printf("\tComputed doubled updated: %u\n", value);
    return nullptr; // No cleanup needed
  },
  {.name = "Print Doubled Effect"});

// Define a computed value that quadruples the signal
Computed<uint16_t> quadrupled(
  []() {
    uint16_t value = number.get() * 4;
    return value;
  },
  {.name = "Quadrupled Computed"});

// Define an effect that prints whenever 'quadrupled' changes
Effect<> print_quad_effect(
  []() {
    uint16_t value = quadrupled.get();
    Serial.printf("\tComputed quadrupled updated: %u\n", value);
    return nullptr; // No cleanup needed
  },
  {.name = "Print Quadrupled Effect"});

// These nodes create the following dependency graph:
// graph TD
//   S0["Number Signal"]
//   C1["Doubled Computed"]
//   E2["Print Doubled Effect"]
//   C3["Quadrupled Computed"]
//   E4["Print Quadrupled Effect"]
//   S0 --> C1
//   C1 --> E2
//   S0 --> C3
//   C3 --> E4

// Read Serial input and process commands
void serialRead();
/* ---------------------------------------------------------------------------------------------- */

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("=======================================");
  Serial.println("ReactiveESP32 - DependencyGraph Example");
  Serial.println("=======================================");

  // Start the ReactiveESP32 dispatcher
  if (!Dispatcher::start()) {
    Serial.println("Failed to start ReactiveESP32 Dispatcher!");
    while (true) {
      delay(1000);
    }
  }
}

void loop() { serialRead(); }

void serialRead() {
  if (!Serial.available()) return;

  char c = Serial.read();

  if (c == '\r') return;
  if (c == '\n') c = ' ';
  Serial.printf("> %c\n", c);

  switch (c) {
    case '0':
    {
      // Restart the ESP32
      ESP.restart();
    } break;

    case 'p':
    {
      // Print the dependency graph to Serial
      // This will output a mermaid diagram representation
      // You can paste the output to https://mermaid.live/ to visualize it
      Utils::printGraphMermaidToStream();
    } break;

    case 's':
    {
      // Update the signal to current + 1
      number.update([](const uint8_t& value) {
        uint8_t new_value = value + 1;
        Serial.printf("%s updated to: %u\n", number.getName(), new_value);
        return new_value;
      });
    } break;
  }
}

#endif

See Also

  • Core - Core API Reference

  • Filters - Filters API Reference

  • Helpers - Helpers API Reference