diff --git a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java index 3a5139195ac..4636330784b 100644 --- a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java +++ b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java @@ -2,10 +2,11 @@ import java.util.List; import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Function; import io.openems.edge.common.channel.AbstractChannelListenerManager; -import io.openems.edge.common.channel.IntegerReadChannel; -import io.openems.edge.common.channel.LongReadChannel; +import io.openems.edge.common.channel.Channel; import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.sum.GridMode; import io.openems.edge.common.type.TypeUtils; @@ -27,26 +28,39 @@ public ChannelManager(EssClusterImpl parent) { * @param esss the List of {@link SymmetricEss} */ protected void activate(List esss) { - this.calculateGridMode(esss); - + // SymmetricEss this.calculateSoc(esss); + this.calculate(INTEGER_SUM, esss, SymmetricEss.ChannelId.CAPACITY); + this.calculateGridMode(esss); + this.calculate(INTEGER_SUM, esss, SymmetricEss.ChannelId.ACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, SymmetricEss.ChannelId.REACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, SymmetricEss.ChannelId.MAX_APPARENT_POWER); - this.calculateSumInteger(esss, SymmetricEss.ChannelId.ACTIVE_POWER); - this.calculateSumInteger(esss, SymmetricEss.ChannelId.REACTIVE_POWER); - this.calculateSumInteger(esss, SymmetricEss.ChannelId.MAX_APPARENT_POWER); + this.calculate(LONG_SUM, esss, SymmetricEss.ChannelId.ACTIVE_CHARGE_ENERGY); + this.calculate(LONG_SUM, esss, SymmetricEss.ChannelId.ACTIVE_DISCHARGE_ENERGY); - this.calculateSumLong(esss, SymmetricEss.ChannelId.ACTIVE_CHARGE_ENERGY); - this.calculateSumLong(esss, SymmetricEss.ChannelId.ACTIVE_DISCHARGE_ENERGY); + this.calculate(INTEGER_MIN, esss, SymmetricEss.ChannelId.MIN_CELL_VOLTAGE); + this.calculate(INTEGER_MAX, esss, SymmetricEss.ChannelId.MAX_CELL_VOLTAGE); + this.calculate(INTEGER_MIN, esss, SymmetricEss.ChannelId.MIN_CELL_TEMPERATURE); + this.calculate(INTEGER_MAX, esss, SymmetricEss.ChannelId.MAX_CELL_TEMPERATURE); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L1); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L2); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L3); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L1); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L2); - this.calculateSumInteger(esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L3); + // AsymmetricEss + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L1, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.ACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L2, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.ACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.ACTIVE_POWER_L3, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.ACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L1, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.REACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L2, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.REACTIVE_POWER); + this.calculate(INTEGER_SUM, esss, AsymmetricEss.ChannelId.REACTIVE_POWER_L3, // + DIVIDE_BY_THREE, SymmetricEss.ChannelId.REACTIVE_POWER); - this.calculateSumInteger(esss, ManagedSymmetricEss.ChannelId.ALLOWED_CHARGE_POWER); - this.calculateSumInteger(esss, ManagedSymmetricEss.ChannelId.ALLOWED_DISCHARGE_POWER); + // ManagedSymmetricEss + this.calculate(INTEGER_SUM, esss, ManagedSymmetricEss.ChannelId.ALLOWED_CHARGE_POWER); + this.calculate(INTEGER_SUM, esss, ManagedSymmetricEss.ChannelId.ALLOWED_DISCHARGE_POWER); } /** @@ -117,21 +131,42 @@ private void calculateSoc(List esss) { } } + private final static Function DIVIDE_BY_THREE = (value) -> { + return TypeUtils.divide(value, 3); + }; + private final static BiFunction INTEGER_MIN = (result, value) -> { + return TypeUtils.min(result, value); + }; + + private final static BiFunction INTEGER_MAX = (result, value) -> { + return TypeUtils.max(result, value); + }; + + private final static BiFunction INTEGER_SUM = (result, value) -> { + return TypeUtils.sum(result, value); + }; + + private final static BiFunction LONG_SUM = (result, value) -> { + return TypeUtils.sum(result, value); + }; + /** - * Sum up Integer Channels of {@link SymmetricEss}. + * Aggregate Channels of {@link SymmetricEss}s. * - * @param esss the List of {@link SymmetricEss} - * @param channelId the SymmetricEss.ChannelId + * @param aggregator the aggregator function + * @param esss the List of {@link SymmetricEss} + * @param channelId the SymmetricEss.ChannelId */ - private void calculateSumInteger(List esss, SymmetricEss.ChannelId channelId) { - final BiConsumer, Value> callback = (oldValue, newValue) -> { - Integer result = null; + private void calculate(BiFunction aggregator, List esss, + SymmetricEss.ChannelId channelId) { + final BiConsumer, Value> callback = (oldValue, newValue) -> { + T result = null; for (SymmetricEss ess : esss) { - IntegerReadChannel channel = ess.channel(channelId); - result = TypeUtils.sum(result, channel.getNextValue().get()); + Channel channel = ess.channel(channelId); + result = aggregator.apply(result, channel.getNextValue().get()); } - IntegerReadChannel channel = this.parent.channel(channelId); + Channel channel = this.parent.channel(channelId); channel.setNextValue(result); }; @@ -141,84 +176,106 @@ private void calculateSumInteger(List esss, SymmetricEss.ChannelId } /** - * Sum up Integer Channels of {@link ManagedSymmetricEss}. + * Aggregate Channels of {@link ManagedSymmetricEss}s. * - * @param esss the List of {@link ManagedSymmetricEss} - * @param channelId the ManagedSymmetricEss.ChannelId + * @param aggregator the aggregator function + * @param esss the List of {@link SymmetricEss} + * @param channelId the SymmetricEss.ChannelId */ - private void calculateSumInteger(List esss, ManagedSymmetricEss.ChannelId channelId) { - final BiConsumer, Value> callback = (oldValue, newValue) -> { - Integer result = null; + private void calculate(BiFunction aggregator, List esss, + ManagedSymmetricEss.ChannelId channelId) { + final BiConsumer, Value> callback = (oldValue, newValue) -> { + T result = null; for (SymmetricEss ess : esss) { if (ess instanceof ManagedSymmetricEss) { - ManagedSymmetricEss e = (ManagedSymmetricEss) ess; - IntegerReadChannel channel = e.channel(channelId); - result = TypeUtils.sum(result, channel.getNextValue().get()); + Channel channel = ((ManagedSymmetricEss) ess).channel(channelId); + result = aggregator.apply(result, channel.getNextValue().get()); } } - IntegerReadChannel channel = this.parent.channel(channelId); + Channel channel = this.parent.channel(channelId); channel.setNextValue(result); }; for (SymmetricEss ess : esss) { if (ess instanceof ManagedSymmetricEss) { - ManagedSymmetricEss e = (ManagedSymmetricEss) ess; - this.addOnChangeListener(e, channelId, callback); + this.addOnChangeListener((ManagedSymmetricEss) ess, channelId, callback); } } } /** - * Sum up Integer Channels of {@link AsymmetricEss}. + * Aggregate Channels of {@link AsymmetricEss}s. * - * @param esss the List of {@link AsymmetricEss} - * @param channelId the AsymmetricEss.ChannelId + * @param aggregator the aggregator function + * @param esss the List of {@link SymmetricEss} + * @param asymmetricChannelId the AsymmetricEss.ChannelId + * @param asymmetricChannelId the fallback SymmetricEss.ChannelId; used for + * SymmetricEss and divided by 3 */ - private void calculateSumInteger(List esss, AsymmetricEss.ChannelId channelId) { - final BiConsumer, Value> callback = (oldValue, newValue) -> { - Integer result = null; + private void calculate(BiFunction aggregator, List esss, + AsymmetricEss.ChannelId asymmetricChannelId, Function divideFunction, + SymmetricEss.ChannelId symmetricChannelId) { + final BiConsumer, Value> callback = (oldValue, newValue) -> { + T result = null; for (SymmetricEss ess : esss) { if (ess instanceof AsymmetricEss) { - AsymmetricEss e = (AsymmetricEss) ess; - IntegerReadChannel channel = e.channel(channelId); - result = TypeUtils.sum(result, channel.getNextValue().get()); + Channel channel = ((AsymmetricEss) ess).channel(asymmetricChannelId); + result = aggregator.apply(result, channel.getNextValue().get()); + } else { + // SymmetricEss + Channel channel = ess.channel(symmetricChannelId); + result = aggregator.apply(result, divideFunction.apply(channel.getNextValue().get())); } } - IntegerReadChannel channel = this.parent.channel(channelId); + Channel channel = this.parent.channel(asymmetricChannelId); channel.setNextValue(result); }; for (SymmetricEss ess : esss) { if (ess instanceof AsymmetricEss) { - AsymmetricEss e = (AsymmetricEss) ess; - this.addOnChangeListener(e, channelId, callback); - } - } - } - - /** - * Sum up Long Channels of {@link SymmetricEss}. - * - * @param esss the List of {@link SymmetricEss} - * @param channelId the SymmetricEss.ChannelId - */ - private void calculateSumLong(List esss, SymmetricEss.ChannelId channelId) { - final BiConsumer, Value> callback = (oldValue, newValue) -> { - Long result = null; - for (SymmetricEss ess : esss) { - LongReadChannel channel = ess.channel(channelId); - result = TypeUtils.sum(result, channel.getNextValue().get()); + this.addOnChangeListener((AsymmetricEss) ess, asymmetricChannelId, callback); + } else { + this.addOnChangeListener(ess, symmetricChannelId, callback); } - - LongReadChannel channel = this.parent.channel(channelId); - channel.setNextValue(result); - }; - - for (SymmetricEss ess : esss) { - this.addOnChangeListener(ess, channelId, callback); } } +// /** +// * Aggregate Channels of {@link AsymmetricEss}s. +// * +// * @param aggregator the aggregator function +// * @param esss the List of {@link SymmetricEss} +// * @param asymmetricChannelId the AsymmetricEss.ChannelId +// * @param asymmetricChannelId the fallback SymmetricEss.ChannelId; used for +// * SymmetricEss and divided by 3 +// */ +// private void calculate(BiFunction aggregator, List esss, +// AsymmetricEss.ChannelId asymmetricChannelId, SymmetricEss.ChannelId symmetricChannelId) { +// final BiConsumer, Value> callback = (oldValue, newValue) -> { +// Integer result = null; +// for (SymmetricEss ess : esss) { +// if (ess instanceof AsymmetricEss) { +// Channel channel = ((AsymmetricEss) ess).channel(asymmetricChannelId); +// result = aggregator.apply(result, channel.getNextValue().get()); +// } else { +// // SymmetricEss +// Channel channel = ess.channel(symmetricChannelId); +// result = aggregator.apply(result, TypeUtils.divide(channel.getNextValue().get(), 3)); +// } +// } +// +// Channel channel = this.parent.channel(asymmetricChannelId); +// channel.setNextValue(result); +// }; +// +// for (SymmetricEss ess : esss) { +// if (ess instanceof AsymmetricEss) { +// this.addOnChangeListener((AsymmetricEss) ess, asymmetricChannelId, callback); +// } else { +// this.addOnChangeListener(ess, symmetricChannelId, callback); +// } +// } +// } } diff --git a/io.openems.edge.ess.cluster/test/io/openems/edge/ess/cluster/EssClusterTest.java b/io.openems.edge.ess.cluster/test/io/openems/edge/ess/cluster/EssClusterTest.java index 4ac12e4d513..674b169d4c3 100644 --- a/io.openems.edge.ess.cluster/test/io/openems/edge/ess/cluster/EssClusterTest.java +++ b/io.openems.edge.ess.cluster/test/io/openems/edge/ess/cluster/EssClusterTest.java @@ -84,7 +84,7 @@ public void testCluster() throws Exception { .output(CLUSTER_ACTIVE_CHARGE_ENERGY, 3L) // .input(ESS2_ACTIVE_POWER_L1, 1111) // - .output(CLUSTER_ACTIVE_POWER_L1, 1111) // + .output(CLUSTER_ACTIVE_POWER_L1, 1234 / 3 + 1111) // .input(ESS1_ALLOWED_CHARGE_POWER, 11) // .input(ESS2_ALLOWED_CHARGE_POWER, 22) //