mirror of
https://github.com/Legolas-2025/EPrices.git
synced 2026-08-18 12:44:51 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c954569125 | ||
|
|
fc48dd12ff | ||
|
|
e9c66c7d41 | ||
|
|
ea22c138d6 |
@@ -1,5 +1,54 @@
|
||||
# EPrices – Changelog
|
||||
|
||||
## v1.2.3 — 2026-08-04
|
||||
|
||||
### Uptime sensor bucket display and logbook change-detection
|
||||
|
||||
The `Uptime` text sensor previously published a high-precision human-readable
|
||||
uptime string (e.g. `3 h 22 min`, `12 d 4 h 17 min`) on every internal
|
||||
`uptime` sensor update, which runs every 60 seconds. In the Home Assistant
|
||||
activity log, this produced one state change per minute during the first day
|
||||
after a reboot — a noisy stream redundant with the existing `Last Reboot`
|
||||
text sensor.
|
||||
|
||||
The uptime lambda now formats the value into coarse hourly / daily / monthly
|
||||
buckets and only calls `publish_state` when the bucket string actually
|
||||
changes. Result: **one logbook entry per hour** for the first day, **one per
|
||||
day** through the first month, **one per month** through the first year, and
|
||||
**one per month** after that.
|
||||
|
||||
**New display buckets:**
|
||||
|
||||
| Boot age | State | Window |
|
||||
|---|---|---|
|
||||
| 0 – 59 min | `< 1 hour` | 1 h |
|
||||
| 1 – 23 h | `> N hour(s)` | 1 h |
|
||||
| 1 – 30 d | `> N day(s)` | 1 d |
|
||||
| 1 – 11 mo | `> N month(s)` | 30 d |
|
||||
| 12+ mo | `> N year(s)` or `> N year(s) N month(s)` | 30 d |
|
||||
|
||||
Singular/plural is handled in C++ (`1 hour` vs `2 hours`, `1 day` vs
|
||||
`2 days`, etc.). Conventions: 1 month = 30 days, 1 year = 12 months —
|
||||
consistent with the existing `d / 30` month convention used elsewhere in
|
||||
the file.
|
||||
|
||||
**New global:**
|
||||
- `last_published_uptime` (type: `std::string`, `restore_value: false`,
|
||||
`initial_value: '""'`) — tracks the most recently published bucket value.
|
||||
The uptime lambda compares against it and only calls `publish_state` when
|
||||
the bucket string differs.
|
||||
|
||||
The `update_interval: 60s` on the internal `uptime` sensor is kept as-is so
|
||||
the lambda still runs every minute and reliably catches hour-boundary
|
||||
transitions even under transient load.
|
||||
|
||||
**Changed locations in `eprices.yaml`:**
|
||||
- `globals:` — added `last_published_uptime`
|
||||
- Internal `uptime` sensor `on_raw_value` lambda — replaced minute-precision
|
||||
format with bucket display + change-detection guard
|
||||
|
||||
---
|
||||
|
||||
## v1.2.2 — 2026-04-28
|
||||
|
||||
### ESP32 task watchdog timeout increase
|
||||
|
||||
@@ -32,7 +32,8 @@ Assistant automations are required for any core functionality.
|
||||
- **Tomorrow live sensors** evaluate at `now + 86400s` — reflecting tomorrow at the same local time
|
||||
- Supports **any Energy-Charts bidding zone** (SI, DE-LU, AT, FR, HR, HU and more)
|
||||
- Full **diagnostic sensor suite** — NVS status, fetch attempts, API fetch times,
|
||||
data loaded times, WiFi signal, human-readable uptime
|
||||
data loaded times, WiFi signal, human-readable bucketed uptime (one HA logbook
|
||||
entry per hour / day / month — no per-minute churn)
|
||||
- All fee and VAT settings configurable via `secrets.yaml` — **no code changes needed**
|
||||
|
||||
---
|
||||
@@ -265,7 +266,7 @@ safe on DST transition days (23-hour and 25-hour days).
|
||||
| Sensor | Entity ID | Description |
|
||||
|---|---|---|
|
||||
| Last Reboot | `sensor.eprices_last_reboot` | Timestamp of last device boot |
|
||||
| Uptime | `sensor.eprices_uptime` | Human-readable: `45 s` / `5 min` / `3 h 22 min` / `12 d 4 h` / `4 months 12 d` |
|
||||
| Uptime | `sensor.eprices_uptime` | Human-readable bucketed: `< 1 hour` / `> N hours` / `> N days` / `> N months` / `> N year(s) N month(s)` — one logbook entry per hour, day, or month |
|
||||
| WiFi Signal | `sensor.eprices_wifi_signal` | RSSI in dBm, updated every 60s |
|
||||
| Last Update Source | `sensor.eprices_last_update_source` | `NVS_boot` / `HTTP_today` / `midnight_bridge` / `NVS_api` etc. |
|
||||
| Today Data Date | `sensor.eprices_today_data_date` | Date of currently stored today data |
|
||||
|
||||
+35
@@ -1,5 +1,40 @@
|
||||
# EPrices – Version History
|
||||
|
||||
## v1.2.3 — 2026-08-04
|
||||
|
||||
Quietness patch for the Home Assistant activity log. No new sensors, no
|
||||
secrets changes, no entity ID changes. Drop-in replacement for v1.2.2.
|
||||
|
||||
### Uptime display bucketed and change-detected
|
||||
|
||||
The `Uptime` text sensor previously published a new value every minute
|
||||
(e.g. `3 h 22 min`, `12 d 4 h 17 min`) because the underlying internal
|
||||
`uptime` sensor updates every 60 seconds and the lambda always called
|
||||
`publish_state`. In the HA activity log this produced a noisy stream of
|
||||
state changes redundant with the existing `Last Reboot` text sensor.
|
||||
|
||||
The lambda now formats uptime into coarse buckets and only publishes when
|
||||
the bucket string changes — **one logbook entry per hour** for the first
|
||||
day, then **one per day**, then **one per month**.
|
||||
|
||||
**Buckets:**
|
||||
|
||||
| Age | Display |
|
||||
|---|---|
|
||||
| 0 – 59 min | `< 1 hour` |
|
||||
| 1 – 23 h | `> 1 hour` ... `> 23 hours` |
|
||||
| 1 – 30 d | `> 1 day` ... `> 30 days` |
|
||||
| 1 – 11 mo | `> 1 month` ... `> 11 months` |
|
||||
| 12+ mo | `> 1 year` ... `> N year(s) N month(s)` |
|
||||
|
||||
**New global:** `last_published_uptime` (`std::string`) — tracks the last
|
||||
published bucket so the lambda can skip publishing when the value hasn't
|
||||
crossed a boundary.
|
||||
|
||||
See `CHANGELOG.md` for full implementation details.
|
||||
|
||||
---
|
||||
|
||||
## v1.2.2 — 2026-04-28
|
||||
|
||||
Stability patch addressing spontaneous reboots during tomorrow price fetch at ~13:55.
|
||||
|
||||
+54
-19
@@ -1,9 +1,23 @@
|
||||
# =============================================================================
|
||||
# ESPHome: EPrices v1.2.2
|
||||
# ESPHome: EPrices v1.2.3
|
||||
#
|
||||
# Electricity price data provided by Energy-Charts (https://energy-charts.info)
|
||||
# under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/).
|
||||
#
|
||||
# v1.2.3 uptime log noise reduction (2026-08-04):
|
||||
# - Uptime text sensor now uses coarse bucketed display instead of minute
|
||||
# precision: "< 1 hour" / "> N hour(s)" / "> N day(s)" / "> N month(s)" /
|
||||
# "> N year(s)" / "> N year(s) N month(s)"
|
||||
# Buckets update once per hour (first day), once per day (first month),
|
||||
# once per month (first year) — eliminates per-minute state churn in
|
||||
# the HA activity log
|
||||
# - Added global last_published_uptime (std::string) to track the last
|
||||
# published bucket value; the uptime lambda only calls publish_state
|
||||
# when the bucket string actually changes
|
||||
# - Singular/plural handled in C++ (1 hour vs 2 hours, 1 day vs 2 days, etc.)
|
||||
# - Conventions: 1 month = 30 days, 1 year = 12 months — consistent with
|
||||
# the existing d / 30 month convention used elsewhere in the file
|
||||
#
|
||||
# v1.2.2 stability fixes (2026-04-28):
|
||||
# - Added CONFIG_ESP_TASK_WDT_TIMEOUT_S = 40 to give the watchdog extra headroom
|
||||
# during heavy JSON parsing when full price data arrives (~13:55+)
|
||||
@@ -509,6 +523,10 @@ globals:
|
||||
- id: boot_time
|
||||
type: time_t
|
||||
initial_value: '0'
|
||||
- id: last_published_uptime
|
||||
type: std::string
|
||||
restore_value: false
|
||||
initial_value: '""'
|
||||
- id: last_successful_update
|
||||
type: time_t
|
||||
initial_value: '0'
|
||||
@@ -864,27 +882,44 @@ sensor:
|
||||
then:
|
||||
- lambda: |-
|
||||
uint32_t s = (uint32_t)x;
|
||||
char buf[32];
|
||||
if (s < 120) {
|
||||
snprintf(buf, sizeof(buf), "%u s", s);
|
||||
} else if (s < 48 * 3600) {
|
||||
char buf[48];
|
||||
|
||||
if (s < 3600) {
|
||||
// < 1 hour: one state, no logbook churn
|
||||
snprintf(buf, sizeof(buf), "< 1 hour");
|
||||
} else if (s < 86400UL) {
|
||||
// 1..23 hours — bucket by full hour
|
||||
uint32_t h = s / 3600;
|
||||
uint32_t m = (s % 3600) / 60;
|
||||
if (h < 2)
|
||||
snprintf(buf, sizeof(buf), "%u min", s / 60);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%u h %u min", h, m);
|
||||
} else if (s < 90UL * 86400UL) {
|
||||
uint32_t d = s / 86400;
|
||||
uint32_t h = (s % 86400) / 3600;
|
||||
snprintf(buf, sizeof(buf), "%u d %u h", d, h);
|
||||
snprintf(buf, sizeof(buf), "> %lu hour%s", h, h == 1 ? "" : "s");
|
||||
} else if (s < 31UL * 86400UL) {
|
||||
// 1..30 days — bucket by full day
|
||||
uint32_t d = s / 86400UL;
|
||||
snprintf(buf, sizeof(buf), "> %lu day%s", d, d == 1 ? "" : "s");
|
||||
} else if (s < 12UL * 30UL * 86400UL) {
|
||||
// 1..11 months — bucket by full month (1 month = 30 days)
|
||||
uint32_t mo = s / (30UL * 86400UL);
|
||||
snprintf(buf, sizeof(buf), "> %lu month%s", mo, mo == 1 ? "" : "s");
|
||||
} else {
|
||||
uint32_t d = s / 86400;
|
||||
uint32_t mo = d / 30;
|
||||
uint32_t rem = d % 30;
|
||||
snprintf(buf, sizeof(buf), "%u months %u d", mo, rem);
|
||||
// 1 year and up — year + optional months (1 year = 12 months)
|
||||
uint32_t mo_total = s / (30UL * 86400UL);
|
||||
uint32_t y = mo_total / 12;
|
||||
uint32_t mo = mo_total % 12;
|
||||
if (mo == 0) {
|
||||
snprintf(buf, sizeof(buf), "> %lu year%s", y, y == 1 ? "" : "s");
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "> %lu year%s %lu month%s",
|
||||
y, y == 1 ? "" : "s",
|
||||
mo, mo == 1 ? "" : "s");
|
||||
}
|
||||
}
|
||||
|
||||
// Only publish on actual bucket change — prevents
|
||||
// per-minute state churn in HA's activity log
|
||||
std::string new_state(buf);
|
||||
if (new_state != id(last_published_uptime)) {
|
||||
id(last_published_uptime) = new_state;
|
||||
id(uptime_text).publish_state(new_state);
|
||||
}
|
||||
id(uptime_text).publish_state(buf);
|
||||
|
||||
# =============================================================================
|
||||
# TEXT SENSORS – TODAY
|
||||
|
||||
Reference in New Issue
Block a user