libreria-reactive-arduino

Librería Arduino - Reactive Arduino

Reactive Arduino implementa el patrón observable-observador en un procesador como Arduino. El propósito es proporcionar una aproximación a una programación declarativa, dentro de las restricciones de capacidad de un MCU de baja potencia

Reactive Arduino esta basado en ReactiveX y ReactiveUI, adaptado a las necesidades y limitaciones de un MCU.

Más documentación en la Wiki del proyecto en GitHub.

Instrucciones de uso

El uso general de Reactive Arduino consiste en:

  • Definir un observable (Timer, Interval, FromArray, FromProperty…)
  • Encadenar con uno o más operadores (Distinct, Where, Select, First, Last, Sum…)
  • Suscribir un observador (Do, DoFinally, ToProperty, ToArray…)

Por ejemplo:

Reactive::FromRange<int>(10, 20)
>> Reactive::Select<int>([](int x) { return x + 10; })
>> Reactive::ToSerial<int>();
>> Reactive::DoAndFinally<int>(
  [](int x) { Serial.println(x); },
  []() { Serial.println("No more items"); 
});

Crear operadores

Los operadores generalmente se generan a través de un método factoría, proporcionado por la clase Reactive. Por ejemplo:

Reactive::FromArray<int>(values, valuesLength)

Encadenar operadores

Para encadenar operadores Reactive Arduino usa la sobrecarga del operador ’>>’, que permite combinar observables y observadores.

observableInt >> Reactive::ToSerial<bool>();

Templating

Reactive Arduino usa de forma intensiva Templates para definir el tipo de datos que envía o recibe un operador.

Algunos operadores requieren un único Template, cuando emiten el mismo tipo de dato que reciben.

Reactive::Count<float>()

Mientras que otros operadores requieren dos Templates, uno para el dato que recibe y otro para el que emite.

Reactive::Cast<int, float>()

Finalmente algunos operadores no requieren Templates.

Observadores calientes/frios

Reactive Arduino tiene dos tipos de observables. Los observables ‘calientes’ lanzan las acciones cuando otro operador se suscribe a el. Por ejemplo, ‘FromArray(…)’ es un observable caliente.

Reactive::FromArray<int>(values, valuesLength)

Por el contrario, un observador frío no genera ninguna acción al suscribirnos a él. Para ejecutarlo deberemos llamar explicitamente al método ‘Next()‘. Por ejemplo, ‘FromArrayDefer(…)‘.

Reactive::FromArrayDefer<int>(values, valuesLength)

Consideraciones sobre memoria dinámica

En muchas ocasiones generaremos los operadores directamente al encadenar el operador, habitualmente durante el ‘Setup()‘. Sin embargo, tened en cuenta que crear un operador requiere empleo de memoria dinámica. Por tanto, debemos evitarlo crearlos en funciones repetitivas como en la función ‘Loop()‘.

Si se necesita reusasr o acceder a un operador, declararlo como una función global y encadenarlo normalmente.

auto counter = Reactive::Count<int>();
...
//(later in code)
...
obsString >> counter >> Reactive::ToSerial<String>();

Ejemplos

#include "ReactiveArduinoLib.h"

int values[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int valuesLength = sizeof(values) / sizeof(values[0]);

void setup()
{
  Serial.begin(9600);
  while (!Serial) delay(1);

  Reactive::FromArray<int>(values, valuesLength)
    >> Reactive::Cast<int, float>()
    >> Reactive::MovingAverage<float>(4)
    >> Reactive::DoAndFinally<float>(
      [](float x) { Serial.println(x); },
      []() { Serial.println("No more items"); }
  );
}

void loop() 
{
  delay(2000);
}

Código

Todo el código está disponible en Github en https://github.com/luisllamasbinaburo/Arduino-ReactiveArduino. github-full