Skip to content

Commit

Permalink
Zone selection config for Time-of-Use-Tariff Awattar
Browse files Browse the repository at this point in the history
Time-of-use-Tariff Awattar currently only offers price information for Germany. However, for users in Austria, a separate URL needs to be incorporated.
In this implementation the system is updated by introducing a country selection option in the configuration. Users can now choose between Germany and Austria, and the system will provide country-specific prices accordingly.

Co-authored-by: Sagar Venu <[email protected]>
Co-authored-by: Hueseyin Sahutoglu <[email protected]>
  • Loading branch information
3 people committed Feb 1, 2024
1 parent da53816 commit ca1f4a7
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
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 java.util.Map;
import java.util.function.Function;

Expand All @@ -17,7 +20,8 @@
import io.openems.common.session.Language;
import io.openems.common.types.EdgeConfig;
import io.openems.common.utils.JsonUtils;
import io.openems.edge.app.common.props.CommonProps;
import io.openems.edge.app.enums.OptionsFactory;
import io.openems.edge.app.enums.TranslatableEnum;
import io.openems.edge.app.timeofusetariff.AwattarHourly.Property;
import io.openems.edge.common.component.ComponentManager;
import io.openems.edge.core.appmanager.AbstractOpenemsApp;
Expand All @@ -31,9 +35,11 @@
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.formly.JsonFormlyUtil;

/**
* Describes a App for AwattarHourly.
Expand All @@ -47,7 +53,8 @@
"properties":{
"CTRL_ESS_TIME_OF_USE_TARIFF_ID": "ctrlEssTimeOfUseTariff0",
"TIME_OF_USE_TARIFF_PROVIDER_ID": "timeOfUseTariff0",
"CONTROL_MODE": {@link ControlMode}
"CONTROL_MODE": {@link ControlMode},
"ZONE": {@link Zone},
},
"appDescriptor": {
"websiteUrl": {@link AppDescriptor#getWebsiteUrl()}
Expand All @@ -65,7 +72,16 @@ public static enum Property implements Type<Property, AwattarHourly, Type.Parame
TIME_OF_USE_TARIFF_PROVIDER_ID(AppDef.componentId("timeOfUseTariff0")), //

// Properties
ALIAS(CommonProps.alias());
ALIAS(alias()),

ZONE(AppDef.copyOfGeneric(defaultDef(), def -> def //
.setTranslatedLabelWithAppPrefix(".zone.label") //
.setTranslatedDescriptionWithAppPrefix(".zone.description") //
.setRequired(true)//
.setDefaultValue(Zone.GERMANY)//
.setField(JsonFormlyUtil::buildSelectFromNameable, (app, property, l, parameter, field) -> {
field.setOptions(Zone.optionsFactory(), l);
})));

private final AppDef<? super AwattarHourly, ? super Property, ? super Type.Parameter.BundleParameter> def;

Expand Down Expand Up @@ -100,6 +116,7 @@ protected ThrowingTriFunction<ConfigurationTarget, Map<Property, JsonElement>, L
return (t, p, l) -> {
final var timeOfUseTariffProviderId = this.getId(t, p, Property.TIME_OF_USE_TARIFF_PROVIDER_ID);
final var ctrlEssTimeOfUseTariffId = this.getId(t, p, Property.CTRL_ESS_TIME_OF_USE_TARIFF_ID);
final var zone = this.getEnum(p, Zone.class, Property.ZONE);

final var alias = this.getString(p, l, Property.ALIAS);

Expand All @@ -110,6 +127,7 @@ protected ThrowingTriFunction<ConfigurationTarget, Map<Property, JsonElement>, L
.build()), //
new EdgeConfig.Component(timeOfUseTariffProviderId, this.getName(l), "TimeOfUseTariff.Awattar",
JsonUtils.buildJsonObject() //
.addProperty("zone", zone) //
.build())//
);

Expand Down Expand Up @@ -148,4 +166,33 @@ protected AwattarHourly getApp() {
return this;
}

public enum Zone implements TranslatableEnum {
GERMANY("germany"), //
AUSTRIA("austria"), //
;

private static final String TRANSLATION_PREFIX = "App.TimeOfUseTariff.Awattar.zone.option.";

private final String translationKey;

private Zone(String translationKey) {
this.translationKey = TRANSLATION_PREFIX + translationKey;
}

@Override
public final String getTranslation(Language l) {
final var bundle = AbstractOpenemsApp.getTranslationBundle(l);
return TranslationUtil.getTranslation(bundle, this.translationKey);
}

/**
* Creates a {@link OptionsFactory} of this enum.
*
* @return the {@link OptionsFactory}
*/
public static final OptionsFactory optionsFactory() {
return OptionsFactory.of(values());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ App.PvInverter.SolarEdge.Name.short = SolarEdge
# Time of use Tariff
App.TimeOfUseTariff.Awattar.Name = Dynamischer Stromtarif (Awattar HOURLY)
App.TimeOfUseTariff.Awattar.Name.short = Awattar HOURLY
App.TimeOfUseTariff.Awattar.zone.label = Zone
App.TimeOfUseTariff.Awattar.zone.description = z.B. Deutschland, Österreich
App.TimeOfUseTariff.Awattar.zone.option.austria = Österreich
App.TimeOfUseTariff.Awattar.zone.option.germany = Deutschland
App.TimeOfUseTariff.ENTSO-E.Name = Dynamischer Stromtarif (ENTSO-E)
App.TimeOfUseTariff.ENTSO-E.Name.short = ENTSO-E
App.TimeOfUseTariff.ENTSO-E.biddingZone.label = Gebotszone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ App.PvInverter.SolarEdge.Name.short = SolarEdge
# Time of use Tarif
App.TimeOfUseTariff.Awattar.Name = Time-of-Use Tariff (Awattar HOURLY)
App.TimeOfUseTariff.Awattar.Name.short = Awattar HOURLY
App.TimeOfUseTariff.Awattar.zone.label = Zone
App.TimeOfUseTariff.Awattar.zone.description = e.g. Germany, Austria
App.TimeOfUseTariff.Awattar.zone.option.austria = Austria
App.TimeOfUseTariff.Awattar.zone.option.germany = Germany
App.TimeOfUseTariff.ENTSO-E.Name = Time-of-Use Tariff (ENTSO-E)
App.TimeOfUseTariff.ENTSO-E.Name.short = ENTSO-E
App.TimeOfUseTariff.ENTSO-E.biddingZone.label = Bidding Zone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
@AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?")
boolean enabled() default true;

@AttributeDefinition(name = "Zone", description = "Zone corresponding to the customer's location")
Zone zone() default Zone.GERMANY;

String webconsole_configurationFactory_nameHint() default "Time-Of-Use Tariff Awattar [{id}]";
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@
public class TimeOfUseTariffAwattarImpl extends AbstractOpenemsComponent
implements TimeOfUseTariff, OpenemsComponent, TimeOfUseTariffAwattar {

private static final String AWATTAR_API_URL = "https://api.awattar.de/v1/marketdata";

private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private final AtomicReference<ImmutableSortedMap<ZonedDateTime, Float>> prices = new AtomicReference<>(
ImmutableSortedMap.of());
Expand All @@ -60,6 +58,7 @@ public class TimeOfUseTariffAwattarImpl extends AbstractOpenemsComponent
@Reference
private ComponentManager componentManager;

private Config config = null;
private ZonedDateTime updateTimeStamp = null;

public TimeOfUseTariffAwattarImpl() {
Expand All @@ -77,6 +76,7 @@ private void activate(ComponentContext context, Config config) {
return;
}

this.config = config;
this.executor.schedule(this.task, 0, TimeUnit.SECONDS);
}

Expand All @@ -93,8 +93,9 @@ protected void deactivate() {
* Update Map of prices
*/
var client = new OkHttpClient();
final var url = this.config.zone().toUrl();
var request = new Request.Builder() //
.url(AWATTAR_API_URL) //
.url(url) //
// aWATTar currently does not anymore require an Apikey.
// .header("Authorization", Credentials.basic(apikey, "")) //
.build();
Expand Down Expand Up @@ -165,7 +166,7 @@ public static ImmutableSortedMap<ZonedDateTime, Float> parsePrices(String jsonDa
var startTimeStamp = ZonedDateTime //
.ofInstant(Instant.ofEpochMilli(startTimestampLong), ZoneId.systemDefault())
.truncatedTo(ChronoUnit.HOURS);

// Adding the values in the Map.
result.put(startTimeStamp, marketPrice);
result.put(startTimeStamp.plusMinutes(15), marketPrice);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.openems.edge.timeofusetariff.awattar;

/**
* Represents different energy market zones.
*/
public enum Zone {

/**
* The energy market zone for Germany.
*/
GERMANY, //

/**
* The energy market zone for Austria.
*/
AUSTRIA;

/**
* Returns the API URL specific to the {@link Zone}.
*
* @return The {@link Zone} specific API URL.
*/
public String toUrl() {
return switch (this) {
case GERMANY -> "https://api.awattar.de/v1/marketdata";
case AUSTRIA -> "https://api.awattar.at/v1/marketdata";
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class MyConfig extends AbstractComponentConfig implements Config {

public static class Builder {
private String id;
private int zipcode;
private Zone zone;

private Builder() {
}
Expand All @@ -17,6 +17,11 @@ public Builder setId(String id) {
return this;
}

public Builder setZone(Zone zone) {
this.zone = zone;
return this;
}

public MyConfig build() {
return new MyConfig(this);
}
Expand All @@ -38,4 +43,9 @@ private MyConfig(Builder builder) {
this.builder = builder;
}

@Override
public Zone zone() {
return this.builder.zone;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ public void test() throws Exception {
new ComponentTest(awattar) //
.activate(MyConfig.create() //
.setId(CTRL_ID) //
.setZone(Zone.GERMANY) //
.build()) //
;

// Thread.sleep(5000);
// System.out.println(sut.getPrices());
}

@Test
Expand Down

0 comments on commit ca1f4a7

Please sign in to comment.