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