Skip to content

Commit 95d6c03

Browse files
author
Antonio ...
committed
fix: Add throttled logging for sensor errors to prevent log spam (v1.3.16)
Fixed excessive logging when sensors become unavailable, which was causing Home Assistant to log warnings about too frequent logging (200+ messages). Problem: - When sensor.potenza_interna_abitazione returns 'unknown', Solar Surplus validation logs full error every minute - Check runs every 1 minute by default - Results in 200+ identical error messages - Home Assistant detects log spam: "Module logging too frequently" Solution: - Implemented smart sensor error state tracking (_sensor_error_state dictionary) - Only log full error details when error FIRST occurs or changes - Subsequent identical errors: silent (debug level only) - When sensor recovers: log success message with previous error - Per-sensor tracking (independent error states) Behavior: Before (v1.3.15): - 12:35:07 - ❌ Sensor validation failed: Home Consumption unknown - 12:36:07 - ❌ Sensor validation failed: Home Consumption unknown - 12:37:07 - ❌ Sensor validation failed: Home Consumption unknown - ... (200+ identical messages) After (v1.3.16): - 12:35:07 - ❌ Sensor validation failed: Home Consumption unknown [LOGGED ONCE] - 12:36:07 - [silent - debug only] - 12:37:07 - [silent - debug only] - 12:38:07 - ✅ Home Consumption sensor recovered (was: unknown) [LOGGED] Technical Changes: - Added _sensor_error_state dict to SolarSurplusAutomation __init__ - Modified sensor validation loop in _async_periodic_check() - Track error state per sensor entity_id - Detect state changes (new error, changed error, recovered) - Log only on state transitions Impact: - Clean logs, no spam warnings - Easier troubleshooting (see when errors start/stop) - No performance impact - Same diagnostic sensor updates Files Modified: - solar_surplus.py: Added error tracking, modified validation logic - const.py: VERSION = 1.3.16 - manifest.json: version = 1.3.16 - CLAUDE.md: v1.3.16 release notes 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent 507986a commit 95d6c03

4 files changed

Lines changed: 46 additions & 6 deletions

File tree

CLAUDE.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,25 @@ async def _set_amperage(self, target_amperage: int):
753753

754754
## Version History
755755

756+
### v1.3.16 (2025-11-05)
757+
**Throttled Logging for Sensor Errors**
758+
- **Problem Fixed**: When sensors become unavailable (e.g., `unknown` state), Solar Surplus logged errors every minute, causing log spam (200+ messages)
759+
- **Solution**: Implemented smart error state tracking that only logs when errors change
760+
- **New Behavior**:
761+
- First error occurrence: Full error logged with details
762+
- Subsequent occurrences: Silent (only debug level logging)
763+
- Sensor recovery: Success message logged when sensor becomes available again
764+
- **Example**:
765+
```
766+
12:35:07 - ❌ Sensor Home Consumption (sensor.xyz) state is 'unknown' [LOGGED ONCE]
767+
12:36:07 - [silent - error persists]
768+
12:37:07 - [silent - error persists]
769+
12:38:07 - ✅ Home Consumption sensor recovered (was: state is 'unknown') [LOGGED]
770+
```
771+
- **Technical**: Added `_sensor_error_state` dictionary to track per-sensor error states
772+
- **User Impact**: Cleaner logs, no more Home Assistant warnings about excessive logging
773+
- **Upgrade priority**: 🟡 RECOMMENDED - Eliminates log spam when sensors temporarily offline
774+
756775
### v1.3.15 (2025-11-05)
757776
**Unified 60s Stability Delay for All Surplus Operations**
758777
- **Change**: Initial charger start (OFF → ON) now uses same 60s delay as amperage increases

custom_components/ev_smart_charger/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# ========== INTEGRATION METADATA ==========
44
DOMAIN = "ev_smart_charger"
5-
VERSION = "1.3.15"
5+
VERSION = "1.3.16"
66
DEFAULT_NAME = "EV Smart Charger"
77

88
# ========== PLATFORMS ==========

custom_components/ev_smart_charger/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"domain": "ev_smart_charger",
33
"name": "EV Smart Charger",
4-
"version": "1.3.15",
4+
"version": "1.3.16",
55
"documentation": "https://github.com/antbald/ha-ev-smart-charger",
66
"issue_tracker": "https://github.com/antbald/ha-ev-smart-charger/issues",
77
"codeowners": ["@antbald"],

custom_components/ev_smart_charger/solar_surplus.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def __init__(
105105
self._check_count = 0
106106
self._check_count_reset_time = None
107107

108+
# Sensor error tracking (prevent log spam)
109+
self._sensor_error_state = {} # {sensor_entity_id: error_message}
110+
108111
def _find_entity_by_suffix(self, suffix: str) -> str | None:
109112
"""Find an entity by its suffix using EntityRegistryService."""
110113
entity_id = self._registry_service.find_by_suffix_filtered(suffix)
@@ -344,23 +347,41 @@ async def _async_periodic_check(self, now=None) -> None:
344347

345348
self.logger.info(f"Charger status: '{charger_status}' - proceeding")
346349

347-
# === 7. Validate Sensors ===
350+
# === 7. Validate Sensors (with throttled logging to prevent spam) ===
348351
sensor_errors = []
349352
sensors_to_validate = [
350353
(self._fv_production, "Solar Production"),
351354
(self._home_consumption, "Home Consumption"),
352355
(self._grid_import, "Grid Import"),
353356
]
354357

358+
# Check each sensor and track error state changes
359+
new_errors = False
355360
for entity_id, sensor_name in sensors_to_validate:
356361
is_valid, error_msg = validate_sensor(self.hass, entity_id, sensor_name)
362+
357363
if not is_valid:
358364
sensor_errors.append(error_msg)
365+
# Only log if this is a NEW error or error message changed
366+
if entity_id not in self._sensor_error_state or self._sensor_error_state[entity_id] != error_msg:
367+
self._sensor_error_state[entity_id] = error_msg
368+
new_errors = True
369+
else:
370+
# Sensor is now valid - check if it was previously in error state
371+
if entity_id in self._sensor_error_state:
372+
self.logger.info(f"✅ {sensor_name} sensor recovered (was: {self._sensor_error_state[entity_id]})")
373+
del self._sensor_error_state[entity_id]
359374

360375
if sensor_errors:
361-
self.logger.error("Sensor validation failed:")
362-
for error in sensor_errors:
363-
self.logger.error(f" - {error}")
376+
# Only log full error details if there are NEW errors
377+
if new_errors:
378+
self.logger.error("Sensor validation failed:")
379+
for error in sensor_errors:
380+
self.logger.error(f" - {error}")
381+
else:
382+
# Existing errors - just update diagnostic sensor quietly
383+
self.logger.debug(f"Sensor errors still present ({len(sensor_errors)} sensors unavailable)")
384+
364385
await self._update_diagnostic_sensor(
365386
"ERROR: Invalid sensor values",
366387
{"errors": sensor_errors, "last_check": datetime.now().isoformat()}

0 commit comments

Comments
 (0)