class HotWaterDB():
    def __init__(self, hotWaterDBConfig, entityDBConfig):
        self.entityDB = MariaDB_handler(**entityDBConfig)
        self.hotWaterAPI = HotWaterAPI()
        self.hotWaterDBObject = MariaDB_handler(**hotWaterDBConfig)
        self.hotWaterDBObject.createTables(hotWaterModel.Base)

    def getAllBuildingData(self):
        try:
            buildings = []
            session_entity = self.entityDB.create_session()
            for building in self.entityDB.getAll(session_entity,
                                                 entitymodel.Building):
                buildings.append((building.name, building.lat, building.long))
        except Exception as e:
            print("Please Update database with entities")
            print(e)
            raise e
        finally:
            self.entityDB.close_session(session_entity)
        print(buildings)
        return buildings

    def getPowerDHW(self, timestamp, buildingName, latitude, longitude):
        try:
            session = self.hotWaterDBObject.create_session()
            latitude = round(float(latitude), 4)
            longitude = round(float(longitude), 4)
            powerDHWValue = session.query(hotWaterModel.HotWater).filter(hotWaterModel.HotWater.timestamp == timestamp). \
                filter(hotWaterModel.HotWater.buildingName == buildingName).first()
            if powerDHWValue:
                powerDHWDict = powerDHWValue.toDict()
            print(powerDHWDict)
            return powerDHWDict['powerDHW']
        except Exception as e:
            print(e)
            self.hotWaterDBObject.close_session(session)

    def writePowerDHWToDB(self, timestamp):
        buildings = self.getAllBuildingData()
        session = self.hotWaterDBObject.create_session()
        try:
            for building in buildings:
                buildingName = building[0]
                latitude = building[1]
                longitude = building[2]
                powerDHW = self.hotWaterAPI.getThermalPowerDHW(buildingName)
                hotWaterDBData = hotWaterModel.HotWater(
                    timestamp, buildingName, latitude, longitude, powerDHW)
                self.hotWaterDBObject.addElementToDatabase(
                    session, hotWaterDBData)
        except Exception as e:
            print(e)
        finally:
            self.hotWaterDBObject.close_session(session)
class Optimzer_DB():

    def __init__(self, schduleDBConfig, entityDBConfig, priceDBConfig, number_of_time_steps=24, time_limit=None, gap_factor=10):
        self.scheduleDB = MariaDB_handler(**schduleDBConfig)
        self.scheduleDB.createTables(optimizerModel.Base)
        self.entityDB = MariaDB_handler(**entityDBConfig)
        self.entityDB.createTables(entitymodel.Base)
        self.priceDB = MariaDB_handler(**priceDBConfig)
        self.priceDB.createTables(pricesModel.Base)
        self.number_of_time_steps = number_of_time_steps
        self.time_limit = time_limit
        self.gap_factor = gap_factor

    def writeScheduleToDB(self, obj_function, use_this=False):
        '''
        Loads all data, generates a schedule and writes it to the database.
        '''
        self.__loadGrid()
        date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
        self.__loadForecast(date)
        self.__loadBatteryEnergy(date)
        try:
            self.__loadPrices(date)
        except NotEnoughDataException:
            print('No current prices. Use the prices from yesterday.')
            self.__loadPrices(date - timedelta(days=1))
        obj_value, schedule = self.__optimize(obj_function, self.time_limit, self.gap_factor)
        try:
            session_scheduleDB = self.scheduleDB.create_session()
            schedule_DB_data = session_scheduleDB.query(optimizerModel.Schedule) \
                .filter(
                    optimizerModel.Schedule.date == date,
                    optimizerModel.Schedule.obj_function == obj_function
                    ).first()
            if schedule_DB_data:
                schedule_DB_data.obj_value = obj_value
                schedule_DB_data.schedule = schedule
                self.scheduleDB.commitOrRollback(session_scheduleDB)
            else:
                schedule_DB_data = optimizerModel.Schedule(date, obj_function, obj_value,schedule)
                self.scheduleDB.addElementToDatabase(session_scheduleDB, schedule_DB_data)
        finally:
            self.scheduleDB.close_session(session_scheduleDB)
        return schedule_DB_data

    def setObjectiveInDB(self, obj_function):
        '''
        Sets the objective of the next day.
        '''
        date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
        try:
            session_scheduleDB = self.scheduleDB.create_session()
            objective_DB_data = session_scheduleDB.query(optimizerModel.Objective) \
                .filter(
                    optimizerModel.Objective.date == date
                    ).first()
            if objective_DB_data:
                objective_DB_data.obj_function = obj_function
                self.scheduleDB.commitOrRollback(session_scheduleDB)
            else:
                objective_DB_data = optimizerModel.Objective(date, obj_function)
                self.scheduleDB.addElementToDatabase(session_scheduleDB, objective_DB_data)
        finally:
            self.scheduleDB.close_session(session_scheduleDB)
        return objective_DB_data

    def setSameObjectiveAsLastDay(self):
        '''
        Sets the objective of the next day with the value of the objective of this day, if there is no objective for tomorrow.
        '''
        date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        try:
            session_scheduleDB = self.scheduleDB.create_session()
            objective_DB_data = session_scheduleDB.query(optimizerModel.Objective) \
                .filter(
                    optimizerModel.Objective.date == date
                    ).first()
            if objective_DB_data:
                objective = objective_DB_data.obj_function
            else:
                objective = 'cost'
            new_date = date + timedelta(days=1)
            new_objective_DB_data = session_scheduleDB.query(optimizerModel.Objective) \
                .filter(
                    optimizerModel.Objective.date == new_date
                    ).first()
            if not  new_objective_DB_data:
                new_objective_DB_data = optimizerModel.Objective(new_date, objective)
                self.scheduleDB.addElementToDatabase(session_scheduleDB, new_objective_DB_data)
        finally:
            self.scheduleDB.close_session(session_scheduleDB)
        return new_objective_DB_data



    def __loadGrid(self):
        ''' 
        Loads the micro grid from the database.
        '''
        self.windTurbines = []
        self.solarPanels = []
        self.batteries = []
        self.buildings = []
        try:
            session_entityDB = self.entityDB.create_session()
            for windturbine in self.entityDB.getAll(session_entityDB,entitymodel.WindTurbine):
                self.windTurbines.append(windturbine)

            for solarpanel in self.entityDB.getAll(session_entityDB, entitymodel.SolarPanel):
                self.solarPanels.append(solarpanel)

            for building in self.entityDB.getAll(session_entityDB, entitymodel.Building):
                self.buildings.append(building)

            for battery in self.entityDB.getAll(session_entityDB, entitymodel.Battery):
                self.batteries.append(battery)
        finally:
            self.entityDB.close_session(session_entityDB)

    def __loadForecast(self, date):
        '''
        Loads the simulation forecast data from the database.
        '''
        date_start = date.replace(hour=0, minute=0, second=0, microsecond=0)
        date_end = date_start + timedelta(days=1)
        self.gen_forecasts = {}
        try:
            session_entityDB = self.entityDB.create_session() 
            for solarpanel in self.solarPanels:
                forcast = session_entityDB \
                    .query(entitymodel.SimulationForecastSolarPanel) \
                    .filter(
                        entitymodel.SimulationForecastSolarPanel.solarpanel_name == solarpanel.name,
                        entitymodel.SimulationForecastSolarPanel.timestamp >= date_start, 
                        entitymodel.SimulationForecastSolarPanel.timestamp < date_end
                        ).all()
                if len(forcast) != self.number_of_time_steps:
                    raise NotEnoughDataException(f'Not enough forcast data for {solarpanel.name}.')
                self.gen_forecasts[solarpanel.name] = [item.supply for item in forcast]

            for windturbine in self.windTurbines:
                forcast = session_entityDB \
                    .query(entitymodel.SimulationForecastWindTurbine) \
                    .filter(
                        entitymodel.SimulationForecastWindTurbine.windturbine_name == windturbine.name,
                        entitymodel.SimulationForecastWindTurbine.timestamp >= date_start, 
                        entitymodel.SimulationForecastWindTurbine.timestamp < date_end
                        ).all()
                if len(forcast) != self.number_of_time_steps:
                    raise NotEnoughDataException(f'Not enough forcast data for {windturbine.name}.')
                self.gen_forecasts[windturbine.name] = [item.supply for item in forcast]
        finally:
            self.entityDB.close_session(session_entityDB)

    def __loadPrices(self, date):
        '''
        Loads the prices from the database.
        '''
        date_start = date.replace(hour=0, minute=0, second=0, microsecond=0)
        date_end = date_start + timedelta(days=1)
        try:
            session_priceDB = self.priceDB.create_session()
            price_data = session_priceDB \
                .query(pricesModel.PriceForecast) \
                    .filter(
                        pricesModel.PriceForecast.timestamp >= date_start,
                        pricesModel.PriceForecast.timestamp < date_end
                    ).all()
            if len(price_data) != self.number_of_time_steps:
                    raise NotEnoughDataException(f'Not enough price data.')
            self.prices_buy = [price.price for price in price_data]
            # sell prices are are 10 percent less than buy prices due to taxes
            self.prices_sell = [price.price*0.9 for price in price_data]
        finally:
            self.priceDB.close_session(session_priceDB)

    def __loadBatteryEnergy(self, date):
        '''
        Loads the battery energy from the last schedue, so that energy can be transfered to the next day.
        If there is no last schedule, initialize all batteries with energy 0.
        '''
        self.batteries_startEnergy = {}
        date = date.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=1)
        try:
            session_scheduleDB = self.scheduleDB.create_session()
            objective_DB_data = session_scheduleDB.query(optimizerModel.Objective) \
                .filter(
                    optimizerModel.Objective.date == date
                    ).first()
            if objective_DB_data:
                objective = objective_DB_data.obj_function
            else:
                objective = 'cost'
            last_schedule = session_scheduleDB \
                .query(optimizerModel.Schedule) \
                .filter(
                    optimizerModel.Schedule.date==date,
                    optimizerModel.Schedule.obj_function==objective
                    ).first()
            if last_schedule:
                battery_schedule = last_schedule['batteries']
                for battery in self.batteries:
                    self.batteries_startEnergy[battery.name] = battery_schedule[battery.name]['energy'][24]
            else:
                for battery in self.batteries:
                    self.batteries_startEnergy[battery.name] = 0
        finally:
            self.scheduleDB.close_session(session_scheduleDB)



    def __optimize(self, obj_function, time_limit=None, gap_factor=10):
        '''
        Initialize the optimizer and run the optimization.
        '''
        opt = Optimizer(self.number_of_time_steps)
        for building in self.buildings:
            opt.addBuilding(building)
        for battery in self.batteries:
            opt.addBattery(battery, self.batteries_startEnergy[battery.name])
        for name, forecast in self.gen_forecasts.items():
            opt.addGenerator(name, forecast)
        opt.addPriceBuy(self.prices_buy)
        opt.addPriceSell(self.prices_sell)
        if time_limit:
            opt.set_time_limit(time_limit)
        # Try the optimization until is works with the specified time limit and mip gap
        # After each time out triple the mip gap and try it again
        while(True):
            try:
                opt.optimize(obj_function)
                break
            except TimeoutError:
                opt.multiply_mip_gap(gap_factor)
        return opt.getObjFuncValue(), opt.getSchedule()
예제 #3
0
class WeatherDB():

    def __init__(self, weatherDBConfig, entityDBConfig):
        self.weatherDB = MariaDB_handler(**weatherDBConfig)
        self.weatherDB.createTables(weathermodel.Base)
        self.entityDB = MariaDB_handler(**entityDBConfig)
        self.entityDB.createTables(entitymodel.Base)
        self.weatherAPI = WeatherAPI()

    def writeWeatherToDB(self):
        locations = []
        try:
            session_entity = self.entityDB.create_session()
            for solarpanel in self.entityDB.getAll(session_entity, entitymodel.SolarPanel):
                locations.append((solarpanel.lat, solarpanel.long))
            for windturbine in self.entityDB.getAll(session_entity, entitymodel.WindTurbine):
                locations.append((windturbine.lat, windturbine.long))
        except Exception as e:
            print("Please Update database with entities")
            print (e)
            raise e
        finally:
            self.entityDB.close_session(session_entity)
        # remove duplicates
        locations = set(locations)
        print(locations)
        try:
            session_weather = self.weatherDB.create_session()
            for location in locations:
                lat = location[0]
                long = location[1]
                currentWeatherData = self.weatherAPI.getCurrent(lat, long)
                currentWeather = session_weather.query(weathermodel.WeatherCurrent).filter_by(lat=lat, long=long, timestamp=currentWeatherData["timestamp"]).first()
                if currentWeather:
                    currentWeather.temp = currentWeatherData["temp"]
                    currentWeather.windSpeed = currentWeatherData["windSpeed"]
                    currentWeather.pressure = currentWeatherData["pressure"]
                    currentWeather.relativeHumidity = currentWeatherData["relativeHumidity"]
                    currentWeather.s_horizontal = currentWeatherData["s_horizontal"]
                    self.weatherDB.commitOrRollback(session_weather)
                else:
                    currentWeather = weathermodel.WeatherCurrent(lat, long, **currentWeatherData)
                    self.weatherDB.addElementToDatabase(session_weather, currentWeather)

            
            for location in locations:
                lat = location[0]
                long = location[1]
                forecastWeatherList = self.weatherAPI.getForecast(lat, long)
                for forecastWeatherData in forecastWeatherList:
                    forecastWeather = session_weather.query(weathermodel.WeatherForecast).filter_by(lat=lat, long=long, timestamp=forecastWeatherData["timestamp"]).first()
                    if forecastWeather:
                        forecastWeather.temp = forecastWeatherData["temp"]
                        forecastWeather.windSpeed = forecastWeatherData["windSpeed"]
                        forecastWeather.pressure = forecastWeatherData["pressure"]
                        forecastWeather.relativeHumidity = forecastWeatherData["relativeHumidity"]
                        forecastWeather.s_horizontal = forecastWeatherData["s_horizontal"]
                        self.weatherDB.commitOrRollback(session_weather)
                    else:
                        forecastWeather = weathermodel.WeatherForecast(lat, long, **forecastWeatherData)
                        self.weatherDB.addElementToDatabase(session_weather, forecastWeather)
        except Exception as e:
            raise e
        finally:
            self.weatherDB.close_session(session_weather)
class SpaceHeatingDB():
    def __init__(self, spaceHeatingDBConfig, entityDBConfig):
        self.entityDB = MariaDB_handler(**entityDBConfig)
        self.spaceHeatingDBObject = MariaDB_handler(**spaceHeatingDBConfig)
        self.spaceHeatingDBObject.createTables(spaceHeatingModel.Base)
        self.buildings = self.getAllBuildingData()
        self.spaceHeatingAPI = SpaceHeatingAPI(spaceHeatingDBConfig)

    def getAllBuildingData(self):
        try:
            buildings = []
            session_entity = self.entityDB.create_session()
            for building in self.entityDB.getAll(session_entity,
                                                 entitymodel.Building):
                mathematicalModel = {
                    "thermalResistance": building.thermalResistance,
                    "heatCapacityAirIndoor": building.heatCapacityAirIndoor
                }
                buildings.append((building.name, building.lat, building.long,
                                  mathematicalModel))
        except Exception as e:
            print("Please Update database with entities")
            print(e)
            raise e
        finally:
            self.entityDB.close_session(session_entity)

        print(buildings)
        return buildings

    def getPowerSH(self, timestamp, buildingName, latitude, longitude):
        try:
            session = self.spaceHeatingDBObject.create_session()
            latitude = round(float(latitude), 4)
            longitude = round(float(longitude), 4)
            print(timestamp, buildingName, latitude, longitude)
            powerSHValue = session.query(spaceHeatingModel.SpaceHeating).filter(spaceHeatingModel.SpaceHeating.timestamp == timestamp). \
                filter(spaceHeatingModel.SpaceHeating.buildingName == buildingName).first()
            if powerSHValue:
                powerSHDict = powerSHValue.toDict()
                print(powerSHDict)
            return powerSHDict['powerSH']
        except Exception as e:
            print(e)
            self.spaceHeatingDBObject.close_session(session)

    def writePowerSHToDB(self, timestamp):
        if self.buildings == None:
            self.building = self.getAllBuildingData()
        try:
            session = self.spaceHeatingDBObject.create_session()
            print("Pinging weather service")
            for building in self.buildings:
                buildingName = building[0]
                latitude = building[1]
                longitude = building[2]
                mathematicalModel = building[3]
                payload = {'lat': latitude, 'longi': longitude}
                response = requests.get(config.URL_WEATHER_SERVICE +
                                        "/currentWeather",
                                        params=payload)
                response = json.loads(response.text)
                currentWeather = response['currentWeatherData']
                response_code = response['response_code']

                if response_code != 200:
                    print("Weather Data Unavailable!!")

                currentTempOutdoor = currentWeather['temp']
                currentTempIndoor, thermalPowerSH = self.spaceHeatingAPI.calculateThermalPowerSH(
                    timestamp, buildingName, currentTempOutdoor,
                    mathematicalModel)
                print(currentTempIndoor, thermalPowerSH)
                spaceHeatingData = spaceHeatingModel.SpaceHeating(
                    timestamp, buildingName, latitude, longitude,
                    currentTempIndoor, currentTempOutdoor, thermalPowerSH)
                self.spaceHeatingDBObject.addElementToDatabase(
                    session, spaceHeatingData)
            self.spaceHeatingDBObject.close_session(session)

        except Exception as e:
            print(e)
            self.spaceHeatingDBObject.close_session(session)
예제 #5
0
class Simulation():
    def __init__(self, weatherDBConfig, entityDBConfig, scheduleDBConfig):
        # init weater database
        self.weatherDB = MariaDB_handler(**weatherDBConfig)
        self.weatherDB.createTables(weathermodel.Base)
        # init entity database
        self.entityDB = MariaDB_handler(**entityDBConfig)
        self.entityDB.createTables(entitymodel.Base)
        # init schedule database
        self.scheduleDB = MariaDB_handler(**scheduleDBConfig)
        self.scheduleDB.createTables(schedulemodel.Base)
        self.windTurbines = {}
        self.solarPanels = {}
        self.batteries = {}
        self.buildings = {}

    def init_sim(self, startingTime):
        self.time = startingTime.replace(minute=0, second=0, microsecond=0)
        self.__loadMicroGridFromDatabase()

        self.simObj = entitymodel.Simulation(self.time, True)
        try:
            session_entityDB = self.entityDB.create_session()
            # stop running simulations
            sims = session_entityDB.query(
                entitymodel.Simulation).filter_by(running=True).all()
            for sim in sims:
                sim.running = False
            self.entityDB.commitOrRollback(session_entityDB)
            self.entityDB.addElementToDatabase(session_entityDB, self.simObj)
        finally:
            self.entityDB.close_session(session_entityDB)

    def close_sim(self):
        try:
            session_entityDB = self.entityDB.create_session()
            self.simObj = session_entityDB.query(
                entitymodel.Simulation).filter_by(id=self.simObj.id).first()
            self.simObj.running = False
            self.entityDB.commitOrRollback(session_entityDB)
        finally:
            self.entityDB.close_session(session_entityDB)

    def __loadMicroGridFromDatabase(self):
        self.windTurbines = {}
        self.solarPanels = {}
        self.batteries = {}
        self.buildings = {}
        try:
            session_entityDB = self.entityDB.create_session()
            for windturbine in self.entityDB.getAll(session_entityDB,
                                                    entitymodel.WindTurbine):
                self.windTurbines[
                    windturbine.name] = WindTurbineSim.createFromModel(
                        windturbine)

            for solarpanel in self.entityDB.getAll(session_entityDB,
                                                   entitymodel.SolarPanel):
                self.solarPanels[
                    solarpanel.name] = SolarPanelSim.createFromModel(
                        solarpanel)

            for building in self.entityDB.getAll(session_entityDB,
                                                 entitymodel.Building):
                self.buildings[building.name] = BuildingSim.createFromModel(
                    building)

            for battery in self.entityDB.getAll(session_entityDB,
                                                entitymodel.Battery):
                self.batteries[battery.name] = BatterySim.createFromModel(
                    battery)
        finally:
            self.entityDB.close_session(session_entityDB)

    def __getCurrentWeatherData(self, lat, long):
        try:
            session_weatherDB = self.weatherDB.create_session()
            currentWeather = session_weatherDB.query(
                weathermodel.WeatherCurrent).filter_by(
                    lat=lat, long=long, timestamp=self.time).first()
            if currentWeather:
                return currentWeather
            forecastWeather = session_weatherDB.query(
                weathermodel.WeatherForecast).filter_by(
                    lat=lat, long=long, timestamp=self.time).first()
        finally:
            self.weatherDB.close_session(session_weatherDB)
        if forecastWeather:
            print("return forecast")
            return forecastWeather
        raise NoWeatherDataException(
            f"No data is available. lat:{lat}, long:{long}, timestamp:{str(self.time)}"
        )

    def __getForecastWeatherDataList(self, lat, long):
        try:
            session_weatherDB = self.weatherDB.create_session()
            forecastWeather = session_weatherDB.query(weathermodel.WeatherForecast) \
                .filter(
                    weathermodel.WeatherForecast.timestamp>=self.time,
                    weathermodel.WeatherForecast.lat==lat,
                     weathermodel.WeatherForecast.long==long) \
                .all()
        finally:
            self.weatherDB.close_session(session_weatherDB)
        if forecastWeather:
            return forecastWeather
        raise NoWeatherDataException(
            f"No forecast data is available. lat:{lat}, long:{long}, timestamp:{str(self.time)}"
        )

    def simulateNextHour(self):
        self.__loadSchedule()
        day_of_the_year = self.time.timetuple().tm_yday
        hour_of_the_day = self.time.timetuple().tm_hour
        total_energy = 0
        total_energy += self.__simulateWindTurbines()
        total_energy += self.__simulateSolarPanels(day_of_the_year)
        total_energy -= self.__simulateBuildings(hour_of_the_day)
        total_energy -= self.__simulateBatteries(hour_of_the_day)
        try:
            session_entityDB = self.entityDB.create_session()
            total_sim = session_entityDB.query(
                entitymodel.SimulationTotalEnergy).filter_by(
                    timestamp=self.time).first()
            if total_sim:
                total_sim.energy = total_energy
                self.entityDB.commitOrRollback(session_entityDB)
            else:
                self.entityDB.addElementToDatabase(
                    session_entityDB,
                    entitymodel.SimulationTotalEnergy(self.time, total_energy))
        finally:
            self.entityDB.close_session(session_entityDB)
        self.time = self.time + timedelta(hours=1)

    def simulateForecast(self):
        try:
            session_entityDB = self.entityDB.create_session()
            for windturbine in self.windTurbines.values():
                try:
                    forecastList = self.__getForecastWeatherDataList(
                        windturbine.lat, windturbine.long)
                except NoWeatherDataException as e:
                    print(e)
                for forecast in forecastList:
                    supply = windturbine.computePower(
                        forecast.temp, forecast.pressure, forecast.windSpeed,
                        forecast.relativeHumidity)
                    forecast_data = session_entityDB.query(
                        entitymodel.SimulationForecastWindTurbine).filter_by(
                            windturbine_name=windturbine.name,
                            timestamp=forecast.timestamp).first()
                    if forecast_data:
                        forecast_data.supply = supply
                        self.entityDB.commitOrRollback(session_entityDB)
                    else:
                        forecast_data = entitymodel.SimulationForecastWindTurbine(
                            windturbine.name, forecast.timestamp, supply)
                        self.entityDB.addElementToDatabase(
                            session_entityDB, forecast_data)

            for solarpanel in self.solarPanels.values():
                try:
                    forecastList = self.__getForecastWeatherDataList(
                        solarpanel.lat, solarpanel.long)
                except NoWeatherDataException as e:
                    print(e)
                for forecast in forecastList:
                    day_of_the_year = forecast.timestamp.timetuple().tm_yday
                    supply = solarpanel.computePower(day_of_the_year,
                                                     forecast.temp,
                                                     forecast.s_horizontal)
                    forecast_data = session_entityDB.query(
                        entitymodel.SimulationForecastSolarPanel).filter_by(
                            solarpanel_name=solarpanel.name,
                            timestamp=forecast.timestamp).first()
                    if forecast_data:
                        forecast_data.supply = supply
                        self.entityDB.commitOrRollback(session_entityDB)
                    else:
                        forecast_data = entitymodel.SimulationForecastSolarPanel(
                            solarpanel.name, forecast.timestamp, supply)
                        self.entityDB.addElementToDatabase(
                            session_entityDB, forecast_data)
        finally:
            self.entityDB.close_session(session_entityDB)

    def __simulateWindTurbines(self):
        total_suppy = 0
        try:
            session_entityDB = self.entityDB.create_session()
            for windturbine in self.windTurbines.values():
                weather_data = self.__getCurrentWeatherData(
                    windturbine.lat, windturbine.long)
                supply = windturbine.computePower(
                    weather_data.temp, weather_data.pressure,
                    weather_data.windSpeed, weather_data.relativeHumidity)
                total_suppy += supply
                windturbine_sim = session_entityDB.query(
                    entitymodel.SimulationWindTurbine).filter_by(
                        windturbine_name=windturbine.name,
                        timestamp=self.time).first()
                if windturbine_sim:
                    windturbine_sim.supply = supply
                    self.entityDB.commitOrRollback(session_entityDB)
                else:
                    self.entityDB.addElementToDatabase(
                        session_entityDB,
                        entitymodel.SimulationWindTurbine(
                            windturbine.name, self.time, supply))
            return total_suppy
        finally:
            self.entityDB.close_session(session_entityDB)

    def __simulateSolarPanels(self, day_of_the_year):
        total_suppy = 0
        try:
            session_entityDB = self.entityDB.create_session()
            for solarpanel in self.solarPanels.values():
                weather_data = self.__getCurrentWeatherData(
                    solarpanel.lat, solarpanel.long)
                supply = solarpanel.computePower(day_of_the_year,
                                                 weather_data.temp,
                                                 weather_data.s_horizontal)
                total_suppy += supply
                solarpanel_sim = session_entityDB.query(
                    entitymodel.SimulationSolarPanel).filter_by(
                        solarpanel_name=solarpanel.name,
                        timestamp=self.time).first()
                if solarpanel_sim:
                    solarpanel_sim.supply = supply
                    self.entityDB.commitOrRollback(session_entityDB)
                else:
                    self.entityDB.addElementToDatabase(
                        session_entityDB,
                        entitymodel.SimulationSolarPanel(
                            solarpanel.name, self.time, supply))
            return total_suppy
        finally:
            self.entityDB.close_session(session_entityDB)

    def __simulateBuildings(self, hour):
        total_demand = 0
        try:
            session_entityDB = self.entityDB.create_session()
            for name, building in self.buildings.items():
                building.setSchedule(self.schedule['buildings'][name])
                demand = building.getDemand(hour)
                componentState = building.getComponentState(hour)
                total_demand += demand
                building_sim = session_entityDB.query(
                    entitymodel.SimulationBuilding).filter_by(
                        building_name=name, timestamp=self.time).first()
                if building_sim:
                    building_sim.demand = demand
                    building_sim.componentState = componentState
                    self.entityDB.commitOrRollback(session_entityDB)
                else:
                    self.entityDB.addElementToDatabase(
                        session_entityDB,
                        entitymodel.SimulationBuilding(name, self.time, demand,
                                                       componentState))
            return total_demand
        finally:
            self.entityDB.close_session(session_entityDB)

    def __simulateBatteries(self, hour):
        total_charging_rate = 0
        try:
            session_entityDB = self.entityDB.create_session()
            for name, battery in self.batteries.items():
                battery.setSchedule(self.schedule['batteries'][name])
                rate = battery.getRate(hour)
                total_charging_rate += rate
                energy = battery.getEnergy(hour)
                battery_sim = session_entityDB.query(
                    entitymodel.SimulationBattery).filter_by(
                        battery_name=name, timestamp=self.time).first()
                if battery_sim:
                    battery_sim.energy = energy
                    battery_sim.rate = rate
                    self.entityDB.commitOrRollback(session_entityDB)
                else:
                    self.entityDB.addElementToDatabase(
                        session_entityDB,
                        entitymodel.SimulationBattery(
                            name, self.time, energy, rate,
                            battery.energyUpperBound))
            return total_charging_rate
        finally:
            self.entityDB.close_session(session_entityDB)

    def __loadSchedule(self):
        schedule_date = self.time.replace(hour=0,
                                          minute=0,
                                          second=0,
                                          microsecond=0)
        schedule_data = None
        try:
            session_scheduleDB = self.scheduleDB.create_session()
            objective_data = session_scheduleDB.query(
                schedulemodel.Objective).filter_by(date=schedule_date).first()
            if objective_data:
                schedule_data = session_scheduleDB.query(schedulemodel.Schedule) \
                    .filter(
                        schedulemodel.Schedule.date == schedule_date,
                        schedulemodel.Schedule.obj_function == objective_data.obj_function
                        ).first()
        finally:
            self.scheduleDB.close_session(session_scheduleDB)
        if schedule_data:
            self.schedule = schedule_data.schedule
        else:
            self.__generateDefaultSchedule()

    def __generateDefaultSchedule(self):
        schedule = {'buildings': {}, 'batteries': {}}
        zero = [0 for i in range(0, 24)]
        idle = ['idle' for i in range(0, 24)]
        for name, building in self.buildings.items():
            schedule['buildings'][name] = {}
            for comp in building.listOfComponets:
                schedule['buildings'][name][comp.name] = {
                    'start': comp.let - comp.lot,
                    'end': comp.let
                }
        for name, battery in self.batteries.items():
            schedule['batteries'][name] = {
                'state': idle,
                'rate': zero,
                'energy': zero
            }
        self.schedule = schedule