From 400c2347c7dc35c28398d192a3471eb65427a636 Mon Sep 17 00:00:00 2001 From: Pooran Chandrashekaraiah Date: Wed, 16 Dec 2020 16:10:27 +0100 Subject: [PATCH 1/2] on/off grid state machine --- io.openems.edge.ess.sinexcel/bnd.bnd | 3 +- .../io/openems/edge/ess/sinexcel/Config.java | 22 +- .../edge/ess/sinexcel/EssSinexcel.java | 11 +- .../edge/ess/sinexcel/EssSinexcelImpl.java | 113 ++++++++- .../edge/ess/sinexcel/OngridHandler.java | 80 ------ .../edge/ess/sinexcel/StateMachine.java | 60 ----- .../ess/sinexcel/statemachine/Context.java | 236 ++++++++++++++++++ .../sinexcel/statemachine/ErrorHandler.java | 51 ++++ .../statemachine/GroundSetHandler.java | 47 ++++ .../statemachine/StartInverterHandler.java | 29 +++ .../sinexcel/statemachine/StateMachine.java | 151 +++++++++++ .../statemachine/StopInverterHandler.java | 26 ++ .../statemachine/TotalOffGridHandler.java | 75 ++++++ .../statemachine/TotalOnGridHandler.java | 73 ++++++ .../statemachine/UndefinedHandler.java | 42 ++++ .../ess/sinexcel/EssSinexcelImplTest.java | 73 +++++- .../openems/edge/ess/sinexcel/MyConfig.java | 69 +++++ .../src/io/openems/edge/wago/Wago.java | 2 +- 18 files changed, 1012 insertions(+), 151 deletions(-) delete mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/OngridHandler.java delete mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/StateMachine.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java create mode 100644 io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java diff --git a/io.openems.edge.ess.sinexcel/bnd.bnd b/io.openems.edge.ess.sinexcel/bnd.bnd index 0107f4c2c2d..962e1c56188 100644 --- a/io.openems.edge.ess.sinexcel/bnd.bnd +++ b/io.openems.edge.ess.sinexcel/bnd.bnd @@ -10,7 +10,8 @@ Bundle-Version: 1.0.0.${tstamp} io.openems.edge.bridge.modbus,\ io.openems.edge.common,\ io.openems.edge.ess.api,\ - io.openems.edge.meter.api + io.openems.edge.meter.api,\ + io.openems.edge.io.api -testpath: \ ${testpath},\ diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/Config.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/Config.java index 7c61508a2c4..e645d31f9c1 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/Config.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/Config.java @@ -7,7 +7,7 @@ @ObjectClassDefinition( // name = "ESS Sinexcel", // description = "Implements the Sinexcel battery inverter.") -@interface Config { +public @interface Config { @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") String id() default "ess0"; @@ -33,6 +33,26 @@ @AttributeDefinition(name = "Topping charge", description = "The topping charge voltage is the voltage that the battery supposed to finally reach in the charging procedure") int toppingCharge() default 4370; + // input channel ------------------------ + @AttributeDefinition(name = "Main contactor", description = "Input channle to control Main Contactor") + String digitalInput1() default "io0/DigitalInputM1C1"; + + @AttributeDefinition(name = "Grid detector", description = "Input channel to detect grid") + String digitalInput2() default "io0/DigitalInputM1C2"; + + @AttributeDefinition(name = "Grounding", description = "Input channel to control grounding") + String digitalInput3() default "io0/DigitalInputM2C1"; + + // output channel ------------------------ + @AttributeDefinition(name = "DigitalOutput", description = "Output channel 1") + String digitalOutput1() default "io0/DigitalInputM3C1"; + + @AttributeDefinition(name = "DigitalOutput", description = "Output channel 2") + String digitalOutput2() default "io0/DigitalInputM3C2"; + + @AttributeDefinition(name = "DigitalOutput", description = "Output channel to control grounding") + String digitalOutput3() default "io0/DigitalInputM4C1"; + @AttributeDefinition(name = "Start and stop", description = "Turn ON and turn OFF the Inverter") InverterState InverterState() default InverterState.ON; diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcel.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcel.java index fb07a302823..b9a1b0a3efc 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcel.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcel.java @@ -17,11 +17,15 @@ import io.openems.edge.common.sum.GridMode; import io.openems.edge.ess.api.ManagedSymmetricEss; import io.openems.edge.ess.api.SymmetricEss; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State;; public interface EssSinexcel extends SymmetricEss, ManagedSymmetricEss, EventHandler, OpenemsComponent, ModbusSlave { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { - + + + STATE_MACHINE(Doc.of(State.values()) // + .text("Current State of State-Machine")), // MOD_ON_CMD(Doc.of(FalseTrue.values()) // .accessMode(AccessMode.READ_WRITE)), // MOD_OFF_CMD(Doc.of(FalseTrue.values()) // @@ -117,6 +121,9 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { FREQUENCY(Doc.of(OpenemsType.INTEGER) // .unit(Unit.HERTZ)), // + SET_OFF_GRID_FREQUENCY(Doc.of(OpenemsType.INTEGER) // + .accessMode(AccessMode.READ_WRITE) // + .unit(Unit.HERTZ)), DC_CURRENT(Doc.of(OpenemsType.INTEGER) // .unit(Unit.AMPERE)), // DC_VOLTAGE(Doc.of(OpenemsType.INTEGER) // @@ -342,7 +349,7 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { STATE_70(Doc.of(Level.WARNING) // .text("DC relay short-circuit")), // STATE_71(Doc.of(Level.WARNING) // - .text("DC relay short open")), // + .text("DC realy short open")), // STATE_72(Doc.of(Level.WARNING) // .text("Battery power over load")), // STATE_73(Doc.of(Level.FAULT) // diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java index 79698c94192..dafd165ed2e 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java @@ -23,6 +23,7 @@ import io.openems.common.channel.AccessMode; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.types.ChannelAddress; import io.openems.edge.battery.api.Battery; import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent; import io.openems.edge.bridge.modbus.api.BridgeModbus; @@ -38,6 +39,8 @@ import io.openems.edge.bridge.modbus.api.task.FC3ReadRegistersTask; import io.openems.edge.bridge.modbus.api.task.FC6WriteRegisterTask; import io.openems.edge.common.channel.BooleanReadChannel; +import io.openems.edge.common.channel.BooleanWriteChannel; +import io.openems.edge.common.channel.EnumReadChannel; import io.openems.edge.common.channel.EnumWriteChannel; import io.openems.edge.common.channel.IntegerWriteChannel; import io.openems.edge.common.channel.StateChannel; @@ -55,6 +58,9 @@ import io.openems.edge.ess.power.api.Power; import io.openems.edge.ess.power.api.Pwr; import io.openems.edge.ess.power.api.Relationship; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; +import io.openems.edge.ess.sinexcel.statemachine.Context; @Designate(ocd = Config.class, factory = true) @Component(// @@ -83,8 +89,10 @@ public class EssSinexcelImpl extends AbstractOpenemsModbusComponent private int counterOn = 0; private int counterOff = 0; - // State-Machines - private final StateMachine stateMachine; + /** + * Manages the {@link State}s of the StateMachine. + */ + private final StateMachine stateMachine = new StateMachine(State.UNDEFINED); /** * Helper wrapping class to handle listeners on battery Channels. @@ -148,7 +156,6 @@ public EssSinexcelImpl() throws OpenemsNamedException { EssSinexcel.ChannelId.values() // ); this._setMaxApparentPower(EssSinexcelImpl.MAX_APPARENT_POWER); - this.stateMachine = new StateMachine(this); } // private void getNoOfCells() throws OpenemsNamedException { @@ -247,7 +254,28 @@ public void softStart(boolean switchOn) throws OpenemsNamedException { setDcRelay.setNextWriteValue(0); } } - + + /** + * set the module to on grid mode. Reading back value makes no sense + * + * @throws OpenemsNamedException + */ + public void setOngridCommand() throws OpenemsNamedException { + EnumWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.ON_GRID_CMD); + //IntegerWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.ON_GRID_CMD); + setdataGridOffCmd.setNextWriteValue(FalseTrue.TRUE); // 1: true, other: illegal + } + + /** + * set the module to off grid mode. Reading back value makes no sense + * + * @throws OpenemsNamedException + */ + public void setOffgridCommand() throws OpenemsNamedException { + EnumWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.OFF_GRID_CMD); + setdataGridOffCmd.setNextWriteValue(FalseTrue.TRUE); // 1: true, other: illegal + } + /** * At first the PCS needs a stop command, then is required to remove the AC * connection, after that the Grid OFF command. @@ -295,6 +323,66 @@ public boolean stateOnOff() { return stateOff.isPresent() && stateOff.get(); } + public CurrentState getSinexcelState() { + EnumReadChannel currentState = this.channel(EssSinexcel.ChannelId.SINEXCEL_STATE); + CurrentState curState = currentState.value().asEnum(); + return curState; + } + + /** + * Helper to set all the digital output based on the param + * + * @param value1 boolean true to set-on the relay, false to set-off the relay + * + * @throws IllegalArgumentException on error + * @throws OpenemsNamedException on error + */ + + public void handleWritingDigitalOutputForGrounding(boolean value) + throws IllegalArgumentException, OpenemsNamedException { + + setOutput(this.componentManager.getChannel(ChannelAddress.fromString(this.config.digitalOutput2())), value); + + } + + + public void handleWritingDigitalOutputForMain(boolean value) throws IllegalArgumentException, OpenemsNamedException { + // TODO Auto-generated method stub + setOutput(this.componentManager.getChannel(ChannelAddress.fromString(this.config.digitalOutput1())), value); + + } + + /** + * Helper function to switch an output if it was not switched before. + * + * @param value true to switch ON, false to switch ON + */ + private void setOutput(BooleanWriteChannel channel, boolean value) + throws IllegalArgumentException, OpenemsNamedException { + try { + Optional currentValueOpt = channel.value().asOptional(); + if (!currentValueOpt.isPresent() || currentValueOpt.get() != value) { + this.log.info("Set output [" + channel.address() + "] " + (value) + "."); + channel.setNextWriteValue(value); + } + } catch (OpenemsNamedException e) { + this.log.error("Unable to set output: [" + channel.address() + "] " + e.getMessage()); + + } + } + + /** + * Setting the frequency in the off grid mode + * + * @throws OpenemsNamedException + */ + public void setFrequency() throws OpenemsNamedException { + + IntegerWriteChannel setFreq = this.channel(EssSinexcel.ChannelId.SET_OFF_GRID_FREQUENCY); + setFreq.setNextWriteValue(52); // 52 hz frequency + + } + // /** // * Is Grid Shutdown?. // * @@ -635,7 +723,7 @@ public void handleEvent(Event event) { try { this.setBatteryRanges(); this.doHandlingSlowFloatVoltage(); - this.stateMachine.run(); + handleStateMachine(); } catch (OpenemsNamedException e) { this.logError(this.log, "EventHandler failed: " + e.getMessage()); } @@ -652,6 +740,18 @@ public void handleEvent(Event event) { } + private void handleStateMachine() { + this.channel(EssSinexcel.ChannelId.STATE_MACHINE).setNextValue(this.stateMachine.getCurrentState()); + // Prepare Context + Context context = new Context(this, this.componentManager, this.battery, this.config); + // Call the StateMachine + try { + this.stateMachine.run(context); + } catch (OpenemsNamedException e) { + this.logError(this.log, "StateMachine failed: " + e.getMessage()); + } + } + @Override public Power getPower() { return this.power; @@ -670,4 +770,7 @@ public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { ManagedSymmetricEss.getModbusSlaveNatureTable(accessMode) // ); } + + + } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/OngridHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/OngridHandler.java deleted file mode 100644 index 0cb6f7dbb25..00000000000 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/OngridHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.openems.edge.ess.sinexcel; - -//import io.openems.edge.ess.sinexcel.StateMachine.State; - -public class OngridHandler { -// private final Logger log = LoggerFactory.getLogger(OngridHandler.class); -// private final StateMachine parent; -// -// private State state = State.UNDEFINED; -// -// public OngridHandler(StateMachine parent) { -// this.parent = parent; -// } -// -// public void initialize() { -// this.state = State.UNDEFINED; -// } -// -// protected StateMachine.State run() throws IllegalArgumentException, OpenemsNamedException { -// System.out.println("OngridHandler.run"); -// // Verify that we are still On-Grid -> otherwise switch to "Going Off-Grid" -// GridMode gridMode = this.parent.parent.getGridMode().getNextValue().asEnum(); -// switch (gridMode) { -// case ON_GRID: -// case UNDEFINED: -// break; -// case OFF_GRID: -// return StateMachine.State.OFFGRID; -// } -// -// switch (this.state) { -// case UNDEFINED: -// this.state = this.doUndefined(this.state); -// break; -// case ONGRID: -// this.state = this.doOngrid(this.state); -// break; -// case OFFGRID: -// break; -// default: -// break; -// } -// -// return StateMachine.State.ONGRID; -// } -// -// private State doUndefined(State state) throws OpenemsNamedException { -// return doOperations(); -// } -// -// private State doOngrid(State state) throws OpenemsNamedException { -// return doOperations(); -// } -// -// // Assumptions : defined and ongrid mode is same, as there is only operations to Softstart() -// -// private State doOperations() throws OpenemsNamedException { -// CurrentState currentState = this.parent.getSinexcelState(); -// -// switch (currentState) { -// case UNDEFINED: -// case SLEEPING: -// case MPPT: -// case THROTTLED: -// case STARTED: -// this.parent.parent.softStart(true); -// break; -// case SHUTTINGDOWN: -// case FAULT: -// case STANDBY: -// case OFF: -// this.parent.parent.softStart(false); -// default: -// break; -// -// } -// return state; -// } - -} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/StateMachine.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/StateMachine.java deleted file mode 100644 index eb346e7fba6..00000000000 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/StateMachine.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.openems.edge.ess.sinexcel; - -import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.edge.common.channel.EnumReadChannel; - -public class StateMachine { - - protected final EssSinexcelImpl parent; - - public StateMachine(EssSinexcelImpl parent) throws OpenemsNamedException { - this.parent = parent; - - } - - public void run() throws IllegalArgumentException, OpenemsNamedException { - // To soft start if there is any error or manual change in sinexcel state - CurrentState currentState = this.getSinexcelState(); - - switch (currentState) { - case UNDEFINED: - case SLEEPING: - case MPPT: - case THROTTLED: - case STARTED: - this.parent.softStart(true); - break; - case SHUTTINGDOWN: - case FAULT: - case STANDBY: - case OFF: - // this.parent.softStart(false); - break; - default: - break; - } - } - - private CurrentState getSinexcelState() { - EnumReadChannel currentState = this.parent.channel(EssSinexcel.ChannelId.SINEXCEL_STATE); - CurrentState curState = currentState.value().asEnum(); - return curState; - } - - /* - * public enum State implements OptionsEnum { UNDEFINED(-1, "Undefined"), // - * ONGRID(1, "On-Grid"), // OFFGRID(2, "Off-Grid"), // ERROR(3, "Error"); - * - * private final int value; private final String name; - * - * private State(int value, String name) { this.value = value; this.name = name; - * } - * - * @Override public int getValue() { return value; } - * - * @Override public String getName() { return name; } - * - * @Override public OptionsEnum getUndefined() { return UNDEFINED; } } - */ - -} \ No newline at end of file diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java new file mode 100644 index 00000000000..289df517ab8 --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java @@ -0,0 +1,236 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import java.util.Optional; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.types.ChannelAddress; +import io.openems.edge.battery.api.Battery; +import io.openems.edge.common.channel.BooleanReadChannel; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.ess.sinexcel.Config; +import io.openems.edge.ess.sinexcel.EssSinexcelImpl; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class Context { + protected final EssSinexcelImpl component; + protected final ComponentManager componentManager; + protected final Battery battery; + protected final Config config; + protected boolean startOnce = false; + + public boolean isStartOnce() { + return startOnce; + } + + public void setStartOnce(boolean startOnce) { + this.startOnce = startOnce; + } + + protected Optional mainContactor; + protected Optional gridDetector; + protected Optional grounding; + + public Context(EssSinexcelImpl component, ComponentManager componentManager, Battery battery, Config config) { + super(); + this.component = component; + this.componentManager = componentManager; + this.battery = battery; + this.config = config; + } + + protected State stateTransitionHelper() throws IllegalArgumentException, OpenemsNamedException { + mainContactor = getMainContactor(); + gridDetector = getGridDetector(); + grounding = getGrounding(); + + if (mainContactor.isPresent() && gridDetector.isPresent() && grounding.isPresent()) { + State s = getStateFromInputs(mainContactor.get(), gridDetector.get(), grounding.get()); + //System.out.println(s); + return s; + } else { + return State.UNDEFINED; + } + } + + protected Optional getMainContactor() throws IllegalArgumentException, OpenemsNamedException { + BooleanReadChannel inChannel1 = this.componentManager + .getChannel(ChannelAddress.fromString(this.config.digitalInput1())); + return inChannel1.value().asOptional(); + + } + + protected Optional getGridDetector() throws IllegalArgumentException, OpenemsNamedException { + BooleanReadChannel inChannel2 = this.componentManager + .getChannel(ChannelAddress.fromString(this.config.digitalInput2())); + return inChannel2.value().asOptional(); + } + + protected Optional getGrounding() throws IllegalArgumentException, OpenemsNamedException { + BooleanReadChannel inChannel3 = this.componentManager + .getChannel(ChannelAddress.fromString(this.config.digitalInput3())); + return inChannel3.value().asOptional(); + } + + protected static State getStateFromInputs(boolean mainContactor, boolean gridDetector, boolean grounding) { + +// System.out.println("grid detector : " + gridDetector); +// System.out.println("main : " + mainContactor); +// System.out.println("ground : " + grounding); + + + if (gridDetector) { + // off grid + if (mainContactor) { + // main is true, maincontactor is open + if (grounding) { + // ground is true , grounding is closed + // 1 1 1 + // error + //System.out.println(" one " + State.ERROR); + return State.ERROR; + }else { + // 1 1 0 + //total offgrid + //System.out.println(" one " + State.TOTAL_OFFGRID); + return State.TOTAL_OFFGRID; + } + }else { + // main is false, main contactor is cloased + if (grounding) { + // 0 1 1 + // We are going to off grid + //System.out.println(" one " + State.GROUNDSET); + return State.GROUNDSET; + }else { + //0 1 0 + //System.out.println(" one " + State.ERROR); + return State.GROUNDSET; + } + } + }else { + // on grid + if (mainContactor) { + if (grounding) { + // 1 0 1 + //System.out.println(" one " + State.GROUNDSET); + return State.GROUNDSET; + }else { + // 0 1 0 + //System.out.println(" one " + State.ERROR); + return State.GROUNDSET; + } + + }else { + if (grounding) { + // 0 0 1 + //System.out.println(" one " + State.TOTAL_ONGRID); + return State.TOTAL_ONGRID; + }else { + // 0 0 0 + //System.out.println(" one " + State.GROUNDSET); + return State.GROUNDSET; + + } + + } + } + + + + + + + + + + + + + + + + + + + + + + +// if (gridDetector) { +// // gridDetector = true +// if (!mainContactor && !grounding) { +// // mainContactor = true, grounding = true +// System.out.println(" one " + State.TOTAL_OFFGRID); +// return State.TOTAL_OFFGRID; +// } else if (mainContactor && !grounding) { +// // mainContactor = true, grounding = false +// System.out.println(" two " + State.GROUNDSET); +// return State.GROUNDSET; +// } else { +// System.out.println(" three " + State.UNDEFINED); +// return State.UNDEFINED; +// } +// } else { +// // gridDetector = false +// if (mainContactor && grounding) { +// System.out.println(" four " + State.TOTAL_ONGRID); +// // mainContactor = false, grounding = false +// return State.TOTAL_ONGRID; +// } else if (!mainContactor && grounding) { +// System.out.println(" five " + State.GROUNDSET); +// // mainContactor = false, grounding = true +// return State.GROUNDSET; +// } else if (mainContactor && !grounding) { +// // mainContactor = true, grounding = false +// System.out.println(" six " + State.TOTAL_ONGRID); +// return State.TOTAL_ONGRID; +// } else { +// System.out.println(" seven " + State.UNDEFINED); +// return State.UNDEFINED; +// } +// +// } + + } + +// protected static State getStateFromInputs(boolean mainContactor, boolean gridDetector, boolean grounding) { +// if (mainContactor) { +// if (gridDetector) { +// if (grounding) { +// // 1 1 1 +// return State.TOTAL_OFFGRID; +// } else { +// // 1 1 0 +// return State.GROUNDSET; +// } +// } else { +// if (grounding) { +// // 1 0 1 +// return State.TRANSITION_OFF_TO_ON; +// } else { +// // 1 0 0 +// return State.GOING_ONGRID; +// } +// } +// } else { +// if (gridDetector) { +// if (grounding) { +// // 0 1 1 +// return State.ERROR_ONGRID; +// } else { +// // 0 1 0 +// return State.TRANSITION_ON_TO_OFF; +// } +// } else { +// if (grounding) { +// // 0 0 1 +// return State.GROUNDSET; +// } else { +// // 0 0 0 +// return State.TOTAL_ONGRID; +// } +// } +// } +// } + +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java new file mode 100644 index 00000000000..952f9509e15 --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java @@ -0,0 +1,51 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class ErrorHandler extends StateHandler { + + private int attemptCounter = 0; + + @Override + protected void onEntry(Context context) throws OpenemsNamedException { + this.attemptCounter = 0; + } + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + if (this.attemptCounter > 5) { + // switch off + context.component.inverterOff(); + return State.ERROR; + } else { + + State decisionVariable = context.stateTransitionHelper(); + switch (decisionVariable) { + + case GROUNDSET: + return State.GROUNDSET; + + case TOTAL_OFFGRID: + return State.TOTAL_OFFGRID; + + case TOTAL_ONGRID: + return State.TOTAL_ONGRID; + + case UNDEFINED: + return State.UNDEFINED; + + case ERROR: + case START: + case STOP: + return State.ERROR; + + } + // This should never happen too + this.attemptCounter++; + return State.UNDEFINED; + } + } +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java new file mode 100644 index 00000000000..f4175b84d8f --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java @@ -0,0 +1,47 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class GroundSetHandler extends StateHandler { + + private int attemptCounter = 0; + + @Override + protected void onEntry(Context context) throws OpenemsNamedException { + this.attemptCounter = 0; + } + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + + // isOngrid ? + if (!context.getGridDetector().get() ) { + // grounding set to goto ongrid + context.component.handleWritingDigitalOutputForGrounding(true); + context.component.handleWritingDigitalOutputForMain(false); + + // main also here + this.attemptCounter++; + return State.TOTAL_ONGRID; + } + + // grounding set to goto offgrid + // isOffgrid ? + if (context.getGridDetector().get() ) { + // grounding set to goto ongrid + context.component.handleWritingDigitalOutputForGrounding(false); + this.attemptCounter++; + return State.TOTAL_OFFGRID; + } + + if (this.attemptCounter > 5) { + return State.ERROR; + } + + return State.GROUNDSET; + } + +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java new file mode 100644 index 00000000000..8629787cdee --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java @@ -0,0 +1,29 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class StartInverterHandler extends StateHandler { + + //private final Logger log = LoggerFactory.getLogger(StartInverterHandler.class); + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + //log.info("Inside StartInverter handler"); + // Start the inverter no matter what + context.component.inverterOn(); + + // Started the inverter, Check the grid detector + // If Grid is off + if (context.getGridDetector().get()) { + return State.TOTAL_OFFGRID; + } else { + return State.TOTAL_ONGRID; + } + } +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java new file mode 100644 index 00000000000..a6bafca040a --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java @@ -0,0 +1,151 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import com.google.common.base.CaseFormat; + +import io.openems.common.types.OptionsEnum; +import io.openems.edge.common.statemachine.AbstractStateMachine; +import io.openems.edge.common.statemachine.StateHandler; + +public class StateMachine extends AbstractStateMachine { + + /** + * The states which is used in the sinexcel switch from On-grid mode to off-grid + * mode and vice-versa. This switching needs total to 8 states, because state + * transition is decided with 3 digital inputs + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
DI1DI2DI3State
000State
001State
010State
011State
100State
101State
110State
111State
+ */ + public enum State implements io.openems.edge.common.statemachine.State, OptionsEnum { + + UNDEFINED(-1), // + + TOTAL_ONGRID(1), // + + ERROR(2), // + START(3), // + STOP(4), // + GROUNDSET(5), // + + TOTAL_OFFGRID(6) // + ; // + + private final int value; + + private State(int value) { + this.value = value; + } + + @Override + public int getValue() { + return this.value; + } + + @Override + public String getName() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, this.name()); + } + + @Override + public OptionsEnum getUndefined() { + return UNDEFINED; + } + + @Override + public State[] getStates() { + return State.values(); + } + } + + public StateMachine(State initialState) { + super(initialState); + } + + @Override + public StateHandler getStateHandler(State state) { + switch (state) { + + case TOTAL_ONGRID: + return new TotalOnGridHandler(); + + case TOTAL_OFFGRID: + return new TotalOffGridHandler(); + + case UNDEFINED: + return new UndefinedHandler(); + case ERROR: + return new ErrorHandler(); + case GROUNDSET: + return new GroundSetHandler(); + case START: + return new StartInverterHandler(); + case STOP: + return new StopInverterHandler(); + } + + throw new IllegalArgumentException("Unknown State [" + state + "]"); + } + +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java new file mode 100644 index 00000000000..3c20c0b5be9 --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java @@ -0,0 +1,26 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class StopInverterHandler extends StateHandler { + + private final Logger log = LoggerFactory.getLogger(StopInverterHandler.class); + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + log.info("Inside StopInverter handler"); + //Stop the inverter no matter what + context.component.inverterOff(); + + //go to grounding set step after stopping + return State.GROUNDSET; + + } + +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java new file mode 100644 index 00000000000..f0a2122e5ce --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java @@ -0,0 +1,75 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +//import java.time.Duration; +//import java.time.Instant; + +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.common.sum.GridMode; +import io.openems.edge.ess.sinexcel.CurrentState; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class TotalOffGridHandler extends StateHandler { + + //private final Logger log = LoggerFactory.getLogger(TotalOffGridHandler.class); + + private boolean StartOnce = false; + //private Instant lastAttempt = Instant.MIN; + +// @Override +// protected void onEntry(Context context) throws OpenemsNamedException { +// this.lastAttempt = Instant.MIN; +// } + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + //log.info("Inside total offgrid handler"); + + // If Grid is On + if (!context.getGridDetector().get()) { + // Before going to ON, Wait for some time, so that the grid is not fluctuating + //boolean iswaitingTimePassed = Duration.between(this.lastAttempt, Instant.now()).getSeconds() > 65; + //if (iswaitingTimePassed) { + return State.STOP; + //} + } + + if (!StartOnce) { + this.StartOnce = true; + return State.START; + } + + // Run in the offgrid state + // Set the frequncy + context.component.setFrequency(); + // Give command to make it off-grid + context.component.setOffgridCommand(); + // Set the grid mode to Offgrid + context.component._setGridMode(GridMode.OFF_GRID); + + // Do the softstart of the sinexcel + CurrentState currentState = context.component.getSinexcelState(); + switch (currentState) { + case UNDEFINED: + case SLEEPING: + case MPPT: + case THROTTLED: + case STARTED: + context.component.softStart(true); + break; + case SHUTTINGDOWN: + case FAULT: + case STANDBY: + case OFF: + default: + context.component.softStart(false); + } + + return State.TOTAL_OFFGRID; + + } +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java new file mode 100644 index 00000000000..1717e02a65a --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java @@ -0,0 +1,73 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.common.sum.GridMode; +import io.openems.edge.ess.sinexcel.CurrentState; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +//import java.time.Duration; +//import java.time.Instant; +// +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; + +public class TotalOnGridHandler extends StateHandler { + +// private final Logger log = LoggerFactory.getLogger(TotalOnGridHandler.class); + + protected boolean StartOnce = false; +// private Instant lastAttempt = Instant.MIN; + +// @Override +// protected void onEntry(Context context) throws OpenemsNamedException { +// this.lastAttempt = Instant.MIN; +// } + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + //log.info("Inside total ongrid handler"); + + // If Grid is off + if (context.getGridDetector().get() ) { + + // Before going to ON, Wait for some time, so that the grid is not fluctuating + //boolean iswaitingTimePassed = Duration.between(this.lastAttempt, Instant.now()).getSeconds() > 65; + //if (iswaitingTimePassed) { + return State.STOP; + //} + } + + if (!StartOnce) { + this.StartOnce = true; + return State.START; + } + + // Run in the ongrid state + // Give command to make it on-grid + context.component.setOngridCommand(); + // Set the grid mode to Ongrid + context.component._setGridMode(GridMode.ON_GRID); + + // Do the softstart of the sinexcel + CurrentState currentState = context.component.getSinexcelState(); + switch (currentState) { + case UNDEFINED: + case SLEEPING: + case MPPT: + case THROTTLED: + case STARTED: + context.component.softStart(true); + break; + case SHUTTINGDOWN: + case FAULT: + case STANDBY: + case OFF: + default: + context.component.softStart(false); + } + + return State.TOTAL_ONGRID; + } +} diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java new file mode 100644 index 00000000000..ba514e13275 --- /dev/null +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java @@ -0,0 +1,42 @@ +package io.openems.edge.ess.sinexcel.statemachine; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.statemachine.StateHandler; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; + +public class UndefinedHandler extends StateHandler { + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + + State decisionVariable = context.stateTransitionHelper(); + switch (decisionVariable) { + case ERROR: + return State.ERROR; + + case GROUNDSET: + return State.GROUNDSET; + + case TOTAL_OFFGRID: + return State.TOTAL_OFFGRID; + + case TOTAL_ONGRID: + return State.TOTAL_ONGRID; + + case UNDEFINED: + return State.UNDEFINED; + + // This should never happen + case START: + case STOP: + break; + + } + // This should never happen too + return State.UNDEFINED; + + } + + + +} diff --git a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java index 8e53b3c3400..63ea8484550 100644 --- a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java +++ b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java @@ -2,18 +2,32 @@ import org.junit.Test; +import io.openems.common.types.ChannelAddress; import io.openems.edge.battery.test.DummyBattery; import io.openems.edge.bridge.modbus.test.DummyModbusBridge; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyConfigurationAdmin; +import io.openems.edge.ess.sinexcel.statemachine.StateMachine; import io.openems.edge.ess.test.DummyPower; import io.openems.edge.ess.test.ManagedSymmetricEssTest; +import io.openems.edge.io.test.DummyInputOutput; public class EssSinexcelImplTest { private static final String ESS_ID = "ess0"; private static final String MODBUS_ID = "modbus0"; private static final String BATTERY_ID = "battery0"; + + private static final ChannelAddress STATE_MACHINE = new ChannelAddress(ESS_ID, "StateMachine"); + + private final static String IO_ID = "io0"; + private static final ChannelAddress DIGITAL_INPUT_1 = new ChannelAddress(IO_ID, "InputOutput0"); + private static final ChannelAddress DIGITAL_INPUT_2 = new ChannelAddress(IO_ID, "InputOutput1"); + private static final ChannelAddress DIGITAL_INPUT_3 = new ChannelAddress(IO_ID, "InputOutput2"); + private static final ChannelAddress DIGITAL_OUTPUT_1 = new ChannelAddress(IO_ID, "InputOutput3"); + private static final ChannelAddress DIGITAL_OUTPUT_2 = new ChannelAddress(IO_ID, "InputOutput4"); + private static final ChannelAddress DIGITAL_OUTPUT_3 = new ChannelAddress(IO_ID, "InputOutput5"); @Test public void test() throws Exception { @@ -23,13 +37,70 @@ public void test() throws Exception { .addReference("power", new DummyPower()) // .addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) // .addReference("setBattery", new DummyBattery(BATTERY_ID)) // + .addComponent(new DummyInputOutput(IO_ID)) // .activate(MyConfig.create() // .setId(ESS_ID) // .setModbusId(MODBUS_ID) // .setBatteryId(BATTERY_ID) // .setInverterState(InverterState.ON) // - .setToppingCharge(0) // + .setToppingCharge(3900) // + .setDigitalInput1(DIGITAL_INPUT_1.toString()) // + .setDigitalInput2(DIGITAL_INPUT_2.toString()) // + .setDigitalInput3(DIGITAL_INPUT_3.toString()) // + .setDigitalOutput1(DIGITAL_OUTPUT_1.toString()) // + .setDigitalOutput2(DIGITAL_OUTPUT_2.toString()) // + .setDigitalOutput3(DIGITAL_OUTPUT_3.toString()) // .build()) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.UNDEFINED)) // + .next(new TestCase() // + .input(DIGITAL_INPUT_1, false) // + .input(DIGITAL_INPUT_2, false) // + .input(DIGITAL_INPUT_3, true)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_ONGRID))// + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.START)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_ONGRID)) // + .next(new TestCase() // + .input(DIGITAL_INPUT_1, false) // + .input(DIGITAL_INPUT_2, true) // + .input(DIGITAL_INPUT_3, false)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.STOP)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.GROUNDSET) + .output(DIGITAL_OUTPUT_2, false)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_OFFGRID)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.START)) // + .next(new TestCase()) + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_OFFGRID)) // + .next(new TestCase()) + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_OFFGRID)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_OFFGRID)) // + .next(new TestCase() // + .input(DIGITAL_INPUT_1, false) // + .input(DIGITAL_INPUT_2, false) // + .input(DIGITAL_INPUT_3, true)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.STOP)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.GROUNDSET) + .output(DIGITAL_OUTPUT_2, true) + .output(DIGITAL_OUTPUT_1, false)) // + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_ONGRID)) // + + .next(new TestCase() // + .output(STATE_MACHINE, StateMachine.State.TOTAL_ONGRID)) // + + ; } diff --git a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/MyConfig.java b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/MyConfig.java index 0355a1df68f..a868bcca7f2 100644 --- a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/MyConfig.java +++ b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/MyConfig.java @@ -14,6 +14,14 @@ protected static class Builder { private int toppingCharge; private InverterState inverterState; + private String digitalInput1 = null; + private String digitalInput2 = null; + private String digitalInput3 = null; + + private String digitalOutput1 = null; + private String digitalOutput2 = null; + private String digitalOutput3 = null; + private Builder() { } @@ -41,6 +49,37 @@ public Builder setInverterState(InverterState inverterState) { this.inverterState = inverterState; return this; } + + public Builder setDigitalInput1(String digitalInput1) { + this.digitalInput1 = digitalInput1; + return this; + } + + public Builder setDigitalInput2(String digitalInput2) { + this.digitalInput2 = digitalInput2; + return this; + } + + public Builder setDigitalInput3(String digitalInput3) { + this.digitalInput3 = digitalInput3; + return this; + } + + public Builder setDigitalOutput1(String digitalOutput1) { + this.digitalOutput1 = digitalOutput1; + return this; + } + + public Builder setDigitalOutput2(String digitalOutput2) { + this.digitalOutput2 = digitalOutput2; + return this; + } + + public Builder setDigitalOutput3(String digitalOutput3) { + this.digitalOutput3 = digitalOutput3; + return this; + } + public MyConfig build() { return new MyConfig(this); @@ -93,4 +132,34 @@ public InverterState InverterState() { return this.builder.inverterState; } + @Override + public String digitalInput1() { + return this.builder.digitalInput1; + } + + @Override + public String digitalInput2() { + return this.builder.digitalInput2; + } + + @Override + public String digitalInput3() { + return this.builder.digitalInput3; + } + + @Override + public String digitalOutput1() { + return this.builder.digitalOutput1; + } + + @Override + public String digitalOutput2() { + return this.builder.digitalOutput2; + } + + @Override + public String digitalOutput3() { + return this.builder.digitalOutput3; + } + } \ No newline at end of file diff --git a/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java b/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java index 33a0359478b..61c906fcf08 100644 --- a/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java +++ b/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java @@ -362,4 +362,4 @@ public BooleanWriteChannel[] digitalOutputChannels() { protected BooleanReadChannel addChannel(FieldbusChannelId channelId) { return (BooleanReadChannel) super.addChannel(channelId); } -} +} \ No newline at end of file From 97810df0e371a69ed5132c822bf74743a0b9e3fe Mon Sep 17 00:00:00 2001 From: Pooran Chandrashekaraiah Date: Mon, 8 Mar 2021 11:29:44 +0100 Subject: [PATCH 2/2] Changes for the state machine --- .../edge/ess/sinexcel/EssSinexcelImpl.java | 158 +++++++++++------- .../ess/sinexcel/statemachine/Context.java | 8 +- .../sinexcel/statemachine/ErrorHandler.java | 2 +- .../statemachine/GroundSetHandler.java | 29 +--- .../statemachine/StartInverterHandler.java | 18 +- .../sinexcel/statemachine/StateMachine.java | 142 ++++++++-------- .../statemachine/StopInverterHandler.java | 58 ++++++- .../statemachine/TotalOffGridHandler.java | 90 ++++++---- .../statemachine/TotalOnGridHandler.java | 67 ++++---- .../statemachine/UndefinedHandler.java | 2 +- .../ess/sinexcel/EssSinexcelImplTest.java | 2 +- .../src/io/openems/edge/wago/Wago.java | 1 + 12 files changed, 339 insertions(+), 238 deletions(-) diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java index eb6528a01b0..9f63488cd37 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/EssSinexcelImpl.java @@ -42,8 +42,10 @@ import io.openems.edge.common.channel.BooleanWriteChannel; import io.openems.edge.common.channel.EnumReadChannel; import io.openems.edge.common.channel.EnumWriteChannel; +import io.openems.edge.common.channel.IntegerReadChannel; import io.openems.edge.common.channel.IntegerWriteChannel; import io.openems.edge.common.channel.StateChannel; +import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.event.EdgeEventConstants; @@ -85,10 +87,6 @@ public class EssSinexcelImpl extends AbstractOpenemsModbusComponent protected int slowChargeVoltage = 4370; // for new batteries - 3940 protected int floatChargeVoltage = 4370; // for new batteries - 3940 - private int a = 0; - private int counterOn = 0; - private int counterOff = 0; - /** * Manages the {@link State}s of the StateMachine. */ @@ -290,7 +288,7 @@ public void softStart(boolean switchOn) throws OpenemsNamedException { setDcRelay.setNextWriteValue(0); } } - + /** * set the module to on grid mode. Reading back value makes no sense * @@ -298,10 +296,11 @@ public void softStart(boolean switchOn) throws OpenemsNamedException { */ public void setOngridCommand() throws OpenemsNamedException { EnumWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.ON_GRID_CMD); - //IntegerWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.ON_GRID_CMD); + // IntegerWriteChannel setdataGridOffCmd = + // this.channel(EssSinexcel.ChannelId.ON_GRID_CMD); setdataGridOffCmd.setNextWriteValue(FalseTrue.TRUE); // 1: true, other: illegal } - + /** * set the module to off grid mode. Reading back value makes no sense * @@ -310,7 +309,13 @@ public void setOngridCommand() throws OpenemsNamedException { public void setOffgridCommand() throws OpenemsNamedException { EnumWriteChannel setdataGridOffCmd = this.channel(EssSinexcel.ChannelId.OFF_GRID_CMD); setdataGridOffCmd.setNextWriteValue(FalseTrue.TRUE); // 1: true, other: illegal - } + } + + public void setclearFailureCommand() throws OpenemsNamedException { + EnumWriteChannel setClearFailureCmd = this.channel(EssSinexcel.ChannelId.CLEAR_FAILURE_CMD); + setClearFailureCmd.setNextWriteValue(FalseTrue.TRUE); // 1: true, other: illegal + } + /** * At first the PCS needs a stop command, then is required to remove the AC @@ -365,6 +370,13 @@ public CurrentState getSinexcelState() { return curState; } +// SF: was commented before +// public boolean stateOn() { +// StateChannel v = this.channel(EssSinexcel.ChannelId.Sinexcel_STATE_9); +// Optional stateOff = v.getNextValue().asOptional(); +// return stateOff.isPresent() && stateOff.get(); +// } + /** * Helper to set all the digital output based on the param * @@ -380,12 +392,12 @@ public void handleWritingDigitalOutputForGrounding(boolean value) setOutput(this.componentManager.getChannel(ChannelAddress.fromString(this.config.digitalOutput2())), value); } - - - public void handleWritingDigitalOutputForMain(boolean value) throws IllegalArgumentException, OpenemsNamedException { + + public void handleWritingDigitalOutputForMain(boolean value) + throws IllegalArgumentException, OpenemsNamedException { // TODO Auto-generated method stub setOutput(this.componentManager.getChannel(ChannelAddress.fromString(this.config.digitalOutput1())), value); - + } /** @@ -419,34 +431,17 @@ public void setFrequency() throws OpenemsNamedException { } -// /** -// * Is Grid Shutdown?. -// * -// * @return true if grid is shut down -// */ -// public boolean faultIslanding() { -// StateChannel channel = this.channel(EssSinexcel.ChannelId.STATE_4); -// Optional islanding = channel.getNextValue().asOptional(); -// return islanding.isPresent() && islanding.get(); -// } -// -// /** -// * Is inverter state ON?. -// * -// * @return true if inverter is in ON-State -// */ -// public boolean isStateOn() { -// StateChannel channel = this.channel(EssSinexcel.ChannelId.STATE_18); -// Optional stateOff = channel.getNextValue().asOptional(); -// return stateOff.isPresent() && stateOff.get(); -// } + /** + * Setting the frequency in the off grid mode + * + * @throws OpenemsNamedException + */ + public Value getFrequency() throws OpenemsNamedException { - // SF: was commented before -// public boolean stateOn() { -// StateChannel v = this.channel(EssSinexcel.ChannelId.Sinexcel_STATE_9); -// Optional stateOff = v.getNextValue().asOptional(); -// return stateOff.isPresent() && stateOff.get(); -// } + IntegerReadChannel getFreq = this.channel(EssSinexcel.ChannelId.FREQUENCY); + return getFreq.getNextValue(); + + } protected ModbusProtocol defineModbusProtocol() throws OpenemsException { return new ModbusProtocol(this, // @@ -714,30 +709,15 @@ public void applyPower(int activePower, int reactivePower) throws OpenemsNamedEx IntegerWriteChannel setReactivePower = this.channel(EssSinexcel.ChannelId.SET_REACTIVE_POWER); setReactivePower.setNextWriteValue(reactivePower / 100); - if (this.stateOnOff() == false) { - a = 1; - } - - if (this.stateOnOff() == true) { - a = 0; - } + this.inverterOn(); + boolean isOn = this.stateOnOff(); - if (activePower == 0 && reactivePower == 0 && a == 0) { - this.counterOff++; - if (this.counterOff == 48) { - this.inverterOff(); - this.counterOff = 0; - } - - } else if ((activePower != 0 || reactivePower != 0) && a == 1) { - this.counterOn++; - if (this.counterOn == 48) { - this.inverterOn(); - this.counterOn = 0; - } + if (!isOn) { + this.inverterOn(); + } else { + return; } break; - case OFF: if (this.stateOnOff() == true) { this.inverterOff(); @@ -748,6 +728,62 @@ public void applyPower(int activePower, int reactivePower) throws OpenemsNamedEx } } +// @Override +// public void applyPower(int activePower, int reactivePower) throws OpenemsNamedException { +// +// IntegerWriteChannel setActivePower = this.channel(EssSinexcel.ChannelId.SET_ACTIVE_POWER); +// setActivePower.setNextWriteValue(activePower / 100); +// +// IntegerWriteChannel setReactivePower = this.channel(EssSinexcel.ChannelId.SET_REACTIVE_POWER); +// setReactivePower.setNextWriteValue(reactivePower / 100); +// +// +// } + +// @Override +// public void applyPower(int activePower, int reactivePower) throws OpenemsNamedException { +// switch (this.inverterState) { +// case ON: +// IntegerWriteChannel setActivePower = this.channel(EssSinexcel.ChannelId.SET_ACTIVE_POWER); +// setActivePower.setNextWriteValue(activePower / 100); +// +// IntegerWriteChannel setReactivePower = this.channel(EssSinexcel.ChannelId.SET_REACTIVE_POWER); +// setReactivePower.setNextWriteValue(reactivePower / 100); +// +// if (this.stateOnOff() == false) { +// a = 1; +// } +// +// if (this.stateOnOff() == true) { +// a = 0; +// } +// +// if (activePower == 0 && reactivePower == 0 && a == 0) { +// this.counterOff++; +// if (this.counterOff == 48) { +// this.inverterOff(); +// this.counterOff = 0; +// } +// +// } else if ((activePower != 0 || reactivePower != 0) && a == 1) { +// this.counterOn++; +// if (this.counterOn == 48) { +// this.inverterOn(); +// this.counterOn = 0; +// } +// } +// break; +// +// case OFF: +// if (this.stateOnOff() == true) { +// this.inverterOff(); +// } else { +// return; +// } +// break; +// } +// } + @Override public void handleEvent(Event event) { if (!this.isEnabled()) { @@ -807,6 +843,4 @@ public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { ); } - - } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java index 289df517ab8..ad5d497587b 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/Context.java @@ -7,11 +7,13 @@ import io.openems.edge.battery.api.Battery; import io.openems.edge.common.channel.BooleanReadChannel; import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.common.statemachine.AbstractContext; import io.openems.edge.ess.sinexcel.Config; +import io.openems.edge.ess.sinexcel.EssSinexcel; import io.openems.edge.ess.sinexcel.EssSinexcelImpl; import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; -public class Context { +public class Context extends AbstractContext{ protected final EssSinexcelImpl component; protected final ComponentManager componentManager; protected final Battery battery; @@ -30,8 +32,8 @@ public void setStartOnce(boolean startOnce) { protected Optional gridDetector; protected Optional grounding; - public Context(EssSinexcelImpl component, ComponentManager componentManager, Battery battery, Config config) { - super(); + public Context(EssSinexcelImpl component, ComponentManager componentManager, Battery battery, Config config) { + super(component); this.component = component; this.componentManager = componentManager; this.battery = battery; diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java index 952f9509e15..c310301b334 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/ErrorHandler.java @@ -15,7 +15,7 @@ protected void onEntry(Context context) throws OpenemsNamedException { @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { - + context.getParent(); if (this.attemptCounter > 5) { // switch off context.component.inverterOff(); diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java index f4175b84d8f..513839d173a 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/GroundSetHandler.java @@ -5,43 +5,24 @@ import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; public class GroundSetHandler extends StateHandler { - - private int attemptCounter = 0; - - @Override - protected void onEntry(Context context) throws OpenemsNamedException { - this.attemptCounter = 0; - } @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { - - + // isOngrid ? - if (!context.getGridDetector().get() ) { + if (!context.getGridDetector().get()) { // grounding set to goto ongrid - context.component.handleWritingDigitalOutputForGrounding(true); + context.component.handleWritingDigitalOutputForGrounding(false); context.component.handleWritingDigitalOutputForMain(false); - - // main also here - this.attemptCounter++; return State.TOTAL_ONGRID; } - // grounding set to goto offgrid // isOffgrid ? - if (context.getGridDetector().get() ) { + if (context.getGridDetector().get()) { // grounding set to goto ongrid - context.component.handleWritingDigitalOutputForGrounding(false); - this.attemptCounter++; + context.component.handleWritingDigitalOutputForGrounding(true); return State.TOTAL_OFFGRID; } - - if (this.attemptCounter > 5) { - return State.ERROR; - } - return State.GROUNDSET; } - } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java index 8629787cdee..569156940e1 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StartInverterHandler.java @@ -1,7 +1,7 @@ package io.openems.edge.ess.sinexcel.statemachine; -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.edge.common.statemachine.StateHandler; @@ -9,14 +9,22 @@ public class StartInverterHandler extends StateHandler { - //private final Logger log = LoggerFactory.getLogger(StartInverterHandler.class); + private final Logger log = LoggerFactory.getLogger(StartInverterHandler.class); @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { - //log.info("Inside StartInverter handler"); - // Start the inverter no matter what + log.info("Inside StartInverter handler"); + + // Start the inverter context.component.inverterOn(); + + boolean isInvOn = context.component.stateOnOff(); + log.info("Is inverter on ? :" + isInvOn); + + if (!isInvOn) { + return State.START; + } // Started the inverter, Check the grid detector // If Grid is off diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java index a6bafca040a..625a36174b9 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StateMachine.java @@ -8,76 +8,6 @@ public class StateMachine extends AbstractStateMachine { - /** - * The states which is used in the sinexcel switch from On-grid mode to off-grid - * mode and vice-versa. This switching needs total to 8 states, because state - * transition is decided with 3 digital inputs - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
DI1DI2DI3State
000State
001State
010State
011State
100State
101State
110State
111State
- */ public enum State implements io.openems.edge.common.statemachine.State, OptionsEnum { UNDEFINED(-1), // @@ -148,4 +78,76 @@ public StateHandler getStateHandler(State state) { throw new IllegalArgumentException("Unknown State [" + state + "]"); } + + + /** + * The states which is used in the sinexcel switch from On-grid mode to off-grid + * mode and vice-versa. This switching needs total to 8 states, because state + * transition is decided with 3 digital inputs + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
DI1DI2DI3State
000State
001State
010State
011State
100State
101State
110State
111State
+ */ } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java index 3c20c0b5be9..f6e3e66476f 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/StopInverterHandler.java @@ -3,24 +3,64 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; +import java.time.Instant; + import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.edge.common.statemachine.StateHandler; import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; public class StopInverterHandler extends StateHandler { - + + private Instant lastAttempt = Instant.MIN; + private final Logger log = LoggerFactory.getLogger(StopInverterHandler.class); + @Override + protected void onEntry(Context context) throws OpenemsNamedException { + + this.lastAttempt = Instant.now(); + System.out.println(this.lastAttempt); + } + @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { - - log.info("Inside StopInverter handler"); - //Stop the inverter no matter what - context.component.inverterOff(); - - //go to grounding set step after stopping - return State.GROUNDSET; - + + Instant now = Instant.now(); + + log.info("last attempt - now is : " + Duration.between(this.lastAttempt, now).getSeconds()); + long waitingSeconds = 0; + + // isOngrid ? + if (!context.getGridDetector().get()) { + log.info("Going from off-grid to on-grid"); + waitingSeconds = 65; + } + + // isOffgrid ? + if (context.getGridDetector().get()) { + + log.info("Going from on-grid to off-grid"); + waitingSeconds = 3; + } + + boolean isWaitingTimePassed = Duration.between(this.lastAttempt, now).getSeconds() > waitingSeconds; + + if (isWaitingTimePassed) { + log.info("Inside StopInverter handler"); + // Stop the inverter no matter what + context.component.inverterOff(); + context.component.inverterOff(); + + log.info("Is inverter on ? :" + context.component.stateOnOff()); + + // go to grounding set step after stopping + return State.GROUNDSET; + } else { + log.info("Waiting seconds " + Duration.between(this.lastAttempt, now).getSeconds() + " seconds"); + return State.STOP; + } + } } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java index f0a2122e5ce..d7a397821c8 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOffGridHandler.java @@ -1,12 +1,10 @@ package io.openems.edge.ess.sinexcel.statemachine; -//import java.time.Duration; -//import java.time.Instant; - -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.statemachine.StateHandler; import io.openems.edge.common.sum.GridMode; import io.openems.edge.ess.sinexcel.CurrentState; @@ -14,44 +12,72 @@ public class TotalOffGridHandler extends StateHandler { - //private final Logger log = LoggerFactory.getLogger(TotalOffGridHandler.class); - - private boolean StartOnce = false; - //private Instant lastAttempt = Instant.MIN; - -// @Override -// protected void onEntry(Context context) throws OpenemsNamedException { -// this.lastAttempt = Instant.MIN; -// } + private final Logger log = LoggerFactory.getLogger(TotalOffGridHandler.class); @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { - //log.info("Inside total offgrid handler"); + log.info("Inside total offgrid handler"); - // If Grid is On if (!context.getGridDetector().get()) { - // Before going to ON, Wait for some time, so that the grid is not fluctuating - //boolean iswaitingTimePassed = Duration.between(this.lastAttempt, Instant.now()).getSeconds() > 65; - //if (iswaitingTimePassed) { - return State.STOP; - //} - } - - if (!StartOnce) { - this.StartOnce = true; - return State.START; + return State.STOP; } + context.component.setclearFailureCommand(); + // Set start command to inverter + context.component.inverterOn(); + context.component.softStart(true); + boolean isInvOn = context.component.stateOnOff(); + log.info("Is inverter on ? :" + isInvOn); - // Run in the offgrid state - // Set the frequncy context.component.setFrequency(); - // Give command to make it off-grid + Value freq = context.component.getFrequency(); + log.info("frequency is : " + freq.get() + " hz"); + + context.component.setOffgridCommand(); - // Set the grid mode to Offgrid + + // 3. Set the grid mode to Offgrid , // do this before , make it undefined context.component._setGridMode(GridMode.OFF_GRID); + + if (isInvOn) { + // Inverter is on + + // 1. Set the frequncy + context.component.setFrequency(); + + if (freq.get() == 52) { - // Do the softstart of the sinexcel + // 2. Give command to make it off-grid + context.component.setOffgridCommand(); + + // 3. Set the grid mode to Offgrid , // do this before , make it undefined + context.component._setGridMode(GridMode.OFF_GRID); + } else { + log.info("frequency is not 52 yet, goign back again to check freq"); + return State.TOTAL_OFFGRID; + } + + } else { + log.info("Inverter is not on, going back to swithc on inverter"); + return State.TOTAL_OFFGRID; + } + + // Run in the offgrid state + +// // 1. Set the frequncy +// context.component.setFrequency(); +// +// // 2. Give command to make it off-grid +// context.component.setOffgridCommand(); +// +// // 3. Set the grid mode to Offgrid , // do this before , make it undefined +// context.component._setGridMode(GridMode.OFF_GRID); + + // 4. Do the softstart of the sinexcel + + log.info("parameters are set for the inverter to the softstart"); + + CurrentState currentState = context.component.getSinexcelState(); switch (currentState) { case UNDEFINED: @@ -59,11 +85,11 @@ protected State runAndGetNextState(Context context) throws OpenemsNamedException case MPPT: case THROTTLED: case STARTED: + case STANDBY: context.component.softStart(true); break; case SHUTTINGDOWN: case FAULT: - case STANDBY: case OFF: default: context.component.softStart(false); diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java index 1717e02a65a..bcc4c5e7982 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/TotalOnGridHandler.java @@ -1,73 +1,80 @@ package io.openems.edge.ess.sinexcel.statemachine; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.statemachine.StateHandler; import io.openems.edge.common.sum.GridMode; import io.openems.edge.ess.sinexcel.CurrentState; import io.openems.edge.ess.sinexcel.statemachine.StateMachine.State; -//import java.time.Duration; -//import java.time.Instant; -// -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TotalOnGridHandler extends StateHandler { -// private final Logger log = LoggerFactory.getLogger(TotalOnGridHandler.class); + private final Logger log = LoggerFactory.getLogger(TotalOnGridHandler.class); protected boolean StartOnce = false; -// private Instant lastAttempt = Instant.MIN; - -// @Override -// protected void onEntry(Context context) throws OpenemsNamedException { -// this.lastAttempt = Instant.MIN; -// } @Override protected State runAndGetNextState(Context context) throws OpenemsNamedException { + log.info("inside total ongrid state"); + if (context.getGridDetector().get()) { + return State.STOP; + } - //log.info("Inside total ongrid handler"); + context.component.inverterOn(); + context.component.softStart(true); + boolean isInvOn = context.component.stateOnOff(); + log.info("Is inverter on ? :" + isInvOn); + Value freq = context.component.getFrequency(); + log.info("frequency is : " + freq.get() + " hz"); + + + if (isInvOn) { + // Inverter is on - // If Grid is off - if (context.getGridDetector().get() ) { - // Before going to ON, Wait for some time, so that the grid is not fluctuating - //boolean iswaitingTimePassed = Duration.between(this.lastAttempt, Instant.now()).getSeconds() > 65; - //if (iswaitingTimePassed) { - return State.STOP; - //} - } + // 1. Give command to make it on-grid + context.component.setOngridCommand(); - if (!StartOnce) { - this.StartOnce = true; - return State.START; - } + // do this before , make it undefined + + // 2. Set the grid mode to Ongrid + context.component._setGridMode(GridMode.ON_GRID); + + } else { + log.info("Inverter is not on , going back to swithc on inverter"); + return State.TOTAL_ONGRID; + } + // Run in the ongrid state - // Give command to make it on-grid + + // 1. Give command to make it on-grid context.component.setOngridCommand(); - // Set the grid mode to Ongrid + + // 2. Set the grid mode to Ongrid context.component._setGridMode(GridMode.ON_GRID); - // Do the softstart of the sinexcel + // 3. Do the softstart of the sinexcel CurrentState currentState = context.component.getSinexcelState(); + switch (currentState) { case UNDEFINED: case SLEEPING: case MPPT: case THROTTLED: case STARTED: + case STANDBY: context.component.softStart(true); break; case SHUTTINGDOWN: case FAULT: - case STANDBY: case OFF: default: context.component.softStart(false); } - return State.TOTAL_ONGRID; } } diff --git a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java index ba514e13275..969ad21ac9d 100644 --- a/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java +++ b/io.openems.edge.ess.sinexcel/src/io/openems/edge/ess/sinexcel/statemachine/UndefinedHandler.java @@ -28,7 +28,7 @@ protected State runAndGetNextState(Context context) throws OpenemsNamedException // This should never happen case START: - case STOP: + case STOP: break; } diff --git a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java index 63ea8484550..601f58232c7 100644 --- a/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java +++ b/io.openems.edge.ess.sinexcel/test/io/openems/edge/ess/sinexcel/EssSinexcelImplTest.java @@ -35,7 +35,7 @@ public void test() throws Exception { .addReference("cm", new DummyConfigurationAdmin()) // .addReference("componentManager", new DummyComponentManager()) // .addReference("power", new DummyPower()) // - .addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) // + .addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) //. .addReference("setBattery", new DummyBattery(BATTERY_ID)) // .addComponent(new DummyInputOutput(IO_ID)) // .activate(MyConfig.create() // diff --git a/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java b/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java index 61c906fcf08..1a79ea5d8d2 100644 --- a/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java +++ b/io.openems.edge.io.wago/src/io/openems/edge/wago/Wago.java @@ -161,6 +161,7 @@ private static Document downloadConfigXml(InetAddress ip, String username, Strin private static Document downloadConfigXml(InetAddress ip, String filename, String username, String password) throws ParserConfigurationException, SAXException, IOException { + //URL url = new URL(String.format("http://%s/etc/%s", "localhost:8083", filename)); URL url = new URL(String.format("http://%s/etc/%s", ip.getHostAddress(), filename)); String authStr = String.format("%s:%s", username, password); byte[] bytesEncoded = Base64.getEncoder().encode(authStr.getBytes());