From 2680513b7ee9fcfd8d651db2982e0d10cbcbe2c9 Mon Sep 17 00:00:00 2001 From: Tavis Date: Fri, 10 Jul 2026 08:37:55 -0700 Subject: [PATCH 1/4] Fix hassgraph crash on empty or non-numeric HA states. Skip invalid history states before float conversion so raw data plotting and stats no longer fail when Home Assistant returns empty strings. Co-authored-by: Cursor --- apps/hassgraph/hass_graph.star | 41 +++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/apps/hassgraph/hass_graph.star b/apps/hassgraph/hass_graph.star index 0dadc5ac2..531cd6139 100644 --- a/apps/hassgraph/hass_graph.star +++ b/apps/hassgraph/hass_graph.star @@ -57,6 +57,24 @@ MAX_TIME_PERIOD = 24 TIME_FORMAT = "2006-01-02T15:04:05Z" +def parse_state_value(state): + if state in ("unavailable", "unknown", "none", ""): + return None + s = state.strip() + if not s: + return None + if s.startswith("-"): + s = s[1:] + if not s: + return None + parts = s.split(".") + if len(parts) not in [1, 2]: + return None + for part in parts: + if not part.isdigit(): + return None + return float(state) + def main(config): timezone = None location = config.get("location") @@ -91,9 +109,9 @@ def main(config): if len(parts) == 2: min_val = float(parts[0]) max_val = float(parts[1]) - if current_value == "unavailable" or current_value == "unknown": + val = parse_state_value(current_value) + if val == None: return [] - val = float(current_value) if val < min_val or val > max_val: return [] stats = calc_stats(timezone, data) @@ -105,9 +123,10 @@ def calculate_hourly_average(config, data): if config.bool("use_raw_data"): points = [] for i, entry in enumerate(data): - if entry["state"] == "unavailable" or entry["state"] == "unknown": + value = parse_state_value(entry["state"]) + if value == None: continue - points.append((i, float(entry["state"]))) + points.append((i, value)) return points hourly_averages = {} @@ -117,12 +136,12 @@ def calculate_hourly_average(config, data): index = 0 for entry in data: - if entry["state"] == "unavailable" or entry["state"] == "unknown": + value = parse_state_value(entry["state"]) + if value == None: continue timestamp = entry["last_changed"] hour = int(timestamp.split("T")[1].split(":")[0]) - value = float(entry["state"]) if hour != current_hour: if current_hour != None: @@ -152,10 +171,9 @@ def calc_stats(timezone, data): count = 0 for entry in data: - if entry["state"] == "unavailable" or entry["state"] == "unknown": + value = parse_state_value(entry["state"]) + if value == None: continue - - value = float(entry["state"]) total_value += value count += 1 if value < lowest_value: @@ -252,7 +270,10 @@ def render_graph_column(config, current_value, points, unit, label): )) if (config.str("round_to") in ["0", "1", "2"]): decimal = int(config.get("round_to")) - val = round(float(current_value), decimal) + val = parse_state_value(current_value) + if val == None: + val = 0 + val = round(val, decimal) current_value = str(int(val)) if val == int(val) else str(val) children.append(render.Text(content = current_value + unit, font = "6x13")) align = "space_between" if label else "end" From 097bcae012e00e565dfdadf7d4ecd31ff3892d5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 10 Jul 2026 15:39:20 +0000 Subject: [PATCH 2/4] chore: auto-update manifest metadata [skip ci] --- apps/hassgraph/manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hassgraph/manifest.yaml b/apps/hassgraph/manifest.yaml index ddd3065c3..d6c790ce6 100644 --- a/apps/hassgraph/manifest.yaml +++ b/apps/hassgraph/manifest.yaml @@ -13,4 +13,4 @@ tags: - sports - utility published: '2024-06-19T15:18:22Z' -updated: '2026-07-06T22:24:02Z' +updated: '2026-07-10T15:37:55Z' From 266d1432ff3afd26b8c9cf0c58b4dd7b7f862820 Mon Sep 17 00:00:00 2001 From: Tavis Date: Fri, 10 Jul 2026 08:44:48 -0700 Subject: [PATCH 3/4] Update apps/hassgraph/hass_graph.star Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- apps/hassgraph/hass_graph.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hassgraph/hass_graph.star b/apps/hassgraph/hass_graph.star index 531cd6139..1ca2aa5fe 100644 --- a/apps/hassgraph/hass_graph.star +++ b/apps/hassgraph/hass_graph.star @@ -58,7 +58,7 @@ MAX_TIME_PERIOD = 24 TIME_FORMAT = "2006-01-02T15:04:05Z" def parse_state_value(state): - if state in ("unavailable", "unknown", "none", ""): + if state == None or state in ("unavailable", "unknown", "none", ""): return None s = state.strip() if not s: From cd585799f717a735864f2b445080436069ebb0bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 10 Jul 2026 15:45:06 +0000 Subject: [PATCH 4/4] chore: auto-update manifest metadata [skip ci] --- apps/hassgraph/manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hassgraph/manifest.yaml b/apps/hassgraph/manifest.yaml index d6c790ce6..59ee39a5f 100644 --- a/apps/hassgraph/manifest.yaml +++ b/apps/hassgraph/manifest.yaml @@ -13,4 +13,4 @@ tags: - sports - utility published: '2024-06-19T15:18:22Z' -updated: '2026-07-10T15:37:55Z' +updated: '2026-07-10T15:44:48Z'