Proposal - Connect OpenEMS to OpenEMS

Hallo,

wir haben nun den Fall, dass wir mehrere Hardwaregeräte (OpenEMS) miteinander kommunizieren lassen wollen.
Dies kann aus folgenden Gründen sinnvoll sein:

  • Logik des einen Controllers beeinflusst den anderen
  • Räumliche Trennung und nur Verbindung über eine Netzwerkverbindung (Eine Edge wird nur lesend verwended?)

Dazu hätten wir eine Rest-Api-Bridge angelegt, die die Werte über Rest anfrägt/setzt.
@s.feilmeier hatte aber die gute Anmerkung, dass dies über Sockets wahrscheinlich sinnvoller wäre um weniger Verbindungen auf und abbauen zu müssen.

Welche Anforderungen gäbe es noch?

Probleme/Herausforderungen auf die wir gestoßen sind.

  • Wie kann man die Channels möglich allgemein gültig definieren und auch in einem anderen Controller verwenden, als ob der Channel lokal verfügbar wäre?
  • Kann man im Core eine Möglichkeit zur Verfügung stellen, dass die Nature/Controller lokal verfügbar ist oder als Zwilling über die Remote-Anbindung verfügbar ist?

Hello,

we now have the case that we want to let several hardware devices (OpenEMS) communicate with each other.
This can be useful for the following reasons:

  • logic of one controller affects the other
  • Spatial separation and only connection via a network connection (An Edge is only used for reading?)

For this we would have created a Rest-Api-Bridge, which requests/sets the values via Rest.
@s.feilmeier had the good comment that this would probably be more useful to have less connections to and from sockets.

What other requirements would there be?

Problems/challenges we encountered.

  • How can you define the channels in a general way and use them in another controller as if the channel was available locally?
  • Is it possible to provide a way in the core that the nature/controller is locally available or available as a twin over the remote connection?

Translated with www.DeepL.com/Translator (free version)

Hallo Paul,

danke für das Proposal! (-> hier nochmal der Link zum Start-Thread: Rest API für Devices).

Mein Vorschlag für die Umsetzung wäre, sich dabei an die bestehende Edge-zu-Backend-Kommunikation anzulehnen. Das “Master”-Edge wäre dann das Backend, mit dem sich mehrere “Slave”-Edges verbinden. Auf Master-Seite bräuchte man einen Websocket-Server - ähnlich dem EdgeWebsocket im Backend; auf Slave-Seite einen Websocket-Client - ähnlich dem Backend-Api-Controller.

Nehmen wir als Beispiel einen Temperaturfühler.

  • Die Nature Thermometer definiert den Channel Temperature.
  • Im “Slave”-Edge laufen folgende Services:
    • Bridge.Onewire als physische Verbindung zur Temperaturfühler-Hardware
    • OneWire.Thermometer, das die Nature Thermometer implementiert
    • Controller.Api.OpenemsMaster, das eine Websocket-Verbindung zum “Master”-Edge herstellt. Authentifizierung über eine Art apikey.
  • Im “Master”-Edge laufen folgende Services:
    • Bridge.OpenemsSlave.Server, das den Websocket-Server für Controller.Api.OpenemsMaster bereitstellt
    • Bridge.OpenemsSlave, das die Verbindung zu einem bestimmten “Slave”-Edge repräsentiert. Es hat als Konfigurationsparameter:
      • slaveServerId: Component-ID der Bridge.OpenemsSlave.Websocket
      • apikey: zur Identifikation des “Slave”-Edge
    • Slave.Thermometer, das die Nature Thermometer implementiert und über die Bridge.OpenemsSlave kommuniziert. Es hat als Konfigurationsparameter:
      • slaveId: Component-ID der Bridge.OpenemsSlave
      • remoteComponentId: Component-ID des OneWire.Thermometer am “Slave”-Edge.

Slave.Thermometer ist unser Zwilling auf Seiten des “Master”-Edge. Sobald es aktiviert wird und die Verbindung über Bridge.OpenemsSlave und Bridge.OpenemsSlave.Server hergestellt ist, schickt es einen subscribeChannels JSON-RPC Request auf alle Channels, die für die Nature gebraucht werden (im Beispiel nur Temperature). Ab dann sendet das “Slave”-Edge ständig über currentData JSON-RPC Notifications die geänderten Werte über seinen Controller.Api.OpenemsMaster zurück.

Dazu ein Bild wie ich mir das vorstelle. (Die Namen sind noch nicht so ganz toll gewählt…)

Live-Edit

Ein paar Ideen/Gedanken dazu:

  • da der Zwilling die richtigen Interfaces implementiert, kann er genauso eingesetzt werden wie eine “native” Komponente
  • statt JSON-RPC könnten wir natürlich auch AMQP, MQTT usw. nehmen.
  • die Verbindung wird vom Slave zum Master hergestellt, was die Firewall-Problematik vereinfachen dürfte
  • da der Websocket-Client am Slave ein Controller ist, kann er von hier auch steuern und unterliegt den entsprechenden Einschränkungen in Bezug auf die Priorität
  • Nicht so einfach ist leider:
    • alles, was kein Channel ist (z. B. Methodenaufrufe in Natures - z. B. getStaticConstraints() bei ManagedSymmetricEss)
    • Übermittlung von Fehlermeldungen. Diese werden zwar im State-Channel gesammelt, dabei geht aber die eigentliche Fehlermeldung (der Fehler-Channel) verloren.
    • diese Probleme sollten sich aber über individuelle JSON-RPC-Requests lösen lassen - vgl. ComponentJsonApi

Würde das für euch funktionieren?
Hast du Bedenken?
Wie sieht das der Rest der Community? Sind damit auch eure Anforderungen abgedeckt?

(Sorry for using German language… please translate this page to your language and you are welcome to reply in Englisch anytime!)

1 Like

Hei Stefan,

das klingt sehr nach einer praktikablen Lösung. Wir hätten den anderen Weg genommen vom Master zum Slave. Aber ich gebe dir Recht, dass es oft leichter ist nur den Master in der Firewall freizugeben, anstatt viele Slaves. wir wären wohl im selben Internen Netz.

Im Prinzip habe ich das meiste verstanden. Aber dann siehst du das “leider” auch so, dass man alle Natures nachprogrammieren müsste, dass diese auch über Websockets erreichbar wären?
Hier ist mir konzeptionell leider auch noch keine gute Lösung eingefallen.

Aber es wäre ja sehr schick, wenn man evtl zukünftig jeder Nature auch zugleich die Funktionalität als “Slave” zur Verfügung stellt.

Also quasi immer das orginal kommuniziert über Bridge XY. aber man kann auch einstellen “clone”/“slave” und dann kommuniziert es über Bridge.OpenemsSlave.
Schönen Gruß

Paul

Hallo Paul,

super - freut mich, wenn dir der Vorschlag gefällt.

Das “Nachprogrammieren” der Natures lässt sich vermutlich nicht vermeiden, weil wir ja echte Services brauchen, die die jeweiligen Java interfaces implementieren. Das würde sich zwar vielleicht auch per Java Reflection usw. lösen lassen, aber das würde ich gerne vermeiden.

Ich denke auch, dass so eine “OpenemsSlave”-Komponente direkt in dem Api-Bundle liegen könnte. Wenn wir uns dann eine schöne AbstractOpenemsSlave-Implementierung bauen, die ähnlich zur AbstractModbusComponent alle Funktionen automatisiert (z. B. Subscribe auf die Channels usw.), dürfte der Overhead je Nature recht klein sein.

1 Like

ja, das denk ich auch. Super. ich schaue, dass ich da gegen ende der Woche dazukomme, etwas rumzuprobieren

1 Like

Hallo Zusammen,

die Idee von @Stefan für die Channel-Implementierung gefällt mir gut. Der Mechanismus ist transparent für das Master-Edge und funktioniert problemlos für viele Channel. Das ist elegant und erlaubt direkt die Abbildung von komplexeren Hierarchien auf mehreren Ebenen. Ich finde es ebenfalls gut die Verbindung aktiv vom Slave zum Master zu öffnen (selber Grund: Firewallproblematik), sowie für Methodenaufrufe in Natures und die Fehlermeldungen eine “OpenemsSlave”-Komponente im Api-Bundle zu implementieren. Alles andere würde vermutlich schnell zu Wildwuchs führen.

Zu diesem Topic möchte ich gerne noch eine Ergänzung machen:
Ich beschäftige mich mit Eclipse Kura Client. Kura ist ein auf OSGI basierendes IoT Edge Framework, welches einen vollwertigen MQTT Broker/Client beinhaltet. Beide Frameworks ergänzen sich meiner Meinung nach gut. OpenEMS bringt die Funktionalität für Energiemanagement, Kura die Funktionalität für das Gerätemanagement (Update, Backup, Configuration, …). Ich spiele mit dem Gedanken eine OpenEMS-Kura-Komponente, sowie eine Kura- OpenEMS-Komponente zu entwickeln um die beiden Systeme näher aneinanderzurücken. Kura bietet bereits Connectoren für verschiedene Cloud-Plattformen (AWS IoT, Azure IoT, Eclipse Kapua). Das eröffnet umgehend großes Potential für das Gerätemanagement. Der MQTT-Mechanismus von Kura könnte gleichzeitig für die OpenEMS-to-OpenEMS connectivity verwendet werden.

Was denkt die Community über diesen Ansatz? Lohnt es die Idee hier weiterzuverfolgen?

Dazu ein paar Gedanken von mir:

  • Eclipse Kura löst elegant das Management Problem von mehreren OpenEMS-Installationen, eine OpenEMS-Energiemanagement-Plattform wird dadurch zu einem “Thing” im Internet der Dinge und könnte damit für eine weitere Verbreitung von OpenEMS führen
  • Eclipse Kura hat eine hohe Lernkurve, höher als die von OpenEMS, weil schlecht dokumentiert.
  • es würde eine unnötige Abhängigkeit zu Eclipse Kura eingeführt werden
  • der Kura MQTT Client/Broker könnte direkt in OpenEMS übernommen werden (Apache ActiveMQ Artemis MQTT Broker und Eclipse Paho MQTT Client).
  • eine OpenEMS MQTT Anbindung
    • würde einer einfacheren Anbindung von Hausautomation(Sensorik/Aktorik) die Türe öffnen
    • könnte sicherheitstechnisch die Angriffsfläche stark vergrößern

Viele Grüße,
Christian

1 Like

Hallo Christian,

wir hatten auch schon Kura genauer angeschaut. sehr interessant und besonders mit opensource und auch auf OSGI basis. evtl nicht so kompliziert integrierbar.

Allerdings wäre dies ein separates Proposal/Featuer, richtig? und in Energiemanagement-Features ist OpenEMS aktuell deutlich stärker/weiter, unserer Meinung nach. Auch die Performance ist nicht zu unterschätzen bei Kura/Kapua.

Schönen Gruß

Paul

Hallo Paul,
ich bin nicht sicher ob ich deine Frage richtig verstanden habe. Ich denke OpenEMS und Kura sollten auf jeden Fall zwei getrennte Projekte bleiben. Die SW-Qualität von OpenEMS empfinde ich als deutlich profesioneller, insbesondere was Architektur, Performance und Systemsicherheit angeht. Ich dachte eher daran, bestimmte ausgewählte OpenEMS Informationen via Kura und MQTT in das IoT-Management einzuspeisen (so etwas wie genereller Status, Bundlestatusänderungen, Anzahl Logeinträge pro Tag und ausgewählte Ereignisse: z.B. Ladevorgang gestartet).

Bezogen auf das konkrete OpenEMS-to-OpenEMS Problem:
Die Existenz von Kura könnte dafür sprechen, die von Stefan angeregte OpenEMS Channel-Informationen und eine “OpenemsSlave”-Komponente via MQTT zu implementieren. Eine OpenEMS MQTT Client/Broker Anbindung würde eine direkte Kommunikation zwischen mehreren OpenEMS-Instanzen auch ohne weitere Infrastruktur ermöglichen und erlaubt nebenbei eine einfachere Integration in das “Internet-der-Dinge”.

Da Kura eine OSGI-MQTT Client/Broker Implementierung besitzt, könnte man diese einfach in OpenEMS integrieren. Der Mehraufwand zu @Stefans Vorschlag bestünde dann darin, die Controller.Api.OpenemsMaster und Bridge.OpenemsSlave.Server nicht durch Websocket-Komponenten, sondern durch MQTT Komponenten zu ersetzen.

Wir haben bereits eine für uns funktionierende Anbindung zwischen Kura und OpenEMS - einen Quick-and-Dirty Hack. Aber wenn anderweitig ein Interesse besteht, dann würde ich mir ein paar Gedanken zu dem Thema machen und ein neues Proposal anlegen, mit dem Ziel:

  • eine generelle OpenEMS MQTT Bridge zu definieren
  • den Kura MQTT Client/Broker in OpenEMS zu integrieren
  • Daten via MQTT zwischen mehreren OpenEMS Instanzen auszutauschen
  • Daten zwischen Kura und OpenEMS auszutauschen

Da dies ein langfristiges und zeitintensives Projekt wäre, würde ich gerne vorab erfahren, ob dies von generellem Interesse für die Community ist und ob es Argumente dafür/dagegen gibt, insbesondere auch ganz konkret bezogen auf das in diesem Proposal beschriebene Problem?

Viele Grüße,
Christian

Hallo Christian,

bin ich deiner Meinung mit OpenEMS und Kura getrennt, da aber beides Opensource und auf OSGI kann man evtl einzelne Komponenten “Integrieren”, wie du auch meintest z.B. mqtt oder auch dieses “Graph”, etc.

Wir wollten evtl auch in OpenEMS mqtt als Bachelorarbeit bei uns gerade ausschrieben. Da wäre es natürlich eine große Hilfe, wenn ihr schon vorarbeit gemacht habt.

zu: “zwischen Kura und OpenEMS - einen Quick-and-Dirty Hack”. Würdet ihr den Teilen?

Besonders auch ganz gezielt Daten über MQTT richtung Cloud/IoT auszutauschen, sehen wir als sehr relevant.

ob die Interne Kommunikation hier auf Basis von MQTT oder Socket müsste man die Vor- und Nachteile besprechen. und dann gern entscheiden. :slight_smile:

Schönen Gruß

Paul

Hallo Paul, ich schicke dir gleich eine private Nachricht. VG Christian

Hallo Paul,

“Ende der Woche” ist vorbei :wink: Hast du dich mit dem Thema beschäftigt? Brauchst du Unterstützung - oder sollten wir mal eine gemeinsame Session in die Richtung starten?

Gruß,
Stefan

Hallo Stefan,

also wir werden so gut wie sicher unserem Bacheloranten diese Themenstellung geben.
Ich kämpfe gerade noch mit einem skript für intelij (dass man nicht 10 libraries hinzufügen muss bei jedem modul, sind ja doch ein paar). Dann will ich noch die doku schreiben, zu externe libraries einbinden (kostet mich doch mehr zeit als gedacht). Anschließend wollte ich endlich unsere Module vernünftig reviewen, damit sie von dir leichter/schneller übernommen werden können.

zu mqtt werde ich nicht viel vor Start der BA im August kommen.
Schönen Gruß

Paul

Hallo Paul, hallo Stefan,

kurzes Update zu MQTT von meiner Seite:
Ich habe mich eine Zeit mit der Java Hive-MQ-Client Library beschäftigt (MQTT3.1 und MQTT5). Es war für mich schwer die Basisfunktionatlität unter OpenEMS (OSGI) zu Nutzen. Nachdem ich für die Library weitere 25MB an Abhängigkeiten in OpenEMS eingezogen hatte, habe ich den Versuch abgebrochen. Das steht für mich in keinem Verhältnis zur Leistung (insbesondere aus Sicht der Systemsicherheit) -
Derzeit habe ich die Eclipse Paho Client library experimentell unter OpenEMS am laufen. Diese unterstützt nur MQTT3.1, hat aber keine weiteren Abhängigkeiten und scheint unter OpenEMS stabil zu laufen. Ich möchte noch ein paar Versuche damit fahren und würde mich dann hier im Forum melden.
Leider gibt es für mich im Moment andere Dinge zu tun. Ich werde also noch Zeit
bis “Ende der Woche” benötigen. Vielleicht auch noch zwei, drei Wochen darüber hinaus :wink:.

Viele Grüße,
Christian

Zu eurer Info, ich habe einen Proof-Of-Concept einer OpenEMS Edge-to-Edge Implementierung via Modbus erstellt. Das ist nicht der Weisheit letzter Schluss (ich halte die Websocket/JSON-RPC-Api nach wie vor für effizienter), aber es ist eine schöne kleine Referenzimplementierung für unsere Websocket-Api “FEMS App Modbus/TCP Lese- und Schreibzugriff” (Untitled :: FENECON Dokumente)

1 Like