diff --git a/.github/workflows/publish_docker.yaml b/.github/workflows/publish_docker.yaml index 3969f97..605fb93 100644 --- a/.github/workflows/publish_docker.yaml +++ b/.github/workflows/publish_docker.yaml @@ -41,39 +41,39 @@ jobs: --aarch64 \ --target emhass \ --docker-hub davidusb - publish_armhf: - name: Publish-armhf - runs-on: ubuntu-latest - steps: - - name: Checkout the repository - uses: actions/checkout@v2 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Publish - uses: home-assistant/builder@master - with: - args: | - --armhf \ - --target emhass \ - --docker-hub davidusb - publish_armv7: - name: Publish-armv7 - runs-on: ubuntu-latest - steps: - - name: Checkout the repository - uses: actions/checkout@v2 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Publish - uses: home-assistant/builder@master - with: - args: | - --armv7 \ - --target emhass \ - --docker-hub davidusb + # publish_armhf: + # name: Publish-armhf + # runs-on: ubuntu-latest + # steps: + # - name: Checkout the repository + # uses: actions/checkout@v2 + # - name: Login to DockerHub + # uses: docker/login-action@v1 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + # - name: Publish + # uses: home-assistant/builder@master + # with: + # args: | + # --armhf \ + # --target emhass \ + # --docker-hub davidusb + # publish_armv7: + # name: Publish-armv7 + # runs-on: ubuntu-latest + # steps: + # - name: Checkout the repository + # uses: actions/checkout@v2 + # - name: Login to DockerHub + # uses: docker/login-action@v1 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + # - name: Publish + # uses: home-assistant/builder@master + # with: + # args: | + # --armv7 \ + # --target emhass \ + # --docker-hub davidusb diff --git a/emhass/CHANGELOG.md b/emhass/CHANGELOG.md index c884510..f0b9875 100644 --- a/emhass/CHANGELOG.md +++ b/emhass/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.42] - 2022-05-05 +### Fix +- Fixed issue on correct defferable load total energy computation, following emhass v0.2.14. + +## [0.1.41] - 2022-05-04 +### Improvement +- Added support for semi-continuous deferrable loads. +- Changed to plotting using stairs. +- Using now lists directly defined in the options.json file. +### Fix +- Fixed issue on add-on installing caused by changed parameter type to strings. + ## [0.1.40] - 2022-05-01 ### Improvement - Added support to pass list of PV plant parameters. This will enable to simulate mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). diff --git a/emhass/DOCS.md b/emhass/DOCS.md index 8558906..6b75475 100644 --- a/emhass/DOCS.md +++ b/emhass/DOCS.md @@ -41,11 +41,12 @@ These are the configuration parameters needed to correctly use this module. We will define now the paramters associated with the energy cost. -- peak_hours_periods_start_hours: This is a list of start hours of peak hours periods. A list of comma separated hours in 24h HH:MM format. For example for two peak hour periods: 02:54, 17:24 -- peak_hours_periods_end_hours: This is a list of end hours of peak hours periods. A list of comma separated hours in 24h HH:MM format. For example for two peak hour periods: 15:24, 20:24 +- peak_hours_periods_start_hours: This is a list of start hours of peak hours periods. A list of hours in 24h HH:MM format. +- peak_hours_periods_end_hours: This is a list of end hours of peak hours periods. A list of hours in 24h HH:MM format. -In this previous example the first peak hour will start at 02:54 and end at 15:24, and so on. If you don't have a peak/off-peak hours contract, then just leave these defaults period values and set the following peak/off-peak hours cost at the same value. +In the default configuration example the first peak hour will start at 02:54 and end at 15:24, and so on. If you don't have a peak/off-peak hours contract, then just leave these defaults period values and set the following peak/off-peak hours cost at the same value. +- treat_deferrable_load_as_semi_cont: Define if we should treat each deferrable load as a semi-continuous variable. Semi-continuous variables are variables that cana take either their nominal value or zero. - load_peak_hours_cost: The cost of the electrical energy from the grid during peak hours in €/kWh. Defaults to 0.1907. - load_offpeak_hours_cost: The cost of the electrical energy from the grid during non-peak hours in €/kWh. Defaults to 0.1419. - photovoltaic_production_sell_price: The paid price for energy injected to the grid from excedent PV production in €/kWh. Defaults to 0.065. @@ -57,12 +58,12 @@ The following parameters are associated with the technical specifications of the We will define the technical parameters of the PV installation. For the modeling task we rely on the PVLib Python package. For more information see: [https://pvlib-python.readthedocs.io/en/stable/](https://pvlib-python.readthedocs.io/en/stable/) The complete list of supported modules and inverter models can be found here: [https://pvlib-python.readthedocs.io/en/stable/generated/pvlib.pvsystem.retrieve_sam.html](https://pvlib-python.readthedocs.io/en/stable/generated/pvlib.pvsystem.retrieve_sam.html) -- pv_module_model: The PV module model. For example: 'CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M'. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). When finding the correct model for your installation remember to replace all the special characters in the model name by '_'. -- pv_inverter_model: The PV inverter model. For example: 'Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_'. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). When finding the correct model for your installation remember to replace all the special characters in the model name by '_'. -- surface_tilt: The tilt angle of your solar panels. This is a value between 0 and 90. Defaults to 30. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). -- surface_azimuth: The azimuth of your PV installation. This is a value between 0 and 360. Defaults to 205. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). -- modules_per_string: The number of modules per string. Defaults to 16. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). -- strings_per_inverter: The number of used strings per inverter. Defaults to 1. This parameter can be a list of comma separated strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). +- pv_module_model: The PV module model. For example: 'CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M'. This parameter can be a list of strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). When finding the correct model for your installation remember to replace all the special characters in the model name by '_'. +- pv_inverter_model: The PV inverter model. For example: 'Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_'. This parameter can be a list of strings to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). When finding the correct model for your installation remember to replace all the special characters in the model name by '_'. +- surface_tilt: The tilt angle of your solar panels. This is a value between 0 and 90. Defaults to 30. This parameter can be a list of integers to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). +- surface_azimuth: The azimuth of your PV installation. This is a value between 0 and 360. Defaults to 205. This parameter can be a list of integers to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). +- modules_per_string: The number of modules per string. Defaults to 16. This parameter can be a list of integers to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). +- strings_per_inverter: The number of used strings per inverter. Defaults to 1. This parameter can be a list of integers to enable the simulation of mixed orientation systems, for example one east-facing array (azimuth=90) and one west-facing array (azimuth=270). - set_use_battery: Set to True if we should consider an energy storage device such as a Li-Ion battery. Defaults to False. If the `set_use_battery` is set to `true`, then the following parameters need to be defined properly. If you don't have a battery then just leave the default values, they will not be used. @@ -86,7 +87,7 @@ This add-on exposes a simple webserver on port 5000. You can access it by clicki When you access the webserver you will be looking at the latests results stored in a csv file on the data folder inside the add-on. This will look something like this: -![](./images/screenshot_emhass_webui.png) +![](https://raw.githubusercontent.com/davidusb-geek/emhass-add-on/master/emhass/images/screenshot_emhass_webui.png) Each time that you launch the optimization task this csv file is rewritten and the graph and table in the UI can be refreshed. I left an initial csv file in the data folder so that the first time an user access the webserver it can check what type of results EMHASS will obtain when launching the optimization task. This initial csv was obtained with the default configuration presented in the configuration pane. The graph is interactive, so what you can do is use the legend to turn off the visualization of all variables except the deferrable load powers. In that example we have two deferrable loads and what you’re seeing is the result of the optimization. This is giving you the optimal evolution and turn on/off times of those deferrable loads in order to maximize profit for example, depending on what objective function you choose and all the forecast data that have been entered to EMHASS. diff --git a/emhass/app_server.py b/emhass/app_server.py index ad59aae..0906e5c 100644 --- a/emhass/app_server.py +++ b/emhass/app_server.py @@ -19,6 +19,7 @@ def get_injection_dict(df, plot_size = 1366): # Create plots fig = px.line(df, title='Systems powers and optimization cost results', template='seaborn', width=plot_size, height=0.75*plot_size) + fig.update_traces(line_shape="vh") # Get full path to image image_path_0 = fig.to_html(full_html=False, default_width='75%') # The tables @@ -85,12 +86,12 @@ def build_params(params, options): # Updating variables in optim_conf params['optim_conf'][0]['set_use_battery'] = options['set_use_battery'] params['optim_conf'][2]['num_def_loads'] = options['number_of_deferrable_loads'] - params['optim_conf'][3]['P_deferrable_nom'] = [int(i) for i in options['nominal_power_of_deferrable_loads'].split(',')] - params['optim_conf'][4]['def_total_hours'] = [int(i) for i in options['operating_hours_of_each_deferrable_load'].split(',')] - params['optim_conf'][5]['treat_def_as_semi_cont'] = [True for i in range(len(params['optim_conf'][3]['P_deferrable_nom']))] + params['optim_conf'][3]['P_deferrable_nom'] = [i['nominal_power_of_deferrable_loads'] for i in options['list_nominal_power_of_deferrable_loads']] + params['optim_conf'][4]['def_total_hours'] = [i['operating_hours_of_each_deferrable_load'] for i in options['list_operating_hours_of_each_deferrable_load']] + params['optim_conf'][5]['treat_def_as_semi_cont'] = [i['treat_deferrable_load_as_semi_cont'] for i in options['list_treat_deferrable_load_as_semi_cont']] params['optim_conf'][6]['set_def_constant'] = [False for i in range(len(params['optim_conf'][3]['P_deferrable_nom']))] - start_hours_list = options['peak_hours_periods_start_hours'].split(',') - end_hours_list = options['peak_hours_periods_end_hours'].split(',') + 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'][10]['list_hp_periods'] = list_hp_periods_list @@ -100,12 +101,12 @@ def build_params(params, options): params['optim_conf'][15]['set_total_pv_sell'] = options['set_total_pv_sell'] # Updating variables in plant_conf params['plant_conf'][0]['P_grid_max'] = options['maximum_power_from_grid'] - params['plant_conf'][1]['module_model'] = options['pv_module_model'].split(',') - params['plant_conf'][2]['inverter_model'] = options['pv_inverter_model'].split(',') - params['plant_conf'][3]['surface_tilt'] = [int(i) for i in options['surface_tilt'].split(',')] - params['plant_conf'][4]['surface_azimuth'] = [int(i) for i in options['surface_azimuth'].split(',')] - params['plant_conf'][5]['modules_per_string'] = [int(i) for i in options['modules_per_string'].split(',')] - params['plant_conf'][6]['strings_per_inverter'] = [int(i) for i in options['strings_per_inverter'].split(',')] + params['plant_conf'][1]['module_model'] = [i['pv_module_model'] for i in options['list_pv_module_model']] + params['plant_conf'][2]['inverter_model'] = [i['pv_inverter_model'] for i in options['list_pv_inverter_model']] + params['plant_conf'][3]['surface_tilt'] = [i['surface_tilt'] for i in options['list_surface_tilt']] + params['plant_conf'][4]['surface_azimuth'] = [i['surface_azimuth'] for i in options['list_surface_azimuth']] + params['plant_conf'][5]['modules_per_string'] = [i['modules_per_string'] for i in options['list_modules_per_string']] + params['plant_conf'][6]['strings_per_inverter'] = [i['strings_per_inverter'] for i in options['list_strings_per_inverter']] params['plant_conf'][7]['Pd_max'] = options['battery_discharge_power_max'] params['plant_conf'][8]['Pc_max'] = options['battery_charge_power_max'] params['plant_conf'][9]['eta_disch'] = options['battery_discharge_efficiency'] diff --git a/emhass/config.yml b/emhass/config.yml index 9c01f4b..6c0d168 100644 --- a/emhass/config.yml +++ b/emhass/config.yml @@ -1,7 +1,7 @@ name: EMHASS description: Energy Management for Home Assistant url: https://github.com/davidusb-geek/emhass -version: 0.1.40 +version: 0.1.42 slug: emhass arch: - aarch64 @@ -27,20 +27,37 @@ options: sensor_power_photovoltaics: sensor.power_photovoltaics sensor_power_load_no_var_loads: sensor.power_load_no_var_loads number_of_deferrable_loads: 2 - nominal_power_of_deferrable_loads: 3000,750 - operating_hours_of_each_deferrable_load: 5,8 - peak_hours_periods_start_hours: 02:54,17:24 - peak_hours_periods_end_hours: 15:24,20:24 + 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: 5 + - operating_hours_of_each_deferrable_load: 8 + 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:24 + list_treat_deferrable_load_as_semi_cont: + - treat_deferrable_load_as_semi_cont: true + - treat_deferrable_load_as_semi_cont: true load_peak_hours_cost: 0.1907 load_offpeak_hours_cost: 0.1419 photovoltaic_production_sell_price: 0.065 maximum_power_from_grid: 9000 - pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_ - surface_tilt: 30 - surface_azimuth: 205 - modules_per_string: 16 - strings_per_inverter: 1 + list_pv_module_model: + - pv_module_model: CSUN_Eurasia_Energy_Systems_Industry_and_Trade_CSUN295_60M + list_pv_inverter_model: + - pv_inverter_model: Fronius_International_GmbH__Fronius_Primo_5_0_1_208_240__240V_ + list_surface_tilt: + - surface_tilt: 30 + list_surface_azimuth: + - surface_azimuth: 205 + list_modules_per_string: + - modules_per_string: 16 + list_strings_per_inverter: + - strings_per_inverter: 1 set_use_battery: false battery_discharge_power_max: 1000 battery_charge_power_max: 1000 @@ -61,20 +78,32 @@ schema: sensor_power_photovoltaics: str sensor_power_load_no_var_loads: str number_of_deferrable_loads: int(1,10) - nominal_power_of_deferrable_loads: str - operating_hours_of_each_deferrable_load: str - peak_hours_periods_start_hours: str - peak_hours_periods_end_hours: str + list_nominal_power_of_deferrable_loads: + - nominal_power_of_deferrable_loads: int(0,) + list_operating_hours_of_each_deferrable_load: + - operating_hours_of_each_deferrable_load: int(0,) + list_peak_hours_periods_start_hours: + - peak_hours_periods_start_hours: str + list_peak_hours_periods_end_hours: + - peak_hours_periods_end_hours: str + list_treat_deferrable_load_as_semi_cont: + - treat_deferrable_load_as_semi_cont: bool load_peak_hours_cost: float(0,) load_offpeak_hours_cost: float(0,) photovoltaic_production_sell_price: float(0,) maximum_power_from_grid: int(0,) - pv_module_model: str - pv_inverter_model: str - surface_tilt: str - surface_azimuth: str - modules_per_string: str - strings_per_inverter: str + list_pv_module_model: + - pv_module_model: str + list_pv_inverter_model: + - pv_inverter_model: str + list_surface_tilt: + - surface_tilt: int(0,90) + list_surface_azimuth: + - surface_azimuth: int(0,360) + list_modules_per_string: + - modules_per_string: int(0,) + list_strings_per_inverter: + - strings_per_inverter: int(0,) set_use_battery: bool battery_discharge_power_max: int(0,) battery_charge_power_max: int(0,) diff --git a/emhass/requirements.txt b/emhass/requirements.txt index de410c4..97b7eaa 100644 --- a/emhass/requirements.txt +++ b/emhass/requirements.txt @@ -15,5 +15,5 @@ flask>=2.0.3 #waitress>=2.1.1 #Paste>=3.5.0 plotly>=5.6.0 -emhass==0.2.13 +emhass==0.2.14 #git+https://github.com/davidusb-geek/emhass.git@0f67c27 \ No newline at end of file