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

Implement Asymmetric Active Power Voltage Characteristic and Symmetric Reactive Power Voltage Characteristic Controllers #1258

Merged
merged 69 commits into from
Nov 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
7d67635
active power characteristic added which allows to set fix power accor…
huseyinsaht Jul 29, 2019
e7bb908
name changed on symmetric
huseyinsaht Jul 29, 2019
44b8ef1
Certain values out of safe zone improved
huseyinsaht Jul 31, 2019
93a4c71
debug deleted
huseyinsaht Aug 1, 2019
ee758d0
Active and reactive power characteristics splitted
huseyinsaht Aug 2, 2019
e871393
grid voltage priority changed
huseyinsaht Aug 3, 2019
8d1b390
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Aug 4, 2019
20abc41
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Aug 4, 2019
ea9947f
added some channels
huseyinsaht Aug 7, 2019
c94e4fc
some channels issue, reactive power scale changed
huseyinsaht Aug 8, 2019
9859096
frequency b30 meter, channel voltage ratio
huseyinsaht Sep 13, 2019
83bfca2
some additional channel on SMA and doc changed
huseyinsaht Sep 23, 2019
92c66f6
Each of the phases controlled separately with detecting ess "id"= rel…
huseyinsaht Oct 16, 2019
ab7b464
20sec rule added for hysteresis and calculated power fixed in safe zone
huseyinsaht Oct 19, 2019
9b65945
timeline charge contr added
huseyinsaht Nov 7, 2019
95c0cd8
time line is in update process, deleted will add later on, name chang…
huseyinsaht Nov 11, 2019
d7c7e9d
project name changed to asymmetric
huseyinsaht Feb 8, 2020
019a65c
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Feb 12, 2020
931e9e8
deleted unneccesary sysout
huseyinsaht Feb 12, 2020
6645c10
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Feb 12, 2020
3cc712d
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Sep 23, 2020
06a6e0c
Created an abstract class for power characteristic classes
huseyinsaht Sep 23, 2020
3dc773d
reactive json config second param. converted from percent to power, …
huseyinsaht Sep 23, 2020
e0da1e7
Created abstract class for active and reactive power
venu-sagar Sep 23, 2020
5c5d687
Merge branch 'feature/powervoltagecharacteristic' of https://github.c…
venu-sagar Sep 23, 2020
592793f
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Sep 30, 2020
df74c55
Deleted unused files
huseyinsaht Sep 30, 2020
0985229
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Sep 30, 2020
2b094da
power chr package name changed to activepowervoltagecharacteristic pa…
huseyinsaht Oct 5, 2020
20676af
Test cases added and voltage ratio calculation optimized ==> ess3, gr…
huseyinsaht Oct 5, 2020
d669aff
Update reactive power voltage characteristic
huseyinsaht Oct 5, 2020
3810a7b
add gitignore in test
huseyinsaht Oct 6, 2020
1fa8b25
reactive ctrl deleted
huseyinsaht Oct 6, 2020
230f1e7
Test cases added in Reactive Power Voltage Characteristic Implementation
huseyinsaht Oct 6, 2020
267b368
missing bundles added in EdgeApp.bndrun
huseyinsaht Oct 6, 2020
96163b4
AbstractPowerCharacteristic chanellId extended, hysteresis feature an…
huseyinsaht Oct 20, 2020
3105805
test lines commented
huseyinsaht Oct 20, 2020
953424a
clock and Junit test cases updated
huseyinsaht Oct 20, 2020
5961c62
test case
huseyinsaht Oct 20, 2020
40e899a
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Oct 20, 2020
da4f9e3
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Oct 21, 2020
4033631
EdgeApp fixed
huseyinsaht Oct 21, 2020
bb35184
ActivePowerVoltageCharacteristic, ReactivePowerVoltageCharacteristic …
huseyinsaht Oct 21, 2020
7ae9f6f
AbstractPowerCharacteristic activate methods deleted
huseyinsaht Oct 23, 2020
b1f3bc2
deleted, generated files for removed projects
huseyinsaht Oct 23, 2020
96493c2
SMA modbus registers are reversed
huseyinsaht Oct 23, 2020
d43f413
AbstractPowerCharacteristic converted to AbstractRampFunction, Json e…
huseyinsaht Oct 23, 2020
26f4fb2
HashMap replaced with TreeMap
huseyinsaht Nov 3, 2020
fe4c5d9
Symmetric/Asymmetric Controller changed to Ess Controller
huseyinsaht Nov 3, 2020
06fcf1b
*Export and Private are not required packages deleted from bndtools, …
huseyinsaht Nov 4, 2020
f1f77af
1 more test case added in ActivePowerVoltageCharacteristicImpl
huseyinsaht Nov 4, 2020
59b2e16
parseLine made static
huseyinsaht Nov 4, 2020
3643aca
getLineValue method first parameter changed from String to JsonArray
huseyinsaht Nov 4, 2020
60f7238
Another mistake on casting and method return type
huseyinsaht Nov 4, 2020
604988f
unnneccesarz trz and catch deleted in method parseLine
huseyinsaht Nov 4, 2020
7d8dc6b
voltageRatio and power conf parameters converted to xCoord and yCoord
huseyinsaht Nov 4, 2020
3eab791
PolyLine interfaces will be used instead AbstractRampFunction class
huseyinsaht Nov 4, 2020
3ea312a
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Nov 4, 2020
9ff3697
checkstyle applied
huseyinsaht Nov 4, 2020
a9cf0db
some comments and checkstyle again
huseyinsaht Nov 4, 2020
16bd8ff
readme doc for active and reactive contrllers
huseyinsaht Nov 4, 2020
91e4ab3
a bit more doc, conf param added in doc
huseyinsaht Nov 4, 2020
41fcc59
EdgeApp updated
huseyinsaht Nov 4, 2020
c8492a2
Merge branch 'develop' into feature/powervoltagecharacteristic
huseyinsaht Nov 5, 2020
470ba39
checkstyle deactivated for controllers, and commit prepared via prepa…
huseyinsaht Nov 5, 2020
6ab2a5c
Review
sfeilmeier Nov 5, 2020
a3df0cd
Checkstyle PolyLine
sfeilmeier Nov 5, 2020
e257580
Update readme
sfeilmeier Nov 5, 2020
2f83d7f
review + reset
sfeilmeier Nov 6, 2020
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
2 changes: 1 addition & 1 deletion cnf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
<dependency>
<groupId>org.ops4j.pax.logging</groupId>
<artifactId>pax-logging-api</artifactId>
<version>2.0.5</version>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.logging</groupId>
Expand Down
16 changes: 14 additions & 2 deletions io.openems.common/src/io/openems/common/utils/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

import io.openems.common.exceptions.NotImplementedException;
import io.openems.common.exceptions.OpenemsError;
import io.openems.common.exceptions.OpenemsException;
import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.exceptions.OpenemsException;

public class JsonUtils {

Expand Down Expand Up @@ -124,7 +124,7 @@ public static float getAsFloat(JsonElement jElement) throws OpenemsNamedExceptio
}
throw OpenemsError.JSON_NO_FLOAT.exception(jPrimitive.toString().replaceAll("%", "%%"));
}

public static float getAsFloat(JsonElement jElement, String memberName) throws OpenemsNamedException {
JsonPrimitive jPrimitive = getAsPrimitive(jElement, memberName);
if (jPrimitive.isNumber()) {
Expand Down Expand Up @@ -725,6 +725,11 @@ public JsonObjectBuilder addProperty(String property, boolean value) {
return this;
}

public JsonObjectBuilder addProperty(String property, double value) {
j.addProperty(property, value);
return this;
}

public JsonObjectBuilder addPropertyIfNotNull(String property, String value) {
if (value != null) {
j.addProperty(property, value);
Expand Down Expand Up @@ -753,6 +758,13 @@ public JsonObjectBuilder addPropertyIfNotNull(String property, Boolean value) {
return this;
}

public JsonObjectBuilder addPropertyIfNotNull(String property, Double value) {
if (value != null) {
j.addProperty(property, value);
}
return this;
}

public JsonObjectBuilder add(String property, JsonElement value) {
j.add(property, value);
return this;
Expand Down
6 changes: 4 additions & 2 deletions io.openems.edge.application/EdgeApp.bndrun
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@
bnd.identity;id='io.openems.edge.controller.debug.detailedlog',\
bnd.identity;id='io.openems.edge.controller.debug.log',\
bnd.identity;id='io.openems.edge.controller.ess.acisland',\
bnd.identity;id='io.openems.edge.controller.ess.activepowervoltagecharacteristic',\
bnd.identity;id='io.openems.edge.controller.ess.delaycharge',\
bnd.identity;id='io.openems.edge.controller.ess.delayedselltogrid',\
bnd.identity;id='io.openems.edge.controller.ess.hybrid.surplusfeedtogrid',\
bnd.identity;id='io.openems.edge.controller.ess.limittotaldischarge',\
bnd.identity;id='io.openems.edge.controller.ess.mindischargeperiod',\
bnd.identity;id='io.openems.edge.controller.ess.onefullcycle',\
bnd.identity;id='io.openems.edge.controller.ess.predictivedelaycharge',\
bnd.identity;id='io.openems.edge.controller.ess.reactivepowervoltagecharacteristic',\
bnd.identity;id='io.openems.edge.controller.ess.selltogridlimit',\
bnd.identity;id='io.openems.edge.controller.evcs',\
bnd.identity;id='io.openems.edge.controller.evcs.fixactivepower',\
Expand All @@ -79,7 +81,6 @@
bnd.identity;id='io.openems.edge.controller.symmetric.linearpowerband',\
bnd.identity;id='io.openems.edge.controller.symmetric.peakshaving',\
bnd.identity;id='io.openems.edge.controller.symmetric.randompower',\
bnd.identity;id='io.openems.edge.controller.symmetric.reactivepowervoltagecharacteristic',\
bnd.identity;id='io.openems.edge.controller.symmetric.timeslotpeakshaving',\
bnd.identity;id='io.openems.edge.core',\
bnd.identity;id='io.openems.edge.ess.byd.container',\
Expand Down Expand Up @@ -176,13 +177,15 @@
io.openems.edge.controller.debug.detailedlog;version=snapshot,\
io.openems.edge.controller.debug.log;version=snapshot,\
io.openems.edge.controller.ess.acisland;version=snapshot,\
io.openems.edge.controller.ess.activepowervoltagecharacteristic;version=snapshot,\
io.openems.edge.controller.ess.delaycharge;version=snapshot,\
io.openems.edge.controller.ess.delayedselltogrid;version=snapshot,\
io.openems.edge.controller.ess.hybrid.surplusfeedtogrid;version=snapshot,\
io.openems.edge.controller.ess.limittotaldischarge;version=snapshot,\
io.openems.edge.controller.ess.mindischargeperiod;version=snapshot,\
io.openems.edge.controller.ess.onefullcycle;version=snapshot,\
io.openems.edge.controller.ess.predictivedelaycharge;version=snapshot,\
io.openems.edge.controller.ess.reactivepowervoltagecharacteristic;version=snapshot,\
io.openems.edge.controller.ess.selltogridlimit;version=snapshot,\
io.openems.edge.controller.evcs;version=snapshot,\
io.openems.edge.controller.evcs.fixactivepower;version=snapshot,\
Expand All @@ -202,7 +205,6 @@
io.openems.edge.controller.symmetric.linearpowerband;version=snapshot,\
io.openems.edge.controller.symmetric.peakshaving;version=snapshot,\
io.openems.edge.controller.symmetric.randompower;version=snapshot,\
io.openems.edge.controller.symmetric.reactivepowervoltagecharacteristic;version=snapshot,\
io.openems.edge.controller.symmetric.timeslotpeakshaving;version=snapshot,\
io.openems.edge.core;version=snapshot,\
io.openems.edge.ess.api;version=snapshot,\
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package io.openems.edge.common.linecharacteristic;

import java.util.Map.Entry;
import java.util.TreeMap;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.utils.JsonUtils;

/**
* Defines a polyline built of multiple points defined by a JsonArray.
*
* <p>
* This class can be used e.g. to build Q-by-U characteristics Controllers.
*/
public class PolyLine {

private final TreeMap<Float, Float> points;

/**
* Creates a PolyLine from two points.
*
* @param x1 'x' value of point 1
* @param y1 'y' value of point 1
* @param x2 'x' value of point 2
* @param y2 'y' value of point 2
* @throws OpenemsNamedException on error
*/
public PolyLine(Float x1, Float y1, Float x2, Float y2) throws OpenemsNamedException {
TreeMap<Float, Float> points = new TreeMap<>();
points.put(x1, y1);
points.put(x2, y2);
this.points = points;
}

/**
* Creates a PolyLine from a JSON line configuration.
*
* @param x the name of the 'x' value inside the Json-Array
* @param y the name of the 'y' value inside the Json-Array
* @param lineConfig the configured x and y coordinates values; parsed to a
* Json-Array
* @throws OpenemsNamedException on error
*/
public PolyLine(String x, String y, String lineConfig) throws OpenemsNamedException {
this(x, y, JsonUtils.getAsJsonArray(JsonUtils.parse(lineConfig)));
}

/**
* Creates a PolyLine from a JSON line configuration.
*
* <p>
* Parse the given JSON line format to x and y parameters.
*
* <pre>
* [
* { "x": 0.9, "y":-4000 },
* { "x": 0.93, "y":-1000 },
* { "x": 1.07, "y":1000 },
* { "x": 1.1, "y":4000 }
* ]
* </pre>
*
* @param x the name of the 'x' value inside the Json-Array
* @param y the name of the 'y' value inside the Json-Array
* @param lineConfig the configured x and y coordinates values
* @throws OpenemsNamedException on error
*/
public PolyLine(String x, String y, JsonArray lineConfig) throws OpenemsNamedException {
TreeMap<Float, Float> points = new TreeMap<>();
for (JsonElement element : lineConfig) {
Float xValue = JsonUtils.getAsFloat(element, x);
Float yValue = JsonUtils.getAsFloat(element, y);
points.put(xValue, yValue);
}
this.points = points;
}

/**
* Gets the Y-value for the given X.
*
* @param x the 'x' value
* @return the 'y' value
* @throws OpenemsNamedException on error
*/
public Float getValue(float x) throws OpenemsNamedException {
Entry<Float, Float> floorEntry = this.points.floorEntry(x);
Entry<Float, Float> ceilingEntry = this.points.ceilingEntry(x);

if (floorEntry == null && ceilingEntry == null) {
return null;

} else if (floorEntry == null) {
return ceilingEntry.getValue();

} else if (ceilingEntry == null) {
return floorEntry.getValue();

} else if (floorEntry.equals(ceilingEntry)) {
return floorEntry.getValue();

} else {
Float m = (ceilingEntry.getValue() - floorEntry.getValue()) / (ceilingEntry.getKey() - floorEntry.getKey());
Float t = floorEntry.getValue() - m * floorEntry.getKey();
return m * x + t;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@org.osgi.annotation.versioning.Version("1.0.0")
@org.osgi.annotation.bundle.Export
package io.openems.edge.common.linecharacteristic;
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.openems.edge.common.linecharacteristic;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import com.google.gson.JsonArray;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.utils.JsonUtils;

public class PolyLineTest {

@Test
public void test() throws OpenemsNamedException {
JsonArray lineConfig = JsonUtils.buildJsonArray()//
.add(JsonUtils.buildJsonObject()//
.addProperty("xCoord", 0.9) //
.addProperty("yCoord", 60) //
.build()) //
.add(JsonUtils.buildJsonObject()//
.addProperty("xCoord", 0.93) //
.addProperty("yCoord", 0) //
.build()) //
.add(JsonUtils.buildJsonObject()//
.addProperty("xCoord", 1.07) //
.addProperty("yCoord", 0) //
.build()) //
.add(JsonUtils.buildJsonObject()//
.addProperty("xCoord", 1.1) //
.addProperty("yCoord", -60) //
.build() //
).build();

PolyLine polyline = new PolyLine("xCoord", "yCoord", lineConfig);

// exactly first
assertEquals(60f, polyline.getValue(0.9f), 0.00001);

// exactly last
assertEquals(-60f, polyline.getValue(1.1f), 0.00001);

// beyond last
assertEquals(-60f, polyline.getValue(1.2f), 0.00001);

// before first
assertEquals(60f, polyline.getValue(0.7f), 0.00001);

// between first two
assertEquals(30f, polyline.getValue(0.915f), 0.001);
}

@Test
public void testEmpty() throws OpenemsNamedException {
JsonArray lineConfig = JsonUtils.buildJsonArray().build();

PolyLine polyline = new PolyLine("xCoord", "yCoord", lineConfig);

// exactly first
assertEquals(null, polyline.getValue(0.9f));
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>io.openems.edge.controller.symmetric.reactivepowervoltagecharacteristic</name>
<name>io.openems.edge.controller.ess.activepowervoltagecharacteristic</name>
<comment></comment>
<projects>
</projects>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Bundle-Name: OpenEMS Edge Controller Symmetric Reactive-Power Voltage Characteristics
Bundle-Name: OpenEMS Edge Controller Ess Active Power Voltage Characteristics
Bundle-Vendor: FENECON GmbH
Bundle-License: https://opensource.org/licenses/EPL-2.0
Bundle-Version: 1.0.0.${tstamp}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
= Ess Active Power Voltage Characteristic

* This controller charges/discharges an energy storage system with active power in order to keep the grid voltage within an acceptable range.

* The active power set-point depends on the ratio of the grid voltage divided by the configured `nominalVoltage` parameter.

* The active power per voltage ratio is defined by a poly-line graph in the `lineConfig` parameter. It takes a Json-Array of the following form:

----
[
{
"voltageRatio":0.95,
"power":4000
},
{
"voltageRatio":0.97999,
"power":1000
},
{
"voltageRatio":0.98,
"power":0
},
{
"voltageRatio":1.0299,
"power":0
},
{
"voltageRatio":1.03,
"power":-1000
},
{
"voltageRatio":1.05,
"power":-4000
}
]
----

* `waitForHysteresis` parameter: active power set-point is not updated more often than the hysteresis time in seconds. Default value is 20 seconds. The purpose of this parameter is to avoid oscillation in grid voltage via frequently setting power.

https://github.com/OpenEMS/openems/tree/feature/develop/io.openems.edge.controller.ess.activepowervoltagecharacteristic[Source Code icon:github[]]
Loading