Verknüpfung ESS / Controller in beide Richtungen

Hallo Forum,

Über meinen neuen (noch zu veröffentlichen) Controller nehme ich Einfluss auf das untere und obere SoC-Limit des ESS. Funktioniert prima bisher.

Umgekehrt will ich vom ESS aus auf den steuernden Controller zugreifen um dessen eingestellte Limits abzufragen. Daraus, aus der Kapazität, usw. wird dann eine Art “netto” Beladung errechnet.

Den Weg über einen Target Filter:

	@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, //
			cardinality = ReferenceCardinality.MULTIPLE, //
			target = "(enabled=true)")
	private volatile List<ControllerEssChargeDischargeLimiter> ctrlChargeDischargeLimiters = new CopyOnWriteArrayList<>();

und einem UpdateReference-Filter in der Activate-Methode habe ich nicht hinbekommen. Ich müsste ja quasi ermitteln, ob der Controller meine ESS-Instanz als Ziel in seiner Konfiguration hinterlegt hat.
Somit folge ich Stefan´s Vorgehensweise im ToU-Controller. Allerdings bekomme ich so eine Liste aller Controller seiner Art (ControllerEssChargeDischargeLimiter) und nicht nur bezogen auf meine ESS-Instanz. Kommt zum Tragen, falls es mehrere ESS gibt.

Über einen kleinen Filter fliegen die Controller raus, die nicht relevant sind:

	public static void filterControllersByEssId(List<ControllerEssChargeDischargeLimiter> controllers, String myEssId) {
	    Iterator<ControllerEssChargeDischargeLimiter> iterator = controllers.iterator();
	    while (iterator.hasNext()) {
	        ControllerEssChargeDischargeLimiter controller = iterator.next();
	        if (!myEssId.equals(controller.getEssId())) { // Check if controller's ESS ID matches
	            iterator.remove(); // Remove controllers that do not refer to the specified ESS
	        }
	    }
	}

Dies setzt aber die Methode getEssId im Controller voraus - oder man würde durch den Stream des Controllerts iterieren.
Mein Ansatz funktioniert soweit, ist aber recht umständlich. Mit den OSGI-Target Filtern kam ich nicht weiter - bin auch nicht sicher, ob das in die Richtung überhaupt funktionieren könnte.

Vielleicht kann mir jemand einen Tipp für eine simple Lösung geben?

Alles Gute & Gruß
klinki

Hallo Klinki,

spannendes Thema! Es ist toll zu sehen, dass dein Controller-Ansatz bereits Fortschritte macht. Dein Ansatz, die Controller zu filtern, die nicht zu deiner ESS-Instanz gehören, ist schon ziemlich smart, auch wenn er auf den ersten Blick vielleicht etwas umständlich wirkt. Der Vorteil dabei ist, dass du flexibel bleibst, falls mehrere ESS-Instanzen im System vorhanden sind.

Alternative Lösungsidee

OSGi-Target-Filter könnten theoretisch eine Möglichkeit sein, aber wie du schon vermutest, sind sie in diesem Fall schwierig umzusetzen. Eine andere Herangehensweise könnte wie folgt aussehen:

  1. Controller-Instanzbindung über spezifische IDs
    Du könntest in der @Reference-Annotation den Target-Filter spezifizieren, um nur die Instanzen zu referenzieren, die mit deiner ESS-ID übereinstimmen. Dies würde allerdings voraussetzen, dass deine ESS-Instanz-ID im OSGi-Service-Kontext verfügbar und filterbar ist.
  2. ServiceRegistry zur gezielten Abfrage
    Falls die dynamische Referenzierung problematisch bleibt, könntest du alternativ mit dem OSGi ServiceTracker oder ServiceReference arbeiten. Damit könntest du gezielt nur jene Services tracken, die mit der benötigten ESS-ID übereinstimmen. Auf diese Weise sparst du dir die gesamte Liste und sprichst nur den relevanten Controller-Service an.
  3. Direkte Schnittstelle oder Custom Event Mechanismus
    Eventuell wäre auch eine spezielle Schnittstelle oder ein kleiner Event-Mechanismus zwischen ESS und Controller denkbar. Wenn das ESS den Controller über ein Event “anfragt” und seine ID dabei mitgibt, könnte der Controller gezielt reagieren und seine Limits bereitstellen.

Beispiel für ServiceTracker

Falls du mit dem ServiceTracker arbeiten möchtest, könnte der Code etwa so aussehen:

ServiceTracker<ControllerEssChargeDischargeLimiter, ControllerEssChargeDischargeLimiter> tracker = 
     new ServiceTracker<>(context, ControllerEssChargeDischargeLimiter.class, null) {
         @Override
         public ControllerEssChargeDischargeLimiter addingService(ServiceReference<ControllerEssChargeDischargeLimiter> reference) {
             ControllerEssChargeDischargeLimiter service = context.getService(reference);
             if (myEssId.equals(service.getEssId())) { 
                 return service;
             }
             return null;
         }
     };
tracker.open();

Mit diesem Ansatz würdest du nur die gewünschten Instanzen in den Tracker aufnehmen und das manuelle Filtern umgehen.

Ich hoffe, das gibt dir einige neue Anregungen. Viel Erfolg weiterhin bei deinem Projekt!

Viele Grüße,
Hannes

1 Like

ServiceTracker…wieder was gelernt. Sieht vielversprechend aus! Ich komme hoffentlich in den nächsten Tagen dazu.

Nochmal drüber nachgedacht, würde die OSGI-Referenz wahrscheinlich in einem Zirkel-Bezug enden. Das hätte eh nicht funktioniert.

Vielen Dank für den Input :grinning:

Gruß,
Klinki

1 Like

Hi @klinki ,

ich habe mir den Code mal angesehen von Victron - kannst du mir sagen, wieso man den ControllerEssChargeDischargeLimiter beim Victron braucht? Ohne den lässt sich ja das Bundle nicht mal komilieren. Ist der dringend notwendig für die Funktion oder hast du den nur für dich mal so implementiert?

Moin @Sn0w3y ,

Ja, bisher nur für mich. Ich müsste den sinnigerweise auf optional setzen. War mir nicht klar, dass der da auch so tief drin steckt :roll_eyes:

Anyway. Ich schau mir das mal an. Missen will ich den Controller aber nicht - den hab ich mittlerweile auf allen meinen Systemen installiert. Lt. @stefan.feilmeier müsste ich den bei ToU V2 nicht mehr explizit verbauen, sondern über den Scheduler arbeiten. Das würde die ganze Sache natürlich deutlich einfacher und flexibler machen. Wenn da nicht dieses dumme Zeit-Problem wäre…

Gruß,

klinki

JEIN, das bringt nur leider nichts, wenn der nicht im upstream develop ist :slight_smile: Weil der ja dann bei den anderen Leuten nicht im Code ist und dementsprechend als Code fehlt :slight_smile: Ich arbeite gerade an einer “cleanen” version davon - könntest du das dann testen?

klar, kann ich machen. Aber für den Develop-Branch ist noch ne Menge “cleaning up” zu tun. Ich bin ganz aktuell mit @GrisuBerlin dran es zu testen. Es gab da noch Fragezeichen bzgl. des Gridmeters.

Einen PR würde ich (noch) nicht machen wollen. Wenn Du Dich aber damit beschäftigen willst: gerne!

Gerne mal testen :slight_smile:

@Sn0w3y Den Namespace kannst du vielleicht gleich auf io.openems.edge.victron ändern, da es ja nicht nur ein Battery-Inverter ist. Dann kann das Bundle vielleicht auch bald rein - auch wenn nicht “jede Ecke” schon final fertig ist.

1 Like

@stefan.feilmeier ja, denke auch, dass das eine gute Idee ist. Den Namespace hatte ich seinerzeit so von @c.lehne ´s Team übernommen.Mit @Sn0w3y hatte ich das schon kurz diskutiert: In meiner Impl. ist noch ein Controller enthalten, der den SoC oben und unten begrenzt. Weiter nutze ich als Ergebnis eine Art “netto SoC”. Darauf kann ich in den Produktiv-Anlagen nicht verzichten.
Also wäre die Idee, dass @Sn0w3y die Victron-Komponente als PR einreicht. Ich würde das testen, aber halt nicht als Dauertest.

@GrisuBerlin : Vielleicht könntest Du da mit einsteigen? Wenn Victron in´s offizielle Repo kommt, hättest Du es auch etwas einfacher und müsstest nicht immer auf meine Updates warten.

@stefan.feilmeier : wenn ich Dich recht verstanden habe, werden ab ToU V2 limitierende Controller wie z.B. emergencyReserve über den scheduler eingebunden und müssen nicht mehr hart im ToU verarbeitet werden. Wäre das so schon nutzbar (ist V2 schon soweit)?

Gruß,

klinki

1 Like

Ich habe mir das Repository nicht im Detail angeschaut - danke für den Hinweis. Wenn ihr (oder @Sn0w3y) einen PR macht mit den “unkritischen” Dingen, dann können wir das denke ich recht schnell mergen. Ich versuche da pragmatischer zu werden (ohne ganz auf Qualität zu verzichten…)

@stefan.feilmeier : wenn ich Dich recht verstanden habe, werden ab ToU V2 limitierende Controller wie z.B. emergencyReserve über den scheduler eingebunden und müssen nicht mehr hart im ToU verarbeitet werden. Wäre das so schon nutzbar (ist V2 schon soweit)?

Richtig und ja - seit ein paar Wochen funktioniert das richtig gut, weil wir noch starke Performanceverbesserungen geschafft haben. Eine gute Vorlage für dich wäre der Controller.Ess.LimitTotalDischarge mit seinem EnergyScheduler.

Mir wäre es wichtig da ein “GO” von @klinki und/oder @GrisuBerlin zu bekommen, dass es funktioniert, so wie ich es refactored habe, dann würde ich das als PR stellen.

Grüße !

2 Likes

Mir wäre es wichtig da ein “GO” von @klinki und/oder @GrisuBerlin zu bekommen, dass es funktioniert, so wie ich es refactored habe, dann würde ich das als PR stellen.

Technisch sinnvoller wäre es evtl. sogar anders rum. Stell erst den PR, dann reviewe ich den und schau ob noch “Schnitzer” drin sind - und dann kann man nochmal produktiv testen. Außer du hast noch generelle Bedenken, dass dein Ansatz falsch ist.

1 Like

@Sn0w3y / @stefan.feilmeier

Bin aktuell dabei @Sn0w3y `s Cleanup in meinem Repo zu aktualisieren. Ich würde meine Controller zunächst drin lassen damit ich das Ganze in einen Dauertest bringen kann. Was ich bisher gesehen hatte sind die meisten Änderungen kosmetischer Natur.

Letzten Endes sind es nicht viele kritische Stellen. Wenn OK, gebe ich @Sn0w3y bescheid damit er den PR erstellen kann. Sonst könnte es echt kompliziert werden…

@GrisuBerlin hatte auch wieder sein Victron Meter an den Start gebracht. Das war auch noch so ein Thema. Kann ich nicht testen da mir die Hardware fehlt. Außerdem hat er ein 1p System - ich “nur” 2 3p Systeme.
Unsere Tests würde ich abwarten…

Geplanter Zeitraum für einen Dauertest: ca. 1 Woche. Mit @GrisuBerlin stehe ich in recht engem Kontakt. Ich gehe davon aus, dass er mitzieht.
Update: Er zieht mit :wink:

2 Likes

Auf einer meiner Anlagen läuft die Victron Impl. von @Sn0w3y - halt noch mit ChargeDischargeLimiter. Der Rest ist aber gleich.
Heute ist ein guter Tag zum Testen. Zur Abwechslung gibt´s mal etwas Sonne..

Den OffgridInverter hab ich rausgeschmissen (auch im PR).
@Sn0w3y : Die nicht genutzten Enums würde ich nicht löschen. Der komplette “Victron-Zoo” ist ja noch nicht umgesetzt, DC-Charger, Generator, usw. - das fehlt ja alles noch.

@GrisuBerlin wird wohl auch bald installieren.

Ich würde Sie persönlich aktuell gelöscht lassen und bei neuen PRs dann halt Step-by-Step hinzufügen, was hältst du davon? Sonst haben wir ja aktuell “toten” Code rumliegen :slight_smile: Oder?

2 Likes

Du hast ja nicht unrecht. Problem: Mir fehlt die Hardware um weiter daran arbeiten zu können. Jeder, der sich später dem Projekt annimmt, würde sich dann über die Enums freuen. Steckt ne Menge Arbeit drin. So gesehen wäre zum Beispiel auch der DC_Charger ungetesteter Code und damit “tot”.
Insofern vielleicht die beste Variante alles Ungetestete rauszuwerfen. Falls Du der gleichen Meinung sein solltest, diskutieren wir über PN oder Messenger weiter…

knifflig. Entscheide Du. Oder wirf ne Münze. Oder beides. :wink:

Ich würde sagen wir lassen da @stefan.feilmeier den Vortritt :slight_smile: Privat ist immer ein bisschen “doof”, weil dann niemand was mitbekommt :slight_smile:

korrekt. Meine Intention war auch weniger die Geheimhaltung, als dass ich sagen kann was wir schon getestet haben und was nicht. Würde den Rahmen des Threads vielleicht sprengen

1 Like

Pragmatischer Vorschlag: auskommentieren und mit entsprechendem Kommentar versehen. Dann liegt kein toter ausführbarer Code herum, und wenn jemand später weiter entwickelt ist das Wissen gleichzeitig noch vorhanden.