# Understanding queryHistoricData

**URL:** <https://community.openems.io/t/understanding-queryhistoricdata/748>\
**Category:** Software-Entwicklung\
**Created:** [January 21, 2022, 9:13am UTC](https://community.openems.io/t/understanding-queryhistoricdata/748 "2022-01-21T09:13:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Laksh](https://community.openems.io/user_avatar/community.openems.io/laksh/32/277_2.png) [@Laksh](https://community.openems.io/u/Laksh)\
**Post date:** [January 21, 2022, 9:13am UTC](https://community.openems.io/t/understanding-queryhistoricdata/748/1 "2022-01-21T09:13:21Z")

</div>

Liebe Community

Derzeit haben wir in unserem Projekt mehrere Prognosealgorithmen, die bereits von OpenEMS unabhängig arbeiten. Aber natürlich brauchen wir die prognostizierten Daten in OpenEMS, damit die Controller mit ihnen für weitere Optimierungen arbeiten können.

Ich habe diese Standardfunktion aus der Timdata-Interface herausgefunden:`queryHistoricData` (z.B. in L331 [InfluxConnector](https://github.com/OpenEMS/openems/blob/develop/io.openems.shared.influxdb/src/io/openems/shared/influxdb/InfluxConnector.java#L331)). Ich denke, das ist genau das, wonach ich suche. Ich kann es so programmieren, dass ich n\*Datenzeilen aus der DB in einem einzigen Schritt erhalte. Aber ich finde es schwer zu verstehen, wie die Funktion außerhalb von einem anderen Bundle verwendet wird.

Ich habe auch eine Implementierung gefunden [PersistenceModelPredictorImpl](https://github.com/OpenEMS/openems/blob/f52227a89baab2f72bcc4faed098858ef0505ffa/io.openems.edge.predictor.persistencemodel/src/io/openems/edge/predictor/persistencemodel/PersistenceModelPredictorImpl.java#L75), die diese Funktion verwendet. Was ich finde es schwer zu verstehen ist, wie diese implementaion weiß, welche Timedata Source oder edgeId mit zu verbinden (Angesichts der Tatsache, dass wir mit mehreren MSSQL DBs verbinden möchten, da die Prognosen auf verschiedenen Servern laufen, also haben wir mehre Timedata instance). In der Implementierung werden die Timedata nur initialisiert, ohne weitere Details (siehe [Initialization Timedata](https://github.com/OpenEMS/openems/blob/f52227a89baab2f72bcc4faed098858ef0505ffa/io.openems.edge.predictor.persistencemodel/src/io/openems/edge/predictor/persistencemodel/PersistenceModelPredictorImpl.java#L44))

Ein weiterer Punkt, der für mich schwer zu verstehen ist, ist, ob OpenEMS bereits sicherstellt, dass sich Anfragen nicht überschneiden, wenn dieselbe Funktion `queryHistoricData` von verschiedenen Bundles zur gleichen Zeit verwendet wird, d.h. als paralleler Prozess.

Ich hoffe, ich konnte mein Problem erklären. Ich wäre Ihnen sehr dankbar für Ihre Hilfe.

Danke  
Laksh

---

<div class="post-metadata">

**Author:** ![stefan.feilmeier](https://community.openems.io/user_avatar/community.openems.io/stefan.feilmeier/32/2585_2.png) [@stefan.feilmeier](https://community.openems.io/u/stefan.feilmeier)\
**Post date:** [February 2, 2022, 9:27pm UTC](https://community.openems.io/t/understanding-queryhistoricdata/748/2 "2022-02-02T21:27:03Z")

</div>

Hallo Laksh,

ich kenne euren Systemaufbau nicht, aber OpenEMS unterscheidet eigentlich zwischen einem `Timedata` service, der historische Daten zur Verfügung stellt und einem `Predictor`, der prognostizierte Daten liefert.

`Timedata` wird z. B. verwendet, um im OpenEMS UI historische Daten anzuzeigen. Was du beschreibst klingt für mich eher nach `Predictor`, aber es kann natürlich sein, dass auch der aktuell nicht zu 100 % das abdeckt, was ihr braucht. Wenn ihr mit `Timedata` zurecht kommt, ist das also auch ok.

Wie `@Reference` in OpenEMS mit OSGi Declarative Services funktioniert, habe ich an anderer Stelle erklärt:

> [@Speichern von Snapshots oder Checkpoints von Algorithmen während des EMS-Laufs](https://community.openems.io/t/speichern-von-snapshots-oder-checkpoints-von-algorithmen-wahrend-des-ems-laufs/656/6):
>
> Hallo Laksh, die Variable timedata hat eine Reference-Annotation: @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) private volatile Timedata timedata = null; Diese Declarative Services Annotation sorgt dafür, dass das OSGi Framework zur Laufzeit einen Service injiziert, der das Timedata-Interface implementiert. Declarative Services werden an sehr vielen Stellen in OpenEMS verwendet, um die Komponenten mitei…

Diesen `@Reference`-Annotationen kann man auch einen `target` Filter geben. Dieser sorgt dann dafür, dass nur ganz bestimmte Services injiziert werden.

Hier etwas zu `target` in der Spezifikation:

> **[112 Declarative Services Specification - OSGi Compendium 7](https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html)**

OpenEMS verwendet an einigen Stellen diese expliziten Filter. Beispiel: der “ESS Fix Active Power Controller” arbeitet immer mit einem anhand seiner Component-ID klar definierten Speichersystem. Dazu schreibt die Methode `OpenemsComponent.updateReferenceFilter()` die `target` Property so, dass nur die Komponente mit dieser ID akzeptiert wird.

[https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/EssFixActivePowerImpl.java#L64-L65](https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/EssFixActivePowerImpl.java#L64-L65)

Das gleiche Prinzip lässt sich auch auf Timedata anwenden, wenn ein ganz bestimmter `Timedata` Service notwendig ist.

War das verständlich erklärt?

Gruß,  
Stefan

---

<div class="post-metadata">

**Author:** ![Laksh](https://community.openems.io/user_avatar/community.openems.io/laksh/32/277_2.png) [@Laksh](https://community.openems.io/u/Laksh)\
**Post date:** [March 1, 2022, 12:52pm UTC](https://community.openems.io/t/understanding-queryhistoricdata/748/3 "2022-03-01T12:52:54Z")

</div>

Hallo Stefan,

danke für die ausführliche Antwort.

Ich habe das Konzept im Allgemeinen verstanden. Was du meinst ist, dass wir in der Komponente `@ProviderType`, d.h. in unserem Fall die Klasse, die die “Timedata” Interface implementiert, angeben können, welche Komponenten-Ids mit der gegebenen API interagieren dürfen, oder ist es andersherum?

Ich lade eine Skizze hoch, so ist es für mich einfacher, es zu verstehen.

 ![grafik](https://community.openems.io/uploads/default/original/1X/4ccaea120326cb52c04cffc480f01448b21bfc6b.png)

Vielen Dank  
Laksh

---

<div class="post-metadata">

**Author:** ![stefan.feilmeier](https://community.openems.io/user_avatar/community.openems.io/stefan.feilmeier/32/2585_2.png) [@stefan.feilmeier](https://community.openems.io/u/stefan.feilmeier)\
**Post date:** [March 5, 2022, 8:56am UTC](https://community.openems.io/t/understanding-queryhistoricdata/748/4 "2022-03-05T08:56:40Z")

</div>

Hallo Laksh,

ich versuche es auch mit einer Grafik zu verdeutlichen:

 ![grafik](https://community.openems.io/uploads/default/original/1X/456d5c1a44e0314a30e6f768d4397818aef96fef.png)

Links sind die Provider definiert:

- das Interface `Timedata`
- die beiden Beispiel-Implementierungen (Klassen) `TimedataInfluxDB` und `TimedataRRD4j` implementieren `Timedata`
- davon gibt es insgesamt drei Objeke/Instanzen mit den Component-IDs `timedata0`, `timedata1` und `timedata2`

Rechts sind zwei beispielhafte Instanzen mit Referenzen auf Timedata. Oben ohne `target` filter, unten mit `target`filter (z. B. generiert durch einen Aufruf von `OpenemsComponent.updateReferenceFilter()`.

Im Beispiel oben wird das OSGi Framework einen zufälligen Service injizieren, der `Timedata` implementiert - also `timedata0`, `timedata1` und `timedata2`

Im Beispiel unten sagt der `target` filter, dass der zu injizierende Service `Timedata` implementieren muss _und_ die `id=timedata1` sein muss. Somit wird explizit genau `timedata1` injiziert. Sollte `timedata1` nicht vorhanden sein, so kann diese `MyController`-Instanz nicht aktiviert werden, weil nicht alle Referenzen aufgelöst werden können.

Ist es jetzt klarer - oder habe ich deine Frage noch nicht richtig verstanden?

Gruß,  
Stefan
