Files
battery-charging-optimizer/diagnostic_pyscript_issues.md
felix.zoesch 0fa03a566a feat: Major update - Battery Optimizer v3.4.0 with comprehensive fixes
## 🎯 Hauptänderungen

### Version 3.4.0 - SOC-Drift & Charging Capacity
-  Sicherheitspuffer (20-50% konfigurierbar) für untertägige SOC-Schwankungen
-  Monatliche automatische Batterie-Kalibrierung
- 🐛 SOC-Plausibilitäts-Check (filtert 65535% Spikes beim Modus-Wechsel)
- 🐛 Zeitabhängige API-Abfrage (vor/nach 14:00 Uhr)

### Neue Features
- 🔋 **Safety Buffer**: Kompensiert SOC-Drift und Eigenverbrauch
- 🔋 **Auto-Calibration**: Monatlicher Vollzyklus für SOC-Genauigkeit
- 🔋 **Spike Protection**: 4-fach Schutz gegen ungültige SOC-Werte
- 🔋 **Smart API**: Verhindert HTTP 500 Errors bei fehlenden Tomorrow-Preisen

### Dokumentation
- 📚 SOC_CALIBRATION_GUIDE.md - Umfassender Kalibrierungs-Guide
- 📚 FIX_CHARGING_CAPACITY.md - Sicherheitspuffer-Dokumentation
- 📚 FIX_SOC_SPIKE_PROBLEM.md - Spike-Protection-Lösung
- 📚 FIX_API_TIMING.md - Zeitabhängige API-Abfrage
- 📚 DIAGNOSE_LADE_PROBLEM.md - Debug-Guide

### Neue Dateien
- battery_calibration_automation.yaml - 4 Automations für Kalibrierung
- battery_calibration_input_helper.yaml - Input Helper Config
- battery_optimizer_input_helper_safety_buffer.yaml - Puffer Config
- debug_schedule.py - Umfassendes Debug-Script

### Scripts
- battery_charging_optimizer.py v3.4.0
- hastrom_flex_extended.py v1.1.0
- debug_schedule.py v1.0.0

### Fixes
- 🐛 SOC springt auf 65535% beim ESS-Modus-Wechsel → Debounce + Plausibilitäts-Check
- 🐛 API-HTTP-500 vor 14:00 → Zeitabhängige Abfrage
- 🐛 Batterie nicht bis 100% geladen → Sicherheitspuffer
- 🐛 SOC driftet ohne Vollzyklen → Automatische Kalibrierung

## 🚀 Installation

1. Input Helper erstellen (siehe battery_optimizer_input_helper_safety_buffer.yaml)
2. Automations installieren (siehe battery_calibration_automation.yaml)
3. Scripts aktualisieren (battery_charging_optimizer.py v3.4.0)
4. PyScript neu laden

## 📊 Verbesserungen

- Präzisere Ladeplanung durch Sicherheitspuffer
- Robustheit gegen SOC-Drift
- Keine API-Fehler mehr vor 14:00
- Hardware-Stopp bei 100% wird respektiert
- Bessere Batterie-Gesundheit durch regelmäßige Kalibrierung

🤖 Generated with Claude Code (claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 08:04:07 +01:00

11 KiB

PyScript Battery Optimizer - Diagnostic Report

Date: 2025-11-20 Files Analyzed:

  • /config/pyscript/battery_charging_optimizer.py (v3.2.0)
  • /config/pyscript/hastrom_flex_extended.py (v2.0)

Syntax Check Results

Both files have valid Python syntax - No compilation errors detected

Potential Runtime Issues Found

1. CRITICAL: Missing Import in hastrom_flex_extended.py

Issue: The script uses task.executor() but doesn't import the PyScript-specific modules that provide this functionality.

Location: Line 37 in hastrom_flex_extended.py

response = task.executor(requests.get, url)

Problem: In PyScript, task is a built-in PyScript object, but if the PyScript integration isn't loading properly or if there's an initialization issue, this will fail with NameError: name 'task' is not defined.

Expected Error:

NameError: name 'task' is not defined

Solution: This should work in PyScript environment, but verify PyScript is properly loaded.


2. Timezone Import Compatibility

Issue: Both files use from zoneinfo import ZoneInfo

Location:

  • Line 11 in battery_charging_optimizer.py
  • Line 4 in hastrom_flex_extended.py

Problem: zoneinfo is part of Python 3.9+ standard library. Home Assistant should have this, but PyScript might have restrictions.

Expected Error (if zoneinfo not available):

ModuleNotFoundError: No module named 'zoneinfo'

Alternative: Use PyScript's built-in timezone handling or pytz library if available.


3. State Access Pattern Issues

Issue: Direct state access using dot notation and dictionary methods mixed

Locations:

  • Line 33: state.get('input_boolean.battery_optimizer_enabled')
  • Line 35: input_text.battery_optimizer_status = "Deaktiviert"
  • Line 66: state.get('sensor.esssoc')

Problem: PyScript has specific patterns for accessing and setting states. The mixing of:

  • state.get() (dictionary-style)
  • input_text.battery_optimizer_status = (attribute-style)

This should work, but if there's a timing issue or entity doesn't exist, it will fail silently or raise AttributeError.

Expected Errors:

AttributeError: 'state' object has no attribute 'input_text'

or

TypeError: 'NoneType' object is not subscriptable

4. Datetime Comparison with ISO Strings

Issue: Comparing datetime objects with ISO strings from stored schedule

Location: Lines 590-605 in battery_charging_optimizer.py

for entry in schedule:
    entry_dt = datetime.fromisoformat(entry['datetime'])
    # ...
    if entry_date == current_date and entry_hour == current_hour:

Problem: The schedule stores datetime as ISO string (line 391), then loads it back. If the stored format doesn't match exactly what fromisoformat() expects, this will fail.

Expected Error:

ValueError: Invalid isoformat string: '...'

5. Service Decorator Registration

Issue: Services defined with @service decorator

Locations:

  • Line 22: @service for calculate_charging_schedule()
  • Line 556: @service for execute_charging_schedule()
  • Line 15: @service for getprices_extended()

Problem: If PyScript isn't fully initialized or there's a registration conflict, services won't be available.

Expected Behavior: Services should appear as:

  • pyscript.calculate_charging_schedule
  • pyscript.execute_charging_schedule
  • pyscript.getprices_extended

Check Command (in HA Developer Tools → Services): Search for services starting with pyscript.


6. Time Trigger Cron Syntax

Issue: Multiple cron triggers defined

Locations in battery_charging_optimizer.py:

  • Line 646: @time_trigger("cron(5 14 * * *)") - Daily at 14:05
  • Line 653: @time_trigger("cron(5 * * * *)") - Hourly at xx:05
  • Line 659: @time_trigger("cron(5 0 * * *)") - Midnight at 00:05

Locations in hastrom_flex_extended.py:

  • Line 151: @time_trigger("cron(0 * * * *)") - Hourly
  • Line 156: @time_trigger("cron(5 14 * * *)") - Daily at 14:05
  • Line 162: @time_trigger("cron(5 0 * * *)") - Midnight

Problem: PyScript cron syntax might differ from standard cron. Some implementations use different formats.

Expected Error (if syntax wrong):

ValueError: Invalid cron expression

Verify: Check PyScript documentation for correct cron syntax.


7. Attribute Access on State Objects

Issue: Accessing attributes from state objects

Location: Lines 114-141 in battery_charging_optimizer.py

prices_attr_ext = state.getattr(price_entity_ext)
prices_today = prices_attr.get('prices_today', [])

Problem: state.getattr() might return None if entity doesn't exist, then .get() on None will fail.

Expected Error:

AttributeError: 'NoneType' object has no attribute 'get'

Better Pattern:

prices_attr_ext = state.getattr(price_entity_ext) or {}

8. State.set() with Attributes

Issue: Setting state with complex attribute structures

Location: Lines 484-500 in battery_charging_optimizer.py

state.set(
    'pyscript.battery_charging_schedule',
    value='active',
    new_attributes={
        'schedule': schedule,  # This could be very large
        'last_update': get_local_now().isoformat(),
        ...
    }
)

Problem:

  1. Large schedule arrays might exceed PyScript state size limits
  2. ISO format string from datetime might not match expected format
  3. Datetime objects in schedule must be serializable

Expected Errors:

ValueError: State attributes too large

or

TypeError: Object of type datetime is not JSON serializable

Most Likely Issues Based on "Not Working" Symptom

Primary Suspects:

1. PyScript Not Loading Files

  • PyScript might not be finding the files at /config/pyscript/
  • File permissions issue
  • PyScript integration disabled or in error state

Check: Look in HA UI → Settings → Devices & Services → PyScript


2. Entity Dependencies Missing

  • Required entities don't exist or are unavailable:
    • sensor.hastrom_flex_pro_ext (created by hastrom script)
    • sensor.esssoc (from OpenEMS)
    • input_boolean.battery_optimizer_enabled
    • Various input_number helpers

Check: Developer Tools → States, search for these entities


3. Timezone Module Import Failure

  • If zoneinfo import fails, entire script won't load
  • PyScript would show error on startup

Check: Home Assistant logs for ModuleNotFoundError


4. Service Not Calling Other Service

  • Line 650: pyscript.calculate_charging_schedule()
  • This calls the service from within PyScript

Problem: Service-to-service calls in PyScript require specific syntax Correct Syntax: task.unique("calc") or use the decorated function directly


5. Schedule State Not Persisting

  • State created by one script not accessible to other
  • State lost on Home Assistant restart
  • Wrong entity ID format

Step 1: Check PyScript Status

# In Home Assistant Developer Tools → Services:
service: pyscript.reload

Look for errors in logs immediately after reload.

Step 2: Verify Entity Existence

Check if these entities exist:

  • sensor.hastrom_flex_pro_ext
  • sensor.hastrom_flex_ext
  • pyscript.battery_charging_schedule
  • sensor.esssoc
  • input_boolean.battery_optimizer_enabled

Step 3: Manual Service Call

Try calling services manually:

service: pyscript.getprices_extended

Then:

service: pyscript.calculate_charging_schedule

Watch for errors in Home Assistant logs (Settings → System → Logs)

Step 4: Check Home Assistant Logs

Look for these specific error patterns:

  • ModuleNotFoundError: No module named 'zoneinfo'
  • NameError: name 'task' is not defined
  • AttributeError: (various)
  • Traceback lines mentioning pyscript or your script names

Step 5: Verify File Locations

Ensure files are at:

  • /config/pyscript/battery_charging_optimizer.py
  • /config/pyscript/hastrom_flex_extended.py

Not:

  • /config/pyscripts/ (note the 's')
  • Any other location

Quick Fix Attempts

Fix 1: Add Error Handling to getprices_extended

In hastrom_flex_extended.py, line 37, add try-catch:

try:
    response = task.executor(requests.get, url)
    data = response.json()
except Exception as e:
    log.error(f"API call failed: {e}")
    log.error(f"Exception type: {type(e).__name__}")
    return

Fix 2: Add Null Checks for State Access

In battery_charging_optimizer.py, line 115-125:

prices_attr_ext = state.getattr(price_entity_ext) or {}
prices_attr_old = state.getattr(price_entity_old) or {}

if prices_attr_ext.get('prices_today'):
    # ... use extended

Fix 3: Alternative Timezone Import

At top of both files, try:

try:
    from zoneinfo import ZoneInfo
except ImportError:
    from datetime import timezone, timedelta
    # Fallback: create Europe/Berlin manually
    TIMEZONE = timezone(timedelta(hours=1))  # CET

Expected Log Entries If Working

You should see these log messages if scripts are working:

From hastrom_flex_extended.py:

Lade Preise für 20251120 und 20251121 (lokale Zeit: ...)
✓ API-Abfrage erfolgreich: 48 Datenpunkte
📊 haStrom FLEX PRO Extended - Preise aktualisiert:
  ├─ Heute: 24 Stunden
  └─ Morgen: 24 Stunden (verfügbar: True)

From battery_charging_optimizer.py:

=== Batterie-Optimierung gestartet (v3.2 - FIXED Timezones) ===
Konfiguration geladen: SOC 20-100%, Max 5000W
Strompreise geladen: 48 Stunden (Tomorrow: True)
PV-Prognose: Heute X.X kWh, Morgen X.X kWh
Aktueller SOC: XX%
🎯 Benötigte Ladestunden: X (bei 5000W pro Stunde)
✓ Top X günstigste Stunden ausgewählt:
✓ Ladeplan gespeichert: XX Stunden, X Ladungen
=== Optimierung abgeschlossen ===

Conclusion

Without access to live Home Assistant logs, the most likely issues are:

  1. zoneinfo import failure - Python environment in PyScript might not have it
  2. Entity dependencies missing - Required sensors/helpers don't exist
  3. PyScript not loading scripts - File location or permission issue
  4. State access returning None - Entities not ready when script runs

RECOMMENDED ACTION: Access Home Assistant logs via:

  • Settings → System → Logs (Web UI)
  • Or download logs via: Settings → System → Advanced → Download Logs
  • Or SSH into HA and check: /config/home-assistant.log

Look specifically for errors containing:

  • battery_charging_optimizer
  • hastrom_flex_extended
  • pyscript
  • ModuleNotFoundError
  • NameError
  • AttributeError

The actual error message will pinpoint the exact issue.