Skip to content

Commit 44097b5

Browse files
Merge pull request #695 from davidusb-geek/davidusb-geek/fix/hot_fix_influxdb_credentials
Hot fix for InfluxDB not passed credentials
2 parents 937800b + 91b1c45 commit 44097b5

File tree

7 files changed

+52
-12
lines changed

7 files changed

+52
-12
lines changed

CHANGELOG.md

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

3+
## 0.16.1 - 2026-01-23
4+
### Fix
5+
- Hot fix for InfluxDB not passed credentials
6+
- Fixed optimization window size mismatch issue
7+
- Fixed optim_status key not found error when falling back to LP problem
8+
39
## 0.16.0 - 2026-01-21
410

511
### 🚀 Major Optimization Engine Overhaul

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.16.0" %}
2+
{% set version = "0.16.1" %}
33

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

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
author = "David HERNANDEZ TORRES"
2424

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

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

docs/publish_data.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,24 @@ By default, running an optimization in EMHASS will output the results into the C
4949
```bash
5050
# RUN dayahead
5151
curl -i -H 'Content-Type:application/json' -X POST -d {} http://localhost:5000/action/dayahead-optim
52-
# Then publish teh results of dayahead
52+
# Then publish the results of dayahead
5353
curl -i -H 'Content-Type:application/json' -X POST -d {} http://localhost:5000/action/publish-data
5454
```
5555
*Note, the published entities from the publish-data action will not automatically update the entities' current state (current state being used to check when to turn on and off appliances via Home Assistant automations). To update the EMHASS entities state, another publish would have to be re-run later when the current time matches the next value's timestamp (e.g. every 30 minutes). See examples below for methods to automate the publish-action.*
5656

57+
```{note}
58+
59+
If your are using the thermal model, then for this manual publish implementation you need to indicate which of your deferrable loads are thermal.
60+
We do this with the `"def_load_config"` entry.
61+
62+
If you have just one deferrable load which is a thermal load then the payload of `curl` publish command should look like:
63+
`{"def_load_config": [{"thermal_config": {}}]}`
64+
65+
Similarly if you have three deferrable loads where the second load is a thermal load the payload would have been:
66+
`{"def_load_config": [{},{"thermal_config": {}},{}]}`
67+
68+
```
69+
5770
### Continual_publish *(EMHASS Automation)*
5871
Setting `continual_publish` to `true` in the configuration saves the output of the optimization into the `data_path/entities` folder *(a .json file for each sensor/entity)*. A constant loop (in `optimization_time_step` minutes) will run, observe the .json files in that folder, and publish the saved files periodically (updating the current state of the entity by comparing date.now with the saved data value timestamps).
5972

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "emhass"
3-
version = "0.16.0"
3+
version = "0.16.1"
44
description = "An Energy Management System for Home Assistant"
55
readme = "README.md"
66
requires-python = ">=3.10, <3.13"

src/emhass/optimization.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ def __init__(
7575
self.freq = self.retrieve_hass_conf["optimization_time_step"]
7676
self.time_zone = self.retrieve_hass_conf["time_zone"]
7777
self.time_step = self.freq.seconds / 3600 # in hours
78-
self.time_delta = pd.to_timedelta(opt_time_delta, "hours") # The period of optimization
7978
self.var_pv = self.retrieve_hass_conf["sensor_power_photovoltaics"]
8079
self.var_load = self.retrieve_hass_conf["sensor_power_load_no_var_loads"]
8180
self.var_load_new = self.var_load + "_positive"
@@ -86,6 +85,19 @@ def __init__(
8685
self.var_prod_price = var_prod_price
8786
self.optim_status = None
8887

88+
# Prioritize config value over default arg
89+
if "delta_forecast_daily" in self.optim_conf:
90+
# If configured in days (int/float), convert to timedelta
91+
val = self.optim_conf["delta_forecast_daily"]
92+
if isinstance(val, int) or isinstance(val, float):
93+
self.time_delta = pd.to_timedelta(val, "days")
94+
else:
95+
# Assume it is already a timedelta or compatible
96+
self.time_delta = pd.to_timedelta(val)
97+
else:
98+
# Fallback to the argument (default 24h)
99+
self.time_delta = pd.to_timedelta(opt_time_delta, "hours")
100+
89101
# Configuration for Solver
90102
if "num_threads" in optim_conf.keys():
91103
if optim_conf["num_threads"] == 0:
@@ -1715,18 +1727,21 @@ def pad_list(input_list, target_len, fill=0):
17151727
self.optim_status = status_raw.title() if status_raw else "Failure"
17161728

17171729
# Helper: Ensure we return "Optimal" for tests if it was "Optimal (Relaxed)" or "Optimal_Inaccurate"
1718-
if "Optimal" in self.optim_status:
1719-
pass # Keep it as is (e.g. "Optimal (Relaxed)")
1720-
1721-
self.logger.info("Status: " + self.optim_status)
1722-
17231730
if self.prob.value is None or self.prob.status not in [
17241731
cp.OPTIMAL,
17251732
cp.OPTIMAL_INACCURATE,
17261733
"Optimal (Relaxed)",
17271734
]:
17281735
self.logger.warning("Cost function cannot be evaluated or Infeasible/Unbounded")
1729-
return pd.DataFrame()
1736+
1737+
# Create a DataFrame with the correct index (timestamps)
1738+
opt_tp = pd.DataFrame(index=data_opt.index)
1739+
1740+
# explicitely set the status column so downstream functions (like get_injection_dict)
1741+
# don't crash when trying to access or drop it.
1742+
opt_tp["optim_status"] = self.optim_status
1743+
1744+
return opt_tp
17301745
else:
17311746
self.logger.info(
17321747
"Total value of the Cost function = %.02f",
@@ -1785,7 +1800,7 @@ def perform_perfect_forecast_optim(
17851800
day_end = day + self.time_delta - self.freq
17861801
if day_start.tzinfo != day_end.tzinfo:
17871802
self.logger.warning(
1788-
f"Skipping day {day} as days have ddifferent timezone, probably because of DST."
1803+
f"Skipping day {day} as days have different timezone, probably because of DST."
17891804
)
17901805
continue # Skip this day and move to the next iteration
17911806
else:

src/emhass/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,12 @@ async def build_params(
21042104
params["retrieve_hass_conf"]["Latitude"] = params_secrets.get("Latitude")
21052105
params["retrieve_hass_conf"]["Longitude"] = params_secrets.get("Longitude")
21062106
params["retrieve_hass_conf"]["Altitude"] = params_secrets.get("Altitude")
2107+
if params_secrets.get("influxdb_username") is not None:
2108+
params["retrieve_hass_conf"]["influxdb_username"] = params_secrets.get("influxdb_username")
2109+
params["params_secrets"]["influxdb_username"] = params_secrets.get("influxdb_username")
2110+
if params_secrets.get("influxdb_password") is not None:
2111+
params["retrieve_hass_conf"]["influxdb_password"] = params_secrets.get("influxdb_password")
2112+
params["params_secrets"]["influxdb_password"] = params_secrets.get("influxdb_password")
21072113
# Update optional param secrets
21082114
if params["optim_conf"].get("weather_forecast_method", None) is not None:
21092115
if params["optim_conf"]["weather_forecast_method"] == "solcast":

0 commit comments

Comments
 (0)