def abort_simulation(id):  # noqa: E501
    """Aborts a running simulation

    If the user of the professional GUI decides to abort a running simulation this call will be triggered # noqa: E501


    :rtype: None
    """

    try:
        redis_db = RedisDB()
        flag = redis_db.get("run:" + id)
        message = ""
        if flag is not None and flag == "running":
            logger.debug("System running and trying to stop")
            redis_db.set("run:" + id, "stop")
            time.sleep(1)
            flag = redis_db.get("run:" + id)
            logger.debug("Flag in stop: " + str(flag))

            if flag is None:
                logger.debug("System stopped succesfully")
                message = "System stopped succesfully"
            elif "stopping" in flag:
                message = "System stopped succesfully"
                counter = 0
                while ("stopping" in flag):
                    flag = redis_db.get("run:" + id)
                    counter = counter + 1
                    if counter >= 15:
                        message = "system stopped succesfully"
                        break
                    else:
                        time.sleep(1)
                logger.debug("System stopped succesfully")
            elif "stopped" in flag:
                logger.debug("System stopped succesfully")
                message = "System stopped succesfully"
            else:
                message = "Problems while stopping the system"
        elif flag is not None and flag == "stopped":
            logger.debug("System already stopped")
            message = "System already stopped"
        elif flag is None:
            logger.debug("System already stopped")
            message = "System already stopped"
    except Exception as e:
        logger.error(e)
        message = "Error stoping the system"
    return message
def run_simulation(id, body=None):  # noqa: E501
    """Runs a simulation

    Runs a simulation # noqa: E501

    :param id: ID of the simulation that should be started
    :type id: str
    :param body: Configuration data for the simulation e.g. duration
    :type body: dict | bytes

    :rtype: List[SimulationResult]
    """
    logger.info("Running Simulation ...")
    if connexion.request.is_json:
        logger.info("Start command for simulation ID: " + id)
        data = connexion.request.get_json()
        logger.debug("data " + str(data) + " type " + str(type(data)))

        dir = os.path.join("data", str(id))
        if not os.path.exists(dir):
            return "Id not existing"

        redisDB = RedisDB()
        # flag = redis_db.get(id)
        flag = redisDB.get("run:" + id)
        logger.info("flag: " + str(flag))
        if flag is not None and flag == "running":
            return "System already running"
        else:
            try:
                # start random values for the status to become zero

                msg = variable.run(id, data)
                if msg == 0:
                    msg_to_send = "System started succesfully"
                else:
                    msg_to_send = "System could not start"
                return msg_to_send
            except (InvalidModelException, MissingKeysException) as e:
                logger.error("Error " + str(e))
                redisDB.set("run:" + id, "stopped")
                return str(e)

    else:
        logger.error("Wrong Content-Type")
        return "Wrong Content-Type"
        """if flag is not None and flag == "created":
def get_simulation_status(id):  # noqa: E501
    """Get the status of the simulation

     # noqa: E501

    :param id: ID of the simulation
    :type id: str

    :rtype: float
    """
    try:
        dir = os.path.join("data", str(id))
        if not os.path.exists(dir):
            return "Id not existing"
        redis_db = RedisDB()
        flag = redis_db.get("run:" + id)
        logger.info("flag: " + str(flag))
        if flag == None or flag == "created":
            return "Simulation has not been started"
        logger.debug("#############Getting status#####################")
        status_message = redis_db.get("status_" + str(id))
        if status_message == "OK":
            timestep = int(redis_db.get("timestep_" + str(id)))
            logger.debug("timestep " + str(timestep))
            sim_hours = int(redis_db.get("sim_hours_" + str(id)))
            logger.debug("sim_hours " + str(sim_hours))

            status = (timestep / (sim_hours - 1)) * 100.0

            if timestep == (sim_hours - 1):
                flag_stop = redis_db.get("opt_stop_" + id)
                logger.debug("flag stop " + str(flag_stop))
                if flag_stop == "False":
                    status = status - 1
            return int(status)
        else:
            return status_message, 406

    except Exception as e:
        logger.error(e)
        status = "id not present"
 def __init__(self):
     self.factory = {}
     self.redisDB = RedisDB()
     self.statusThread = {}
     self.running = {}
     self.utils = Utils()
class CommandController:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if CommandController._instance is None:
            with CommandController._lock:
                if CommandController._instance is None:
                    CommandController._instance = super(
                        CommandController, cls).__new__(cls)
        return CommandController._instance

    def __init__(self):
        self.factory = {}
        self.redisDB = RedisDB()
        self.statusThread = {}
        self.running = {}
        self.utils = Utils()

    def set_isRunning(self, id, bool):
        self.running[id] = bool

    def set(self, id, object):
        logger.debug("Object in set: " + str(object))
        try:
            self.factory[id] = object
            # fname="factory_"+str(id)
            #path = os.path.join("data", fname)
            #self.utils.store_data(path, object)
        except Exception as e:
            logger.debug(e)

    def get(self, id):
        return self.factory[id]
        #fname= "factory_"+str(id)
        #path = os.path.join("data", fname)
        # return self.utils.get_stored_data(path)

    def isRunningExists(self):
        logger.debug("IsRunning exists: " + str(len(self.running)))
        if len(self.running):
            return True
        else:
            return False

    def get_isRunning(self, id):
        if id in self.running.keys():
            return self.running[id]
        else:
            return False

    def get_running(self):
        return self.running

    def get_statusThread(self, id):
        return self.statusThread[id]

    def run(self, id, json_object):
        logger.debug("Run in command controller started")
        self.id = id
        self.duration = json_object["sim_duration_in_hours"]
        logger.debug("Duration: " + str(self.duration))
        self.redisDB.set("timestep_" + str(id), str(0))
        self.redisDB.set("sim_hours_" + str(id), str(self.duration))

        #gridController = gControl()
        #self.factory= jsonpickle.decode(self.redisDB.get("factory: "+id))
        #self.redisDB.get("factory: " + id)
        #logger.debug("This is the factory for command controller: "+str(self.factory))
        #self.set(self.id, self.redisDB.get("factory: " + id))
        # gridController.setParameters(id,)
        #logger.debug("Thread set")
        #
        try:

            self.set(self.id, ThreadFactory(self.id, self.duration))
            logger.debug("Factory instance stored")

            # redis_db.set("factory: "+id, json.dumps(factory))
            # logger.debug("Factory: "+str(factory[id]))
            # object=redis_db.get("factory: "+id)
            # logger.debug("Factory stored in redisDB: "+str(object))
            # test= json.loads(object[id])
            # logger.debug("Factory stored in redisDB: " + str(test)+" type: "+str(type(test)))
            #self.redisDB.set("run:" + self.id, "running")
            self.redisDB.set("run:" + id, "starting")
            logger.debug("Status: " + str(self.redisDB.get("run:" + self.id)))
            logger.debug("Thread: " + str(self.get(self.id)))
            msg = self.get(self.id).startController()
            logger.debug("Answer from Thread factory: " + str(msg))
            if msg == 0:
                self.set_isRunning(id, True)
                logger.debug("Flag isRunning set to True")
                self.statusThread[id] = threading.Thread(
                    target=self.run_status, args=(id, ))
                logger.debug("Status of the Thread started")
                self.statusThread[id].start()
                meta_data = {"id": id, "ztarttime": time.time()}
                self.redisDB.set("run:" + id, "running")
                self.redisDB.set("id_meta:" + id, json.dumps(meta_data))
                logger.info("running status " + str(self.running))
                logger.debug("Command controller start finished")
                return 0
            else:
                self.set_isRunning(id, False)
                logger.debug("Flag isRunning set to False")
                self.redisDB.set("run:" + id, "stopped")
                logger.error("Command controller start could not be finished")
                return 1
            #self.redisDB.set("run:" + self.id, "stop")
            # return buildAnswer(listNames, listValues, json_object.threshold_high, json_object.threshold_medium,
            #                  json_object.threshold_low)

        except Exception as e:
            logger.error(e)
            return e
        #self.set_isRunning(self.id, True)
        #logger.debug("Flag isRunning set to True")
        #logger.info("running status " + str(self.running))

        #logger.info("running status " + str(self.redisDB.get("run:" + self.id)))
        #logger.debug("from redis: "+str(self.factory)+" type: "+str(type(self.factory)))
        # self.factory=ThreadFactory()
        #logger.debug("Normal: " + str(self.factory) + " type: " + str(type(self.factory)))
        #listNames, listValues = self.factory.startController()

        # return "started"
        # return (listNames, listValues)
        # return buildAnswer(listNames, listValues, json_object.threshold_high, json_object.threshold_medium, json_object.threshold_low)

    def abort(self, id):
        logger.debug("Abort signal received")
        logger.debug("This is the factory object: " + str(self.get(id)))
        if self.factory[id]:
            self.factory[id].stopControllerThread()
            self.set_isRunning(id, False)
            message = "System stopped succesfully"
            self.redisDB.set("run:" + id, "stopped")
            logger.debug(message)
        else:
            message = "No threads found"
            logger.debug(message)

    def run_status(self, id):
        count = 0
        while True:
            status = self.get(id).is_running()
            flag = self.redisDB.get("run:" + id)
            if count == 15:
                count = 0
                logger.debug("Control run_status: " + str(flag))
            #logger.debug("status " + str(status))
            if status == "True" or (flag is not None and flag == "stop"):
                logger.debug("Control run_status: " + str(flag))
                self.redisDB.set("run:" + id, "stopping")
                self.abort(id)
                break
            time.sleep(2)
            count += 1
def create_simulation(body):  # noqa: E501
    """Send grid data to simulation engine in order to create a new simulation

     # noqa: E501

    :param radial: Grid to be simulated
    :type radial: dict | bytes

    :rtype: str
    """
    if connexion.request.is_json:
        logger.debug("Post grid request")
        body = Grid.from_dict(connexion.request.get_json())  # noqa: E501
        data = connexion.request.get_json()
        #temp = json.loads(json.dumps(data))
        #logger.debug("Data: " + str(temp)) #shows the raw data sent from client
        grid = Grid.from_dict(data)  # noqa: E501. SOMETHING IS NOT GOOD HERE
        #logger.debug("Grid: " + str(grid)) #shows the raw data sent from client
        id = utils.create_and_get_ID()
        redis_db = RedisDB()
        redis_db.set(id, "created")
        flag = redis_db.get(id)
        logger.debug("id stored in RedisDB: " + str(flag))
        redis_db.set("run:" + id, "created")

        radial = data["radials"]
        models_list = [
            "Maximize Self-Consumption", "Maximize Self-Production",
            "MinimizeCosts"
        ]

        count = 0
        for values in radial:

            new_data = check_power_lines(values)
            if not isinstance(new_data, tuple):
                data["radials"][count]["powerLines"] = new_data
            else:
                return new_data

            new_data = check_loads(values)
            if not isinstance(new_data, tuple):
                data["radials"][count]["loads"] = new_data
            else:
                return new_data

            new_data = check_power_profiles(values)
            if not isinstance(new_data, tuple):
                data["radials"][count]["powerProfiles"] = new_data
            else:
                return new_data

            new_data = check_pvs(values)
            if not isinstance(new_data, tuple):
                data["radials"][count]["photovoltaics"] = new_data
            else:
                return new_data

            data_to_store = []

            if "storageUnits" in values.keys():
                if values["storageUnits"] is not None:
                    logger.debug("Checking Storage")

                    if not is_PV(radial):
                        message = "Error: no PV element defined for each storage element"
                        return message
                    storage = values["storageUnits"]
                    bus_pv = get_PV_nodes(values["photovoltaics"])
                    logger.debug("bus pv " + str(bus_pv))
                    bus_load = get_Load_nodes(values["loads"])
                    logger.debug("bus loads " + str(bus_load))
                    bus_ess = get_ESS_nodes(storage)
                    logger.debug("bus ess " + str(bus_ess))
                    for element in bus_ess:
                        if not element in bus_pv:
                            message = "Error: no PV element or wrong bus definition of PV element for storage element with bus: " + str(
                                element)
                            return message, 406
                        if not element in bus_load:
                            message = "Error: no Load element or wrong bus definition of Load element for storage element with bus: " + str(
                                element)
                            return message, 406

                    is_price_needed = False
                    for storage_elements in storage:
                        # checking if default values are given
                        storage_eleement_change = storage_elements
                        if not "charge_efficiency" in storage_elements.keys():
                            storage_eleement_change["charge_efficiency"] = 90
                        if not "discharge_efficiency" in storage_elements.keys(
                        ):
                            storage_eleement_change[
                                "discharge_efficiency"] = 90
                        if not "global_control" in storage_elements.keys():
                            storage_eleement_change["global_control"] = False

                        data_to_store.append(storage_eleement_change)

                        #checking the optimization models
                        if "optimization_model" in storage_elements.keys():
                            if not storage_elements[
                                    "optimization_model"] in models_list:
                                message = "Solely the following optimization models for storage control are possible: " + str(
                                    models_list)
                                return message, 406

                            if storage_elements[
                                    "optimization_model"] == "MinimizeCosts":
                                is_price_needed = True

                        else:
                            message = "No optimization model given"
                            return message, 406

                        if "global_control" in storage_elements.keys():
                            logger.debug(
                                "global control " +
                                str(storage_elements["global_control"]))
                            if storage_elements["global_control"]:
                                is_price_needed = True
                                logger.debug("price profile needed")

            logger.debug("Storage successfully checked")

            data_to_store_cs = []
            if "chargingStations" in values.keys():
                if values["chargingStations"] is not None:
                    logger.debug("Checking Charging stations")

                    cs = values["chargingStations"]
                    if is_PV(radial):
                        bus_pv = get_PV_nodes(values["photovoltaics"])
                        logger.debug("bus_pv_cs " + str(bus_pv))
                    if is_ESS(radial):
                        bus_ess = get_ESS_nodes(values["storageUnits"])
                        logger.debug("bus_ess_cs " + str(bus_ess))

                    for cs_element in cs:
                        # checking if default values are given
                        cs_element_change = cs_element
                        if not "type_application" in cs_element.keys():
                            cs_element_change[
                                "type_application"] = "residential"

                        data_to_store_cs.append(cs_element_change)

                        # checking if there is ESS with charging station. If one present then PV should be present
                        if is_ESS(radial):
                            #logger.debug("cs_bus "+str([cs_element["bus"]]))
                            cs_bus = cs_element["bus"]
                            if "." in cs_bus:
                                if [cs_bus.split(".")[0]] in bus_ess:
                                    if not [cs_bus] in bus_ess:
                                        message = "Error: wrong bus definition for charging station element with bus: " + str(
                                            cs_bus)
                                        return message, 406
                                    else:
                                        if not [cs_element["bus"]] in bus_pv:
                                            message = "Error: no aggreement in bus definition for PV element, Storage element and charging station element with bus: " + str(
                                                cs_bus)
                                            return message, 406
                            elif [cs_bus] in bus_ess:
                                if not [cs_element["bus"]] in bus_pv:
                                    message = "Error: no aggreement in bus definition for PV element, Storage element and charging station element with bus: " + str(
                                        cs_bus)
                                    return message, 406

                    bus_cs = get_charging_station_nodes(data_to_store_cs)
                    logger.debug("bus_cs " + str(bus_cs))
                    for cs_element in data_to_store_cs:
                        logger.debug("cs_element " + str(cs_element))
                        # checking if there is just one residential
                        #if cs_element["type_application"] == "residential":"""

            logger.debug("Charging stations successfully checked")

            #logger.debug("data to store "+str(data_to_store))

            data["radials"][0]["storageUnits"] = data_to_store
            data["radials"][0]["chargingStations"] = data_to_store_cs
            count = count + 1

        #logger.debug("data"+str(data))
        #logger.debug("data" + str(data["radials"][0]["storageUnits"]))
        ####generates an id an makes a directory with the id for the data and for the registry
        try:

            dir_data = os.path.join("data", str(id))

            if not os.path.exists(dir_data):
                os.makedirs(dir_data)

            fname = str(id) + "_input_grid"
            logger.debug("File name = " + str(fname))
            path = os.path.join("data", str(id), fname)
            utils.store_data(path, data)

        except Exception as e:
            logger.error(e)

        logger.debug("Grid data stored")
        return id
    else:
        return "Bad JSON Format"