Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hackaton Doc Example #2792

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions io.openems.edge.application/EdgeApp.bndrun
Original file line number Diff line number Diff line change
Expand Up @@ -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)',\
Expand Down Expand Up @@ -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)'
stax2-api;version='[4.2.2,4.2.3)',\
io.openems.edge.example.gruenstrom;version=snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
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.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.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;
import io.openems.edge.core.appmanager.validator.ValidatorConfig;
@Component(name = "App.GruenStrom")
public class GruenStrom extends AbstractOpenemsAppWithProps<GruenStrom, Property, Type.Parameter.BundleParameter>
implements OpenemsApp {

public static enum Property implements Type<Property, GruenStrom, Type.Parameter.BundleParameter>, 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<? super GruenStrom, ? super Property, ? super Type.Parameter.BundleParameter> def;

private Property(AppDef<? super GruenStrom, ? super Property, ? super Type.Parameter.BundleParameter> def) {
this.def = def;
}

@Override
public Property self() {
return this;
}

@Override
public AppDef<? super GruenStrom, ? super Property, ? super BundleParameter> def() {
return this.def;
}

@Override
public Function<GetParameterValues<GruenStrom>, 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<ConfigurationTarget, Map<Property, JsonElement>, 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;
}
}
12 changes: 12 additions & 0 deletions io.openems.edge.example.gruenstrom/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
<classpathentry kind="src" output="bin" path="src"/>
<classpathentry kind="src" output="bin_test" path="test">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
1 change: 1 addition & 0 deletions io.openems.edge.example.gruenstrom/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/generated/
23 changes: 23 additions & 0 deletions io.openems.edge.example.gruenstrom/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>io.openems.edge.example.gruenstrom</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>bndtools.core.bndbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>bndtools.core.bndnature</nature>
</natures>
</projectDescription>
12 changes: 12 additions & 0 deletions io.openems.edge.example.gruenstrom/bnd.bnd
Original file line number Diff line number Diff line change
@@ -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}
Original file line number Diff line number Diff line change
@@ -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 the location to be read.", required = true)
String plz() default "94469";

String webconsole_configurationFactory_nameHint() default "GruenStrom Reader [{id}]";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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.IntegerReadChannel;
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.INTEGER)), //
;
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 IntegerReadChannel getGreenLevelChannel() {
return this.channel(ChannelId.GREEN_LEVEL);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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;
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 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;

@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) {
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);

// TODO: Implement api

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(54);
}
}

} catch (OpenemsNamedException e) {
// log message or error message
}

});

}

@Override
@Deactivate
protected void deactivate() {
super.deactivate();
this.httpBridgeFactory.unget(this.httpBridge);
this.httpBridge = null;
}

}
Loading