emhass 0.8.0__tar.gz → 0.8.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {emhass-0.8.0 → emhass-0.8.2}/CHANGELOG.md +19 -0
  2. {emhass-0.8.0 → emhass-0.8.2}/PKG-INFO +37 -25
  3. {emhass-0.8.0 → emhass-0.8.2}/README.md +34 -22
  4. {emhass-0.8.0 → emhass-0.8.2}/setup.py +5 -5
  5. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/forecast.py +3 -3
  6. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/optimization.py +3 -0
  7. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/retrieve_hass.py +1 -1
  8. emhass-0.8.2/src/emhass/static/advanced.html +32 -0
  9. emhass-0.8.2/src/emhass/static/basic.html +12 -0
  10. emhass-0.8.2/src/emhass/static/img/feather-sprite.svg +1 -0
  11. emhass-0.8.2/src/emhass/static/script.js +425 -0
  12. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/style.css +132 -23
  13. emhass-0.8.2/src/emhass/templates/index.html +70 -0
  14. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/templates/template.html +1 -0
  15. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/web_server.py +66 -23
  16. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/PKG-INFO +37 -25
  17. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/SOURCES.txt +4 -1
  18. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/requires.txt +2 -2
  19. emhass-0.8.0/data/logger_emhass.log +0 -198
  20. emhass-0.8.0/src/emhass/templates/index.html +0 -374
  21. {emhass-0.8.0 → emhass-0.8.2}/CODE_OF_CONDUCT.md +0 -0
  22. {emhass-0.8.0 → emhass-0.8.2}/CONTRIBUTING.md +0 -0
  23. {emhass-0.8.0 → emhass-0.8.2}/LICENSE +0 -0
  24. {emhass-0.8.0 → emhass-0.8.2}/MANIFEST.in +0 -0
  25. {emhass-0.8.0 → emhass-0.8.2}/data/data_load_cost_forecast.csv +0 -0
  26. {emhass-0.8.0 → emhass-0.8.2}/data/data_load_forecast.csv +0 -0
  27. {emhass-0.8.0 → emhass-0.8.2}/data/data_prod_price_forecast.csv +0 -0
  28. {emhass-0.8.0 → emhass-0.8.2}/data/data_train_load_clustering.pkl +0 -0
  29. {emhass-0.8.0 → emhass-0.8.2}/data/data_train_load_forecast.pkl +0 -0
  30. {emhass-0.8.0 → emhass-0.8.2}/data/data_weather_forecast.csv +0 -0
  31. {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_latest.csv +0 -0
  32. {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_cost.csv +0 -0
  33. {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_profit.csv +0 -0
  34. {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_self-consumption.csv +0 -0
  35. {emhass-0.8.0 → emhass-0.8.2}/data/test_df_final.pkl +0 -0
  36. {emhass-0.8.0 → emhass-0.8.2}/data/test_response_get_data_get_method.pbz2 +0 -0
  37. {emhass-0.8.0 → emhass-0.8.2}/data/test_response_scrapper_get_method.pbz2 +0 -0
  38. {emhass-0.8.0 → emhass-0.8.2}/data/test_response_solarforecast_get_method.pbz2 +0 -0
  39. {emhass-0.8.0 → emhass-0.8.2}/data/test_response_solcast_get_method.pbz2 +0 -0
  40. {emhass-0.8.0 → emhass-0.8.2}/pyproject.toml +0 -0
  41. {emhass-0.8.0 → emhass-0.8.2}/setup.cfg +0 -0
  42. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/__init__.py +0 -0
  43. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/command_line.py +0 -0
  44. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/machine_learning_forecaster.py +0 -0
  45. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/img/emhass_icon.png +0 -0
  46. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/img/emhass_logo_short.svg +0 -0
  47. {emhass-0.8.0 → emhass-0.8.2}/src/emhass/utils.py +0 -0
  48. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/dependency_links.txt +0 -0
  49. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/entry_points.txt +0 -0
  50. {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/top_level.txt +0 -0
  51. {emhass-0.8.0 → emhass-0.8.2}/tests/test_command_line_utils.py +0 -0
  52. {emhass-0.8.0 → emhass-0.8.2}/tests/test_forecast.py +0 -0
  53. {emhass-0.8.0 → emhass-0.8.2}/tests/test_machine_learning_forecaster.py +0 -0
  54. {emhass-0.8.0 → emhass-0.8.2}/tests/test_optimization.py +0 -0
  55. {emhass-0.8.0 → emhass-0.8.2}/tests/test_retrieve_hass.py +0 -0
  56. {emhass-0.8.0 → emhass-0.8.2}/tests/test_utils.py +0 -0
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.2] - 2024-03-10
4
+ ### Improvement
5
+ - Proposed a new solution to survive DST using special option of Pandas `round` method
6
+ - Added option to `web_server` to init `data_path` as an options param
7
+ - Styling docs and html files on webui
8
+ - Advanced and basic pages improvements on webui
9
+ ### Fix
10
+ - Fixed support for ARM achitectures
11
+
12
+ ## [0.8.1] - 2024-02-28
13
+ ### Improvement
14
+ - Improved documentation
15
+ ### Fix
16
+ - Persistent data storage fix
17
+ - Docker Standalone Publish Workspace Fix
18
+
3
19
  ## [0.8.0] - 2024-02-25
4
20
  ### Improvement
5
21
  - Thanks to the great work from @GeoDerp we now have a unified/centralized Dockerfile that allows for testing different installation configuration methods in one place. This greatly helps testing, notably emulating the add-on environment. This will improve overall testing for both teh core code and the add-on. Again many thanks!
@@ -580,6 +596,9 @@ Thanks to @GeoDerp for this great work!
580
596
  [0.7.6]: https://github.com/davidusb-geek/emhass/releases/tag/v0.7.6
581
597
  [0.7.7]: https://github.com/davidusb-geek/emhass/releases/tag/v0.7.7
582
598
  [0.7.8]: https://github.com/davidusb-geek/emhass/releases/tag/v0.7.8
599
+ [0.8.0]: https://github.com/davidusb-geek/emhass/releases/tag/v0.8.0
600
+ [0.8.1]: https://github.com/davidusb-geek/emhass/releases/tag/v0.8.1
601
+ [0.8.2]: https://github.com/davidusb-geek/emhass/releases/tag/v0.8.2
583
602
 
584
603
  # Notes
585
604
  All notable changes to this project will be documented in this file.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: emhass
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: An Energy Management System for Home Assistant
5
5
  Home-page: https://github.com/davidusb-geek/emhass
6
6
  Author: David HERNANDEZ
@@ -16,8 +16,8 @@ Requires-Python: >=3.9, <3.12
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: wheel
19
- Requires-Dist: numpy<=1.26
20
- Requires-Dist: scipy<=1.11.3
19
+ Requires-Dist: numpy==1.26.4
20
+ Requires-Dist: scipy==1.12.0
21
21
  Requires-Dist: pandas<=2.0.3
22
22
  Requires-Dist: pvlib>=0.10.2
23
23
  Requires-Dist: protobuf>=3.0.0
@@ -132,38 +132,44 @@ These architectures are supported: `amd64`, `armv7`, `armhf` and `aarch64`.
132
132
  ### Method 2) Using Docker in standalone mode
133
133
 
134
134
  You can also install EMHASS using docker. This can be in the same machine as Home Assistant (if using the supervised install method) or in a different distant machine. To install first pull the latest image from docker hub:
135
- ```
135
+ ```bash
136
136
  docker pull davidusb/emhass-docker-standalone
137
137
  ```
138
138
 
139
139
  You can also build your image locally. For this clone this repository, setup your `config_emhass.yaml` file and use the provided make file with this command:
140
- ```
140
+ ```bash
141
141
  make -f deploy_docker.mk clean_deploy
142
142
  ```
143
143
  Then load the image in the .tar file:
144
- ```
144
+ ```bash
145
145
  docker load -i <TarFileName>.tar
146
146
  ```
147
147
  Finally check your image tag with `docker images` and launch the docker itself:
148
- ```
148
+ ```bash
149
149
  docker run -it --restart always -p 5000:5000 -e "LOCAL_COSTFUN=profit" -v $(pwd)/config_emhass.yaml:/app/config_emhass.yaml -v $(pwd)/secrets_emhass.yaml:/app/secrets_emhass.yaml --name DockerEMHASS <REPOSITORY:TAG>
150
150
  ```
151
+ - If you wish to keep a local, persistent copy of the EMHASS generated data, create a local folder on your device, then mount said folder inside the container.
152
+ ```bash
153
+ mkdir -p $(pwd)/data #linux: create data folder on local device
154
+
155
+ docker run -it --restart always -p 5000:5000 -e "LOCAL_COSTFUN=profit" -v $(pwd)/config_emhass.yaml:/app/config_emhass.yaml -v $(pwd)/data:/app/data -v $(pwd)/secrets_emhass.yaml:/app/secrets_emhass.yaml --name DockerEMHASS <REPOSITORY:TAG>
156
+ ```
151
157
 
152
158
  ### Method 3) Legacy method using a Python virtual environment
153
159
 
154
160
  With this method it is recommended to install on a virtual environment.
155
161
  For this you will need `virtualenv`, install it using:
156
- ```
162
+ ```bash
157
163
  sudo apt install python3-virtualenv
158
164
  ```
159
165
  Then create and activate the virtual environment:
160
- ```
166
+ ```bash
161
167
  virtualenv -p /usr/bin/python3 emhassenv
162
168
  cd emhassenv
163
169
  source bin/activate
164
170
  ```
165
171
  Install using the distribution files:
166
- ```
172
+ ```bash
167
173
  python3 -m pip install emhass
168
174
  ```
169
175
  Clone this repository to obtain the example configuration files.
@@ -174,7 +180,7 @@ We will suppose that this repository is cloned to:
174
180
  This will be the root path containing the yaml configuration files (`config_emhass.yaml` and `secrets_emhass.yaml`) and the different needed folders (a `data` folder to store the optimizations results and a `scripts` folder containing the bash scripts described further below).
175
181
 
176
182
  To upgrade the installation in the future just use:
177
- ```
183
+ ```bash
178
184
  python3 -m pip install --upgrade emhass
179
185
  ```
180
186
 
@@ -210,7 +216,7 @@ The available arguments are:
210
216
  - `--version`: Show the current version of EMHASS.
211
217
 
212
218
  For example, the following line command can be used to perform a day-ahead optimization task:
213
- ```
219
+ ```bash
214
220
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml' --costfun 'profit'
215
221
  ```
216
222
  Before running any valuable command you need to modify the `config_emhass.yaml` and `secrets_emhass.yaml` files. These files should contain the information adapted to your own system. To do this take a look at the special section for this in the [documentation](https://emhass.readthedocs.io/en/latest/config.html).
@@ -224,7 +230,7 @@ Then additional optimization strategies were developed, that can be used in comb
224
230
  ### Dayahead Optimization - Method 1) Add-on and docker standalone
225
231
 
226
232
  In `configuration.yaml`:
227
- ```
233
+ ```yaml
228
234
  shell_command:
229
235
  dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
230
236
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"
@@ -232,25 +238,25 @@ shell_command:
232
238
  ### Dayahead Optimization - Method 2) Legacy method using a Python virtual environment
233
239
 
234
240
  In `configuration.yaml`:
235
- ```
241
+ ```yaml
236
242
  shell_command:
237
243
  dayahead_optim: /home/user/emhass/scripts/dayahead_optim.sh
238
244
  publish_data: /home/user/emhass/scripts/publish_data.sh
239
245
  ```
240
246
  Create the file `dayahead_optim.sh` with the following content:
241
- ```
247
+ ```bash
242
248
  #!/bin/bash
243
249
  . /home/user/emhassenv/bin/activate
244
250
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml'
245
251
  ```
246
252
  And the file `publish_data.sh` with the following content:
247
- ```
253
+ ```bash
248
254
  #!/bin/bash
249
255
  . /home/user/emhassenv/bin/activate
250
256
  emhass --action 'publish-data' --config '/home/user/emhass/config_emhass.yaml'
251
257
  ```
252
258
  Then specify user rights and make the files executables:
253
- ```
259
+ ```bash
254
260
  sudo chmod -R 755 /home/user/emhass/scripts/dayahead_optim.sh
255
261
  sudo chmod -R 755 /home/user/emhass/scripts/publish_data.sh
256
262
  sudo chmod +x /home/user/emhass/scripts/dayahead_optim.sh
@@ -259,7 +265,7 @@ sudo chmod +x /home/user/emhass/scripts/publish_data.sh
259
265
  ### Common for any installation method
260
266
 
261
267
  In `automations.yaml`:
262
- ```
268
+ ```yaml
263
269
  - alias: EMHASS day-ahead optimization
264
270
  trigger:
265
271
  platform: time
@@ -276,7 +282,7 @@ In `automations.yaml`:
276
282
  In these automations the day-ahead optimization is performed everyday at 5:30am and the data is published every 5 minutes.
277
283
 
278
284
  The final action will be to link a sensor value in Home Assistant to control the switch of a desired controllable load. For example imagine that I want to control my water heater and that the `publish-data` action is publishing the optimized value of a deferrable load that I want to be linked to my water heater desired behavior. In this case we could use an automation like this one below to control the desired real switch:
279
- ```
285
+ ```yaml
280
286
  automation:
281
287
  - alias: Water Heater Optimized ON
282
288
  trigger:
@@ -291,7 +297,7 @@ automation:
291
297
  entity_id: switch.water_heater_switch
292
298
  ```
293
299
  A second automation should be used to turn off the switch:
294
- ```
300
+ ```yaml
295
301
  automation:
296
302
  - alias: Water Heater Optimized OFF
297
303
  trigger:
@@ -313,7 +319,7 @@ The `publish-data` command will push to Home Assistant the optimization results
313
319
  The `publish-data` command will also publish PV and load forecast data on sensors `p_pv_forecast` and `p_load_forecast`. If using a battery, then the battery optimized power and the SOC will be published on sensors `p_batt_forecast` and `soc_batt_forecast`. On these sensors the future values are passed as nested attributes.
314
320
 
315
321
  It is possible to provide custm sensor names for all the data exported by the `publish-data` command. For this, when using the `publish-data` endpoint just add some runtime parameters as dictionaries like this:
316
- ```
322
+ ```yaml
317
323
  shell_command:
318
324
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"custom_load_forecast_id\": {\"entity_id\": \"sensor.p_load_forecast\", \"unit_of_measurement\": \"W\", \"friendly_name\": \"Load Power Forecast\"}}' http://localhost:5000/action/publish-data"
319
325
  ```
@@ -321,7 +327,7 @@ shell_command:
321
327
  These keys are available to modify: `custom_pv_forecast_id`, `custom_load_forecast_id`, `custom_batt_forecast_id`, `custom_batt_soc_forecast_id`, `custom_grid_forecast_id`, `custom_cost_fun_id`, `custom_deferrable_forecast_id`, `custom_unit_load_cost_id` and `custom_unit_prod_price_id`.
322
328
 
323
329
  If you provide the `custom_deferrable_forecast_id` then the passed data should be a list of dictionaries, like this:
324
- ```
330
+ ```yaml
325
331
  shell_command:
326
332
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"custom_deferrable_forecast_id\": [{\"entity_id\": \"sensor.p_deferrable0\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"Deferrable Load 0\"},{\"entity_id\": \"sensor.p_deferrable1\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"Deferrable Load 1\"}]}' http://localhost:5000/action/publish-data"
327
333
  ```
@@ -371,11 +377,11 @@ The valid values to pass for both forecast data and MPC related data are explain
371
377
  It is possible to provide EMHASS with your own forecast data. For this just add the data as list of values to a data dictionary during the call to `emhass` using the `runtimeparams` option.
372
378
 
373
379
  For example if using the add-on or the standalone docker installation you can pass this data as list of values to the data dictionary during the `curl` POST:
374
- ```
380
+ ```bash
375
381
  curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93, 1164.33, 1046.68, 1559.1, 2091.26, 1556.76, 1166.73, 1516.63, 1391.13, 1720.13, 820.75, 804.41, 251.63, 79.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}' http://localhost:5000/action/dayahead-optim
376
382
  ```
377
383
  Or if using the legacy method using a Python virtual environment:
378
- ```
384
+ ```bash
379
385
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml' --runtimeparams '{"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93, 1164.33, 1046.68, 1559.1, 2091.26, 1556.76, 1166.73, 1516.63, 1391.13, 1720.13, 820.75, 804.41, 251.63, 79.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}'
380
386
  ```
381
387
 
@@ -448,10 +454,16 @@ When applying this controller, the following `runtimeparams` should be defined:
448
454
 
449
455
  A correct call for a MPC optimization should look like:
450
456
 
457
+ ```bash
458
+ curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6}' http://192.168.3.159:5000/action/naive-mpc-optim
451
459
  ```
452
- curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6,"def_total_hours":[1,3],"def_start_timestep":[0,3],"def_end_timestep":[0,6],}' http://localhost:5000/action/naive-mpc-optim
460
+ *Example with :`def_total_hours`, `def_start_timestep`, `def_end_timestep`.*
461
+ ```bash
462
+ curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6,"def_total_hours":[1,3],"def_start_timestep":[0,3],"def_end_timestep":[0,6]}' http://localhost:5000/action/naive-mpc-optim
453
463
  ```
454
464
 
465
+
466
+
455
467
  ## A machine learning forecaster
456
468
 
457
469
  Starting in v0.4.0 a new machine learning forecaster class was introduced.
@@ -97,38 +97,44 @@ These architectures are supported: `amd64`, `armv7`, `armhf` and `aarch64`.
97
97
  ### Method 2) Using Docker in standalone mode
98
98
 
99
99
  You can also install EMHASS using docker. This can be in the same machine as Home Assistant (if using the supervised install method) or in a different distant machine. To install first pull the latest image from docker hub:
100
- ```
100
+ ```bash
101
101
  docker pull davidusb/emhass-docker-standalone
102
102
  ```
103
103
 
104
104
  You can also build your image locally. For this clone this repository, setup your `config_emhass.yaml` file and use the provided make file with this command:
105
- ```
105
+ ```bash
106
106
  make -f deploy_docker.mk clean_deploy
107
107
  ```
108
108
  Then load the image in the .tar file:
109
- ```
109
+ ```bash
110
110
  docker load -i <TarFileName>.tar
111
111
  ```
112
112
  Finally check your image tag with `docker images` and launch the docker itself:
113
- ```
113
+ ```bash
114
114
  docker run -it --restart always -p 5000:5000 -e "LOCAL_COSTFUN=profit" -v $(pwd)/config_emhass.yaml:/app/config_emhass.yaml -v $(pwd)/secrets_emhass.yaml:/app/secrets_emhass.yaml --name DockerEMHASS <REPOSITORY:TAG>
115
115
  ```
116
+ - If you wish to keep a local, persistent copy of the EMHASS generated data, create a local folder on your device, then mount said folder inside the container.
117
+ ```bash
118
+ mkdir -p $(pwd)/data #linux: create data folder on local device
119
+
120
+ docker run -it --restart always -p 5000:5000 -e "LOCAL_COSTFUN=profit" -v $(pwd)/config_emhass.yaml:/app/config_emhass.yaml -v $(pwd)/data:/app/data -v $(pwd)/secrets_emhass.yaml:/app/secrets_emhass.yaml --name DockerEMHASS <REPOSITORY:TAG>
121
+ ```
116
122
 
117
123
  ### Method 3) Legacy method using a Python virtual environment
118
124
 
119
125
  With this method it is recommended to install on a virtual environment.
120
126
  For this you will need `virtualenv`, install it using:
121
- ```
127
+ ```bash
122
128
  sudo apt install python3-virtualenv
123
129
  ```
124
130
  Then create and activate the virtual environment:
125
- ```
131
+ ```bash
126
132
  virtualenv -p /usr/bin/python3 emhassenv
127
133
  cd emhassenv
128
134
  source bin/activate
129
135
  ```
130
136
  Install using the distribution files:
131
- ```
137
+ ```bash
132
138
  python3 -m pip install emhass
133
139
  ```
134
140
  Clone this repository to obtain the example configuration files.
@@ -139,7 +145,7 @@ We will suppose that this repository is cloned to:
139
145
  This will be the root path containing the yaml configuration files (`config_emhass.yaml` and `secrets_emhass.yaml`) and the different needed folders (a `data` folder to store the optimizations results and a `scripts` folder containing the bash scripts described further below).
140
146
 
141
147
  To upgrade the installation in the future just use:
142
- ```
148
+ ```bash
143
149
  python3 -m pip install --upgrade emhass
144
150
  ```
145
151
 
@@ -175,7 +181,7 @@ The available arguments are:
175
181
  - `--version`: Show the current version of EMHASS.
176
182
 
177
183
  For example, the following line command can be used to perform a day-ahead optimization task:
178
- ```
184
+ ```bash
179
185
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml' --costfun 'profit'
180
186
  ```
181
187
  Before running any valuable command you need to modify the `config_emhass.yaml` and `secrets_emhass.yaml` files. These files should contain the information adapted to your own system. To do this take a look at the special section for this in the [documentation](https://emhass.readthedocs.io/en/latest/config.html).
@@ -189,7 +195,7 @@ Then additional optimization strategies were developed, that can be used in comb
189
195
  ### Dayahead Optimization - Method 1) Add-on and docker standalone
190
196
 
191
197
  In `configuration.yaml`:
192
- ```
198
+ ```yaml
193
199
  shell_command:
194
200
  dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
195
201
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"
@@ -197,25 +203,25 @@ shell_command:
197
203
  ### Dayahead Optimization - Method 2) Legacy method using a Python virtual environment
198
204
 
199
205
  In `configuration.yaml`:
200
- ```
206
+ ```yaml
201
207
  shell_command:
202
208
  dayahead_optim: /home/user/emhass/scripts/dayahead_optim.sh
203
209
  publish_data: /home/user/emhass/scripts/publish_data.sh
204
210
  ```
205
211
  Create the file `dayahead_optim.sh` with the following content:
206
- ```
212
+ ```bash
207
213
  #!/bin/bash
208
214
  . /home/user/emhassenv/bin/activate
209
215
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml'
210
216
  ```
211
217
  And the file `publish_data.sh` with the following content:
212
- ```
218
+ ```bash
213
219
  #!/bin/bash
214
220
  . /home/user/emhassenv/bin/activate
215
221
  emhass --action 'publish-data' --config '/home/user/emhass/config_emhass.yaml'
216
222
  ```
217
223
  Then specify user rights and make the files executables:
218
- ```
224
+ ```bash
219
225
  sudo chmod -R 755 /home/user/emhass/scripts/dayahead_optim.sh
220
226
  sudo chmod -R 755 /home/user/emhass/scripts/publish_data.sh
221
227
  sudo chmod +x /home/user/emhass/scripts/dayahead_optim.sh
@@ -224,7 +230,7 @@ sudo chmod +x /home/user/emhass/scripts/publish_data.sh
224
230
  ### Common for any installation method
225
231
 
226
232
  In `automations.yaml`:
227
- ```
233
+ ```yaml
228
234
  - alias: EMHASS day-ahead optimization
229
235
  trigger:
230
236
  platform: time
@@ -241,7 +247,7 @@ In `automations.yaml`:
241
247
  In these automations the day-ahead optimization is performed everyday at 5:30am and the data is published every 5 minutes.
242
248
 
243
249
  The final action will be to link a sensor value in Home Assistant to control the switch of a desired controllable load. For example imagine that I want to control my water heater and that the `publish-data` action is publishing the optimized value of a deferrable load that I want to be linked to my water heater desired behavior. In this case we could use an automation like this one below to control the desired real switch:
244
- ```
250
+ ```yaml
245
251
  automation:
246
252
  - alias: Water Heater Optimized ON
247
253
  trigger:
@@ -256,7 +262,7 @@ automation:
256
262
  entity_id: switch.water_heater_switch
257
263
  ```
258
264
  A second automation should be used to turn off the switch:
259
- ```
265
+ ```yaml
260
266
  automation:
261
267
  - alias: Water Heater Optimized OFF
262
268
  trigger:
@@ -278,7 +284,7 @@ The `publish-data` command will push to Home Assistant the optimization results
278
284
  The `publish-data` command will also publish PV and load forecast data on sensors `p_pv_forecast` and `p_load_forecast`. If using a battery, then the battery optimized power and the SOC will be published on sensors `p_batt_forecast` and `soc_batt_forecast`. On these sensors the future values are passed as nested attributes.
279
285
 
280
286
  It is possible to provide custm sensor names for all the data exported by the `publish-data` command. For this, when using the `publish-data` endpoint just add some runtime parameters as dictionaries like this:
281
- ```
287
+ ```yaml
282
288
  shell_command:
283
289
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"custom_load_forecast_id\": {\"entity_id\": \"sensor.p_load_forecast\", \"unit_of_measurement\": \"W\", \"friendly_name\": \"Load Power Forecast\"}}' http://localhost:5000/action/publish-data"
284
290
  ```
@@ -286,7 +292,7 @@ shell_command:
286
292
  These keys are available to modify: `custom_pv_forecast_id`, `custom_load_forecast_id`, `custom_batt_forecast_id`, `custom_batt_soc_forecast_id`, `custom_grid_forecast_id`, `custom_cost_fun_id`, `custom_deferrable_forecast_id`, `custom_unit_load_cost_id` and `custom_unit_prod_price_id`.
287
293
 
288
294
  If you provide the `custom_deferrable_forecast_id` then the passed data should be a list of dictionaries, like this:
289
- ```
295
+ ```yaml
290
296
  shell_command:
291
297
  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"custom_deferrable_forecast_id\": [{\"entity_id\": \"sensor.p_deferrable0\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"Deferrable Load 0\"},{\"entity_id\": \"sensor.p_deferrable1\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"Deferrable Load 1\"}]}' http://localhost:5000/action/publish-data"
292
298
  ```
@@ -336,11 +342,11 @@ The valid values to pass for both forecast data and MPC related data are explain
336
342
  It is possible to provide EMHASS with your own forecast data. For this just add the data as list of values to a data dictionary during the call to `emhass` using the `runtimeparams` option.
337
343
 
338
344
  For example if using the add-on or the standalone docker installation you can pass this data as list of values to the data dictionary during the `curl` POST:
339
- ```
345
+ ```bash
340
346
  curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93, 1164.33, 1046.68, 1559.1, 2091.26, 1556.76, 1166.73, 1516.63, 1391.13, 1720.13, 820.75, 804.41, 251.63, 79.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}' http://localhost:5000/action/dayahead-optim
341
347
  ```
342
348
  Or if using the legacy method using a Python virtual environment:
343
- ```
349
+ ```bash
344
350
  emhass --action 'dayahead-optim' --config '/home/user/emhass/config_emhass.yaml' --runtimeparams '{"pv_power_forecast":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93, 1164.33, 1046.68, 1559.1, 2091.26, 1556.76, 1166.73, 1516.63, 1391.13, 1720.13, 820.75, 804.41, 251.63, 79.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}'
345
351
  ```
346
352
 
@@ -413,10 +419,16 @@ When applying this controller, the following `runtimeparams` should be defined:
413
419
 
414
420
  A correct call for a MPC optimization should look like:
415
421
 
422
+ ```bash
423
+ curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6}' http://192.168.3.159:5000/action/naive-mpc-optim
416
424
  ```
417
- curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6,"def_total_hours":[1,3],"def_start_timestep":[0,3],"def_end_timestep":[0,6],}' http://localhost:5000/action/naive-mpc-optim
425
+ *Example with :`def_total_hours`, `def_start_timestep`, `def_end_timestep`.*
426
+ ```bash
427
+ curl -i -H 'Content-Type:application/json' -X POST -d '{"pv_power_forecast":[0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93], "prediction_horizon":10, "soc_init":0.5,"soc_final":0.6,"def_total_hours":[1,3],"def_start_timestep":[0,3],"def_end_timestep":[0,6]}' http://localhost:5000/action/naive-mpc-optim
418
428
  ```
419
429
 
430
+
431
+
420
432
  ## A machine learning forecaster
421
433
 
422
434
  Starting in v0.4.0 a new machine learning forecaster class was introduced.
@@ -19,7 +19,7 @@ long_description = (here / 'README.md').read_text(encoding='utf-8')
19
19
 
20
20
  setup(
21
21
  name='emhass', # Required
22
- version='0.8.0', # Required
22
+ version='0.8.2', # Required
23
23
  description='An Energy Management System for Home Assistant', # Optional
24
24
  long_description=long_description, # Optional
25
25
  long_description_content_type='text/markdown', # Optional (see note above)
@@ -40,8 +40,8 @@ setup(
40
40
  python_requires='>=3.9, <3.12',
41
41
  install_requires=[
42
42
  'wheel',
43
- 'numpy<=1.26',
44
- 'scipy<=1.11.3',
43
+ 'numpy==1.26.4',
44
+ 'scipy==1.12.0',
45
45
  'pandas<=2.0.3',
46
46
  'pvlib>=0.10.2',
47
47
  'protobuf>=3.0.0',
@@ -62,6 +62,6 @@ setup(
62
62
  'emhass=emhass.command_line:main',
63
63
  ],
64
64
  },
65
- package_data={'emhass': ['templates/index.html','templates/template.html',
66
- 'static/style.css','static/img/emhass_icon.png','static/img/emhass_logo_short.svg']},
65
+ package_data={'emhass': ['templates/index.html','templates/template.html','static/advanced.html','static/basic.html', 'static/script.js',
66
+ 'static/style.css','static/img/emhass_icon.png','static/img/emhass_logo_short.svg', 'static/img/feather-sprite.svg']},
67
67
  )
@@ -159,7 +159,7 @@ class Forecast(object):
159
159
  self.end_forecast = (self.start_forecast + self.optim_conf['delta_forecast']).replace(microsecond=0)
160
160
  self.forecast_dates = pd.date_range(start=self.start_forecast,
161
161
  end=self.end_forecast-self.freq,
162
- freq=self.freq).round(self.freq)
162
+ freq=self.freq).round(self.freq, ambiguous='infer', nonexistent=self.freq)
163
163
  if params is not None:
164
164
  if 'prediction_horizon' in list(self.params['passed_data'].keys()):
165
165
  if self.params['passed_data']['prediction_horizon'] is not None:
@@ -184,7 +184,7 @@ class Forecast(object):
184
184
  freq_scrap = pd.to_timedelta(60, "minutes") # The scrapping time step is 60min
185
185
  forecast_dates_scrap = pd.date_range(start=self.start_forecast,
186
186
  end=self.end_forecast-freq_scrap,
187
- freq=freq_scrap).round(freq_scrap)
187
+ freq=freq_scrap).round(freq_scrap, ambiguous='infer', nonexistent=freq_scrap)
188
188
  # Using the clearoutside webpage
189
189
  response = get("https://clearoutside.com/forecast/"+str(round(self.lat, 2))+"/"+str(round(self.lon, 2))+"?desktop=true")
190
190
  '''import bz2 # Uncomment to save a serialized data for tests
@@ -476,7 +476,7 @@ class Forecast(object):
476
476
  end_forecast_csv = (start_forecast_csv + self.optim_conf['delta_forecast']).replace(microsecond=0)
477
477
  forecast_dates_csv = pd.date_range(start=start_forecast_csv,
478
478
  end=end_forecast_csv+timedelta(days=timedelta_days)-self.freq,
479
- freq=self.freq).round(self.freq)
479
+ freq=self.freq).round(self.freq, ambiguous='infer', nonexistent=self.freq)
480
480
  if self.params is not None:
481
481
  if 'prediction_horizon' in list(self.params['passed_data'].keys()):
482
482
  if self.params['passed_data']['prediction_horizon'] is not None:
@@ -85,6 +85,9 @@ class Optimization:
85
85
  self.lp_solver_path = 'empty'
86
86
  if self.lp_solver != 'COIN_CMD' and self.lp_solver_path != 'empty':
87
87
  self.logger.error("Use COIN_CMD solver name if you want to set a path for the LP solver")
88
+ if self.lp_solver == 'COIN_CMD' and self.lp_solver_path == 'empty': #if COIN_CMD but lp_solver_path is empty
89
+ self.logger.warning("lp_solver=COIN_CMD but lp_solver_path=empty, attempting to use lp_solver_path=/usr/bin/cbc")
90
+ self.lp_solver_path = '/usr/bin/cbc'
88
91
 
89
92
  def perform_optimization(self, data_opt: pd.DataFrame, P_PV: np.array, P_load: np.array,
90
93
  unit_load_cost: np.array, unit_prod_price: np.array,
@@ -149,7 +149,7 @@ class RetrieveHass:
149
149
  from_date = pd.to_datetime(df_raw['last_changed'], format="ISO8601").min()
150
150
  to_date = pd.to_datetime(df_raw['last_changed'], format="ISO8601").max()
151
151
  ts = pd.to_datetime(pd.date_range(start=from_date, end=to_date, freq=self.freq),
152
- format='%Y-%d-%m %H:%M').round(self.freq)
152
+ format='%Y-%d-%m %H:%M').round(self.freq, ambiguous='infer', nonexistent=self.freq)
153
153
  df_day = pd.DataFrame(index = ts)
154
154
  # Caution with undefined string data: unknown, unavailable, etc.
155
155
  df_tp = df_raw.copy()[['state']].replace(
@@ -0,0 +1,32 @@
1
+ <!-- action button elements section -->
2
+ <div class="loading-div" id="advance">
3
+ <h4>Use the buttons below to manually launch different optimization tasks</h4>
4
+ <div id=loader></div> <!-- status dynamic element -->
5
+ </div>
6
+ <button type="button" id="perfect-optim" class="button button1">Perfect Optimization</button>
7
+ <button type="button" id="dayahead-optim" class="button button2">Day-ahead Optimization</button>
8
+ <button type="button" id="naive-mpc-optim" class="button button3">MPC Optimization</button>
9
+ <!--ml toggled div button -->
10
+ <h4>Use the button below to publish the optimized variables at the current timestamp</h4>
11
+ <button type="button" id="publish-data" class="button button1">Publish Optimization Results</button>
12
+ <h4>Use the buttons below to fit, predict and tune a machine learning model for testing</h4>
13
+ <button type="button" id="forecast-model-fit" class="button button1">ML forecast model fit</button>
14
+ <button type="button" id="forecast-model-predict" class="button button2">ML forecast model
15
+ predict</button>
16
+ <button type="button" id="forecast-model-tune" class="button button3">ML forecast model tune</button>
17
+ <!-- -->
18
+ <!--dynamic input elements section -->
19
+ <h4>Input Runtime Parameters</h4>
20
+ <div class="input-button-container">
21
+ <div class="input-buttons">
22
+ <button type="button" id="input-plus">+</button>
23
+ <button type="button" id="input-minus">-</button>
24
+ <select name="Select" id="input-select">
25
+ <option value="List" selected>List</option>
26
+ <option value="Box">Box</option>
27
+ </select>
28
+ <button type="button" id="input-clear">Clear</button>
29
+ </div>
30
+ </div>
31
+ <div id="input-container"> <!-- (Box/List) dynamic input elements will be added here -->
32
+ </div>
@@ -0,0 +1,12 @@
1
+ <!-- action button elements section -->
2
+ <div class="loading-div" id="basic">
3
+ <h4>Use the button below to manually launch optimization task</h4>
4
+ <div id=loader></div> <!-- status dynamic element -->
5
+ </div>
6
+ <button type="button" id="dayahead-optim-basic" class="button button1">Day-ahead Optimization</button>
7
+ <div class="info">
8
+ <p>The day-ahead optimization button will run once, based on the values entered into the configuration page.
9
+ </br>
10
+ After a few seconds, the charts and table below should be updated to reflect the optimization plan for the next 24 hours.
11
+ </p>
12
+ </div>