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:
felix.zoesch
2025-12-12 08:04:07 +01:00
parent 5ab422426f
commit 0fa03a566a
90 changed files with 22002 additions and 0 deletions

329
QUICK_FIX_REFERENCE.md Normal file
View File

@@ -0,0 +1,329 @@
# Battery Optimizer - Quick Fix Reference Card
**Print this page and keep it handy for quick troubleshooting!**
---
## 🚨 Emergency Quick Checks (5 Minutes)
### 1⃣ Check PyScript Status
```
Settings → Devices & Services → Search "PyScript" → Should show "Configured"
```
### 2⃣ Reload PyScript
```yaml
Developer Tools → Services → Call Service:
service: pyscript.reload
```
### 3⃣ Check Logs for Errors
```
Settings → System → Logs → Filter "pyscript" → Look for RED messages
```
### 4⃣ Verify Services Exist
```
Developer Tools → Services → Search "pyscript."
Should show: calculate_charging_schedule, execute_charging_schedule, getprices_extended
```
### 5⃣ Check Files in Correct Location
```bash
# Via SSH or File Editor:
ls -la /config/pyscript/
# Should show: battery_charging_optimizer.py, hastrom_flex_extended.py
```
---
## 🔧 Common Fixes
### ❌ "ModuleNotFoundError: No module named 'zoneinfo'"
**Quick Fix**: Add fallback to both scripts
Replace in BOTH files:
```python
from zoneinfo import ZoneInfo
TIMEZONE = ZoneInfo("Europe/Berlin")
```
With:
```python
try:
from zoneinfo import ZoneInfo
TIMEZONE = ZoneInfo("Europe/Berlin")
except ImportError:
import pytz
TIMEZONE = pytz.timezone("Europe/Berlin")
```
Then: `pyscript.reload`
---
### ❌ "AttributeError: 'state' object has no attribute..."
**Cause**: Missing helper entity
**Quick Fix**: Create missing entities
Go to: `Settings → Devices & Services → Helpers → Create Helper`
**Required Helpers**:
- **Toggle**: `input_boolean.battery_optimizer_enabled` (initial: ON)
- **Toggle**: `input_boolean.goodwe_manual_control` (initial: OFF)
- **Toggle**: `input_boolean.battery_optimizer_manual_override` (initial: OFF)
- **Number**: `input_number.battery_capacity_kwh` (min: 0, max: 50, initial: 10)
- **Number**: `input_number.battery_optimizer_min_soc` (min: 0, max: 100, initial: 20)
- **Number**: `input_number.battery_optimizer_max_soc` (min: 0, max: 100, initial: 100)
- **Number**: `input_number.battery_optimizer_max_charge_power` (min: 0, max: 10000, initial: 5000)
- **Number**: `input_number.charge_power_battery` (min: 0, max: 10000, initial: 0)
- **Text**: `input_text.battery_optimizer_status` (max: 255)
Then: `pyscript.reload`
---
### ❌ Services Not Showing Up
**Cause**: PyScript didn't load scripts
**Quick Fix**:
1. Check file location: `/config/pyscript/` (not `pyscripts`)
2. Check file permissions: Should be readable by HA
3. Call: `pyscript.reload`
4. Check logs immediately for errors
---
### ❌ "NameError: name 'task' is not defined"
**Cause**: PyScript not initialized or wrong version
**Quick Fix**:
1. Check PyScript version: Settings → Devices & Services → PyScript
2. Update to latest: HACS → PyScript → Update
3. Restart Home Assistant
4. Call: `pyscript.reload`
---
### ❌ Time Triggers Not Firing
**Quick Fix**: Create automation instead
**configuration.yaml**:
```yaml
automation:
- alias: "Battery Optimizer - Daily Calculation"
trigger:
platform: time
at: "14:05:00"
action:
service: pyscript.calculate_charging_schedule
- alias: "Battery Optimizer - Hourly Execution"
trigger:
platform: time_pattern
minutes: "05"
action:
service: pyscript.execute_charging_schedule
```
Restart Home Assistant.
---
### ❌ Sensors Not Created (hastrom_flex_pro_ext)
**Quick Fix**: Check if price is None
Add logging to `hastrom_flex_extended.py` around line 86:
```python
log.info(f"DEBUG: current_price = {current_price}")
if current_price is not None:
state.set("sensor.hastrom_flex_ext", value=float(current_price))
else:
log.error("Current price is None - cannot create sensor")
```
Then: `pyscript.reload` and call `pyscript.getprices_extended`
---
## 🧪 Manual Test Sequence
**Run these in order to isolate the problem:**
### Test 1: Price Fetcher
```yaml
service: pyscript.getprices_extended
```
Wait 5 seconds, then check:
```
Developer Tools → States → sensor.hastrom_flex_pro_ext
Should have: prices_today, prices_tomorrow in attributes
```
### Test 2: Optimizer
```yaml
service: pyscript.calculate_charging_schedule
```
Wait 5 seconds, then check:
```
Developer Tools → States → pyscript.battery_charging_schedule
Should have: schedule array, num_charges, last_update
```
### Test 3: Executor
```yaml
service: pyscript.execute_charging_schedule
```
Immediately check logs:
```
Should see: "Suche Ladeplan für ..."
```
---
## 📋 Log Error Patterns & Fixes
| Error in Logs | Quick Fix |
|---------------|-----------|
| `ModuleNotFoundError: zoneinfo` | Add pytz fallback (see above) |
| `NameError: task` | Update PyScript integration |
| `AttributeError: state` | Create missing helper entity |
| `Fehler beim Abrufen` | Check network/API access |
| `SyntaxError` | Re-copy files, check encoding |
| `ValueError: State attributes` | Reduce schedule size |
| No errors, but not working | Check if optimizer is enabled |
---
## 🎛️ Enable/Disable Optimizer
### Enable
```yaml
service: input_boolean.turn_on
data:
entity_id: input_boolean.battery_optimizer_enabled
```
### Disable
```yaml
service: input_boolean.turn_off
data:
entity_id: input_boolean.battery_optimizer_enabled
```
### Check Status
```
Developer Tools → States → input_boolean.battery_optimizer_enabled
Should show: "on" or "off"
```
---
## 📊 Debug Logging
**configuration.yaml**:
```yaml
logger:
default: info
logs:
custom_components.pyscript: debug
```
Restart, then check logs again.
---
## ✅ Success Indicators
### Price Fetcher Working:
```
Log shows: "✓ API-Abfrage erfolgreich: 48 Datenpunkte"
State exists: sensor.hastrom_flex_pro_ext with prices_today array
```
### Optimizer Working:
```
Log shows: "=== Batterie-Optimierung gestartet" ... "=== Optimierung abgeschlossen ==="
State exists: pyscript.battery_charging_schedule with schedule array
Status shows: "X Ladungen" in input_text.battery_optimizer_status
```
### Executor Working:
```
Log shows: "🔋 AKTIVIERE LADEN" OR "✓ Auto-Modus bereits aktiv"
Manual control toggles: input_boolean.goodwe_manual_control changes state
```
---
## 🆘 Still Not Working?
### Gather This Info:
1. Home Assistant version (Settings → System → Info)
2. PyScript version (Settings → Devices & Services → PyScript)
3. Last 50 lines of logs with "pyscript" filter
4. List of services starting with "pyscript."
5. Which entities from "Required Helpers" exist
### Get Help:
- Home Assistant Community: https://community.home-assistant.io/
- PyScript GitHub: https://github.com/custom-components/pyscript/issues
- Include all info from "Gather This Info" above
---
## 📁 File Locations Cheat Sheet
| File | Production Location | Dev Location |
|------|---------------------|--------------|
| Optimizer | `/config/pyscript/battery_charging_optimizer.py` | `./openems/battery_charging_optimizer.py` |
| Price Fetcher | `/config/pyscript/hastrom_flex_extended.py` | `./openems/hastrom_flex_extended.py` |
| Logs | `/config/home-assistant.log` | Settings → System → Logs |
| Config | `/config/configuration.yaml` | N/A |
---
## 🔢 Default Configuration Values
```yaml
battery_capacity_kwh: 10
min_soc: 20
max_soc: 100
max_charge_power: 5000
price_threshold: 28
reserve_capacity: 2
pv_threshold: 500
```
---
## ⏰ Trigger Schedule
| Time | Service | Purpose |
|------|---------|---------|
| 14:05 daily | `getprices_extended` | Fetch tomorrow prices |
| 14:05 daily | `calculate_charging_schedule` | Plan next 48h |
| 00:05 daily | Both services | Midnight update |
| XX:05 hourly | `execute_charging_schedule` | Apply current hour action |
| XX:00 hourly | `getprices_extended` | Update current price |
---
## 🔗 Quick Links
- Detailed Troubleshooting: `TROUBLESHOOTING_GUIDE.md`
- Full Diagnosis: `DIAGNOSIS_SUMMARY.md`
- Validation Script: `validate_pyscript.py`
- Technical Details: `diagnostic_pyscript_issues.md`
---
**Last Updated**: 2025-11-20
**Version**: 3.2.0 (battery_charging_optimizer) + 2.0 (hastrom_flex_extended)