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.
- {emhass-0.8.0 → emhass-0.8.2}/CHANGELOG.md +19 -0
- {emhass-0.8.0 → emhass-0.8.2}/PKG-INFO +37 -25
- {emhass-0.8.0 → emhass-0.8.2}/README.md +34 -22
- {emhass-0.8.0 → emhass-0.8.2}/setup.py +5 -5
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/forecast.py +3 -3
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/optimization.py +3 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/retrieve_hass.py +1 -1
- emhass-0.8.2/src/emhass/static/advanced.html +32 -0
- emhass-0.8.2/src/emhass/static/basic.html +12 -0
- emhass-0.8.2/src/emhass/static/img/feather-sprite.svg +1 -0
- emhass-0.8.2/src/emhass/static/script.js +425 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/style.css +132 -23
- emhass-0.8.2/src/emhass/templates/index.html +70 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/templates/template.html +1 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/web_server.py +66 -23
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/PKG-INFO +37 -25
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/SOURCES.txt +4 -1
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/requires.txt +2 -2
- emhass-0.8.0/data/logger_emhass.log +0 -198
- emhass-0.8.0/src/emhass/templates/index.html +0 -374
- {emhass-0.8.0 → emhass-0.8.2}/CODE_OF_CONDUCT.md +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/CONTRIBUTING.md +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/LICENSE +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/MANIFEST.in +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_load_cost_forecast.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_load_forecast.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_prod_price_forecast.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_train_load_clustering.pkl +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_train_load_forecast.pkl +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/data_weather_forecast.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_latest.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_cost.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_profit.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/opt_res_perfect_optim_self-consumption.csv +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/test_df_final.pkl +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/test_response_get_data_get_method.pbz2 +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/test_response_scrapper_get_method.pbz2 +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/test_response_solarforecast_get_method.pbz2 +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/data/test_response_solcast_get_method.pbz2 +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/pyproject.toml +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/setup.cfg +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/__init__.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/command_line.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/machine_learning_forecaster.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/img/emhass_icon.png +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/static/img/emhass_logo_short.svg +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass/utils.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/dependency_links.txt +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/entry_points.txt +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/src/emhass.egg-info/top_level.txt +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/tests/test_command_line_utils.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/tests/test_forecast.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/tests/test_machine_learning_forecaster.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/tests/test_optimization.py +0 -0
- {emhass-0.8.0 → emhass-0.8.2}/tests/test_retrieve_hass.py +0 -0
- {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.
|
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
|
20
|
-
Requires-Dist: scipy
|
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
|
-
|
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
|
-
|
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.
|
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
|
44
|
-
'scipy
|
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>
|