diff --git a/src/main/java/ch/hevs/isi/MinecraftController.java b/src/main/java/ch/hevs/isi/MinecraftController.java index 1e6b4ac..2aec9fd 100644 --- a/src/main/java/ch/hevs/isi/MinecraftController.java +++ b/src/main/java/ch/hevs/isi/MinecraftController.java @@ -1,5 +1,8 @@ package ch.hevs.isi; +import ch.hevs.isi.core.BooleanDataPoint; +import ch.hevs.isi.core.DataPoint; +import ch.hevs.isi.core.FloatDataPoint; import ch.hevs.isi.db.DatabaseConnector; import ch.hevs.isi.field.FieldConnector; import ch.hevs.isi.utils.Utility; @@ -34,7 +37,7 @@ public class MinecraftController { } @SuppressWarnings("all") - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { // ------------------------------------- DO NOT CHANGE THE FOLLOWING LINES ------------------------------------- String dbProtocol = "http"; @@ -99,17 +102,47 @@ public class MinecraftController { Utility.pDebug("Database URL: " + DatabaseConnector.url); Utility.pDebug("Config: " + properties.getProperty("DB.URL")); DatabaseConnector.getMySelf().initialize(DatabaseConnector.url); + System.out.println("Database is running on " + DatabaseConnector.url); } // Initialize the Modbus TCP connector FieldConnector.getMySelf().initialize(modbusTcpHost, modbusTcpPort,"src/main/resources/ModbusMap.csv"); - - + System.out.println("Field is running on " + modbusTcpHost + ":" + modbusTcpPort); // Initialize the web server String host = properties.getProperty("WEB.URL"); int port = Integer.parseInt(properties.getProperty("WEB.PORT")); WebConnector.getMySelf().initialize(host, port); + System.out.println("Web server is running on " + host + ":" + port); + + + SmartControl smartControl = new SmartControl(); + System.out.println("SmartControl is running"); + while (true) { + BooleanDataPoint man = (BooleanDataPoint) DataPoint.getDataPointOnListFromLabel("REMOTE_MAN_SW"); + boolean autoMode = true; + if(man != null) autoMode = !man.getValue(); + + if (autoMode){ + boolean stateGrid = true; + try { + stateGrid = smartControl.run(); + } catch (Exception e) { + e.printStackTrace(); + } + if(!stateGrid) System.out.println("Grid is not fine"); + } + + FloatDataPoint score = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("SCORE"); + if(score != null) { + if(score.getValue() >= 100) { + System.out.println("Game finished with score: " + score.getValue()); + System.exit(0); + } + } + + Thread.sleep(SmartControl.TIME_BETWEEN_UPDATES); + } } diff --git a/src/main/java/ch/hevs/isi/SmartControl.java b/src/main/java/ch/hevs/isi/SmartControl.java new file mode 100644 index 0000000..9085957 --- /dev/null +++ b/src/main/java/ch/hevs/isi/SmartControl.java @@ -0,0 +1,203 @@ +package ch.hevs.isi; + +import ch.hevs.isi.core.BooleanDataPoint; +import ch.hevs.isi.core.DataPoint; +import ch.hevs.isi.core.FloatDataPoint; + +public class SmartControl { + private static final float GRID_VOLTAGE_MIN = 750f; + private static final float GRID_VOLTAGE_MAX = 875f; + private static final float GRID_VOLTAGE_TOLERANCE = 25f; + public static final long TIME_BETWEEN_UPDATES = 100; + private float spCoal = 0; + private float spFactory = 0; + + + + // Useful data points + private FloatDataPoint clock; + private FloatDataPoint battChrg; + private FloatDataPoint battPwrIn; + private FloatDataPoint remoteCoalSp; + private FloatDataPoint remoteFactorySp; + private FloatDataPoint coalAmount; + + + // Emergency data points + private FloatDataPoint gridVoltage; + + // Ideal goal points variables + private float igpBatteryLevel = 0f; + + // Time variables + private int day = 1; + private boolean dayChanged = false; + private float previousCoalAmount = 0f; + final float kpiFactory = 0.1f; + final float kpiCoal = 0.1f; + + private void defineDataPoints(){ + do { + try { + Thread.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } + clock = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("CLOCK_FLOAT"); + battChrg = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("BATT_CHRG_FLOAT"); + battPwrIn = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("BATT_P_FLOAT"); + remoteCoalSp = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("REMOTE_COAL_SP"); + remoteFactorySp = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("REMOTE_FACTORY_SP"); + coalAmount = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("COAL_AMOUNT"); + gridVoltage = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("GRID_U_FLOAT"); + } while (!testIfDataPointsAreDefined()); + System.out.println("Data points defined"); + } + + private boolean testIfDataPointsAreDefined(){ + if(clock == null) return false; + if(battChrg == null) return false; + if(battPwrIn == null) return false; + if(remoteCoalSp == null) return false; + if(remoteFactorySp == null) return false; + if(coalAmount == null) return false; + if(gridVoltage == null) return false; + return true; + } + + private float getTimeOfTheDay(){ + float timeOfTheDay = clock.getValue(); + timeOfTheDay %= 1; + timeOfTheDay *= 24; + return timeOfTheDay; + } + + private float getUnregProducerPower(){ + float producerPower = 0f; + FloatDataPoint solar = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("SOLAR_P_FLOAT"); + FloatDataPoint wind = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("WIND_P_FLOAT"); + + producerPower += solar.getValue(); + producerPower += wind.getValue(); + + return producerPower; + } + + private float getUnregConsumerPower(){ + float consumerPower = 0f; + FloatDataPoint home = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("HOME_P_FLOAT"); + FloatDataPoint factory = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("FACTORY_P_FLOAT"); + FloatDataPoint bunker = (FloatDataPoint) DataPoint.getDataPointOnListFromLabel("BUNKER_P_FLOAT"); + + consumerPower += home.getValue(); + consumerPower += factory.getValue(); + consumerPower += bunker.getValue(); + return consumerPower; + } + + private boolean checkIfGridIsFine(){ + boolean gridIsFine = true; + + // Grid voltage is too high + if(gridVoltage.getValue() > (GRID_VOLTAGE_MAX-GRID_VOLTAGE_TOLERANCE)) { + gridIsFine = false; + new BooleanDataPoint("SOLAR_CONNECT_ST", true).setValue(false); + new BooleanDataPoint("WIND_CONNECT_ST", true).setValue(false); + remoteCoalSp.setValue(0f); + if(gridVoltage.getValue() > GRID_VOLTAGE_MAX) { + remoteFactorySp.setValue(1f); + } + } + + // Grid voltage is too low + if(gridVoltage.getValue() < (GRID_VOLTAGE_MIN+GRID_VOLTAGE_TOLERANCE)) { + gridIsFine = false; + new BooleanDataPoint("SOLAR_CONNECT_ST", true).setValue(true); + new BooleanDataPoint("WIND_CONNECT_ST", true).setValue(true); + remoteCoalSp.setValue(1f); + if(gridVoltage.getValue() < GRID_VOLTAGE_MIN) { + remoteFactorySp.setValue(0f); + } + } + + return gridIsFine; + } + + private int getPeriodOfDay(){ + float timeOfTheDay = getTimeOfTheDay(); + + // 0 = Night, 1 = Morning, 2 = Afternoon + int periodOfDay = 0; + if(timeOfTheDay >= 0 && timeOfTheDay < 6) periodOfDay = 1; // Night + if(timeOfTheDay >= 6 && timeOfTheDay < 12) periodOfDay = 2; // Morning + if(timeOfTheDay >= 12 && timeOfTheDay < 18) periodOfDay = 3; // Afternoon + if(timeOfTheDay >= 18 && timeOfTheDay < 24) periodOfDay = 4; // Evening + + return periodOfDay; + } + + + public SmartControl() { + + // start the solar and wind power plants + new BooleanDataPoint("REMOTE_SOLAR_SW", true).setValue(true); + new BooleanDataPoint("REMOTE_WIND_SW", true).setValue(true); + new FloatDataPoint("REMOTE_COAL_SP", true).setValue(0f); + new FloatDataPoint("REMOTE_FACTORY_SP", true).setValue(0f); + + defineDataPoints(); + + } + + public boolean run() { + + if ((getTimeOfTheDay() < 0.5f) && !dayChanged) { + dayChanged = true; + day++; + } + if (getTimeOfTheDay() > 23f) dayChanged = false; + if(coalAmount.getValue() > previousCoalAmount) { + previousCoalAmount = coalAmount.getValue(); + day = 1; + } + + String debug = "Day " + day + " - "; + + if(battChrg.getValue()<0.45f){ + igpBatteryLevel = 0.45f; + spCoal = -(battChrg.getValue()-0.45f)*5 + 0.2f; + debug += "BattChrg < 0.45f - "; + } else { + if (getUnregProducerPower() < 500f) { + spCoal = 0.2f; + } + } + + if(battChrg.getValue()>0.55f){ + igpBatteryLevel = 0.55f; + if(battChrg.getValue()>0.6f) spCoal -= (battChrg.getValue()-0.55f)*kpiCoal; + debug += "BattChrg > 0.55f"; + spFactory = (battChrg.getValue()-0.55f)*5; + } + + if(battChrg.getValue()<0.55f){ + igpBatteryLevel = 0.55f; + spFactory += (battChrg.getValue()-0.55f)*kpiFactory; + debug += "BattChrg < 0.55f"; + } + + new FloatDataPoint("IGP_BATTERY_LEVEL", true).setValue(igpBatteryLevel); + + if (spFactory > 1f) spFactory = 1f; + if (spFactory < 0f) spFactory = 0f; + if (spCoal > 1f) spCoal = 1f; + if (spCoal < 0f) spCoal = 0f; + + new FloatDataPoint("REMOTE_FACTORY_SP", true).setValue(spFactory); + new FloatDataPoint("REMOTE_COAL_SP", true).setValue(spCoal); + + System.out.println(debug); + + return checkIfGridIsFine(); + } +} diff --git a/src/main/java/ch/hevs/isi/db/DatabaseConnector.java b/src/main/java/ch/hevs/isi/db/DatabaseConnector.java index 63eb65a..5a2bbc0 100644 --- a/src/main/java/ch/hevs/isi/db/DatabaseConnector.java +++ b/src/main/java/ch/hevs/isi/db/DatabaseConnector.java @@ -163,7 +163,7 @@ public class DatabaseConnector implements DataPointListener { if(respondCode != 204){ System.out.println("Error: " + respondCode + ", Data: " + data); } else { - System.out.println(data + " -> Database"); + Utility.pDebug(data + " -> Database"); } con.disconnect(); con = null; diff --git a/src/main/java/ch/hevs/isi/field/FieldConnector.java b/src/main/java/ch/hevs/isi/field/FieldConnector.java index 5b5b9c1..23a372c 100644 --- a/src/main/java/ch/hevs/isi/field/FieldConnector.java +++ b/src/main/java/ch/hevs/isi/field/FieldConnector.java @@ -3,6 +3,7 @@ package ch.hevs.isi.field; import ch.hevs.isi.core.DataPoint; import ch.hevs.isi.core.DataPointListener; import ch.hevs.isi.core.FloatDataPoint; +import ch.hevs.isi.utils.Utility; import java.io.BufferedReader; import java.io.FileNotFoundException; @@ -89,11 +90,13 @@ public class FieldConnector implements DataPointListener { } private void pushToField(String label, String value){ - System.out.println("Field: " + label + " " + value); + Utility.pDebug("Field: " + label + " " + value); } @Override public void onNewValue(DataPoint dp) { ModbusRegister mR = ModbusRegister.getRegisterFromDatapoint(dp); //search the corresponding register to the datapoint + if(mR == null) return; //if the register is not found, return + if(dp.isOutput()){ //write only on the datapoints, which are outputs if(dp.getLabel().equals("REMOTE_SOLAR_SW") //write only boolean outputs ||dp.getLabel().equals("REMOTE_WIND_SW") diff --git a/src/main/java/ch/hevs/isi/field/SmartControl.java b/src/main/java/ch/hevs/isi/field/SmartControl.java deleted file mode 100644 index 72ac3c7..0000000 --- a/src/main/java/ch/hevs/isi/field/SmartControl.java +++ /dev/null @@ -1,64 +0,0 @@ -package ch.hevs.isi.field; - -import ch.hevs.isi.core.DataPoint; -import ch.hevs.isi.core.FloatDataPoint; - -public class SmartControl { - - public SmartControl(){ - - //time - FloatDataPoint clockFloat = (FloatDataPoint) DataPoint.getDataPointFromLabel("CLOCK_FLOAT"); - int timeOfTheDay = 0; //0=default 1=beginning 2=day 3=end 4=night - if (clockFloat.getValue() > 0.2f && clockFloat.getValue() <= 0.3f) { //beginning of the day - timeOfTheDay =1; - } - if (clockFloat.getValue() > 0.3f && clockFloat.getValue() <= 0.7f){ //day - timeOfTheDay = 2; - } - if (clockFloat.getValue() > 0.7f && clockFloat.getValue() <= 0.8f){ //end of the day - timeOfTheDay = 3; - } - if (clockFloat.getValue() <= 0.2f && clockFloat.getValue() > 0.8f){ //night - timeOfTheDay = 4; - } - - - //Factory and coal - FloatDataPoint battChrgFloat = (FloatDataPoint) DataPoint.getDataPointFromLabel("BATT_CHRG_FLOAT"); - FloatDataPoint remoteCoalSp = (FloatDataPoint) DataPoint.getDataPointFromLabel("REMOTE_COAL_SP"); - FloatDataPoint remoteFactorySp = (FloatDataPoint) DataPoint.getDataPointFromLabel("REMOTE_FACTORY_SP"); - FloatDataPoint coalAmount = (FloatDataPoint) DataPoint.getDataPointFromLabel("COAL_AMOUNT"); - - if (battChrgFloat.getValue() <= 0.4f){ //if battery level is under 40 % - if(coalAmount.getValue() <= 0.5f){ - remoteCoalSp.setValue(0.5f); //start the coal power plant with 50% - }else{ - remoteCoalSp.setValue(1f); //start the coal power plant with 100% - } - remoteFactorySp.setValue(0f); //stop the consumption of the factory - } - if (battChrgFloat.getValue() > 0.4f && battChrgFloat.getValue() < 0.6f){ //if battery lever is between 40% and 60% - remoteCoalSp.setValue(0f); //stop the coal power plant - remoteFactorySp.setValue(0f); //stop the consumption of the factory - } - if(battChrgFloat.getValue() >= 0.6f){ //if battery level is over 60 % - remoteCoalSp.setValue(0f); //stop the coal power plant - remoteFactorySp.setValue(1f); //start the consumption of the factory - } - - //Solar - FloatDataPoint weatherFloat = (FloatDataPoint) DataPoint.getDataPointFromLabel("WEATHER_FLOAT"); - FloatDataPoint weatherCountdownFloat = (FloatDataPoint) DataPoint.getDataPointFromLabel("WEATHER_COUNTDOWN_FLOAT"); - FloatDataPoint weatherForecastFloat = (FloatDataPoint) DataPoint.getDataPointFromLabel("WEATHER_FORECAST_FLOAT"); - - /** TODO Solar Smartcontrol - * check the value of weatherForecastFloat and weatherFloat - */ - - //Wind - /** TODO Wind Smartcontrol - * - */ - } -} diff --git a/src/main/java/ch/hevs/isi/web/WebConnector.java b/src/main/java/ch/hevs/isi/web/WebConnector.java index 9b6f119..292dfab 100644 --- a/src/main/java/ch/hevs/isi/web/WebConnector.java +++ b/src/main/java/ch/hevs/isi/web/WebConnector.java @@ -4,6 +4,7 @@ import ch.hevs.isi.core.BooleanDataPoint; import ch.hevs.isi.core.DataPoint; import ch.hevs.isi.core.DataPointListener; import ch.hevs.isi.core.FloatDataPoint; +import ch.hevs.isi.utils.Utility; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.server.WebSocketServer; @@ -50,7 +51,7 @@ public class WebConnector implements DataPointListener { @Override public void onMessage(WebSocket conn, String message) { - System.out.println("received message from " + conn.getRemoteSocketAddress() + ": " + message); + Utility.pDebug("received message from " + conn.getRemoteSocketAddress() + ": " + message); updateDataPoint(message); } @@ -74,15 +75,15 @@ public class WebConnector implements DataPointListener { private void pushToWeb(DataPoint dp){ wss.broadcast(dp.toString()); - System.out.println(dp.toString() + " -> Web"); + Utility.pDebug(dp.toString() + " -> Web"); } private void updateDataPoint(String message){ String label = message.split("=")[0]; - System.out.println("Label: " + label); + Utility.pDebug("Label: " + label); String value = message.split("=")[1]; - System.out.println("Value: " + value); + Utility.pDebug("Value: " + value); if( (value.equals("true")) || value.equals("false") ) { new BooleanDataPoint(label, true).setValue(Boolean.parseBoolean(value));