From bf4d08269c3e75e68bbff19ba292922626c819d2 Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Thu, 12 Sep 2024 14:21:25 +0200 Subject: [PATCH 1/6] Initial Commit --- io.openems.edge.example.gruenstrom/.project | 23 +++++++ io.openems.edge.example.gruenstrom/bnd.bnd | 12 ++++ .../edge/example/gruenstrom/Config.java | 26 ++++++++ .../example/gruenstrom/GruenStromReader.java | 37 +++++++++++ .../gruenstrom/GruenStromReaderImpl.java | 64 +++++++++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 io.openems.edge.example.gruenstrom/.project create mode 100644 io.openems.edge.example.gruenstrom/bnd.bnd create mode 100644 io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java create mode 100644 io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java create mode 100644 io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java diff --git a/io.openems.edge.example.gruenstrom/.project b/io.openems.edge.example.gruenstrom/.project new file mode 100644 index 0000000000..b418062d81 --- /dev/null +++ b/io.openems.edge.example.gruenstrom/.project @@ -0,0 +1,23 @@ + + + io.openems.edge.example.gruenstrom + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/io.openems.edge.example.gruenstrom/bnd.bnd b/io.openems.edge.example.gruenstrom/bnd.bnd new file mode 100644 index 0000000000..2dd39ede7f --- /dev/null +++ b/io.openems.edge.example.gruenstrom/bnd.bnd @@ -0,0 +1,12 @@ +Bundle-Name: OpenEMS Edge GruenStrom Example +Bundle-Vendor: FENECON GmbH +Bundle-License: https://opensource.org/licenses/EPL-2.0 +Bundle-Version: 1.0.0.${tstamp} + +-buildpath: \ + ${buildpath},\ + io.openems.common,\ + io.openems.edge.common,\ + io.openems.edge.bridge.http +-testpath: \ + ${testpath} diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java new file mode 100644 index 0000000000..037a7175b3 --- /dev/null +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java @@ -0,0 +1,26 @@ +package io.openems.edge.example.gruenstrom; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +@ObjectClassDefinition(name = "GruenStrom Reader", // + description = "Implements a reader that checks how green the elecricity of a given area is.") +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "gstr0"; + + @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") + String alias() default ""; + + @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") + boolean enabled() default true; + + @AttributeDefinition(name = "Debug Mode", description = "Activates the debug mode") + boolean debugMode() default false; + + @AttributeDefinition(name = "Postal Code", description = "The Postal Code of to be read.", required = true) + String plz() default "94469"; + + String webconsole_configurationFactory_nameHint() default "GruenStrom Reader [{id}]"; +} \ No newline at end of file diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java new file mode 100644 index 0000000000..aed6b3680b --- /dev/null +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java @@ -0,0 +1,37 @@ +package io.openems.edge.example.gruenstrom; + +import io.openems.common.types.OpenemsType; +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.channel.StringReadChannel; +import io.openems.edge.common.component.OpenemsComponent; + +public interface GruenStromReader extends OpenemsComponent { + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + /* + * Report 1 + */ + GREEN_LEVEL(Doc.of(OpenemsType.STRING) // + .text("Green Level at the current time")), // + ; + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } + + /** + * Gets the Channel for {@link ChannelId#GREEN_LEVEL}. + * + * @return the Channel + */ + public default StringReadChannel getGreenLevelChannel() { + return this.channel(ChannelId.GREEN_LEVEL); + } + +} diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java new file mode 100644 index 0000000000..896d04d08c --- /dev/null +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java @@ -0,0 +1,64 @@ +package io.openems.edge.example.gruenstrom; + +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.metatype.annotations.Designate; + +import io.openems.edge.bridge.http.api.BridgeHttp; +import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; +import io.openems.edge.bridge.http.api.BridgeHttpFactory; +import io.openems.edge.common.component.AbstractOpenemsComponent; +import io.openems.edge.common.component.OpenemsComponent; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "GruenStrom.Reader", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +public class GruenStromReaderImpl extends AbstractOpenemsComponent implements OpenemsComponent, GruenStromReader { + + @Reference + private BridgeHttpFactory httpBridgeFactory; + private BridgeHttp httpBridge; + + public GruenStromReaderImpl() { + super(OpenemsComponent.ChannelId.values(), // + GruenStromReader.ChannelId.values() // + ); + } + + @Activate + private void activate(ComponentContext context, Config config) { + this.httpBridge = this.httpBridgeFactory.get(); + // Hard code channel value so we can read it in UI + this.getGreenLevelChannel().setNextValue(54); + + + + // TODO: Implement api + + // this.httpBridge.subscribeCycle(30, new Endpoint(// + // null,// Url + // null, // + // 0, // + // 0, // + // null,// + // null // + // ), null, null); + // + } + + @Override + @Deactivate + protected void deactivate() { + super.deactivate(); + this.httpBridgeFactory.unget(this.httpBridge); + this.httpBridge = null; + } + +} From 10b871e50b798766f4535db97c28767a54b2f589 Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Thu, 12 Sep 2024 16:16:51 +0200 Subject: [PATCH 2/6] UI Part --- io.openems.edge.application/EdgeApp.bndrun | 5 ++- .../edge/example/gruenstrom/Config.java | 6 +-- .../example/gruenstrom/GruenStromReader.java | 7 ++-- .../gruenstrom/GruenStromReaderImpl.java | 24 +++++------- .../greunStromComponent_flat.ts | 39 +++++++++++++++++++ .../gruenStromReader/gruenStromComponent.html | 3 ++ .../gruenStromComponent.module.ts | 20 ++++++++++ .../modal/gruenStrom_modal.html | 9 +++++ .../modal/gruenStrom_modal.ts | 25 ++++++++++++ ui/src/app/edge/live/live.component.html | 5 +++ ui/src/app/edge/live/live.module.ts | 32 ++++++++------- 11 files changed, 137 insertions(+), 38 deletions(-) create mode 100644 ui/src/app/edge/live/gruenStromReader/greunStromComponent_flat.ts create mode 100644 ui/src/app/edge/live/gruenStromReader/gruenStromComponent.html create mode 100644 ui/src/app/edge/live/gruenStromReader/gruenStromComponent.module.ts create mode 100644 ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.html create mode 100644 ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.ts diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 1e489ec354..54fe5b8766 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -190,7 +190,7 @@ bnd.identity;id='io.openems.edge.timeofusetariff.hassfurt',\ bnd.identity;id='io.openems.edge.timeofusetariff.rabotcharge',\ bnd.identity;id='io.openems.edge.timeofusetariff.tibber',\ - + bnd.identity;id='io.openems.edge.example.gruenstrom' -runbundles: \ Java-WebSocket;version='[1.5.4,1.5.5)',\ bcpkix;version='[1.70.0,1.70.1)',\ @@ -429,4 +429,5 @@ org.owasp.encoder;version='[1.3.1,1.3.2)',\ reactive-streams;version='[1.0.4,1.0.5)',\ rrd4j;version='[3.9.0,3.9.1)',\ - stax2-api;version='[4.2.2,4.2.3)' \ No newline at end of file + stax2-api;version='[4.2.2,4.2.3)',\ + io.openems.edge.example.gruenstrom;version=snapshot \ No newline at end of file diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java index 037a7175b3..3e45c036b3 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java @@ -3,7 +3,7 @@ import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.ObjectClassDefinition; -@ObjectClassDefinition(name = "GruenStrom Reader", // +@ObjectClassDefinition(name = "GruenStrom.Reader", // description = "Implements a reader that checks how green the elecricity of a given area is.") @interface Config { @@ -19,8 +19,8 @@ @AttributeDefinition(name = "Debug Mode", description = "Activates the debug mode") boolean debugMode() default false; - @AttributeDefinition(name = "Postal Code", description = "The Postal Code of to be read.", required = true) + @AttributeDefinition(name = "Postal Code", description = "The Postal Code of the location to be read.", required = true) String plz() default "94469"; - String webconsole_configurationFactory_nameHint() default "GruenStrom Reader [{id}]"; + String webconsole_configurationFactory_nameHint() default "GruenStrom.Reader [{id}]"; } \ No newline at end of file diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java index aed6b3680b..8ba4577abf 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReader.java @@ -2,7 +2,7 @@ import io.openems.common.types.OpenemsType; import io.openems.edge.common.channel.Doc; -import io.openems.edge.common.channel.StringReadChannel; +import io.openems.edge.common.channel.IntegerReadChannel; import io.openems.edge.common.component.OpenemsComponent; public interface GruenStromReader extends OpenemsComponent { @@ -10,8 +10,7 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { /* * Report 1 */ - GREEN_LEVEL(Doc.of(OpenemsType.STRING) // - .text("Green Level at the current time")), // + GREEN_LEVEL(Doc.of(OpenemsType.INTEGER)), // ; private final Doc doc; @@ -30,7 +29,7 @@ public Doc doc() { * * @return the Channel */ - public default StringReadChannel getGreenLevelChannel() { + public default IntegerReadChannel getGreenLevelChannel() { return this.channel(ChannelId.GREEN_LEVEL); } diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java index 896d04d08c..0b8aed07c5 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java @@ -9,7 +9,6 @@ import org.osgi.service.metatype.annotations.Designate; import io.openems.edge.bridge.http.api.BridgeHttp; -import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; import io.openems.edge.bridge.http.api.BridgeHttpFactory; import io.openems.edge.common.component.AbstractOpenemsComponent; import io.openems.edge.common.component.OpenemsComponent; @@ -27,8 +26,7 @@ public class GruenStromReaderImpl extends AbstractOpenemsComponent implements Op private BridgeHttp httpBridge; public GruenStromReaderImpl() { - super(OpenemsComponent.ChannelId.values(), // - GruenStromReader.ChannelId.values() // + super(OpenemsComponent.ChannelId.values(), GruenStromReader.ChannelId.values() // ); } @@ -38,19 +36,17 @@ private void activate(ComponentContext context, Config config) { // Hard code channel value so we can read it in UI this.getGreenLevelChannel().setNextValue(54); - - // TODO: Implement api - // this.httpBridge.subscribeCycle(30, new Endpoint(// - // null,// Url - // null, // - // 0, // - // 0, // - // null,// - // null // - // ), null, null); - // + // this.httpBridge.subscribeCycle(30, new Endpoint(// + // null,// Url + // null, // + // 0, // + // 0, // + // null,// + // null // + // ), null, null); + // } @Override diff --git a/ui/src/app/edge/live/gruenStromReader/greunStromComponent_flat.ts b/ui/src/app/edge/live/gruenStromReader/greunStromComponent_flat.ts new file mode 100644 index 0000000000..e795024c3b --- /dev/null +++ b/ui/src/app/edge/live/gruenStromReader/greunStromComponent_flat.ts @@ -0,0 +1,39 @@ +import { Component } from "@angular/core"; +import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; +import { CurrentData } from "src/app/shared/shared"; +import { GruenStromModalComponent } from "./modal/gruenStrom_modal"; + +@Component({ + selector: "GruenStromComponent", + templateUrl: "./GruenStromComponent.html", +}) + +export class GruenStromComponent extends AbstractFlatWidget { + protected greenLevel: any; + + + async presentModal() { + const modal = await this.modalController.create({ + component: GruenStromModalComponent, + componentProps: { + component: this.component, + }, + }); + return await modal.present(); + } + + protected override onCurrentData(currentData: CurrentData) { + this.greenLevel = currentData.allComponents[this.componentId + "/GreenLevel"]; + } + + protected override afterIsInitialized(): void { + console.log("test"); + console.log("test"); + console.log("test"); + console.log("test"); + console.log("test"); + console.log("test"); + console.log("test"); + } + +} diff --git a/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.html b/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.html new file mode 100644 index 0000000000..4c018ce75c --- /dev/null +++ b/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.html @@ -0,0 +1,3 @@ + + + diff --git a/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.module.ts b/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.module.ts new file mode 100644 index 0000000000..d14c60eeff --- /dev/null +++ b/ui/src/app/edge/live/gruenStromReader/gruenStromComponent.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; +import { SharedModule } from "src/app/shared/shared.module"; +import { GruenStromComponent } from "./greunStromComponent_flat"; +import { GruenStromModalComponent } from "./modal/gruenStrom_modal"; + +@NgModule({ + imports: [ + BrowserModule, + SharedModule, + ], + declarations: [ + GruenStromComponent, + GruenStromModalComponent, + ], + exports: [ + GruenStromComponent, + ], +}) +export class Reader_Green_Power { } diff --git a/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.html b/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.html new file mode 100644 index 0000000000..67649d4da7 --- /dev/null +++ b/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.html @@ -0,0 +1,9 @@ + + + + + + + diff --git a/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.ts b/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.ts new file mode 100644 index 0000000000..28c439dd3b --- /dev/null +++ b/ui/src/app/edge/live/gruenStromReader/modal/gruenStrom_modal.ts @@ -0,0 +1,25 @@ +import { Component } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { AbstractModal } from "src/app/shared/components/modal/abstractModal"; +import { ChannelAddress } from "src/app/shared/shared"; + +@Component({ + templateUrl: "./gruenStrom_modal.html", +}) +export class GruenStromModalComponent extends AbstractModal { + + + protected override getChannelAddresses() { + const channelAddresses: ChannelAddress[] = []; + channelAddresses.push( + new ChannelAddress(this.component.id, "GreenLevel"), + ); + return channelAddresses; + } + + protected override getFormGroup(): FormGroup { + return this.formBuilder.group({ + postalCode: new FormControl(this.component.properties["plz"]), + }); + } +} diff --git a/ui/src/app/edge/live/live.component.html b/ui/src/app/edge/live/live.component.html index edf538ba7a..8f627120c2 100644 --- a/ui/src/app/edge/live/live.component.html +++ b/ui/src/app/edge/live/live.component.html @@ -81,6 +81,11 @@ + + + + + diff --git a/ui/src/app/edge/live/live.module.ts b/ui/src/app/edge/live/live.module.ts index e3d7bbc0de..a8fbb0eb8e 100644 --- a/ui/src/app/edge/live/live.module.ts +++ b/ui/src/app/edge/live/live.module.ts @@ -2,21 +2,14 @@ import { NgModule } from "@angular/core"; import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { SharedModule } from "./../../shared/shared.module"; -import { Common_Autarchy } from "./common/autarchy/Common_Autarchy"; -import { Common_Consumption } from "./common/consumption/Common_Consumption"; -import { Common_Grid } from "./common/grid/Common_Grid"; -import { Common_Production } from "./common/production/Common_Production"; -import { Common_Selfconsumption } from "./common/selfconsumption/Common_Selfconsumption"; -import { StorageModalComponent } from "./common/storage/modal/modal.component"; -import { StorageComponent } from "./common/storage/storage.component"; import { Controller_ChannelthresholdComponent } from "./Controller/Channelthreshold/Channelthreshold"; import { Controller_ChpSocComponent } from "./Controller/ChpSoc/ChpSoc"; import { Controller_ChpSocModalComponent } from "./Controller/ChpSoc/modal/modal.component"; import { Controller_Ess_FixActivePower } from "./Controller/Ess/FixActivePower/Ess_FixActivePower"; import { Controller_Ess_GridOptimizedCharge } from "./Controller/Ess/GridOptimizedCharge/Ess_GridOptimizedCharge"; import { Controller_Ess_TimeOfUseTariff } from "./Controller/Ess/TimeOfUseTariff/Ess_TimeOfUseTariff"; -import { AdministrationComponent } from "./Controller/Evcs/administration/administration.component"; import { Controller_Evcs } from "./Controller/Evcs/Evcs"; +import { AdministrationComponent } from "./Controller/Evcs/administration/administration.component"; import { Controller_Io_ChannelSingleThresholdComponent } from "./Controller/Io/ChannelSingleThreshold/Io_ChannelSingleThreshold"; import { Controller_Io_ChannelSingleThresholdModalComponent } from "./Controller/Io/ChannelSingleThreshold/modal/modal.component"; import { Controller_Io_FixDigitalOutputComponent } from "./Controller/Io/FixDigitalOutput/Io_FixDigitalOutput"; @@ -26,20 +19,28 @@ import { Controller_Io_HeatpumpComponent } from "./Controller/Io/Heatpump/Io_Hea import { Controller_Io_HeatpumpModalComponent } from "./Controller/Io/Heatpump/modal/modal.component"; import { Controller_Asymmetric_PeakShavingComponent } from "./Controller/PeakShaving/Asymmetric/Asymmetric"; import { Controller_Asymmetric_PeakShavingModalComponent } from "./Controller/PeakShaving/Asymmetric/modal/modal.component"; -import { Controller_Symmetric_PeakShavingModalComponent } from "./Controller/PeakShaving/Symmetric/modal/modal.component"; import { Controller_Symmetric_PeakShavingComponent } from "./Controller/PeakShaving/Symmetric/Symmetric"; -import { Controller_Symmetric_TimeSlot_PeakShavingModalComponent } from "./Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component"; +import { Controller_Symmetric_PeakShavingModalComponent } from "./Controller/PeakShaving/Symmetric/modal/modal.component"; import { Controller_Symmetric_TimeSlot_PeakShavingComponent } from "./Controller/PeakShaving/Symmetric_TimeSlot/Symmetric_TimeSlot"; -import { DelayedSellToGridComponent } from "./delayedselltogrid/delayedselltogrid.component"; -import { DelayedSellToGridModalComponent } from "./delayedselltogrid/modal/modal.component"; -import { EnergymonitorModule } from "./energymonitor/energymonitor.module"; -import { InfoComponent } from "./info/info.component"; +import { Controller_Symmetric_TimeSlot_PeakShavingModalComponent } from "./Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component"; import { Io_Api_DigitalInputComponent } from "./Io/Api_DigitalInput/Io_Api_DigitalInput"; import { Io_Api_DigitalInput_ModalComponent } from "./Io/Api_DigitalInput/modal/modal.component"; -import { LiveComponent } from "./live.component"; import { Evcs_Api_ClusterComponent } from "./Multiple/Evcs_Api_Cluster/Evcs_Api_Cluster"; import { EvcsChartComponent } from "./Multiple/Evcs_Api_Cluster/modal/evcs-chart/evcs.chart"; import { Evcs_Api_ClusterModalComponent } from "./Multiple/Evcs_Api_Cluster/modal/evcsCluster-modal.page"; +import { Common_Autarchy } from "./common/autarchy/Common_Autarchy"; +import { Common_Consumption } from "./common/consumption/Common_Consumption"; +import { Common_Grid } from "./common/grid/Common_Grid"; +import { Common_Production } from "./common/production/Common_Production"; +import { Common_Selfconsumption } from "./common/selfconsumption/Common_Selfconsumption"; +import { StorageModalComponent } from "./common/storage/modal/modal.component"; +import { StorageComponent } from "./common/storage/storage.component"; +import { DelayedSellToGridComponent } from "./delayedselltogrid/delayedselltogrid.component"; +import { DelayedSellToGridModalComponent } from "./delayedselltogrid/modal/modal.component"; +import { EnergymonitorModule } from "./energymonitor/energymonitor.module"; +import { Reader_Green_Power } from "./gruenStromReader/gruenStromComponent.module"; +import { InfoComponent } from "./info/info.component"; +import { LiveComponent } from "./live.component"; import { OfflineComponent } from "./offline/offline.component"; @NgModule({ @@ -52,6 +53,7 @@ import { OfflineComponent } from "./offline/offline.component"; Common_Selfconsumption, Common_Consumption, Common_Grid, + Reader_Green_Power, // Controller Controller_Ess_FixActivePower, Controller_Ess_GridOptimizedCharge, From d8a3c2c6b28b7bd2a14f9d6f45643d68b7810cd0 Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Thu, 12 Sep 2024 16:43:07 +0200 Subject: [PATCH 3/6] Create App --- .../edge/app/timeofusetariff/GruenStrom.java | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java diff --git a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java new file mode 100644 index 0000000000..4cf21cf594 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java @@ -0,0 +1,145 @@ +package io.openems.edge.app.timeofusetariff; + +import static io.openems.edge.app.common.props.CommonProps.alias; +import static io.openems.edge.app.common.props.CommonProps.defaultDef; +import static io.openems.edge.core.appmanager.validator.Checkables.checkHome; + +import java.util.Map; +import java.util.function.Function; + +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +import com.google.common.collect.Lists; +import com.google.gson.JsonElement; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.oem.OpenemsEdgeOem; +import io.openems.common.session.Language; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.enums.OptionsFactory; +import io.openems.edge.app.enums.TranslatableEnum; +import io.openems.edge.app.timeofusetariff.GruenStrom.Property; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.core.appmanager.AbstractOpenemsApp; +import io.openems.edge.core.appmanager.AbstractOpenemsAppWithProps; +import io.openems.edge.core.appmanager.AppConfiguration; +import io.openems.edge.core.appmanager.AppDef; +import io.openems.edge.core.appmanager.AppDescriptor; +import io.openems.edge.core.appmanager.ComponentUtil; +import io.openems.edge.core.appmanager.ConfigurationTarget; +import io.openems.edge.core.appmanager.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.OpenemsAppCardinality; +import io.openems.edge.core.appmanager.OpenemsAppCategory; +import io.openems.edge.core.appmanager.TranslationUtil; +import io.openems.edge.core.appmanager.Type; +import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; +import io.openems.edge.core.appmanager.dependency.Tasks; +import io.openems.edge.core.appmanager.dependency.aggregatetask.SchedulerByCentralOrderConfiguration.SchedulerComponent; +import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; +import io.openems.edge.core.appmanager.validator.ValidatorConfig; +@Component(name = "App.GruenStrom") +public class GruenStrom extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public static enum Property implements Type, Nameable { + // Components + ID(AppDef.componentId("gstr0")), // + + // Properties + ALIAS(alias()), + + POSTAL_CODE(AppDef.copyOfGeneric(defaultDef(), def -> def // + .setLabel("Postal Code") // + .setRequired(true)// + .setDefaultValue("94667")// + .setField(JsonFormlyUtil::buildInput))); + + private final AppDef def; + + private Property(AppDef def) { + this.def = def; + } + + @Override + public Property self() { + return this; + } + + @Override + public AppDef def() { + return this.def; + } + + @Override + public Function, BundleParameter> getParamter() { + return Type.Parameter.functionOf(AbstractOpenemsApp::getTranslationBundle); + } + } + + @Activate + public GruenStrom(@Reference ComponentManager componentManager, ComponentContext context, + @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { + super(componentManager, context, cm, componentUtil); + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + final var id = this.getId(t, p, Property.ID); + + final var alias = this.getString(p, l, Property.ALIAS); + final var postalCode = this.getString(p, l, Property.POSTAL_CODE); + + var components = Lists.newArrayList(// + new EdgeConfig.Component(id, alias, "GruenPower.Reader", + JsonUtils.buildJsonObject() // + .addProperty("plz", postalCode) // + .build()) // + ); + + return AppConfiguration.create() // + .addTask(Tasks.component(components)) // + .build(); + }; + } + + @Override + public AppDescriptor getAppDescriptor(OpenemsEdgeOem oem) { + return AppDescriptor.create() // + .setWebsiteUrl(oem.getAppWebsiteUrl(this.getAppId())) // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.TIME_OF_USE_TARIFF }; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + protected ValidatorConfig.Builder getValidateBuilder() { + return ValidatorConfig.create() // + .setCompatibleCheckableConfigs(checkHome()); + } + + @Override + protected GruenStrom getApp() { + return this; + } +} From ed47dcab4c7e2c98cc5b9ccbb5762b549677cdcd Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Thu, 12 Sep 2024 16:44:34 +0200 Subject: [PATCH 4/6] Imports --- .../src/io/openems/edge/app/timeofusetariff/GruenStrom.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java index 4cf21cf594..7bbaa1db3f 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java +++ b/io.openems.edge.core/src/io/openems/edge/app/timeofusetariff/GruenStrom.java @@ -22,8 +22,6 @@ import io.openems.common.session.Language; import io.openems.common.types.EdgeConfig; import io.openems.common.utils.JsonUtils; -import io.openems.edge.app.enums.OptionsFactory; -import io.openems.edge.app.enums.TranslatableEnum; import io.openems.edge.app.timeofusetariff.GruenStrom.Property; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.core.appmanager.AbstractOpenemsApp; @@ -37,11 +35,9 @@ import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppCardinality; import io.openems.edge.core.appmanager.OpenemsAppCategory; -import io.openems.edge.core.appmanager.TranslationUtil; import io.openems.edge.core.appmanager.Type; import io.openems.edge.core.appmanager.Type.Parameter.BundleParameter; import io.openems.edge.core.appmanager.dependency.Tasks; -import io.openems.edge.core.appmanager.dependency.aggregatetask.SchedulerByCentralOrderConfiguration.SchedulerComponent; import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; import io.openems.edge.core.appmanager.validator.ValidatorConfig; @Component(name = "App.GruenStrom") From 3a1c4b69f0c8e7daf1fafca7300102fde066ec05 Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Fri, 13 Sep 2024 11:29:01 +0200 Subject: [PATCH 5/6] http endpoint --- .../gruenstrom/GruenStromReaderImpl.java | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java index 0b8aed07c5..866f4b38b5 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java @@ -1,5 +1,8 @@ package io.openems.edge.example.gruenstrom; +import java.time.Instant; +import java.util.Map; + import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -8,8 +11,16 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.metatype.annotations.Designate; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.utils.JsonUtils; import io.openems.edge.bridge.http.api.BridgeHttp; +import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; import io.openems.edge.bridge.http.api.BridgeHttpFactory; +import io.openems.edge.bridge.http.api.HttpMethod; import io.openems.edge.common.component.AbstractOpenemsComponent; import io.openems.edge.common.component.OpenemsComponent; @@ -38,15 +49,36 @@ private void activate(ComponentContext context, Config config) { // TODO: Implement api - // this.httpBridge.subscribeCycle(30, new Endpoint(// - // null,// Url - // null, // - // 0, // - // 0, // - // null,// - // null // - // ), null, null); - // + this.httpBridge.request(new Endpoint("https://api.corrently.io/v2.0/gsi/prediction?zip=" + config.plz(), // Url + HttpMethod.GET, // HttpMethod + 30, // + 120, // + "", // + Map.of() // + )).thenAccept(t -> { + final var responseBody = t.data(); + try { + // Using OpenEMS own JsonUtils class + JsonElement je = JsonUtils.parse(responseBody); + JsonObject jo = JsonUtils.getAsJsonObject(je); + JsonArray ja = JsonUtils.getAsJsonArray(jo.get("data")); + final var currentTimestamp = Instant.now().toEpochMilli(); + // Iterate over the array to find the correct entry + for (var dataValue : ja) { + final var dataPoint = JsonUtils.getAsJsonObject(dataValue); + final var time = dataPoint.get("time").getAsLong(); + if (time == currentTimestamp) { + final var co2 = JsonUtils.getAsInt(dataPoint.get("co2")); + this.getGreenLevelChannel().setNextValue(co2); + } + } + + } catch (OpenemsNamedException e) { + // log message or error message + } + + }); + } @Override From e80c11b53d83017dc2e41da67e8b91f17bbea4ca Mon Sep 17 00:00:00 2001 From: "FENECON\\johann.kaufmann" Date: Mon, 16 Sep 2024 09:46:39 +0200 Subject: [PATCH 6/6] activate and classpath fix --- io.openems.edge.example.gruenstrom/.classpath | 12 ++++++++++++ io.openems.edge.example.gruenstrom/.gitignore | 1 + .../io/openems/edge/example/gruenstrom/Config.java | 4 ++-- .../example/gruenstrom/GruenStromReaderImpl.java | 6 +++--- 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 io.openems.edge.example.gruenstrom/.classpath create mode 100644 io.openems.edge.example.gruenstrom/.gitignore diff --git a/io.openems.edge.example.gruenstrom/.classpath b/io.openems.edge.example.gruenstrom/.classpath new file mode 100644 index 0000000000..bbfbdbe40e --- /dev/null +++ b/io.openems.edge.example.gruenstrom/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/io.openems.edge.example.gruenstrom/.gitignore b/io.openems.edge.example.gruenstrom/.gitignore new file mode 100644 index 0000000000..9e0adcc107 --- /dev/null +++ b/io.openems.edge.example.gruenstrom/.gitignore @@ -0,0 +1 @@ +/generated/ diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java index 3e45c036b3..de5afcaf68 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/Config.java @@ -3,7 +3,7 @@ import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.ObjectClassDefinition; -@ObjectClassDefinition(name = "GruenStrom.Reader", // +@ObjectClassDefinition(name = "GruenStrom Reader", // description = "Implements a reader that checks how green the elecricity of a given area is.") @interface Config { @@ -22,5 +22,5 @@ @AttributeDefinition(name = "Postal Code", description = "The Postal Code of the location to be read.", required = true) String plz() default "94469"; - String webconsole_configurationFactory_nameHint() default "GruenStrom.Reader [{id}]"; + String webconsole_configurationFactory_nameHint() default "GruenStrom Reader [{id}]"; } \ No newline at end of file diff --git a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java index 866f4b38b5..75ba0a3b88 100644 --- a/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java +++ b/io.openems.edge.example.gruenstrom/src/io/openems/edge/example/gruenstrom/GruenStromReaderImpl.java @@ -37,12 +37,12 @@ public class GruenStromReaderImpl extends AbstractOpenemsComponent implements Op private BridgeHttp httpBridge; public GruenStromReaderImpl() { - super(OpenemsComponent.ChannelId.values(), GruenStromReader.ChannelId.values() // - ); + super(OpenemsComponent.ChannelId.values(), GruenStromReader.ChannelId.values()); } @Activate private void activate(ComponentContext context, Config config) { + super.activate(context, config.id(), config.alias(), config.enabled()); this.httpBridge = this.httpBridgeFactory.get(); // Hard code channel value so we can read it in UI this.getGreenLevelChannel().setNextValue(54); @@ -69,7 +69,7 @@ private void activate(ComponentContext context, Config config) { final var time = dataPoint.get("time").getAsLong(); if (time == currentTimestamp) { final var co2 = JsonUtils.getAsInt(dataPoint.get("co2")); - this.getGreenLevelChannel().setNextValue(co2); + this.getGreenLevelChannel().setNextValue(54); } }