Zum Hauptinhalt springen

Anbindung eines Arduino-Geräts an NeuroomNet mittels Provider / API "Software API"

Vorbemerkung

Für das Verständnis dieses Kapitels kann die Lektüre folgender Dokumentation nützlich sein:

Einleitung

Hauptaufgabe von NeuroomNet ist die zentrale Fernsteuerung von anderen Geräten / Hardware (also "Komponenten" in der NeuroomNet-Terminologie), welche über diverse Kommunikationskanäle, wie vor allem ein TCP/IP basiertes Netzwerk, erreichbar sind. Hierfür gibt es viele verfügbare Schnittstellen wie KNX, DMX, PJLINK oder es lässt sich auch konfigurativ eine einfache Text-Message basierte TCP/IP oder UDP-Kommunikation einrichten - über so genannte PRT Konfigurationsdateien.

Falls ein anderes Gerät von einem Mikroprozessor gesteuert wird, den man programmieren kann bzw. dann mehr oder weniger ein „PC im Netzwerk“ ist, dann empfiehlt sich die Benutzung einer weiteren Schnittstelle, um ein eigenes Kommunkationsprotokoll festzulegen: Die sog. „Software API“ von NeuroomNet. Diese wird im Folgenden anhand eines praktischen Beispiels vorgestellt und empfiehlt sich vor allem für

  • Software auf „richtigen“ PCs
  • Software auf Raspberry Pi
  • Software auf Arduino
  • Software auf NodeMCU
  • Und alle weiteren programmierbaren Geräte, welche über TCP Textnachrichten empfangen und senden können

Kurzbeschreibung Software API

Die Kommunikation über die „Software API“, mittels der NeuroomNet Software auf im Netzwerk erreichbaren Geräten (im Folgenden als Komponenten oder Client bezeichnet) steuern und Informationen austauschen kann, funktioniert wie folgt:

Die Kommunikation läuft insgesamt über das Protokoll TCP ( https://en.wikipedia.org/wiki/Transmission_Control_Protocol ) und hat daher folgende Eigenschaften:

  • Eine einmal aufgebaute Verbindung (durch einen spezifischen Handshake) zwischen dem NeuroomNet-Server und einem Client bleibt bestehen
  • Solange die Verbindung besteht, können beide Seiten jeweils Messages an die andere Seite schicken (vollduplex)
  • Wenn die Verbindung von einer Seite aus (oder durch das Netzwerk) abgebrochen wird, können keine Nachrichten mehr geschickt werden, sondern die Verbindung muss zunächst wieder neu aufgebaut werden

Im Folgenden benutzen wir die Begriffe Server und NeuroomNet synonym sowie Client und Komponente (Endgerät).

Für NeuroomNet / Software API speziell erfolgt die Verbindung und Kommunikation mittels nachstehender Grundsätze:

  • Ein technischer TCP-Verbindungs-Aufbau wird immer vom Client initiiert (der Default-Port auf NeuroomNet-Seite hierfür ist Port 15400)
  • Nach technischer Initiierung der Verbindung erfolgt die Kommunikation nach einem vorgegebenen inhaltlichen Protokoll, der "Anmeldung der Komponente an NeuroomNet" (unabhängig davon, ob es schon einmal eine Verbindung zwischen dem Client und NeuroomNet-Server zuvor gab):

Sequenzdiagramm zur Anmeldung einer Komponente

Mit diesem Protokoll der Anmeldung der Komponente an NeuroomNet wird folgendes erreicht:

  • NeuroomNet und die Komponente einigen sich auf eine Protokollversion (normalerweise die aktuellste, die beide beherrschen)
  • NeuroomNet wird über in der Komponente verfügbare Aktionen und Ereignisse informiert, so dass diese danach in NeuroomNet auch z.B. in den Modulen Monitoring und Skript Blöcken zur Verfügung stehen

Sämtliche Nachrichten zwischen Komponente und NeuroomNet werden dabei als Text (ggf. als JSON-Struktur) verschickt, wobei allerdings die ersten 4 Bytes einer jeden Nachricht der Größe der Nachricht entsprechen müssen (Größe heißt konkret die Anzahl Bytes der kompletten Nachricht codiert in Little Endian).

Nach Durchführung der Anmeldung der Komponente kann NeuroomNet dann jederzeit Messages folgender Typen an die Komponente schicken:

  • GetStatus
  • DoAction

Dazu kann die Komponente jederzeit Messages folgender Typen an NeuroomNet schicken:

  • Status (zur Beantwortung einer eingegangenen GetStatus-Anfrage, aber auch generell immer proaktiv meldbar)
  • DoEvent
  • Log (Zur Eintragung von Log-Zeilen in NeuroomNet-Logs des Moduls Monitoring)

Eine detaillierte Beschreibung der Software API ist über folgenden Link verfügbar: (Software API 1.0 Provider)

Beispiel: An NeuroomNet angeschlossene Umwelt-Sensoren auf Arduino-Basis

Die Benutzung der Schnittstelle „Software API“ wird am Beispiel einer selbst zusammengebauten Umwelt-Sensoren-Komponente gezeigt:

Foto eines Arduino-Geräts

Diese Umwelt-Sensoren-Komponente besteht aus einem ESP8266 / Arduino und enthält 4 verschiedenen Umweltsensoren zur Feststellung vom CO2-Gehalt in der Luft, Lufttemperatur, Luftfeuchtigkeit und Bodenfeuchtigkeit. Diese Komponente sendet automatisch ihre Daten über die Software API an NeuroomNet, wenn ein Schwellwert der jeweiligen Sensoren überschritten wird.

Dazu sind folgende Aktionen und Ereignisse definiert worden:

  • Aktionen:
    • "Send_All_Environmental_Data" soll die Versendung aller aktuellen Werte aller Sensoren bewirken
  • Ereignisse:
    • "CO2" : Übertragung des aktuellen CO2-Gehalts in der Luft als Integer (Number)
    • "Temperature": Übertragung der aktuellen Temperatur als Integer (Number)
    • "Humidity": Übertragung der aktuellen Luftfeuchtigkeit als Integer (Number)
    • "Moisture": Übertragung der aktuellen Bodenfeuchtigkeit als Integer (Number)

Anmerkung: In der aktuellen Version der Software API (1.0) gibt es kein direktes Konzept von inhaltlichem Request / Response im Sinne von, dass NeuroomNet einen Request an eine externe Komponente schickt und daraufhin eine spezifische Antwort erwartet. Dies ist in der Regel aber keine wesentliche Einschränkung, weil sich dies durch Aktionen und Ereignisse abbilden lässt wie in diesem Beispiel: Die von NeuroomNet initiierte Aktion "Send_All_Environmental_Data" bewirkt dann ein zeitnahes Versenden der Events "CO2", "Temperature", "Humidity" und "Moisture", welche sozusagen die Antwort auf die Aktion "Send_All" sind.

Mit folgendem C++ Code für Arduino kann die Verbindung zu NeuroomNet aufgebaut und in einer Endlos-Schleife nach eingehenden Nachrichten geschaut und geantwortet (Anmerkung: Die meisten eingehenden Nachrichten betreffen den Verbindungsaufbau):

#include <WiFi.h>

WiFiClient wiFiClient;

void sendMessage(String message) {
int32_t messageLength = message.length();
wiFiClient.write((uint8_t *)&messageLength, sizeof(messageLength));
wiFiClient.write(message.c_str(), messageLength);
}

String readMessage() {
uint32_t messageLength = 0;
wiFiClient.read((uint8_t *)&messageLength, sizeof(messageLength));

if (messageLength > 0) {
char message[messageLength + 1];
wiFiClient.readBytes(message, messageLength);
message[messageLength] = '\0';

return message;
}
return "";
}

void setup() {
WiFi.begin("SSID", "Passwort");
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi Connect Failed! Rebooting...");
delay(1000);
ESP.restart();
}

// Connect to NeuroomNet
wiFiClient.connect("192.168.x.x", 15400);
}

void loop() {
if (wiFiClient.available()) {
String message = readMessage();

/////////////////////////////////////////////////////////////////
// React to incoming requests regarding the logon workflow
if (message.indexOf("GetComponentInfo") > 0) {
sendMessage("ComponentInfo\tapiVersion\t1.0\tdisplayName\t<NAME>\tid\t<ID>\tstatus\t<STATUS>\ttype\t<TYPE>");

}
else if (message.indexOf("GetActions") > 0) {
sendMessage("DeclareAction\tid\tSend_All_Environmental_Data");
// ... more actions

sendMessage("EndOfList");

}
else if (message.indexOf("GetEvents") > 0) {
sendMessage("DeclareEvent\tid\tTest"); // <- Example without parameters
sendMessage("DeclareEvent\tid\tCurrentCO2\tparameters\tid\tCO2\trequired\ttrue\ttype\tInt");
// ... more events

sendMessage("EndOfList");

}
/////////////////////////////////////////////////////////////////
// React to incoming requests outside the logon workflow
else if (message.indexOf("GetStatus") > 0) {
sendMessage("Status\tstatus\t<STATUS>");

}
else if (message.indexOf("DoAction") > 0) {
if (message.indexOf("Send_All_Environmental_Data") > 0) {
// do stuff here
}
}
}

if (WiFi.waitForConnectResult() != WL_CONNECTED || wiFiClient.connected() == 0) {
Serial.println("Disconnected! Rebooting...");
delay(1000);
ESP.restart();
}
}

Ein Ereignis über einen neuen CO2-Wert bspw. können wir wie folgt an NeuroomNet senden:

sendMessage("Event\tid\tCurrentCO2\tCO2\t<VALUE>");

Nun lässt sich der Status der Umwelt-Sensoren-Komponente (online / offline) im Modul Monitoring von NeuroomNet tracken und man kann bspw. ein Dashboard erstellen, welches die aktuellen Werte des Sensors anzeigt und wo man auch über einen Button die aktuellsten Werte anfragen könnte:

Screenshot eines Dashboards, welches die aktuellen Werte des Umweltsensors anzeigt]

Konklusion

Mittels NeuroomNets "Software API" und TCP lassen sich einfach Arduino-Geräte oder andere programmierbare Geräte als Komponenten in NeuroomNet einbinden. Einmal eingebunden, kann NeuroomNet

  • Aktionen in diesen Geräten auslösen,
  • auf Events reagieren,
  • das Gerät im Monitoring-Modul anzeigen inkl. Status und Logs
  • das Gerät in Dashboards und Skript-Blöcken verwenden
  • [das Gerät ein- und ausschalten, wobei dies ggf. über andere Komponenten wie KNX-Steckdose oder PC-Client gemacht werden würde und / oder über eine speziell dafür definierte Aktion]