MQTT та ООП


Об’єднав код з двох недавніх постів у одне ціле. Тепер моя Arduino керується з Node-RED по MQTT і у неї всередині крутиться дуже дивний об’єктно-орієнтований код.

Код

Тут публікую лише головну частину прошивки, решта кода в свалці на Github.

#include <Arduino.h>

#include "loop_job.h"
#include "mqtt_io.h"
#include "debouncer.h"
#include "blinking_led.h"

BlinkingLED myBlinker(LED_BUILTIN);

const uint8_t myButtonPin = 2;
Debouncer myButton;

MessageHub mqtt;

TopicSubscription topics[] = {
  {
    "dev/board05/led/set",
    [](char *payload) {
      myBlinker.enabled = (payload[0] == '1');
    }
  }
};

class MyAnalogReader: public ScheduledLoop {
public:
  uint8_t pin;
protected:
  void runScheduled() {
    mqtt.send("dev/board05/A0", analogRead(this->pin));
  }
} myA0;

void setup() {
  Serial.begin(9600);

  mqtt.begin();
  mqtt.subscriptions = topics;
  mqtt.subscriptionsCount = sizeof(topics) / sizeof(topics[0]);

  myBlinker.setup();
  myBlinker.runPeriod = 250000; // 250ms

  pinMode(myButtonPin, INPUT_PULLUP);
  myButton.readingSource = []() {
    return digitalRead(myButtonPin);
  };
  myButton.onFall = []() {
    myBlinker.enabled = !myBlinker.enabled;
    mqtt.send("dev/board05/led", myBlinker.enabled ? 1 : 0);
  };

  pinMode(A0, INPUT);
  myA0.pin = A0;
  myA0.runPeriod = 250000; // 250ms
}

void loop() {
  myBlinker.loop();
  myButton.loop();
  mqtt.loop();
  myA0.loop();
}

Чи краса?

Node-RED

Той самий дашборд.

Знімок екрану дашборду Node-RED

Майже той самий flow. Тільки додав на вхід до вимикача вхідне значення dev/board05/led.

Було:

Знімок екрану Node-RED зі сконфігуро́ваними потоками

Стало:

Ще один екрану Node-RED зі сконфігуро́ваними потоками

Можна вмикати-вимикати блималку за допомогою кнопки, можна вмикати-вимикати з дашборда. Дашборд показує актуальний стан блималки. Без Node-RED (автономно) кнопка продовжує працювати.

Кабель

А, ледь не забув! Додав дуже важливий рядок з pkill в скрипт для MQTT.

#!/bin/sh
while /bin/true; do
  socat -d -d /dev/ttyUSB0,b9600 exec:./mqtt_io
  pkill -A -s 0
  sleep 5
done

Кабель можна від’єднати і приєднати, все працюватиме далі. Але раніше лишалися зайві процеси, яких з кожним перепідключенням кабеля ставало дедалі більше. Тепер без цієї фігні.

Оновлення від 19 березня

Ще більш важливе доповнення про socat.

#!/bin/sh
while /bin/true; do
  socat -d -d file:/dev/ttyUSB0,nonblock,cs8,b9600,cstopb=0,raw,echo=0 exec:./mqtt_io
  pkill -A -s 0
  sleep 5
done

У мене з одним лише флагом b9600 воно іноді працювало, іноді ні. Причому глюки були незрозумілі і якісь нелогічні. Прибив там всі параметри цвяхами наглухо і стало добре.