Skip to content

Commit 13d98bb

Browse files
Add 'CumulatedActiveTime' Channel for Controllers with Relay (OpenEMS#677) (OpenEMS#2230)
Co-authored-by: Sagar Venu <[email protected]>
1 parent c8b6186 commit 13d98bb

File tree

15 files changed

+192
-34
lines changed

15 files changed

+192
-34
lines changed

io.openems.edge.controller.channelthreshold/bnd.bnd

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Bundle-Version: 1.0.0.${tstamp}
77
${buildpath},\
88
io.openems.common,\
99
io.openems.edge.common,\
10-
io.openems.edge.controller.api
10+
io.openems.edge.controller.api,\
11+
io.openems.edge.timedata.api,\
1112

1213
-testpath: \
1314
${testpath}

io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThreshold.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.openems.edge.controller.channelthreshold;
22

3+
import static io.openems.common.channel.PersistencePriority.HIGH;
4+
import static io.openems.common.channel.Unit.CUMULATED_SECONDS;
5+
import static io.openems.common.types.OpenemsType.LONG;
6+
37
import io.openems.edge.common.channel.Doc;
48
import io.openems.edge.common.component.OpenemsComponent;
59
import io.openems.edge.controller.api.Controller;
@@ -8,7 +12,11 @@ public interface ControllerChannelThreshold extends Controller, OpenemsComponent
812

913
public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
1014
STATE_MACHINE(Doc.of(State.values()) //
11-
.text("Current State of State-Machine"));
15+
.text("Current State of State-Machine")),
16+
17+
CUMULATED_ACTIVE_TIME(Doc.of(LONG)//
18+
.unit(CUMULATED_SECONDS) //
19+
.persistencePriority(HIGH));
1220

1321
private final Doc doc;
1422

io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThresholdImpl.java

+30-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import org.osgi.service.component.annotations.ConfigurationPolicy;
77
import org.osgi.service.component.annotations.Deactivate;
88
import org.osgi.service.component.annotations.Reference;
9+
import org.osgi.service.component.annotations.ReferenceCardinality;
10+
import org.osgi.service.component.annotations.ReferencePolicy;
11+
import org.osgi.service.component.annotations.ReferencePolicyOption;
912
import org.osgi.service.metatype.annotations.Designate;
1013
import org.slf4j.Logger;
1114
import org.slf4j.LoggerFactory;
@@ -21,6 +24,9 @@
2124
import io.openems.edge.common.component.OpenemsComponent;
2225
import io.openems.edge.common.type.TypeUtils;
2326
import io.openems.edge.controller.api.Controller;
27+
import io.openems.edge.timedata.api.Timedata;
28+
import io.openems.edge.timedata.api.TimedataProvider;
29+
import io.openems.edge.timedata.api.utils.CalculateActiveTime;
2430

2531
@Designate(ocd = Config.class, factory = true)
2632
@Component(//
@@ -29,9 +35,11 @@
2935
configurationPolicy = ConfigurationPolicy.REQUIRE //
3036
)
3137
public class ControllerChannelThresholdImpl extends AbstractOpenemsComponent
32-
implements ControllerChannelThreshold, Controller, OpenemsComponent {
38+
implements ControllerChannelThreshold, Controller, OpenemsComponent, TimedataProvider {
3339

3440
private final Logger log = LoggerFactory.getLogger(ControllerChannelThresholdImpl.class);
41+
private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this,
42+
ControllerChannelThreshold.ChannelId.CUMULATED_ACTIVE_TIME);
3543

3644
@Reference
3745
private ComponentManager componentManager;
@@ -50,6 +58,9 @@ public class ControllerChannelThresholdImpl extends AbstractOpenemsComponent
5058
/** Should the hysteresis be applied on passing low threshold?. */
5159
private boolean applyLowHysteresis = true;
5260

61+
@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
62+
private volatile Timedata timedata = null;
63+
5364
public ControllerChannelThresholdImpl() {
5465
super(//
5566
OpenemsComponent.ChannelId.values(), //
@@ -237,24 +248,36 @@ private void off() throws IllegalArgumentException, OpenemsNamedException {
237248
}
238249

239250
/**
240-
* Helper function to switch an output if it was not switched before.
251+
* Helper function to switch an output if it was not switched before; Updates
252+
* the cumulated active time channel.
241253
*
242-
* @param value true to switch ON, false to switch ON; is inverted if
254+
* @param value true to switch ON, false to switch OFF; is inverted if
243255
* 'invertOutput' config is set
244256
* @throws OpenemsNamedException on error
245257
* @throws IllegalArgumentException on error
246258
*/
247259
private void setOutput(boolean value) throws IllegalArgumentException, OpenemsNamedException {
260+
var outputValue = value ^ this.invertOutput;
261+
262+
// Update the cumulated active time.
263+
this.calculateCumulatedActiveTime.update(outputValue);
264+
248265
try {
249266
WriteChannel<Boolean> outputChannel = this.componentManager.getChannel(this.outputChannelAddress);
250267
var currentValueOpt = outputChannel.value().asOptional();
251-
if (!currentValueOpt.isPresent() || currentValueOpt.get() != (value ^ this.invertOutput)) {
252-
this.logInfo(this.log, "Set output [" + outputChannel.address() + "] "
253-
+ (value ^ this.invertOutput ? "ON" : "OFF") + ".");
254-
outputChannel.setNextWriteValue(value ^ this.invertOutput);
268+
if (!currentValueOpt.isPresent() || currentValueOpt.get() != outputValue) {
269+
this.logInfo(this.log,
270+
"Set output [" + outputChannel.address() + "] " + (outputValue ? "ON" : "OFF") + ".");
271+
outputChannel.setNextWriteValue(outputValue);
255272
}
273+
256274
} catch (OpenemsException e) {
257275
this.logError(this.log, "Unable to set output: [" + this.outputChannelAddress + "] " + e.getMessage());
258276
}
259277
}
278+
279+
@Override
280+
public Timedata getTimedata() {
281+
return this.timedata;
282+
}
260283
}

io.openems.edge.controller.chp.soc/bnd.bnd

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Bundle-Version: 1.0.0.${tstamp}
99
io.openems.edge.common,\
1010
io.openems.edge.controller.api,\
1111
io.openems.edge.ess.api,\
12-
io.openems.edge.io.api
12+
io.openems.edge.io.api,\
13+
io.openems.edge.timedata.api,\
1314

1415
-testpath: \
1516
${testpath}

io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSoc.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.openems.edge.controller.chp.soc;
22

3+
import static io.openems.common.channel.PersistencePriority.HIGH;
4+
import static io.openems.common.channel.Unit.CUMULATED_SECONDS;
5+
import static io.openems.common.types.OpenemsType.LONG;
6+
37
import io.openems.edge.common.channel.Doc;
48
import io.openems.edge.common.component.OpenemsComponent;
59
import io.openems.edge.controller.api.Controller;
@@ -11,7 +15,10 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
1115
.initialValue(Mode.AUTOMATIC) //
1216
.text("Configured Mode")), //
1317
STATE_MACHINE(Doc.of(State.values()) //
14-
.text("Current State of State-Machine"));
18+
.text("Current State of State-Machine")),
19+
CUMULATED_ACTIVE_TIME(Doc.of(LONG)//
20+
.unit(CUMULATED_SECONDS) //
21+
.persistencePriority(HIGH));
1522

1623
private final Doc doc;
1724

io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java

+22-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import org.osgi.service.component.annotations.ConfigurationPolicy;
77
import org.osgi.service.component.annotations.Deactivate;
88
import org.osgi.service.component.annotations.Reference;
9+
import org.osgi.service.component.annotations.ReferenceCardinality;
10+
import org.osgi.service.component.annotations.ReferencePolicy;
11+
import org.osgi.service.component.annotations.ReferencePolicyOption;
912
import org.osgi.service.metatype.annotations.Designate;
1013
import org.slf4j.Logger;
1114
import org.slf4j.LoggerFactory;
@@ -21,6 +24,9 @@
2124
import io.openems.edge.common.component.OpenemsComponent;
2225
import io.openems.edge.common.type.TypeUtils;
2326
import io.openems.edge.controller.api.Controller;
27+
import io.openems.edge.timedata.api.Timedata;
28+
import io.openems.edge.timedata.api.TimedataProvider;
29+
import io.openems.edge.timedata.api.utils.CalculateActiveTime;
2430

2531
@Designate(ocd = Config.class, factory = true)
2632
@Component(//
@@ -29,13 +35,18 @@
2935
configurationPolicy = ConfigurationPolicy.REQUIRE //
3036
)
3137
public class ControllerChpSocImpl extends AbstractOpenemsComponent
32-
implements ControllerChpSoc, Controller, OpenemsComponent {
38+
implements ControllerChpSoc, Controller, OpenemsComponent, TimedataProvider {
3339

3440
private final Logger log = LoggerFactory.getLogger(ControllerChpSocImpl.class);
41+
private final CalculateActiveTime cumulatedActiveTime = new CalculateActiveTime(this,
42+
ControllerChpSoc.ChannelId.CUMULATED_ACTIVE_TIME);
3543

3644
@Reference
3745
private ComponentManager componentManager;
3846

47+
@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
48+
private volatile Timedata timedata = null;
49+
3950
private ChannelAddress inputChannelAddress;
4051
private ChannelAddress outputChannelAddress;
4152
private int lowThreshold = 0;
@@ -174,13 +185,17 @@ private boolean changeState(State nextState) {
174185
}
175186

176187
/**
177-
* Helper function to switch an output if it was not switched before.
188+
* Helper function to switch an output if it was not switched before; Updates
189+
* the cumulated active time channel.
178190
*
179191
* @param value true to switch ON, false to switch OFF;
180192
* @throws OpenemsNamedException on error
181193
* @throws IllegalArgumentException on error
182194
*/
183195
private void setOutput(Boolean value) throws IllegalArgumentException, OpenemsNamedException {
196+
// Update the cumulated time
197+
this.cumulatedActiveTime.update(value);
198+
184199
try {
185200
WriteChannel<Boolean> outputChannel = this.componentManager.getChannel(this.outputChannelAddress);
186201
var currentValueOpt = outputChannel.value().asOptional();
@@ -206,4 +221,9 @@ private boolean changeMode(Mode nextMode) {
206221
}
207222
return false;
208223
}
224+
225+
@Override
226+
public Timedata getTimedata() {
227+
return this.timedata;
228+
}
209229
}

io.openems.edge.controller.ess.fixactivepower/bnd.bnd

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Bundle-Version: 1.0.0.${tstamp}
99
io.openems.edge.common,\
1010
io.openems.edge.controller.api,\
1111
io.openems.edge.ess.api,\
12-
12+
io.openems.edge.timedata.api,\
13+
1314
-testpath: \
1415
${testpath}

io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePower.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
package io.openems.edge.controller.ess.fixactivepower;
22

3+
import static io.openems.common.channel.PersistencePriority.HIGH;
4+
import static io.openems.common.channel.Unit.CUMULATED_SECONDS;
5+
import static io.openems.common.types.OpenemsType.LONG;
6+
37
import io.openems.edge.common.channel.Doc;
48
import io.openems.edge.common.component.OpenemsComponent;
59
import io.openems.edge.controller.api.Controller;
610

711
public interface ControllerEssFixActivePower extends Controller, OpenemsComponent {
812

913
public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
10-
;
14+
CUMULATED_ACTIVE_TIME(Doc.of(LONG)//
15+
.unit(CUMULATED_SECONDS) //
16+
.persistencePriority(HIGH));
17+
1118
private final Doc doc;
1219

1320
private ChannelId(Doc doc) {

io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java

+34-12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import io.openems.edge.ess.api.ManagedSymmetricEss;
2222
import io.openems.edge.ess.api.PowerConstraint;
2323
import io.openems.edge.ess.power.api.Pwr;
24+
import io.openems.edge.timedata.api.Timedata;
25+
import io.openems.edge.timedata.api.TimedataProvider;
26+
import io.openems.edge.timedata.api.utils.CalculateActiveTime;
2427

2528
@Designate(ocd = Config.class, factory = true)
2629
@Component(//
@@ -29,7 +32,10 @@
2932
configurationPolicy = ConfigurationPolicy.REQUIRE //
3033
)
3134
public class ControllerEssFixActivePowerImpl extends AbstractOpenemsComponent
32-
implements ControllerEssFixActivePower, Controller, OpenemsComponent {
35+
implements ControllerEssFixActivePower, Controller, OpenemsComponent, TimedataProvider {
36+
37+
private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this,
38+
ControllerEssFixActivePower.ChannelId.CUMULATED_ACTIVE_TIME);
3339

3440
@Reference
3541
private ConfigurationAdmin cm;
@@ -39,6 +45,9 @@ public class ControllerEssFixActivePowerImpl extends AbstractOpenemsComponent
3945

4046
private Config config;
4147

48+
@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
49+
private volatile Timedata timedata = null;
50+
4251
public ControllerEssFixActivePowerImpl() {
4352
super(//
4453
OpenemsComponent.ChannelId.values(), //
@@ -76,17 +85,25 @@ protected void deactivate() {
7685

7786
@Override
7887
public void run() throws OpenemsNamedException {
79-
switch (this.config.mode()) {
80-
case MANUAL_ON:
81-
// Apply Active-Power Set-Point
82-
var acPower = getAcPower(this.ess, this.config.hybridEssMode(), this.config.power());
83-
PowerConstraint.apply(this.ess, this.id(), //
84-
this.config.phase(), Pwr.ACTIVE, this.config.relationship(), acPower);
85-
break;
86-
87-
case MANUAL_OFF:
88-
// Do nothing
89-
break;
88+
var isActive = false;
89+
try {
90+
isActive = switch (this.config.mode()) {
91+
case MANUAL_ON -> {
92+
// Apply Active-Power Set-Point
93+
var acPower = getAcPower(this.ess, this.config.hybridEssMode(), this.config.power());
94+
PowerConstraint.apply(this.ess, this.id(), //
95+
this.config.phase(), Pwr.ACTIVE, this.config.relationship(), acPower);
96+
yield true; // is active
97+
}
98+
99+
case MANUAL_OFF -> {
100+
// Do nothing
101+
yield false; // is not active
102+
}
103+
};
104+
105+
} finally {
106+
this.calculateCumulatedActiveTime.update(isActive);
90107
}
91108
}
92109

@@ -115,4 +132,9 @@ protected static Integer getAcPower(ManagedSymmetricEss ess, HybridEssMode hybri
115132

116133
return null; /* should never happen */
117134
}
135+
136+
@Override
137+
public Timedata getTimedata() {
138+
return this.timedata;
139+
}
118140
}

io.openems.edge.controller.io.channelsinglethreshold/bnd.bnd

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Bundle-Version: 1.0.0.${tstamp}
99
io.openems.edge.common,\
1010
io.openems.edge.controller.api,\
1111
io.openems.edge.ess.api,\
12-
io.openems.edge.io.api
12+
io.openems.edge.io.api,\
13+
io.openems.edge.timedata.api,\
1314

1415
-testpath: \
1516
${testpath}

io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThreshold.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.openems.edge.controller.io.channelsinglethreshold;
22

3+
import static io.openems.common.channel.PersistencePriority.HIGH;
4+
import static io.openems.common.channel.Unit.CUMULATED_SECONDS;
5+
import static io.openems.common.types.OpenemsType.LONG;
6+
37
import io.openems.common.channel.Level;
48
import io.openems.edge.common.channel.Doc;
59
import io.openems.edge.common.channel.StateChannel;
@@ -11,7 +15,12 @@ public interface ControllerIoChannelSingleThreshold extends Controller, OpenemsC
1115

1216
public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
1317
AWAITING_HYSTERESIS(Doc.of(Level.INFO) //
14-
.text("Would change State, but hystesis is active")); //
18+
.text("Would change State, but hystesis is active")),
19+
20+
CUMULATED_ACTIVE_TIME(Doc.of(LONG)//
21+
.unit(CUMULATED_SECONDS) //
22+
.persistencePriority(HIGH)) //
23+
; //
1524

1625
private final Doc doc;
1726

0 commit comments

Comments
 (0)