Skip to content

Commit bcac784

Browse files
Merge pull request #677 from davidusb-geek/davidusb-geek/fix/sonarqube_code_improvements
SonarQube code improvements
2 parents 478325b + d209861 commit bcac784

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+10112
-2892
lines changed

.github/workflows/codecov.yaml

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,49 @@ on:
77
branches: [ master ]
88
jobs:
99
run:
10-
runs-on: ${{ matrix.os }}
10+
runs-on: ubuntu-latest
1111
permissions:
1212
actions: read
1313
security-events: write
1414
contents: read
15-
strategy:
16-
matrix:
17-
os: [ubuntu-latest]
18-
env:
19-
OS: ${{ matrix.os }}
2015
steps:
21-
- uses: actions/checkout@master
22-
- name: Install uv
23-
uses: astral-sh/setup-uv@v5
24-
- name: Set up Python
25-
uses: actions/setup-python@v5
26-
with:
27-
python-version-file: ".python-version"
28-
- name: Generate Report
29-
run: |
30-
uv venv
31-
uv sync --reinstall --extra test
32-
uv run coverage run -m --source=emhass unittest
33-
uv run coverage report
34-
uv run coverage xml
35-
- name: Upload coverage reports to Codecov
36-
run: |
37-
# Replace `linux` below with the appropriate OS
38-
# Options are `alpine`, `linux`, `macos`, `windows`
39-
curl -Os https://uploader.codecov.io/latest/linux/codecov
40-
chmod +x codecov
41-
./codecov -t ${CODECOV_TOKEN}
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Install uv
21+
uses: astral-sh/setup-uv@v5
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version-file: ".python-version"
27+
28+
- name: Generate Report
29+
run: |
30+
uv venv
31+
uv sync --reinstall --extra test
32+
uv run coverage run -m --source=emhass unittest
33+
uv run coverage report
34+
uv run coverage xml -o coverage.xml
35+
36+
- name: Upload coverage reports to Codecov
37+
run: |
38+
curl -Os https://uploader.codecov.io/latest/linux/codecov
39+
chmod +x codecov
40+
./codecov -t ${CODECOV_TOKEN}
41+
42+
- name: SonarQube Scan
43+
uses: SonarSource/sonarqube-scan-action@v7
44+
env:
45+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} #
46+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
with:
48+
args: >
49+
-Dsonar.organization=davidusb-geek
50+
-Dsonar.projectKey=davidusb-geek_emhass
51+
-Dsonar.python.coverage.reportPaths=coverage.xml
52+
-Dsonar.sources=./src
53+
-Dsonar.tests=./tests
54+
-Dsonar.host.url=https://sonarcloud.io
55+
-Dsonar.scanner.skipJreProvisioning=true

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## 0.15.4 - 2026-01-13
4+
### Improvement
5+
- Support selecting PV module and inverter models by approximate power rating in addition to explicit database names
6+
- Introduce helper contexts and structured helpers for optimization setup, publishing, and forecast preparation
7+
- Add explicit SonarCloud analysis and Codecov integration in CI workflow
8+
- Added support to publish emhass package to conda repository
9+
- Improved documentation: Reorganize and expand documentation sections, including for using InfluxDB as a data source and for passing secret parameters, clarifying differences between Docker/Python deployments and the Home Assistant add-on, and moving this content into the passing_data guide. Change theme to PyData Sphinx Theme
10+
- Added extensive unit tests around Home Assistant data retrieval helpers, PV adjustment behavior, regressor preparation errors, weather forecast method branching, thermal loads publishing, and web server runtime parameter handling
11+
- Update existing optimization and CLI tests to use mocks for heavy optimization routines allowing faster tests
12+
### Fix
13+
- Ensure InfluxDB is prioritized over WebSocket and REST when configured as a data source to avoid redundant queries to Home Assistant
14+
- Fix runtime parameter parsing in the web server to properly handle malformed JSON payloads and default safely to empty parameters
15+
316
## 0.15.3 - 2026-01-07
417
### Improvement
518
- Added new thermal model plots

Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ RUN uv venv && . .venv/bin/activate
103103

104104
RUN [[ "${TARGETARCH}" == "aarch64" ]] && uv pip install --verbose ndindex || echo "libatomic1 cant be installed"
105105

106-
107-
# install packadges and build EMHASS
106+
# install packages and build EMHASS
108107
RUN uv pip install --verbose .
109108
RUN uv lock
110109

README.md

Lines changed: 6 additions & 308 deletions
Large diffs are not rendered by default.

conda/meta.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% set name = "emhass" %}
2-
{% set version = "0.15.3" %}
2+
{% set version = "0.15.4" %}
33

44
package:
55
name: {{ name|lower }}

docs/_static/css/custom.css

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/* Hide the auto-generated title so only your centered one shows */
2+
section#energy-management-for-home-assistant > h1 {
3+
display: none;
4+
}
5+
16
/* color theme */
27
.light {
38
color: white;
@@ -217,7 +222,7 @@ dl {
217222
}
218223

219224
.wy-nav-top i {
220-
color: #e1e1e1;
225+
color: #767676;
221226
}
222227

223228
.wy-side-nav-search {
@@ -255,15 +260,14 @@ dl {
255260
}
256261

257262
li.toctree-l2 a {
258-
/* background-color: #3f3f3f; */
259263
color: #e1e1e1 !important;
260264
}
261265

262266
a span:hover,
263267
.btn-neutral:hover,
264268
.btn-neutral:visited:hover {
265269
background-color: #7d7d7d !important;
266-
color: #e1e1e1 !important;
270+
color: #767676 !important;
267271
}
268272

269273
.btn-neutral,
@@ -293,12 +297,11 @@ dl {
293297
color: #ccf3ff !important;
294298
}
295299

296-
a:visited,
300+
a:visited,
297301
.wy-nav-top a,
298302
.wy-nav-top,
299303
.icon:visited,
300-
.fa:visited,
301-
a:visited {
304+
.fa:visited {
302305
color: #d2e8f0;
303306
}
304307

docs/automations.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Home Assistant Automations
2+
3+
To automate EMHASS with Home Assistant, we will need to define some shell commands in the Home Assistant `configuration.yaml` file and some basic automations in the `automations.yaml` file.
4+
In the next few paragraphs, we are going to consider the `dayahead-optim` optimization strategy, which is also the first that was implemented, and we will also cover how to publish the optimization results.
5+
Additional optimization strategies were developed later, that can be used in combination with/replace the `dayahead-optim` strategy, such as MPC, or to expand the functionalities such as the Machine Learning method to predict your household consumption. Each of them has some specificities and features and will be considered in dedicated sections.
6+
7+
## Dayahead Optimization - Method 1) Add-on and docker standalone
8+
9+
We can use the `shell_command` integration in `configuration.yaml`:
10+
```yaml
11+
shell_command:
12+
dayahead_optim: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/dayahead-optim"
13+
publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/publish-data"
14+
```
15+
An alternative that will be useful when passing data at runtime (see dedicated section), we can use the the `rest_command` instead:
16+
```yaml
17+
rest_command:
18+
url: http://127.0.0.1:5000/action/dayahead-optim
19+
method: POST
20+
headers:
21+
content-type: application/json
22+
payload: >-
23+
{}
24+
```
25+
26+
## Dayahead Optimization - Method 2) Legacy method using a Python virtual environment
27+
28+
In `configuration.yaml`:
29+
```yaml
30+
shell_command:
31+
dayahead_optim: ~/emhass/scripts/dayahead_optim.sh
32+
publish_data: ~/emhass/scripts/publish_data.sh
33+
```
34+
Create the file `dayahead_optim.sh` with the following content:
35+
```bash
36+
#!/bin/bash
37+
. ~/emhassenv/bin/activate
38+
emhass --action 'dayahead-optim' --config ~/emhass/config.json
39+
```
40+
And the file `publish_data.sh` with the following content:
41+
```bash
42+
#!/bin/bash
43+
. ~/emhassenv/bin/activate
44+
emhass --action 'publish-data' --config ~/emhass/config.json
45+
```
46+
Then specify user rights and make the files executables:
47+
```bash
48+
sudo chmod -R 755 ~/emhass/scripts/dayahead_optim.sh
49+
sudo chmod -R 755 ~/emhass/scripts/publish_data.sh
50+
sudo chmod +x ~/emhass/scripts/dayahead_optim.sh
51+
sudo chmod +x ~/emhass/scripts/publish_data.sh
52+
```
53+
54+
## Common for any installation method
55+
56+
### Options 1, Home Assistant automate publish
57+
58+
In `automations.yaml`:
59+
```yaml
60+
- alias: EMHASS day-ahead optimization
61+
trigger:
62+
platform: time
63+
at: '05:30:00'
64+
action:
65+
- service: shell_command.dayahead_optim
66+
- alias: EMHASS publish data
67+
trigger:
68+
- minutes: /5
69+
platform: time_pattern
70+
action:
71+
- service: shell_command.publish_data
72+
```
73+
In these automations the day-ahead optimization is performed once a day, every day at 5:30am, and the data *(output of automation)* is published every 5 minutes.
74+
75+
### Option 2, EMHASS automated publish
76+
77+
In `automations.yaml`:
78+
```yaml
79+
- alias: EMHASS day-ahead optimization
80+
trigger:
81+
platform: time
82+
at: '05:30:00'
83+
action:
84+
- service: shell_command.dayahead_optim
85+
- service: shell_command.publish_data
86+
```
87+
in configuration page/`config.json`
88+
```json
89+
"method_ts_round": "first"
90+
"continual_publish": true
91+
```
92+
In this automation, the day-ahead optimization is performed once a day, every day at 5:30am.
93+
If the `optimization_time_step` parameter is set to `30` *(default)* in the configuration, the results of the day-ahead optimization will generate 48 values *(for each entity)*, a value for every 30 minutes in a day *(i.e. 24 hrs x 2)*.
94+
95+
Setting the parameter `continual_publish` to `true` in the configuration page will allow EMHASS to store the optimization results as entities/sensors into separate json files. `continual_publish` will periodically (every `optimization_time_step` amount of minutes) run a publish, and publish the optimization results of each generated entities/sensors to Home Assistant. The current state of the sensor/entity being updated every time publish runs, selecting one of the 48 stored values, by comparing the stored values' timestamps, the current timestamp and [`'method_ts_round': "first"`](https://emhass.readthedocs.io/en/latest/publish_data.html#the-publish-data-specificities) to select the optimal stored value for the current state.
96+
97+
option 1 and 2 are very similar, however, option 2 (`continual_publish`) will require a CPU thread to constantly be run inside of EMHASS, lowering efficiency. The reason why you may pick one over the other is explained in more detail below in [continual_publish](https://emhass.readthedocs.io/en/latest/publish_data.html#continual-publish-emhass-automation).
98+
99+
Lastly, we can link an EMHASS published entity/sensor's current state to a Home Assistant entity on/off switch, controlling a desired controllable load.
100+
For example, imagine that I want to control my water heater. I can use a published `deferrable` EMHASS entity to control my water heater's desired behavior. In this case, we could use an automation like the below, to control the desired water heater on and off:
101+
102+
on:
103+
```yaml
104+
automation:
105+
- alias: Water Heater Optimized ON
106+
trigger:
107+
- minutes: /5
108+
platform: time_pattern
109+
condition:
110+
- condition: numeric_state
111+
entity_id: sensor.p_deferrable0
112+
above: 0.1
113+
action:
114+
- service: homeassistant.turn_on
115+
entity_id: switch.water_heater_switch
116+
```
117+
off:
118+
```yaml
119+
automation:
120+
- alias: Water Heater Optimized OFF
121+
trigger:
122+
- minutes: /5
123+
platform: time_pattern
124+
condition:
125+
- condition: numeric_state
126+
entity_id: sensor.p_deferrable0
127+
below: 0.1
128+
action:
129+
- service: homeassistant.turn_off
130+
entity_id: switch.water_heater_switch
131+
```
132+
These automations will turn on and off the Home Assistant entity `switch.water_heater_switch` using the current state from the EMHASS entity `sensor.p_deferrable0`. `sensor.p_deferrable0` being the entity generated from the EMHASS day-ahead optimization and published by examples above. The `sensor.p_deferrable0` entity's current state is updated every 30 minutes (or `optimization_time_step` minutes) via an automated publish option 1 or 2. *(selecting one of the 48 stored data values)*

docs/conf.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,26 @@
1919
# -- Project information -----------------------------------------------------
2020

2121
project = "emhass"
22-
copyright = "2021-2025, David HERNANDEZ"
23-
author = "David HERNANDEZ"
22+
copyright = "2021-2026, David HERNANDEZ TORRES"
23+
author = "David HERNANDEZ TORRES"
2424

2525
# The full version, including alpha/beta/rc tags
26-
release = "0.15.3"
26+
release = "0.15.4"
2727

2828
# -- General configuration ---------------------------------------------------
2929

30+
# Enable linking to specific headers (anchors)
31+
myst_heading_anchors = 3
32+
3033
# Add any Sphinx extension module names here, as strings. They can be
3134
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
3235
# ones.
33-
extensions = ["sphinx.ext.autodoc", "myst_parser"]
36+
extensions = ["sphinx.ext.autodoc", "myst_parser", "sphinx_design"]
3437

3538
myst_enable_extensions = [
3639
"amsmath",
3740
"dollarmath",
41+
"colon_fence",
3842
]
3943

4044
# Add any paths that contain templates here, relative to this directory.
@@ -51,12 +55,30 @@
5155
# The theme to use for HTML and HTML Help pages. See the documentation for
5256
# a list of builtin themes.
5357
#
54-
html_theme = "sphinx_rtd_theme"
58+
html_theme = "pydata_sphinx_theme"
59+
60+
html_theme_options = {
61+
"show_toc_level": 2,
62+
"header_links_before_dropdown": 6,
63+
"navbar_align": "left",
64+
# Add your GitHub repo link if you have one
65+
"icon_links": [
66+
{
67+
"name": "GitHub",
68+
"url": "https://github.com/davidusb-geek/emhass",
69+
"icon": "fa-brands fa-github",
70+
},
71+
],
72+
"logo": {
73+
"image_light": "images/emhass_logo.png",
74+
"image_dark": "images/emhass_logo.png",
75+
},
76+
}
5577

5678
# Add any paths that contain custom static files (such as style sheets) here,
5779
# relative to this directory. They are copied after the builtin static files,
5880
# so a file named "default.css" will overwrite the builtin "default.css".
59-
html_static_path = ["_static"]
81+
# html_static_path = ["_static"]
6082
## EMHASS custom theme
6183
html_css_files = [
6284
"css/custom.css",

0 commit comments

Comments
 (0)