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>
This commit is contained in:
386
diagnostic_pyscript_issues.md
Normal file
386
diagnostic_pyscript_issues.md
Normal file
@@ -0,0 +1,386 @@
|
||||
# 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`
|
||||
```python
|
||||
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`
|
||||
```python
|
||||
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`
|
||||
```python
|
||||
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**:
|
||||
```python
|
||||
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`
|
||||
```python
|
||||
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
|
||||
|
||||
---
|
||||
|
||||
## Recommended Diagnostic Steps
|
||||
|
||||
### Step 1: Check PyScript Status
|
||||
```yaml
|
||||
# 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:
|
||||
```yaml
|
||||
service: pyscript.getprices_extended
|
||||
```
|
||||
|
||||
Then:
|
||||
```yaml
|
||||
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:
|
||||
```python
|
||||
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:
|
||||
```python
|
||||
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:
|
||||
```python
|
||||
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.
|
||||
Reference in New Issue
Block a user