Veröffentlichung Controller

Hallo zusammen,

Ich würde gerne einige von mir programmierte Controller veröffentlichen. ( Wettervorhersage, Berechnung Sonnenauf/untergangszeiten, Ladestation Go-E)

Können sie mir hierzu Instruktionen geben, was es dafür zu tun gibt?

Beste Grüße,

Dominik Bauer

Hallo Dominik,

vielen Dank für deine Anfrage. Die Entwicklungen klingen sehr spannend.

Generell arbeiten wir nach dem “GitHub flow”-Prinzip: https://guides.github.com/introduction/flow/ - d.h.

  1. Jeder Entwickler arbeitet in seinem eigenen Branch und entwickelt dort seine Funktion. Üblicherweise heißt so ein Branch dann “feature/funktionXY”
  2. Der Entwickler erstellt in Github einen Pull-Request
  3. Andere Entwickler “reviewen” den Code. Dabei schauen wir auf…
    3.1 die Umsetzung der Funktion an sich und wie sich diese in die Architektur von OpenEMS einfügt
    3.2 Dokumentation (insb. readme.adoc und bnd.bnd)
    3.3 Code-Qualität (Best Practices, Einhaltung der Java Coding Conventions, unnötige system.out.println, Fehler/Warnungen in Eclipse, Checkstyle - wir haben geplant das mal zu dokumentieren, aktueller Stand ist hier: https://github.com/OpenEMS/openems/pull/1006/files)

Je nach Größe des Pull-Requests kann dieser Vorgang mehr oder weniger lang dauern. Empfehlenswert ist in jedem Fall, einzelne Funktionen in einzelne Pull-Requests zu trennen - also einen Pull-Request für Wettervorhersage, einen für Sonnenauf/untergang, einen für Ladestation, usw.

Am besten starten wir mal mit der einfachsten Entwicklung und exerzieren daran mal den Prozess durch, ok?

Wenn eine Funktion nocht nicht fertig ist, kann ein Pull-Request auch als “Draft” (Entwurf) gestartet werden. Dann wissen zumindest die anderen Mitglieder in der Community schon einmal, dass eine bestimmte Funktion entwickelt wird und können vielleicht auch schon einen ersten Blick auf den Code werfen und Rückmeldungen geben.

Gruß,
Stefan

Hallo Dominik,

das ist sehr interessant, ich arbeite ebenfalls an ähnlichen Controllern.
Vorallem würde mich interessieren, mit welchen Anbieter du die Wettervorhersage holst und wie du mit den Daten auf die Anlagenleistung umrechnest.

Mein Ansatz bisher ist über den australischen Anbieter Solcast (https://docs.solcast.com.au/#introduction), der kostenlos 10 API-Abfragen pro Tag zulässt.

Teilweise Implementiert habe ich es im Energiemonitor


und in der Erzeugung

Leider kann ich noch keine Aussage zur Genauigkeit, da meine Anlage erst in den nächsten Wochen in Betrieb geht.
Konntest du bei dir schon Erfahrungen damit sammeln?

Viele Grüße
Christian

@stefan.feilmeier Ich habe gesehen, dass im Pullrequest https://github.com/OpenEMS/openems/pull/1327 eine neue Prediction-Architektur erstellt wird.
Ist auch eine Implementierung in die UI vorgesehen? Das wäre perfekt für meine Bedürfnisse, die oben dargestellten Verläufe waren sehr spezifisch und nicht allgemein Verwendbar. Schade, dass ich hier zu langsam war.
Mein Trost ist, dass ich in der Zeit doch tiefer in die OpenEMS-Struktur einsteigen konnte.

Gruß
Christian

Genau, daran arbeite ich im Rahmen des Forschungsprojekts EMSIG. Hier eine kurze Präsentation, mit der ich das vor kurzem erst im Konsortium vorgestellt habe (und daraufhin noch ein paar Anpassungen gemacht habe)

2020-12-10 OpenEMS Prediction Architecture.pdf (196.2 KB)

Meine Idee für eine Zweitverwendung der Vorhersage wäre auch - genau wie in deinem Screenshot oben - die “weiße Fläche” in der historischen Ansicht zu befüllen. Ein bisschen Quellcode dazu gibt es auch bereits im Pull-Request. Bisher allerdings nur einen console.log und keine Charts.

Gruß,
Stefan

1 Like

Hallo Stefan,

danke für die Präsentation. Hört sich sehr interessant an und werde ich mir definitiv genauer anschauen.

Gruß
Christian

Hallo Stefan,

ich bekomme leider keine validen Json-Daten anhand der mir vorliegenden Daten zu dem Predictor https://github.com/OpenEMS/openems/files/6043428/2021-02-25.OpenEMS.Prediction.Architecture.pdf

In der Dokumentation steht auf Seite 9 “get24HourPrediction”, korrekt müsste meiner Meinung nach aber “get24HoursPrediction” sein.

Auf folgenden Request

{
“method”: “componentJsonApi”,
“params”:{
“componentID”: “_predictorManager”,
“payload”:{
“method”: “get24HoursPrediction”,
“params”:{
“channel”:“meter0/ActivePower”
}
}
}
}

bekomme ich die Antwort

“Unable to get Response: JSON [componentId] is not a member of [{“componentID”:”_predictorManager",“payload”:{“method”:“get24HoursPrediction”,“params”:{“channel”…]"

Als Predictor habe ich das Persistence-Model eingerichtet

Was mache ich falsch?

Viele Grüße
Christian

Hallo Christian,

sorry für die späte Rückmeldung. Der Name wurde nochmal geändert, weil jetzt mehrere Vorhersagen gleichzeitig abgeholt werden können.

Folgender Request müsste funktionieren:

{
  "method":"componentJsonApi",
  "params":{
    "componentId":"_predictorManager",
    "payload":{
      "method":"get24HoursPrediction",
      "params":{
        "channels":[
          "meter0/ActivePower"
        ]
      }
    }
  }
}

Dein Fehler scheint bei componentId zu liegen: componentId != componentID

“Unable to get Response: JSON [componentId] is not a member of [{“componentID”:”_predictorManager",“payload”:{“method”:“get24HoursPrediction”,“params”:{“channel”…]"

Gruß,
Stefan

Hallo Stefan,
herzlichen Dank für deine Hilfe! Der Fehler lag am Parameter “channel” statt richtig “channels”.
Der Predictor funktioniert nun einwandfrei.

Besteht Interesse daran, den Predictor für den Anbieter Solcast https://solcast.com (10 API Anfragen am Tag kostenlos) zu implementieren?
Den Code dafür habe ich geschrieben und verwende ihn auch schon einige Monate. Ich habe etwas Verschattung und daher weichen die Werte bei niedrigen Sonnenstand etwas ab, dennoch bin recht zufrieden mit den Vorhersagewerten.

Gruß
Christian

1 Like

Hallo Christian,

super, dass wir es lösen könnten. Sorry für die Verwirrung, aber ich glaube die Last-Minute-Änderung, dass mehrere Channels gleichzeitig abgerufen werden können, war es wert. Das ist ein sehr häufiger Use-Case.

Solcast beobachte ich schon länger, bin aber bisher nicht dazu gekommen, mir das Angebot genauer anzusehen. Es wäre toll, wenn du den Predictor als Pull-Request bereitstellen könntest. Wir sind zur Zeit leider etwas hinterher mit den Reviews, aber dieser Beiträg wäre wirklich sehr interessant.

Danke & Gruß,
Stefan

1 Like

Hallo Stefan,

das Feature kann ich selbst auch gut gebrauchen, also kein Problem.

Ich habe den Predictor als Pull-Request in GIthub eingereicht und ist hier zu finden; Feature/prediction solcast by hogmoff · Pull Request #1422 · OpenEMS/openems · GitHub

Gruß
Christian

1 Like

Hello Christian,

First thanks for your sharing.
I’m using your predictor and it’s seems working in my output debugLog !
But I’m interested to get a curve for my prediction on my dashboard in the UI EMS.
Can you help me to do this ?

Thanks you for your answer,

Lucas.

Hello Lucas,

you are welcome.
At the moment you get only the values with a POST-Request over the JsonRPC

I tried some things with the dashboard and this is working good for me. But the code is not generally useable (e.g. fix channeladdresses). So i didn’t add this to the pull-request.

There are some changes necessary in following files

  • add prediction to dataset in ui/src/app/edge/history/energy/energy.component.ts:

      // Prediction
      this.Get24HoursPredictions().then(response2 => {
        let result2 = (response2 as Get24HoursPredictionResponse).result;
        let predictionData = result2['predictorSolcast0/Predict'].map(value => {
          if (value == null) {
            return null
          } else {
            return value / 1000; // convert to kW
          }
        });
    
        if (predictionData.length > 0) {
    
          let StartTime = labels.filter(x => x.getTime() >= Date.now())[0];
          let StartIndex = labels.indexOf(StartTime);
    
          let newpredictionData: number[] = new Array(StartIndex - 1);
          let newlabel = new Date(StartTime.getTime() + 15 * 60000);
          let prodIndex = 0;
          for (let i = StartIndex; i < labels.length; i++) {
            if (labels[i].getTime() >= newlabel.getTime()) {
              newlabel = new Date(newlabel.getTime() + 15 * 60000);
              prodIndex++;
            }
            newpredictionData.push(predictionData[prodIndex]);
          }
    
          datasets.push({
            label: 'Prediction',
            data: newpredictionData,
            hidden: false,
            yAxisID: 'yAxis1',
            position: 'left'
          });
        }
      });
    }
    
  • add Function Get24HoursPredictions() in ui/src/app/edge/history/abstracthistorychart.ts:

    protected Get24HoursPredictions(): Promise<Get24HoursPredictionResponse> {
      return new Promise((resolve, reject) => {
          this.service.getCurrentEdge().then(edge => {
              let channelAddresses = [];
              channelAddresses.push('predictorSolcast0/Predict');
              channelAddresses.push('predictorSolcast0/Predict10');
              channelAddresses.push('predictorSolcast0/Predict90');
              let request = new Get24HoursPredictionRequest(channelAddresses);
              edge.sendPredictorRequest(this.service.websocket, request, channelAddresses).then(response => {
                  let result = (response as Get24HoursPredictionResponse).result;
                  if (Object.keys(result[channelAddresses[0]]).length != 0) {
                      resolve(response as Get24HoursPredictionResponse);
                  } else {
                      reject(new JsonrpcResponseError(response.id, { code: 0, message: "Result was empty" }));
                  }
              }).catch(reason => reject(reason));
          });
      });
    

    }

  • add ‘Prediction’ to Widget-Class in ui/src/app/shared/type/widget.ts

It’s not really complete, maybe this is helpful for you.

Christian

Hello Christian,

Thanks for your fast answer.

I’ve followed your instructions but unfortunately It does’nt work…

I’ve insert : // Prediction
this.Get24HoursPredictions().then(response2 => {…

into private loadLineChart()

I have added:
case ‘Prediction’:
result.push(
new ChannelAddress(‘predictorSolcast0’, ‘Predict’));
break;
into private getEnergyChannelAddresses.

And I’ve done the same for others class to introduce ‘prediction’ in the code and It compiled successfully !

But as I said I’ve no curve…

What’s my mistake ? Can you give me more precision ?

Regards,

Lucas

Hello Lucas,

as i mentioned it is a little bit complicated to describe. You can look to my personal branch where the predictor is fully integrated in the UI.
It’s not good coded but it works fine for me. The go-e Charger is although integrated but not fully functional and buggy. I’m still working on it and when it works fine, then i will make a pull-request.

Here is my branch in Compare with Openems/develop

Regards
Christian

2 Likes