diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f880600..9f8b7c36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [0.7.1] - 2024-01-29 +### Fix +- Patched new version wer server issues accessing correct paths + ## [0.7.0] - 2024-01-28 ### Improvement - Added a new feature to provide operating time windows for deferrable loads. Thanks to @michaelpiron diff --git a/docs/conf.py b/docs/conf.py index 6b06bc42..2101526f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = 'David HERNANDEZ' # The full version, including alpha/beta/rc tags -release = '0.7.0' +release = '0.7.1' # -- General configuration --------------------------------------------------- diff --git a/options.json b/options.json index fb207379..a7c25e55 100644 --- a/options.json +++ b/options.json @@ -1,66 +1,57 @@ -{ - "hass_url": "empty", +{ + "hass_url": "empty", "long_lived_token": "empty", "logging_level": "INFO", - "costfun": "profit", - "optimization_time_step": 30, - "historic_days_to_retrieve": 2, + "costfun": "profit", + "optimization_time_step": 30, + "historic_days_to_retrieve": 2, "method_ts_round": "nearest", "optional_solcast_api_key": "empty", "optional_solcast_rooftop_id": "empty", - "optional_solar_forecast_kwp": 0, - "set_total_pv_sell": false, - "lp_solver": "COIN_CMD", - "lp_solver_path": "/usr/bin/cbc", - "set_nocharge_from_grid": false, + "optional_solar_forecast_kwp": 0, + "set_total_pv_sell": false, + "lp_solver": "COIN_CMD", + "lp_solver_path": "/usr/bin/cbc", + "set_nocharge_from_grid": false, "set_nodischarge_to_grid": true, "set_battery_dynamic": false, "battery_dynamic_max": 0.9, "battery_dynamic_min": -0.9, "weight_battery_discharge": 1.0, "weight_battery_charge": 1.0, - "sensor_power_photovoltaics": "sensor.power_photovoltaics", - "sensor_power_load_no_var_loads": "sensor.power_load_no_var_loads", - "load_negative": false, - "set_zero_min": true, - "number_of_deferrable_loads": 3, - "list_nominal_power_of_deferrable_loads": [ - { - "nominal_power_of_deferrable_loads": 3000 - }, - { - "nominal_power_of_deferrable_loads": 750 - }, - { - "nominal_power_of_deferrable_loads": 2500 - } - ], - "list_operating_hours_of_each_deferrable_load": [ - { - "operating_hours_of_each_deferrable_load": 4 - }, - { - "operating_hours_of_each_deferrable_load": 0 - }, - { - "operating_hours_of_each_deferrable_load": 5 - } + "sensor_power_photovoltaics": "sensor.power_photovoltaics", + "sensor_power_load_no_var_loads": "sensor.power_load_no_var_loads", + "load_negative": false, + "set_zero_min": true, + "number_of_deferrable_loads": 2, + "list_nominal_power_of_deferrable_loads": [ + { + "nominal_power_of_deferrable_loads": 3000 + }, + { + "nominal_power_of_deferrable_loads": 750 + } + ], + "list_operating_hours_of_each_deferrable_load": [ + { + "operating_hours_of_each_deferrable_load": 4 + }, + { + "operating_hours_of_each_deferrable_load": 0 + } ], "weather_forecast_method": "scrapper", "time_zone": "Europe/Paris", "Latitude": 45.83, "Longitude": 6.86, "Altitude": 4807.8, - "load_forecast_method": "naive", + "load_forecast_method": "naive", "delta_forecast_daily": 1, - "load_cost_forecast_method": "hp_hc_periods", + "load_cost_forecast_method": "hp_hc_periods", "list_start_timesteps_of_each_deferrable_load": [ { "start_timesteps_of_each_deferrable_load": 0 }, - { - "start_timesteps_of_each_deferrable_load": 0 - }, { "start_timesteps_of_each_deferrable_load": 0 } @@ -71,31 +62,25 @@ }, { "end_timesteps_of_each_deferrable_load": 0 + } + ], + "list_peak_hours_periods_start_hours": [ + { + "peak_hours_periods_start_hours": "02:54" }, { - "end_timesteps_of_each_deferrable_load": 0 + "peak_hours_periods_start_hours": "17:24" } ], - "list_peak_hours_periods_start_hours": [ - { - "peak_hours_periods_start_hours": "02:54" - }, - { - "peak_hours_periods_start_hours": "17:24" - } - ], - "list_peak_hours_periods_end_hours": [ - { - "peak_hours_periods_end_hours": "15:24" - }, - { - "peak_hours_periods_end_hours": "20:54" - } - ], - "list_treat_deferrable_load_as_semi_cont": [ + "list_peak_hours_periods_end_hours": [ { - "treat_deferrable_load_as_semi_cont": true + "peak_hours_periods_end_hours": "15:24" }, + { + "peak_hours_periods_end_hours": "20:54" + } + ], + "list_treat_deferrable_load_as_semi_cont": [ { "treat_deferrable_load_as_semi_cont": true }, @@ -107,17 +92,14 @@ { "set_deferrable_load_single_constant": false }, - { - "set_deferrable_load_single_constant": false - }, { "set_deferrable_load_single_constant": false } ], - "load_peak_hours_cost": 0.1907, - "load_offpeak_hours_cost": 0.1419, - "production_price_forecast_method": "constant", - "photovoltaic_production_sell_price": 0.1419, + "load_peak_hours_cost": 0.1907, + "load_offpeak_hours_cost": 0.1419, + "production_price_forecast_method": "constant", + "photovoltaic_production_sell_price": 0.1419, "maximum_power_from_grid": 9000, "list_pv_module_model": [ { diff --git a/setup.py b/setup.py index bf7c643d..240849ae 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ setup( name='emhass', # Required - version='0.7.0', # Required + version='0.7.1', # Required description='An Energy Management System for Home Assistant', # Optional long_description=long_description, # Optional long_description_content_type='text/markdown', # Optional (see note above) diff --git a/src/emhass/utils.py b/src/emhass/utils.py index 384e79a4..803aca12 100644 --- a/src/emhass/utils.py +++ b/src/emhass/utils.py @@ -503,7 +503,7 @@ def get_injection_dict(df: pd.DataFrame, plot_size: Optional[int] = 1366) -> dic injection_dict['figure_2'] = image_path_2 injection_dict['subsubtitle1'] = '

Last run optimization results table

' injection_dict['table1'] = table1 - injection_dict['subsubtitle2'] = '

Cost totals for latest optimization results

' + injection_dict['subsubtitle2'] = '

Summary table for latest optimization results

' injection_dict['table2'] = table2 return injection_dict @@ -555,6 +555,139 @@ def get_injection_dict_forecast_model_tune(df_pred_optim: pd.DataFrame, mlf: MLF injection_dict['figure_0'] = image_path_0 return injection_dict +def build_params(params: dict, params_secrets: dict, options: dict, addon: int, logger: logging.Logger) -> dict: + """ + Build the main params dictionary from the loaded options.json when using the add-on. + + :param params: The main params dictionary + :type params: dict + :param params_secrets: The dictionary containing the secret protected variables + :type params_secrets: dict + :param options: The load dictionary from options.json + :type options: dict + :param addon: A "bool" to select if we are using the add-on + :type addon: int + :param logger: The logger object + :type logger: logging.Logger + :return: The builded dictionary + :rtype: dict + """ + if addon == 1: + # Updating variables in retrieve_hass_conf + params['retrieve_hass_conf']['freq'] = options.get('optimization_time_step',params['retrieve_hass_conf']['freq']) + params['retrieve_hass_conf']['days_to_retrieve'] = options.get('historic_days_to_retrieve',params['retrieve_hass_conf']['days_to_retrieve']) + params['retrieve_hass_conf']['var_PV'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_PV']) + params['retrieve_hass_conf']['var_load'] = options.get('sensor_power_load_no_var_loads',params['retrieve_hass_conf']['var_load']) + params['retrieve_hass_conf']['load_negative'] = options.get('load_negative',params['retrieve_hass_conf']['load_negative']) + params['retrieve_hass_conf']['set_zero_min'] = options.get('set_zero_min',params['retrieve_hass_conf']['set_zero_min']) + params['retrieve_hass_conf']['var_replace_zero'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_replace_zero']) + params['retrieve_hass_conf']['var_interp'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_PV']), options.get('sensor_power_load_no_var_loads',params['retrieve_hass_conf']['var_load']) + params['retrieve_hass_conf']['method_ts_round'] = options.get('method_ts_round',params['retrieve_hass_conf']['method_ts_round']) + # Update params Secrets if specified + params['params_secrets'] = params_secrets + params['params_secrets']['time_zone'] = options.get('time_zone',params_secrets['time_zone']) + params['params_secrets']['lat'] = options.get('Latitude',params_secrets['lat']) + params['params_secrets']['lon'] = options.get('Longitude',params_secrets['lon']) + params['params_secrets']['alt'] = options.get('Altitude',params_secrets['alt']) + # Updating variables in optim_conf + params['optim_conf']['set_use_battery'] = options.get('set_use_battery',params['optim_conf']['set_use_battery']) + params['optim_conf']['num_def_loads'] = options.get('number_of_deferrable_loads',params['optim_conf']['num_def_loads']) + try: + params['optim_conf']['P_deferrable_nom'] = [i['nominal_power_of_deferrable_loads'] for i in options.get('list_nominal_power_of_deferrable_loads')] + except: + logger.debug("no list_nominal_power_of_deferrable_loads, defaulting to config file") + try: + params['optim_conf']['def_total_hours'] = [i['operating_hours_of_each_deferrable_load'] for i in options.get('list_operating_hours_of_each_deferrable_load')] + except: + logger.debug("no list_operating_hours_of_each_deferrable_load, defaulting to config file") + try: + params['optim_conf']['treat_def_as_semi_cont'] = [i['treat_deferrable_load_as_semi_cont'] for i in options.get('list_treat_deferrable_load_as_semi_cont')] + except: + logger.debug("no list_treat_deferrable_load_as_semi_cont, defaulting to config file") + params['optim_conf']['weather_forecast_method'] = options.get('weather_forecast_method',params['optim_conf']['weather_forecast_method']) + if params['optim_conf']['weather_forecast_method'] == "solcast": + params['retrieve_hass_conf']['solcast_api_key'] = options.get('optional_solcast_api_key',params['retrieve_hass_conf']['solcast_api_key']) + params['retrieve_hass_conf']['solcast_rooftop_id'] = options.get('optional_solcast_rooftop_id',params['retrieve_hass_conf']['solcast_rooftop_id']) + elif params['optim_conf']['weather_forecast_method'] == "solar.forecast": + params['retrieve_hass_conf']['solar_forecast_kwp'] = options.get('optional_solar_forecast_kwp',params['retrieve_hass_conf']['solar_forecast_kwp']) + params['optim_conf']['load_forecast_method'] = options.get('load_forecast_method',params['optim_conf']['load_forecast_method']) + params['optim_conf']['delta_forecast'] = options.get('delta_forecast_daily',params['optim_conf']['delta_forecast']) + params['optim_conf']['load_cost_forecast_method'] = options.get('load_cost_forecast_method',params['optim_conf']['load_cost_forecast_method']) + try: + params['optim_conf']['set_def_constant'] = [i['set_deferrable_load_single_constant'] for i in options.get('list_set_deferrable_load_single_constant')] + except: + logger.debug("no list_set_deferrable_load_single_constant, defaulting to config file") + try: + start_hours_list = [i['peak_hours_periods_start_hours'] for i in options['list_peak_hours_periods_start_hours']] + end_hours_list = [i['peak_hours_periods_end_hours'] for i in options['list_peak_hours_periods_end_hours']] + num_peak_hours = len(start_hours_list) + list_hp_periods_list = [{'period_hp_'+str(i+1):[{'start':start_hours_list[i]},{'end':end_hours_list[i]}]} for i in range(num_peak_hours)] + params['optim_conf']['list_hp_periods'] = list_hp_periods_list + except: + logger.debug("no list_peak_hours_periods_start_hours, defaulting to config file") + params['optim_conf']['load_cost_hp'] = options.get('load_peak_hours_cost',params['optim_conf']['load_cost_hp']) + params['optim_conf']['load_cost_hc'] = options.get('load_offpeak_hours_cost', params['optim_conf']['load_cost_hc']) + params['optim_conf']['prod_price_forecast_method'] = options.get('production_price_forecast_method', params['optim_conf']['prod_price_forecast_method']) + params['optim_conf']['prod_sell_price'] = options.get('photovoltaic_production_sell_price',params['optim_conf']['prod_sell_price']) + params['optim_conf']['set_total_pv_sell'] = options.get('set_total_pv_sell',params['optim_conf']['set_total_pv_sell']) + params['optim_conf']['lp_solver'] = options.get('lp_solver',params['optim_conf']['lp_solver']) + params['optim_conf']['lp_solver_path'] = options.get('lp_solver_path',params['optim_conf']['lp_solver_path']) + params['optim_conf']['set_nocharge_from_grid'] = options.get('set_nocharge_from_grid',params['optim_conf']['set_nocharge_from_grid']) + params['optim_conf']['set_nodischarge_to_grid'] = options.get('set_nodischarge_to_grid',params['optim_conf']['set_nodischarge_to_grid']) + params['optim_conf']['set_battery_dynamic'] = options.get('set_battery_dynamic',params['optim_conf']['set_battery_dynamic']) + params['optim_conf']['battery_dynamic_max'] = options.get('battery_dynamic_max',params['optim_conf']['battery_dynamic_max']) + params['optim_conf']['battery_dynamic_min'] = options.get('battery_dynamic_min',params['optim_conf']['battery_dynamic_min']) + params['optim_conf']['weight_battery_discharge'] = options.get('weight_battery_discharge',params['optim_conf']['weight_battery_discharge']) + params['optim_conf']['weight_battery_charge'] = options.get('weight_battery_charge',params['optim_conf']['weight_battery_charge']) + try: + params['optim_conf']['def_start_timestep'] = [i['start_timesteps_of_each_deferrable_load'] for i in options.get('list_start_timesteps_of_each_deferrable_load')] + except: + logger.debug("no list_start_timesteps_of_each_deferrable_load, defaulting to config file") + try: + params['optim_conf']['def_end_timestep'] = [i['end_timesteps_of_each_deferrable_load'] for i in options.get('list_end_timesteps_of_each_deferrable_load')] + except: + logger.debug("no list_end_timesteps_of_each_deferrable_load, defaulting to config file") + # Updating variables in plant_con + params['plant_conf']['P_grid_max'] = options.get('maximum_power_from_grid',params['plant_conf']['P_grid_max']) + try: + params['plant_conf']['module_model'] = [i['pv_module_model'] for i in options.get('list_pv_module_model')] + except: + logger.debug("no list_pv_module_model, defaulting to config file") + try: + params['plant_conf']['inverter_model'] = [i['pv_inverter_model'] for i in options.get('list_pv_inverter_model')] + except: + logger.debug("no list_pv_inverter_model, defaulting to config file") + try: + params['plant_conf']['surface_tilt'] = [i['surface_tilt'] for i in options.get('list_surface_tilt')] + except: + logger.debug("no list_surface_tilt, defaulting to config file") + try: + params['plant_conf']['surface_azimuth'] = [i['surface_azimuth'] for i in options.get('list_surface_azimuth')] + except: + logger.debug("no list_surface_azimuth, defaulting to config file") + try: + params['plant_conf']['modules_per_string'] = [i['modules_per_string'] for i in options.get('list_modules_per_string')] + except: + logger.debug("no list_modules_per_string, defaulting to config file") + try: + params['plant_conf']['strings_per_inverter'] = [i['strings_per_inverter'] for i in options.get('list_strings_per_inverter')] + except: + logger.debug("no list_strings_per_inverter, defaulting to config file") + params['plant_conf']['Pd_max'] = options.get('battery_discharge_power_max',params['plant_conf']['Pd_max']) + params['plant_conf']['Pc_max'] = options.get('battery_charge_power_max',params['plant_conf']['Pc_max']) + params['plant_conf']['eta_disch'] = options.get('battery_discharge_efficiency',params['plant_conf']['eta_disch']) + params['plant_conf']['eta_ch'] = options.get('battery_charge_efficiency',params['plant_conf']['eta_ch']) + params['plant_conf']['Enom'] = options.get('battery_nominal_energy_capacity',params['plant_conf']['Enom']) + params['plant_conf']['SOCmin'] = options.get('battery_minimum_state_of_charge',params['plant_conf']['SOCmin']) + params['plant_conf']['SOCmax'] = options.get('battery_maximum_state_of_charge',params['plant_conf']['SOCmax']) + params['plant_conf']['SOCtarget'] = options.get('battery_target_state_of_charge',params['plant_conf']['SOCtarget']) + else: + params['params_secrets'] = params_secrets + # The params dict + params['passed_data'] = {'pv_power_forecast':None,'load_power_forecast':None,'load_cost_forecast':None,'prod_price_forecast':None, + 'prediction_horizon':None,'soc_init':None,'soc_final':None,'def_total_hours':None,'def_start_timestep':None,'def_end_timestep':None,'alpha':None,'beta':None} + return params + def get_days_list(days_to_retrieve: int) -> pd.date_range: """ Get list of past days from today to days_to_retrieve. diff --git a/src/emhass/web_server.py b/src/emhass/web_server.py index 2ea846b0..52e3051c 100644 --- a/src/emhass/web_server.py +++ b/src/emhass/web_server.py @@ -16,129 +16,13 @@ from emhass.command_line import perfect_forecast_optim, dayahead_forecast_optim, naive_mpc_optim from emhass.command_line import forecast_model_fit, forecast_model_predict, forecast_model_tune from emhass.command_line import publish_data -from emhass.utils import get_injection_dict, get_injection_dict_forecast_model_fit, get_injection_dict_forecast_model_tune +from emhass.utils import get_injection_dict, get_injection_dict_forecast_model_fit, \ + get_injection_dict_forecast_model_tune, build_params # Define the Flask instance app = Flask(__name__) -def build_params(params, params_secrets, options, addon): - if addon == 1: - # Updating variables in retrieve_hass_conf - params['retrieve_hass_conf']['freq'] = options.get('optimization_time_step',params['retrieve_hass_conf']['freq']) - params['retrieve_hass_conf']['days_to_retrieve'] = options.get('historic_days_to_retrieve',params['retrieve_hass_conf']['days_to_retrieve']) - params['retrieve_hass_conf']['var_PV'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_PV']) - params['retrieve_hass_conf']['var_load'] = options.get('sensor_power_load_no_var_loads',params['retrieve_hass_conf']['var_load']) - params['retrieve_hass_conf']['load_negative'] = options.get('load_negative',params['retrieve_hass_conf']['load_negative']) - params['retrieve_hass_conf']['set_zero_min'] = options.get('set_zero_min',params['retrieve_hass_conf']['set_zero_min']) - params['retrieve_hass_conf']['var_replace_zero'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_replace_zero']) - params['retrieve_hass_conf']['var_interp'] = options.get('sensor_power_photovoltaics',params['retrieve_hass_conf']['var_PV']), options.get('sensor_power_load_no_var_loads',params['retrieve_hass_conf']['var_load']) - params['retrieve_hass_conf']['method_ts_round'] = options.get('method_ts_round',params['retrieve_hass_conf']['method_ts_round']) - # Update params Secrets if specified - params['params_secrets'] = params_secrets - params['params_secrets']['time_zone'] = options.get('time_zone',params_secrets['time_zone']) - params['params_secrets']['lat'] = options.get('Latitude',params_secrets['lat']) - params['params_secrets']['lon'] = options.get('Longitude',params_secrets['lon']) - params['params_secrets']['alt'] = options.get('Altitude',params_secrets['alt']) - # Updating variables in optim_conf - params['optim_conf']['set_use_battery'] = options.get('set_use_battery',params['optim_conf']['set_use_battery']) - params['optim_conf']['num_def_loads'] = options.get('number_of_deferrable_loads',params['optim_conf']['num_def_loads']) - try: - params['optim_conf']['P_deferrable_nom'] = [i['nominal_power_of_deferrable_loads'] for i in options.get('list_nominal_power_of_deferrable_loads')] - except: - app.logger.debug("no list_nominal_power_of_deferrable_loads, defaulting to config file") - try: - params['optim_conf']['def_total_hours'] = [i['operating_hours_of_each_deferrable_load'] for i in options.get('list_operating_hours_of_each_deferrable_load')] - except: - app.logger.debug("no list_operating_hours_of_each_deferrable_load, defaulting to config file") - try: - params['optim_conf']['treat_def_as_semi_cont'] = [i['treat_deferrable_load_as_semi_cont'] for i in options.get('list_treat_deferrable_load_as_semi_cont')] - except: - app.logger.debug("no list_treat_deferrable_load_as_semi_cont, defaulting to config file") - params['optim_conf']['weather_forecast_method'] = options.get('weather_forecast_method',params['optim_conf']['weather_forecast_method']) - if params['optim_conf']['weather_forecast_method'] == "solcast": - params['retrieve_hass_conf']['solcast_api_key'] = options.get('optional_solcast_api_key',params['retrieve_hass_conf']['solcast_api_key']) - params['retrieve_hass_conf']['solcast_rooftop_id'] = options.get('optional_solcast_rooftop_id',params['retrieve_hass_conf']['solcast_rooftop_id']) - elif params['optim_conf']['weather_forecast_method'] == "solar.forecast": - params['retrieve_hass_conf']['solar_forecast_kwp'] = options.get('optional_solar_forecast_kwp',params['retrieve_hass_conf']['solar_forecast_kwp']) - params['optim_conf']['load_forecast_method'] = options.get('load_forecast_method',params['optim_conf']['load_forecast_method']) - params['optim_conf']['delta_forecast'] = options.get('delta_forecast_daily',params['optim_conf']['delta_forecast']) - params['optim_conf']['load_cost_forecast_method'] = options.get('load_cost_forecast_method',params['optim_conf']['load_cost_forecast_method']) - try: - params['optim_conf']['set_def_constant'] = [i['set_deferrable_load_single_constant'] for i in options.get('list_set_deferrable_load_single_constant')] - except: - app.logger.debug("no list_set_deferrable_load_single_constant, defaulting to config file") - try: - start_hours_list = [i['peak_hours_periods_start_hours'] for i in options['list_peak_hours_periods_start_hours']] - end_hours_list = [i['peak_hours_periods_end_hours'] for i in options['list_peak_hours_periods_end_hours']] - num_peak_hours = len(start_hours_list) - list_hp_periods_list = [{'period_hp_'+str(i+1):[{'start':start_hours_list[i]},{'end':end_hours_list[i]}]} for i in range(num_peak_hours)] - params['optim_conf']['list_hp_periods'] = list_hp_periods_list - except: - app.logger.debug("no list_peak_hours_periods_start_hours, defaulting to config file") - params['optim_conf']['load_cost_hp'] = options.get('load_peak_hours_cost',params['optim_conf']['load_cost_hp']) - params['optim_conf']['load_cost_hc'] = options.get('load_offpeak_hours_cost', params['optim_conf']['load_cost_hc']) - params['optim_conf']['prod_price_forecast_method'] = options.get('production_price_forecast_method', params['optim_conf']['prod_price_forecast_method']) - params['optim_conf']['prod_sell_price'] = options.get('photovoltaic_production_sell_price',params['optim_conf']['prod_sell_price']) - params['optim_conf']['set_total_pv_sell'] = options.get('set_total_pv_sell',params['optim_conf']['set_total_pv_sell']) - params['optim_conf']['lp_solver'] = options.get('lp_solver',params['optim_conf']['lp_solver']) - params['optim_conf']['lp_solver_path'] = options.get('lp_solver_path',params['optim_conf']['lp_solver_path']) - params['optim_conf']['set_nocharge_from_grid'] = options.get('set_nocharge_from_grid',params['optim_conf']['set_nocharge_from_grid']) - params['optim_conf']['set_nodischarge_to_grid'] = options.get('set_nodischarge_to_grid',params['optim_conf']['set_nodischarge_to_grid']) - params['optim_conf']['set_battery_dynamic'] = options.get('set_battery_dynamic',params['optim_conf']['set_battery_dynamic']) - params['optim_conf']['battery_dynamic_max'] = options.get('battery_dynamic_max',params['optim_conf']['battery_dynamic_max']) - params['optim_conf']['battery_dynamic_min'] = options.get('battery_dynamic_min',params['optim_conf']['battery_dynamic_min']) - params['optim_conf']['weight_battery_discharge'] = options.get('weight_battery_discharge',params['optim_conf']['weight_battery_discharge']) - params['optim_conf']['weight_battery_charge'] = options.get('weight_battery_charge',params['optim_conf']['weight_battery_charge']) - try: - params['optim_conf']['def_start_timestep'] = [i['start_timesteps_of_each_deferrable_load'] for i in options.get('list_start_timesteps_of_each_deferrable_load')] - except: - app.logger.debug("no list_start_timesteps_of_each_deferrable_load, defaulting to config file") - try: - params['optim_conf']['def_end_timestep'] = [i['end_timesteps_of_each_deferrable_load'] for i in options.get('list_end_timesteps_of_each_deferrable_load')] - except: - app.logger.debug("no list_end_timesteps_of_each_deferrable_load, defaulting to config file") - # Updating variables in plant_con - params['plant_conf']['P_grid_max'] = options.get('maximum_power_from_grid',params['plant_conf']['P_grid_max']) - try: - params['plant_conf']['module_model'] = [i['pv_module_model'] for i in options.get('list_pv_module_model')] - except: - app.logger.debug("no list_pv_module_model, defaulting to config file") - try: - params['plant_conf']['inverter_model'] = [i['pv_inverter_model'] for i in options.get('list_pv_inverter_model')] - except: - app.logger.debug("no list_pv_inverter_model, defaulting to config file") - try: - params['plant_conf']['surface_tilt'] = [i['surface_tilt'] for i in options.get('list_surface_tilt')] - except: - app.logger.debug("no list_surface_tilt, defaulting to config file") - try: - params['plant_conf']['surface_azimuth'] = [i['surface_azimuth'] for i in options.get('list_surface_azimuth')] - except: - app.logger.debug("no list_surface_azimuth, defaulting to config file") - try: - params['plant_conf']['modules_per_string'] = [i['modules_per_string'] for i in options.get('list_modules_per_string')] - except: - app.logger.debug("no list_modules_per_string, defaulting to config file") - try: - params['plant_conf']['strings_per_inverter'] = [i['strings_per_inverter'] for i in options.get('list_strings_per_inverter')] - except: - app.logger.debug("no list_strings_per_inverter, defaulting to config file") - params['plant_conf']['Pd_max'] = options.get('battery_discharge_power_max',params['plant_conf']['Pd_max']) - params['plant_conf']['Pc_max'] = options.get('battery_charge_power_max',params['plant_conf']['Pc_max']) - params['plant_conf']['eta_disch'] = options.get('battery_discharge_efficiency',params['plant_conf']['eta_disch']) - params['plant_conf']['eta_ch'] = options.get('battery_charge_efficiency',params['plant_conf']['eta_ch']) - params['plant_conf']['Enom'] = options.get('battery_nominal_energy_capacity',params['plant_conf']['Enom']) - params['plant_conf']['SOCmin'] = options.get('battery_minimum_state_of_charge',params['plant_conf']['SOCmin']) - params['plant_conf']['SOCmax'] = options.get('battery_maximum_state_of_charge',params['plant_conf']['SOCmax']) - params['plant_conf']['SOCtarget'] = options.get('battery_target_state_of_charge',params['plant_conf']['SOCtarget']) - else: - params['params_secrets'] = params_secrets - # The params dict - params['passed_data'] = {'pv_power_forecast':None,'load_power_forecast':None,'load_cost_forecast':None,'prod_price_forecast':None, - 'prediction_horizon':None,'soc_init':None,'soc_final':None,'def_total_hours':None,'def_start_timestep':None,'def_end_timestep':None,'alpha':None,'beta':None} - return params - @app.route('/') def index(): app.logger.info("EMHASS server online, serving index.html...") @@ -332,7 +216,7 @@ def action_call(action_name): hass_url = params_secrets['hass_url'] # Build params - params = build_params(params, params_secrets, options, args.addon) + params = build_params(params, params_secrets, options, args.addon, app.logger) with open(str(data_path / 'params.pkl'), "wb") as fid: pickle.dump((config_path, params), fid) diff --git a/tests/test_utils.py b/tests/test_utils.py index d8367c51..8b0e6949 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -221,6 +221,39 @@ def test_treat_runtimeparams_failed(self): self.assertIsInstance(runtimeparams['load_power_forecast'], str) self.assertIsInstance(runtimeparams['load_cost_forecast'], str) self.assertIsInstance(runtimeparams['prod_price_forecast'], str) + + def test_build_params(self): + config_path = root / pathlib.Path("config_emhass.yaml") + with open(config_path, 'r') as file: + config = yaml.load(file, Loader=yaml.FullLoader) + retrieve_hass_conf = config['retrieve_hass_conf'] + optim_conf = config['optim_conf'] + plant_conf = config['plant_conf'] + params = {} + params['retrieve_hass_conf'] = retrieve_hass_conf + params['optim_conf'] = optim_conf + params['plant_conf'] = plant_conf + options_json = root / pathlib.Path("options.json") + # Read options info + with options_json.open('r') as data: + options = json.load(data) + with open(root / pathlib.Path("secrets_emhass(example).yaml"), 'r') as file: + params_secrets = yaml.load(file, Loader=yaml.FullLoader) + addon = 1 + params = utils.build_params(params, params_secrets, options, addon, logger) + expected_keys = ['retrieve_hass_conf', 'params_secrets', 'optim_conf', 'plant_conf', 'passed_data'] + for key in expected_keys: + self.assertTrue(key in params.keys()) + self.assertTrue(params['params_secrets']['time_zone'] == "Europe/Paris") + params = {} + params['retrieve_hass_conf'] = retrieve_hass_conf + params['optim_conf'] = optim_conf + params['plant_conf'] = plant_conf + addon = 0 + params = utils.build_params(params, params_secrets, options, addon, logger) + for key in expected_keys: + self.assertTrue(key in params.keys()) + self.assertTrue(params['params_secrets']['time_zone'] == "Europe/Paris") if __name__ == '__main__': unittest.main()