From 13d98bb8bae263d2f860d6460f35d3028c7095e0 Mon Sep 17 00:00:00 2001 From: Stefan Feilmeier Date: Sat, 17 Jun 2023 22:41:03 +0200 Subject: [PATCH] Add 'CumulatedActiveTime' Channel for Controllers with Relay (#677) (#2230) Co-authored-by: Sagar Venu <32655208+venu-sagar@users.noreply.github.com> --- .../bnd.bnd | 3 +- .../ControllerChannelThreshold.java | 10 +++- .../ControllerChannelThresholdImpl.java | 37 ++++++++++++--- io.openems.edge.controller.chp.soc/bnd.bnd | 3 +- .../controller/chp/soc/ControllerChpSoc.java | 9 +++- .../chp/soc/ControllerChpSocImpl.java | 24 +++++++++- .../bnd.bnd | 3 +- .../ControllerEssFixActivePower.java | 9 +++- .../ControllerEssFixActivePowerImpl.java | 46 ++++++++++++++----- .../bnd.bnd | 3 +- .../ControllerIoChannelSingleThreshold.java | 11 ++++- ...ontrollerIoChannelSingleThresholdImpl.java | 24 +++++++++- .../bnd.bnd | 3 +- .../ControllerIoFixDigitalOutput.java | 9 +++- .../ControllerIoFixDigitalOutputImpl.java | 32 ++++++++++++- 15 files changed, 192 insertions(+), 34 deletions(-) diff --git a/io.openems.edge.controller.channelthreshold/bnd.bnd b/io.openems.edge.controller.channelthreshold/bnd.bnd index c32920b8ff3..b73ac24bf15 100644 --- a/io.openems.edge.controller.channelthreshold/bnd.bnd +++ b/io.openems.edge.controller.channelthreshold/bnd.bnd @@ -7,7 +7,8 @@ Bundle-Version: 1.0.0.${tstamp} ${buildpath},\ io.openems.common,\ io.openems.edge.common,\ - io.openems.edge.controller.api + io.openems.edge.controller.api,\ + io.openems.edge.timedata.api,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThreshold.java b/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThreshold.java index fefad8473bb..e426431414d 100644 --- a/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThreshold.java +++ b/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThreshold.java @@ -1,5 +1,9 @@ package io.openems.edge.controller.channelthreshold; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.Unit.CUMULATED_SECONDS; +import static io.openems.common.types.OpenemsType.LONG; + import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; @@ -8,7 +12,11 @@ public interface ControllerChannelThreshold extends Controller, OpenemsComponent public enum ChannelId implements io.openems.edge.common.channel.ChannelId { STATE_MACHINE(Doc.of(State.values()) // - .text("Current State of State-Machine")); + .text("Current State of State-Machine")), + + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// + .unit(CUMULATED_SECONDS) // + .persistencePriority(HIGH)); private final Doc doc; diff --git a/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThresholdImpl.java b/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThresholdImpl.java index 79525a79957..53d715d75ed 100644 --- a/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThresholdImpl.java +++ b/io.openems.edge.controller.channelthreshold/src/io/openems/edge/controller/channelthreshold/ControllerChannelThresholdImpl.java @@ -6,6 +6,9 @@ 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.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.osgi.service.metatype.annotations.Designate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +24,9 @@ import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.type.TypeUtils; import io.openems.edge.controller.api.Controller; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateActiveTime; @Designate(ocd = Config.class, factory = true) @Component(// @@ -29,9 +35,11 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerChannelThresholdImpl extends AbstractOpenemsComponent - implements ControllerChannelThreshold, Controller, OpenemsComponent { + implements ControllerChannelThreshold, Controller, OpenemsComponent, TimedataProvider { private final Logger log = LoggerFactory.getLogger(ControllerChannelThresholdImpl.class); + private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this, + ControllerChannelThreshold.ChannelId.CUMULATED_ACTIVE_TIME); @Reference private ComponentManager componentManager; @@ -50,6 +58,9 @@ public class ControllerChannelThresholdImpl extends AbstractOpenemsComponent /** Should the hysteresis be applied on passing low threshold?. */ private boolean applyLowHysteresis = true; + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile Timedata timedata = null; + public ControllerChannelThresholdImpl() { super(// OpenemsComponent.ChannelId.values(), // @@ -237,24 +248,36 @@ private void off() throws IllegalArgumentException, OpenemsNamedException { } /** - * Helper function to switch an output if it was not switched before. + * Helper function to switch an output if it was not switched before; Updates + * the cumulated active time channel. * - * @param value true to switch ON, false to switch ON; is inverted if + * @param value true to switch ON, false to switch OFF; is inverted if * 'invertOutput' config is set * @throws OpenemsNamedException on error * @throws IllegalArgumentException on error */ private void setOutput(boolean value) throws IllegalArgumentException, OpenemsNamedException { + var outputValue = value ^ this.invertOutput; + + // Update the cumulated active time. + this.calculateCumulatedActiveTime.update(outputValue); + try { WriteChannel outputChannel = this.componentManager.getChannel(this.outputChannelAddress); var currentValueOpt = outputChannel.value().asOptional(); - if (!currentValueOpt.isPresent() || currentValueOpt.get() != (value ^ this.invertOutput)) { - this.logInfo(this.log, "Set output [" + outputChannel.address() + "] " - + (value ^ this.invertOutput ? "ON" : "OFF") + "."); - outputChannel.setNextWriteValue(value ^ this.invertOutput); + if (!currentValueOpt.isPresent() || currentValueOpt.get() != outputValue) { + this.logInfo(this.log, + "Set output [" + outputChannel.address() + "] " + (outputValue ? "ON" : "OFF") + "."); + outputChannel.setNextWriteValue(outputValue); } + } catch (OpenemsException e) { this.logError(this.log, "Unable to set output: [" + this.outputChannelAddress + "] " + e.getMessage()); } } + + @Override + public Timedata getTimedata() { + return this.timedata; + } } diff --git a/io.openems.edge.controller.chp.soc/bnd.bnd b/io.openems.edge.controller.chp.soc/bnd.bnd index 5a9ae54feb7..674d2cfa9eb 100644 --- a/io.openems.edge.controller.chp.soc/bnd.bnd +++ b/io.openems.edge.controller.chp.soc/bnd.bnd @@ -9,7 +9,8 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.common,\ io.openems.edge.controller.api,\ io.openems.edge.ess.api,\ - io.openems.edge.io.api + io.openems.edge.io.api,\ + io.openems.edge.timedata.api,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSoc.java b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSoc.java index 60bb8e3ba4c..ccdb510ce92 100644 --- a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSoc.java +++ b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSoc.java @@ -1,5 +1,9 @@ package io.openems.edge.controller.chp.soc; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.Unit.CUMULATED_SECONDS; +import static io.openems.common.types.OpenemsType.LONG; + import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; @@ -11,7 +15,10 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { .initialValue(Mode.AUTOMATIC) // .text("Configured Mode")), // STATE_MACHINE(Doc.of(State.values()) // - .text("Current State of State-Machine")); + .text("Current State of State-Machine")), + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// + .unit(CUMULATED_SECONDS) // + .persistencePriority(HIGH)); private final Doc doc; diff --git a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java index 5a0ce6add60..8affca4f438 100644 --- a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java +++ b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java @@ -6,6 +6,9 @@ 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.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.osgi.service.metatype.annotations.Designate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +24,9 @@ import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.type.TypeUtils; import io.openems.edge.controller.api.Controller; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateActiveTime; @Designate(ocd = Config.class, factory = true) @Component(// @@ -29,13 +35,18 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerChpSocImpl extends AbstractOpenemsComponent - implements ControllerChpSoc, Controller, OpenemsComponent { + implements ControllerChpSoc, Controller, OpenemsComponent, TimedataProvider { private final Logger log = LoggerFactory.getLogger(ControllerChpSocImpl.class); + private final CalculateActiveTime cumulatedActiveTime = new CalculateActiveTime(this, + ControllerChpSoc.ChannelId.CUMULATED_ACTIVE_TIME); @Reference private ComponentManager componentManager; + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile Timedata timedata = null; + private ChannelAddress inputChannelAddress; private ChannelAddress outputChannelAddress; private int lowThreshold = 0; @@ -174,13 +185,17 @@ private boolean changeState(State nextState) { } /** - * Helper function to switch an output if it was not switched before. + * Helper function to switch an output if it was not switched before; Updates + * the cumulated active time channel. * * @param value true to switch ON, false to switch OFF; * @throws OpenemsNamedException on error * @throws IllegalArgumentException on error */ private void setOutput(Boolean value) throws IllegalArgumentException, OpenemsNamedException { + // Update the cumulated time + this.cumulatedActiveTime.update(value); + try { WriteChannel outputChannel = this.componentManager.getChannel(this.outputChannelAddress); var currentValueOpt = outputChannel.value().asOptional(); @@ -206,4 +221,9 @@ private boolean changeMode(Mode nextMode) { } return false; } + + @Override + public Timedata getTimedata() { + return this.timedata; + } } diff --git a/io.openems.edge.controller.ess.fixactivepower/bnd.bnd b/io.openems.edge.controller.ess.fixactivepower/bnd.bnd index 177a0572e1e..9b0e7d57001 100644 --- a/io.openems.edge.controller.ess.fixactivepower/bnd.bnd +++ b/io.openems.edge.controller.ess.fixactivepower/bnd.bnd @@ -9,6 +9,7 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.common,\ io.openems.edge.controller.api,\ io.openems.edge.ess.api,\ - + io.openems.edge.timedata.api,\ + -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePower.java b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePower.java index 4e09d304597..df52e77feda 100644 --- a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePower.java +++ b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePower.java @@ -1,5 +1,9 @@ package io.openems.edge.controller.ess.fixactivepower; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.Unit.CUMULATED_SECONDS; +import static io.openems.common.types.OpenemsType.LONG; + import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; @@ -7,7 +11,10 @@ public interface ControllerEssFixActivePower extends Controller, OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { - ; + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// + .unit(CUMULATED_SECONDS) // + .persistencePriority(HIGH)); + private final Doc doc; private ChannelId(Doc doc) { diff --git a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java index e1ee0804daa..ad3f5905e0e 100644 --- a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java +++ b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java @@ -21,6 +21,9 @@ import io.openems.edge.ess.api.ManagedSymmetricEss; import io.openems.edge.ess.api.PowerConstraint; import io.openems.edge.ess.power.api.Pwr; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateActiveTime; @Designate(ocd = Config.class, factory = true) @Component(// @@ -29,7 +32,10 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerEssFixActivePowerImpl extends AbstractOpenemsComponent - implements ControllerEssFixActivePower, Controller, OpenemsComponent { + implements ControllerEssFixActivePower, Controller, OpenemsComponent, TimedataProvider { + + private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this, + ControllerEssFixActivePower.ChannelId.CUMULATED_ACTIVE_TIME); @Reference private ConfigurationAdmin cm; @@ -39,6 +45,9 @@ public class ControllerEssFixActivePowerImpl extends AbstractOpenemsComponent private Config config; + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile Timedata timedata = null; + public ControllerEssFixActivePowerImpl() { super(// OpenemsComponent.ChannelId.values(), // @@ -76,17 +85,25 @@ protected void deactivate() { @Override public void run() throws OpenemsNamedException { - switch (this.config.mode()) { - case MANUAL_ON: - // Apply Active-Power Set-Point - var acPower = getAcPower(this.ess, this.config.hybridEssMode(), this.config.power()); - PowerConstraint.apply(this.ess, this.id(), // - this.config.phase(), Pwr.ACTIVE, this.config.relationship(), acPower); - break; - - case MANUAL_OFF: - // Do nothing - break; + var isActive = false; + try { + isActive = switch (this.config.mode()) { + case MANUAL_ON -> { + // Apply Active-Power Set-Point + var acPower = getAcPower(this.ess, this.config.hybridEssMode(), this.config.power()); + PowerConstraint.apply(this.ess, this.id(), // + this.config.phase(), Pwr.ACTIVE, this.config.relationship(), acPower); + yield true; // is active + } + + case MANUAL_OFF -> { + // Do nothing + yield false; // is not active + } + }; + + } finally { + this.calculateCumulatedActiveTime.update(isActive); } } @@ -115,4 +132,9 @@ protected static Integer getAcPower(ManagedSymmetricEss ess, HybridEssMode hybri return null; /* should never happen */ } + + @Override + public Timedata getTimedata() { + return this.timedata; + } } \ No newline at end of file diff --git a/io.openems.edge.controller.io.channelsinglethreshold/bnd.bnd b/io.openems.edge.controller.io.channelsinglethreshold/bnd.bnd index 144234ed4dc..6b646015cd6 100644 --- a/io.openems.edge.controller.io.channelsinglethreshold/bnd.bnd +++ b/io.openems.edge.controller.io.channelsinglethreshold/bnd.bnd @@ -9,7 +9,8 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.common,\ io.openems.edge.controller.api,\ io.openems.edge.ess.api,\ - io.openems.edge.io.api + io.openems.edge.io.api,\ + io.openems.edge.timedata.api,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThreshold.java b/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThreshold.java index f6e9a2a5e3b..460ceb801bf 100644 --- a/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThreshold.java +++ b/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThreshold.java @@ -1,5 +1,9 @@ package io.openems.edge.controller.io.channelsinglethreshold; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.Unit.CUMULATED_SECONDS; +import static io.openems.common.types.OpenemsType.LONG; + import io.openems.common.channel.Level; import io.openems.edge.common.channel.Doc; import io.openems.edge.common.channel.StateChannel; @@ -11,7 +15,12 @@ public interface ControllerIoChannelSingleThreshold extends Controller, OpenemsC public enum ChannelId implements io.openems.edge.common.channel.ChannelId { AWAITING_HYSTERESIS(Doc.of(Level.INFO) // - .text("Would change State, but hystesis is active")); // + .text("Would change State, but hystesis is active")), + + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// + .unit(CUMULATED_SECONDS) // + .persistencePriority(HIGH)) // + ; // private final Doc doc; diff --git a/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThresholdImpl.java b/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThresholdImpl.java index 35ce7d01214..640347248c2 100644 --- a/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThresholdImpl.java +++ b/io.openems.edge.controller.io.channelsinglethreshold/src/io/openems/edge/controller/io/channelsinglethreshold/ControllerIoChannelSingleThresholdImpl.java @@ -14,6 +14,9 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.osgi.service.metatype.annotations.Designate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +31,9 @@ import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateActiveTime; @Designate(ocd = Config.class, factory = true) @Component(// @@ -36,10 +42,12 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerIoChannelSingleThresholdImpl extends AbstractOpenemsComponent - implements ControllerIoChannelSingleThreshold, Controller, OpenemsComponent { + implements ControllerIoChannelSingleThreshold, Controller, OpenemsComponent, TimedataProvider { private final Logger log = LoggerFactory.getLogger(ControllerIoChannelSingleThresholdImpl.class); private final Set outputChannelAdresses = new HashSet<>(); + private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this, + ControllerIoChannelSingleThreshold.ChannelId.CUMULATED_ACTIVE_TIME); @Reference private ComponentManager componentManager; @@ -49,6 +57,9 @@ public class ControllerIoChannelSingleThresholdImpl extends AbstractOpenemsCompo /** The current state in the State Machine. */ private State state = State.UNDEFINED; + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile Timedata timedata = null; + public ControllerIoChannelSingleThresholdImpl() { super(// OpenemsComponent.ChannelId.values(), // @@ -262,13 +273,17 @@ private void changeState(State nextState) { } /** - * Helper function to switch multiple outputs if they were not switched before. + * Helper function to switch multiple outputs if they were not switched before; + * Updates the cumulated active time channel. * * @param outputChannels the output channels * @param value true to switch ON, false to switch ON * @throws OpenemsNamedException on error */ private void setOutputs(List> outputChannels, boolean value) throws OpenemsNamedException { + // Update the cumulated Time. + this.calculateCumulatedActiveTime.update(value); + for (WriteChannel outputChannel : outputChannels) { var currentValue = outputChannel.value(); if (!currentValue.isDefined() || currentValue.get() != value) { @@ -277,4 +292,9 @@ private void setOutputs(List> outputChannels, boolean valu } } } + + @Override + public Timedata getTimedata() { + return this.timedata; + } } diff --git a/io.openems.edge.controller.io.fixdigitaloutput/bnd.bnd b/io.openems.edge.controller.io.fixdigitaloutput/bnd.bnd index de755a208fa..86751da81fd 100644 --- a/io.openems.edge.controller.io.fixdigitaloutput/bnd.bnd +++ b/io.openems.edge.controller.io.fixdigitaloutput/bnd.bnd @@ -8,7 +8,8 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.common,\ io.openems.edge.common,\ io.openems.edge.controller.api,\ - io.openems.edge.io.api + io.openems.edge.io.api,\ + io.openems.edge.timedata.api,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutput.java b/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutput.java index 915a28be23c..8b80d46ad69 100644 --- a/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutput.java +++ b/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutput.java @@ -1,5 +1,9 @@ package io.openems.edge.controller.io.fixdigitaloutput; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.Unit.CUMULATED_SECONDS; +import static io.openems.common.types.OpenemsType.LONG; + import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; @@ -7,7 +11,10 @@ public interface ControllerIoFixDigitalOutput extends Controller, OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { - ; + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// + .unit(CUMULATED_SECONDS) // + .persistencePriority(HIGH)); + private final Doc doc; private ChannelId(Doc doc) { diff --git a/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutputImpl.java b/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutputImpl.java index 0e741e0a578..44e01f4e131 100644 --- a/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutputImpl.java +++ b/io.openems.edge.controller.io.fixdigitaloutput/src/io/openems/edge/controller/io/fixdigitaloutput/ControllerIoFixDigitalOutputImpl.java @@ -9,6 +9,9 @@ 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.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; import org.osgi.service.metatype.annotations.Designate; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; @@ -18,6 +21,9 @@ import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.controller.api.Controller; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateActiveTime; @Designate(ocd = Config.class, factory = true) @Component(// @@ -26,7 +32,10 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerIoFixDigitalOutputImpl extends AbstractOpenemsComponent - implements ControllerIoFixDigitalOutput, Controller, OpenemsComponent { + implements ControllerIoFixDigitalOutput, Controller, OpenemsComponent, TimedataProvider { + + private final CalculateActiveTime calculateCumulatedActiveTime = new CalculateActiveTime(this, + ControllerIoFixDigitalOutput.ChannelId.CUMULATED_ACTIVE_TIME); @Reference private ConfigurationAdmin cm; @@ -36,9 +45,13 @@ public class ControllerIoFixDigitalOutputImpl extends AbstractOpenemsComponent /** Stores the ChannelAddress of the WriteChannel. */ private ChannelAddress outputChannelAddress = null; + /** Takes the configured "isOn" setting. */ private boolean isOn = false; + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) + private volatile Timedata timedata = null; + public ControllerIoFixDigitalOutputImpl() { super(// OpenemsComponent.ChannelId.values(), // @@ -64,6 +77,7 @@ protected void deactivate() { @Override public void run() throws IllegalArgumentException, OpenemsNamedException { + if (this.isOn) { this.switchOn(); } else { @@ -91,7 +105,18 @@ private void switchOff() throws IllegalArgumentException, OpenemsNamedException this.setOutput(false); } + /** + * Helper function to switch an output if it was not switched before; Updates + * the cumulated active time channel. + * + * @param value true to switch ON, false to switch OFF; + * @throws IllegalArgumentException on error + * @throws OpenemsNamedException on error + */ private void setOutput(boolean value) throws IllegalArgumentException, OpenemsNamedException { + // Update the cumulated active time. + this.calculateCumulatedActiveTime.update(value); + WriteChannel channel = this.componentManager.getChannel(this.outputChannelAddress); if (channel.value().asOptional().equals(Optional.of(value))) { // it is already in the desired state @@ -99,4 +124,9 @@ private void setOutput(boolean value) throws IllegalArgumentException, OpenemsNa channel.setNextWriteValue(value); } } + + @Override + public Timedata getTimedata() { + return this.timedata; + } }