net.sf.sgsimulator.sgsrest.vertx.services.GridLabSimulatorService.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.sgsimulator.sgsrest.vertx.services.GridLabSimulatorService.java

Source

/*
   This file is part of SGSim-REST framework, a game to learn coordination protocols with microgrids
       
Copyright (C) 2017 Rafael Pax, Jorge J. Gomez-Sanz
based on code by Jorge J. Gomez Sanz, Nuria Cuartero-Soler, Sandra Garcia-Rodriguez
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package net.sf.sgsimulator.sgsrest.vertx.services;

import java.awt.Color;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import com.github.aesteve.vertx.nubes.services.Service;
import com.github.aesteve.vertx.nubes.utils.functional.TriConsumer;

import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import mired.ucm.dynamicGLM.XMLUtilities;
import mired.ucm.grid.ElementEMS;
import mired.ucm.grid.TypesElement;
import mired.ucm.grid.TypesGenerator;
import mired.ucm.monitor.Event;
import mired.ucm.monitor.ReadScenario;
import mired.ucm.price.Tariff;
import mired.ucm.properties.PATHS;
import mired.ucm.simulator.GridLabDiscreteEventSimulator;
import mired.ucm.simulator.GridlabActions;
import mired.ucm.simulator.GridlabException;
import mired.ucm.simulator.NetworkElementsStatus;
import mired.ucm.simulator.NetworkListener;
import mired.ucm.simulator.NetworkStatus;
import mired.ucm.simulator.SensorContainerNotFound;
import mired.ucm.simulator.SensorIDS;
import mired.ucm.simulator.SimulatorNotInitializedException;
import mired.ucm.simulator.NetworkStatus.UnknownSensor;
import mired.ucm.simulator.displayer.CtsDisplayer;
import mired.ucm.simulator.displayer.StateWindow;
import mired.ucm.simulator.orders.Order;
import mired.ucm.simulator.orders.SwitchOn;
import mired.ucm.viewer.PowerGridViewer;
import net.sf.sgsimulator.sgsrest.vertx.domain.orders.JsonOrder;

@SuppressWarnings({ "unused", "rawtypes" })
public class GridLabSimulatorService implements NetworkListener, Service {

    private AtomicLong listenerCount = new AtomicLong(0);
    private ConcurrentHashMap<Long, Consumer<JsonObject>> handlers = new ConcurrentHashMap<>();

    private SimpleDateFormat sdf;
    private DecimalFormat decimalFormat;
    private int moments;
    private NetworkElementsStatus nes;
    private boolean intelligence;
    private GridlabActions gridlabActions;
    private int hoursOfSimulation;
    private ArrayBlockingQueue demandCurve;
    private String title;
    private int cycleTimeInMillis;
    private float importedEnergy;
    private float exportedEnergy;
    private float energyLosses;
    private float bill;
    private Tariff tariff;
    private boolean activeClients;
    private ReadScenario rs;
    private String currentTariffPeriod;
    private double currentTariffPrice;
    private GridLabDiscreteEventSimulator gldes;
    private Date startDate;
    private PATHS paths;
    private Double millisperwebpoll;

    private void onInit(Vertx vertx, JsonObject config) throws IOException {
        config = config.getJsonObject("gridlab");
        int cycleTimeInMillis = config.getInteger("cycleTimeInMillis");// 60000;
        boolean intelligence = config.getBoolean("intelligence");// true;
        int moments = config.getInteger("moments");// 30;
        Double minRange = config.getDouble("minRange", null);
        Double maxRange = config.getDouble("maxRange", null);
        millisperwebpoll = config.getDouble("millisperwebpoll", null);
        boolean activeClients = config.getBoolean("activeClients");// true;
        // TODO parametrize
        Tariff tariff = new TariffExample();

        JsonArray sdjson = config.getJsonArray("startDate");
        JsonArray edjson = config.getJsonArray("endDate");
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.set(sdjson.getInteger(0), sdjson.getInteger(1), sdjson.getInteger(2), sdjson.getInteger(3),
                sdjson.getInteger(4), sdjson.getInteger(5));

        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.set(edjson.getInteger(0), edjson.getInteger(1), edjson.getInteger(2), edjson.getInteger(3),
                edjson.getInteger(4), edjson.getInteger(5));

        String configurationFile = config.getString("configurationFile");
        String gridFile = config.getString("gridFile");
        // definition
        String scenarioFile = config.getString("scenarioFile");
        String gridLabFolder = config.getString("gridLabFolder");
        PATHS paths = new PATHS(configurationFile, gridFile, scenarioFile, gridLabFolder);

        Date[] dates = readSimulationTime(paths.getNetXmlSrcFile());
        long diffInMillies = calendarEnd.getTimeInMillis() - calendarStart.getTimeInMillis();

        int hoursOfSimulation = (int) TimeUnit.HOURS.convert(diffInMillies, TimeUnit.MILLISECONDS);
        startDate = calendarStart.getTime();
        init(title, startDate, cycleTimeInMillis, paths, intelligence, hoursOfSimulation, tariff, moments, minRange,
                maxRange, activeClients);
    }

    private void onStart(Future<Void> future) {
        try {
            initSimulator(startDate, 14, cycleTimeInMillis, paths, intelligence);
            this.gldes.start();
            future.complete();
            for (ElementEMS generator : this.nes.getGenerators()) {
                if (generator.getType().equals(TypesElement.GENERATOR)) {
                    this.gldes.getSimulator().queueOrder(new SwitchOn(generator.getName(), getTime(), paths));
                }
            }

        } catch (GridlabException | SimulatorNotInitializedException e) {
            e.printStackTrace();
            future.fail(e);
        }
    }

    private void onStop(Future<Void> future) {
        try {
            this.gldes.stop();
            future.complete();
        } catch (TimeoutException e) {
            future.fail(e);
        }

    }

    private void sendEvent(Date timestampDate, String type, Object value) {
        long timestamp = timestampDate.getTime();
        JsonObject evt = new JsonObject().put("timestamp", timestamp).put("type", type).put("value", value);

        this.handlers.values().forEach(h -> h.accept(evt));
    }

    Date lastTime = new Date();

    @Override
    public void processCycleStatus(NetworkStatus ns, NetworkElementsStatus nes, Date timestampDate) {
        Date cdate = new Date();
        if (cdate.getTime() - lastTime.getTime() > millisperwebpoll) {
            lastTime = cdate;

            /*
             * Consumption
             */
            this.sendEvent(timestampDate, "system-consumption",
                    this.rs.getConsumption(nes.getElements(), timestampDate));
            /*
             * Substation sensors
             */
            ns.getSubstationSensors().forEach((sensorId, value) -> {
                this.sendEvent(timestampDate, "substation-sensor",
                        new JsonObject().put("sensorId", sensorId).put("value", value));
            });
            /*
             * Overvoltage
             */
            this.sendEvent(timestampDate, "overvoltage", ns.thereIsOvervoltage());

            /*
             * Transformer sensors
             */
            forEachTransformerSensor(timestampDate, (tName, sensorId, value) -> {

                this.sendEvent(timestampDate, "transformer-sensor", new JsonObject().put("transformer-name", tName)
                        .put("sensorId", sensorId).put("value", value));
            });
            /*
             * Sun percentage
             */
            this.sendEvent(timestampDate, "sun", this.rs.getSunPercentage(timestampDate));
            /*
             * Wind
             */
            this.sendEvent(timestampDate, "wind", this.rs.getWindPercentage(timestampDate));
            /*
             * Generation sum
             */
            this.sendEvent(timestampDate, "generation-sum", nes.calculateGenerationSum() / 1000.0F);

            this.sendEvent(timestampDate, "demand", getLastKWDemand());

            this.sendEvent(timestampDate, "bill", getCurrentBill());

            this.sendEvent(timestampDate, "export", getLastKWExport());

            this.sendEvent(timestampDate, "import", getLastKWImport());

            this.sendEvent(timestampDate, "consumption", getLastKWConsumption());

            this.sendEvent(timestampDate, "generation", getLastKWGeneration());

            this.sendEvent(timestampDate, "powerdump", getLastKWConsumption() - getLastKWGeneration());

            /**
             * Compute bill, generated energy, and 
             */
        }
        computeAdditionalCycleStatus(ns, nes, timestampDate);

    }

    protected int NUMBER_OF_SERIES = 4;
    protected int CONSUMPTION_SERIES_INDEX = 0;
    protected int GENERATION_SERIES_INDEX = 1;
    protected int DEMAND_SERIES_INDEX = 2;
    protected int LOSSES_SERIES_INDEX = 3;
    protected final int timeUnit = Calendar.MILLISECOND;

    private long realTimeCycleLengthMillis;
    private Object lastTimeStamp;
    private double lastExport;
    private double lastConsumption;

    public float getCurrentBill() {
        return bill;
    }

    public float getTotalImportedEnergykWh() {
        return importedEnergy;
    }

    public float getTotalExportedEnergykWh() {
        return exportedEnergy;
    }

    public double getLastKWImport() {
        return lastImport;
    }

    public double getLastKWDemand() {
        return lastDemand;
    }

    public double getLastKWGeneration() {
        return lastGeneration;
    }

    public double getLastKWExport() {
        return lastExport;
    }

    public double getLastKWConsumption() {
        return lastConsumption;
    }

    private double lastImport = 0;// energy demand from the microgrid
    private double lastGeneration = 0;// energy generation from the microgrid
    private double lastDemand = 0;// energy generation from the microgrid

    public void computeAdditionalCycleStatus(NetworkStatus ns, NetworkElementsStatus nes, Date timestamp) {
        Date init = new Date(); // to measure cycle length

        if (ns.thereIsOvervoltage())
            System.err.println(ns.getOvervoltageTimestamp());

        // UPDATING SIMULATION CHART
        float[] newSimulationData = new float[NUMBER_OF_SERIES];
        newSimulationData[CONSUMPTION_SERIES_INDEX] = (float) rs.getConsumption(nes.getAvailableElements(),
                timestamp); // Getting consumption of energy of the next simtime
        newSimulationData[GENERATION_SERIES_INDEX] = (float) nes.calculateGenerationSum() / 1000; // Getting the sum of the generation of the grid of the next simtime, in kW

        try {
            newSimulationData[DEMAND_SERIES_INDEX] = (float) ns.getSubstationSensor(SensorIDS.POWER_DEMAND) / 1000; // Getting substation demand of the next simtime, in kW
            newSimulationData[LOSSES_SERIES_INDEX] = (float) ns.getSubstationSensor(SensorIDS.LOSSES) / 1000; // Getting losses of the next simtime, in kW
        } catch (UnknownSensor e) {
            e.printStackTrace();
        }

        //Updating data for summary chart (substation demand)

        //   demandCurve.offer(newSimulationData[DEMAND_SERIES_INDEX]);
        lastDemand = newSimulationData[DEMAND_SERIES_INDEX];
        lastGeneration = newSimulationData[GENERATION_SERIES_INDEX];
        lastConsumption = newSimulationData[CONSUMPTION_SERIES_INDEX];

        //      System.out.println(getTime()+"=demand:"+lastDemand+" gen:"+lastGeneration+" lastcons:"+lastConsumption+" import:"+lastImport+" export:"+lastExport);

        // Updating tariff period and price
        if (tariff != null) {
            //labelTariff.setVisible(true);
            //labelPeriod.setVisible(true);
            currentTariffPeriod = tariff.getPeriod(timestamp);
            currentTariffPrice = tariff.getEnergyPrice(currentTariffPeriod);
            //labelPeriod.setText(currentTariffPeriod+" ("+currentTariffPrice+" euros/kWh)");
            //labelPeriod.setForeground(tariff.getPeriodColor(currentTariffPeriod));
        }

        // Updating system losses
        //labelLosses.setVisible(true);
        //labelLosses.setText("Losses: "+decimalFormat.format(newSimulationData[LOSSES_SERIES_INDEX])+" kW");

        // Calculating imported energy, exported energy and bill
        double energyOfLastCycle = (newSimulationData[DEMAND_SERIES_INDEX] * (cycleTimeInMillis / 60000.0)) / 1000;
        if (newSimulationData[DEMAND_SERIES_INDEX] >= 0) {
            importedEnergy += energyOfLastCycle;
            if (tariff != null) {
                bill += (energyOfLastCycle * currentTariffPrice);
            }
            lastImport = Math.abs(energyOfLastCycle);
            lastExport = 0;
        } else {
            exportedEnergy += Math.abs(energyOfLastCycle);
            if (tariff != null) {
                bill += (Math.abs(energyOfLastCycle) * tariff.getFineForExporting(tariff.getPeriod(timestamp)));
            }
            lastImport = 0;
            lastExport = Math.abs(energyOfLastCycle);
        }

        // Calculating energy losses
        energyLosses += (newSimulationData[LOSSES_SERIES_INDEX] * (cycleTimeInMillis / 60000.0));

        // UPDATING WEATHER CHART
        float[] newWeatherData = new float[2];
        newWeatherData[0] = (float) rs.getSunPercentage(timestamp); // Getting the % of sun of the next simulation time
        newWeatherData[1] = (float) rs.getWindPercentage(timestamp); // Getting the % of wind of the next simulation time
        //weatherChart.getDataset().advanceTime();  // Advance to the next simtime
        //weatherChart.getDataset().appendData(newWeatherData); //Append new data to the chart dataset
        try {
            long millisSpent = (new Date().getTime() - init.getTime());
            if (realTimeCycleLengthMillis > millisSpent)
                Thread.currentThread().sleep(realTimeCycleLengthMillis - millisSpent);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        lastTimeStamp = timestamp;
    } // End of processCycleStatus

    private void forEachTransformerSensor(Date timestamp, TriConsumer<String, String, Float> action) {
        for (String tName : getTransformerNames()) {
            getTransformerSensors(tName, timestamp);
        }
    }

    public Set<ElementEMS> getElementsByTransformer(String transformerName) {
        return this.nes.getElementsByTransformer(transformerName);
    }

    public Set<ElementEMS> getGeneratorsByTransformer(String transformerName) {
        HashSet<ElementEMS> set = new HashSet<ElementEMS>(this.nes.getElementsByTransformer(transformerName));
        set.removeIf(s -> s.getType() != TypesElement.GENERATOR);
        return set;
    }

    public Hashtable<SensorIDS, Float> getTransformerSensors(String tName, Long timestamp)
            throws SensorContainerNotFound {
        if (timestamp == null) {
            return this.gridlabActions.getTransformerSensors(tName, getTime());
        } else {
            return this.gridlabActions.getTransformerSensors(tName, new Date(timestamp));
        }
    }

    public Hashtable<SensorIDS, Float> getTransformerSensors(String tName, Date timestamp) {
        try {
            return this.gridlabActions.getTransformerSensors(tName, timestamp);
        } catch (SensorContainerNotFound e) {
            throw new RuntimeException(e);
        }
    }

    public Iterable<String> getTransformerNames() {
        return nes.getTransformers().stream().map(t -> t.getName())::iterator;
    }

    public long addListener(BiConsumer<JsonObject, Long> handler) {
        long handlerId = listenerCount.incrementAndGet();
        this.handlers.put(handlerId, (jobj) -> handler.accept(jobj, handlerId));
        return handlerId;
    }

    public void removeListener(long listenerId) {
        this.handlers.remove(listenerId);
    }

    public void executeOrder(JsonOrder<?> order) {
        System.err.println(order);
        this.gldes.getSimulator().queueOrder(order.toOrder(getTime(), this.paths));
    }

    private Date getTime() {
        return this.gldes.getSimTime();
    }

    @Override
    public void processEvent(Event event) {
        System.out.println("EVENT: " + event);
    }

    private AtomicBoolean initiated = new AtomicBoolean(false);
    private AtomicBoolean started = new AtomicBoolean(false);
    private AtomicBoolean stopped = new AtomicBoolean(false);

    @Override
    public void init(Vertx vertx, JsonObject config) {
        if (!initiated.getAndSet(true)) {
            try {
                this.onInit(vertx, config);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void start(Future<Void> future) {
        if (!started.getAndSet(true)) {
            this.onStart(future);
        } else {
            future.complete();
        }

    }

    @Override
    public void stop(Future<Void> future) {
        if (!stopped.getAndSet(true)) {
            this.onStop(future);
        } else {
            future.complete();
        }

    }

    /**
     * Code taken from {@link mired.ucm.simulator.displayer.SimulatorDisplayer}
     */

    /**
     * @formatter:off
     */
    /*     */ private void init(String title, Date startDate, int cycleTimeInMillis, PATHS paths,
            boolean intelligence, int hoursOfSimulation, Tariff tarif, int moments, Double minRange,
            Double maxRange, boolean activeClients)
    /*     */ {
        this.paths = paths;
        this.startDate = startDate;
        /* 209 */ this.sdf = new SimpleDateFormat("HH:mm:ss");
        /* 210 */ this.decimalFormat = new DecimalFormat("#.##");
        /* 211 */ this.moments = moments;
        /* 212 */ this.nes = new NetworkElementsStatus();
        /* 213 */ this.intelligence = intelligence;
        /* 214 */ this.gridlabActions = new GridlabActions(paths);
        /* 215 */ this.hoursOfSimulation = hoursOfSimulation;
        /* 216 */ this.demandCurve = new ArrayBlockingQueue(100);
        /* 217 */ this.title = title;
        /* 218 */ this.cycleTimeInMillis = cycleTimeInMillis;
        /* 219 */ this.importedEnergy = 0.0F;
        /* 220 */ this.exportedEnergy = 0.0F;
        /* 221 */ this.energyLosses = 0.0F;
        /* 222 */ this.bill = 0.0F;
        /* 223 */ this.tariff = tarif;
        //   /* 224 */     this.mainFrame = new JFrame(title);
        /* 225 */ this.activeClients = activeClients;
        //   /* 226 */     setName("SimulatorDisplayer");
        /*     */
        /* 228 */ this.rs = new ReadScenario(startDate, paths);
        /* 229 */ if (this.tariff != null) {
            /* 230 */ this.currentTariffPeriod = this.tariff.getPeriod(startDate);
            /* 231 */ this.currentTariffPrice = this.tariff.getEnergyPrice(this.currentTariffPeriod);
            /*     */ }
        /*     */
        //   /*     */     try
        //   /*     */     {
        /* 236 */ int minutesToStartCharts = cycleTimeInMillis * moments;
        /* 237 */ Calendar chartCalendar = Calendar.getInstance();
        /* 238 */ chartCalendar.setTime(startDate);
        /* 239 */ chartCalendar.add(14, -minutesToStartCharts);
        /*     */

        /*     */ }

    /*     */ protected void initSimulator(Date startDate, int timeUnit, int timeUnitAmount, PATHS paths,
            boolean intelligence)/*     */ throws GridlabException
    /*     */ {
        /* 523 */ Calendar calendar = Calendar.getInstance();
        /* 524 */ calendar.setTime(startDate);
        /*     */ try
        /*     */ {
            /* 527 */ this.gldes = new GridLabDiscreteEventSimulator(paths, startDate, timeUnit, timeUnitAmount,
                    this.nes, intelligence, this.rs, this.gridlabActions, this.activeClients);
            /* 528 */ this.gldes.registerListener(this);
            /*     */ }
        /*     */ catch (SimulatorNotInitializedException ex) {
            /* 531 */ ex.printStackTrace();
            /*     */ }
        /*     */ }

    /*     */ private Date[] readSimulationTime(String XMLfile)
    /*     */ {
        /* 261 */ Date[] dates = new Date[2];
        /*     */ try {
            /* 263 */ org.w3c.dom.Document doc = XMLUtilities.loadXMLDoc(XMLfile);
            /* 264 */ Node clock = doc.getElementsByTagName("clock").item(0);
            /* 265 */ if (clock.getNodeType() == 1)
            /*     */ {
                /* 267 */ Element eclock = (Element) clock;
                /* 268 */ String starttime = eclock.getElementsByTagName("starttime").item(0).getTextContent();
                /* 269 */ String stoptime = eclock.getElementsByTagName("stoptime").item(0).getTextContent();
                /*     */
                /* 271 */ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                /* 272 */ dates[0] = sdf.parse(starttime);
                /* 273 */ dates[1] = sdf.parse(stoptime);
                /*     */ }
            /*     */ }
        /*     */ catch (ParserConfigurationException e) {
            /* 277 */ e.printStackTrace();
            /*     */ }
        /*     */ catch (SAXException e) {
            /* 280 */ e.printStackTrace();
            /*     */ }
        /*     */ catch (IOException e) {
            /* 283 */ e.printStackTrace();
            /*     */ }
        /*     */ catch (ParseException e) {
            /* 286 */ e.printStackTrace();
            /*     */ }
        /*     */
        /* 289 */ return dates;
        /*     */ }

    public void processStatus(Hashtable<SensorIDS, Float> sensorValues, Date timestamp) {
    }

    /*     */ public void overvoltageEvent(Date timestamp)
    /*     */ {
        /* 743 */ //System.err.println("overvoltage " + timestamp);
        /* 744 */ //this.simulationChart.drawAlternatingMarker(this.simulationChart.getDataset().getEndXValue(0, this.simulationChart.getDataset().getItemCount(0) - 1), "overvoltage", Color.red);
        /*     */ }

    ///*     */for (NetworkListener currentListener : getListeners()) {
    ///* 189 */       currentListener.processCycleStatus(ns, this.nes, timestamp);
    ///* 190 */       if (ns.thereIsOvervoltage()) {
    ///* 191 */         currentListener.overvoltageEvent(ns.getOvervoltageTimestamp());
    ///*     */       }
    ///*     */     }
    /**
     * @formatter:on
     */

    public JsonArray getAppliedOrdersSince(long timestamp) {
        return new JsonArray(this.gldes.getSimulator().getAppliedOrdersSince(new Date(timestamp)));
    }

    public double getSystemConsumption() {
        return this.rs.getConsumption(this.nes.getElements(), getTime());
    }

    public Hashtable<SensorIDS, Float> getSubstationSensors() {
        return this.gridlabActions.getSubstationSensors(getTime());
    }

    public float getLossesSensor() {
        return this.gridlabActions.getLossesSensor(getTime());
    }

    public Hashtable<SensorIDS, Float> getDeviceSensors(String deviceName, Long timestamp) {
        return this.gridlabActions.getDeviceSensors(deviceName,
                timestamp == null ? getTime() : new Date(timestamp));
    }

    public double getCurrentSun(Long timestamp) {
        return this.rs.getSunPercentage(timestamp == null ? getTime() : new Date(timestamp));
    }

    public double getCurrentWind(Long timestamp) {
        return this.rs.getWindPercentage(timestamp == null ? getTime() : new Date(timestamp));
    }

    public double getCurrentEnergy(String batteryName, Long timestamp) {
        String energy = this.gridlabActions.readBatteryEnergy(batteryName,
                timestamp == null ? getTime() : new Date(timestamp));
        if (energy == null) {
            return 0.0D;
        }
        return Double.parseDouble(energy);
    }

    public boolean isServerActive() {
        return this.gldes.isSimulationEnded();
    }

    public int getPendingOrdersSize() {
        return this.gldes.getSimulator().getPendingOrders().size();
    }

    public ElementEMS getElementByName(String found) {
        return this.nes.getElementByName(found);
    }

}