# Battery Optimizer PyScript - Troubleshooting Guide **Problem**: Battery optimizer scripts updated but not working **Files**: battery_charging_optimizer.py v3.2.0 + hastrom_flex_extended.py v2.0 **Date**: 2025-11-20 --- ## Quick Diagnostic Checklist Run through these checks **in order** to identify the problem: ### ✅ 1. Verify Files Are Copied to Correct Location **Location Required**: `/config/pyscript/` (not `/config/pyscripts/` - no 's'!) **Check via SSH** or File Editor add-on: ```bash ls -la /config/pyscript/ ``` **Expected Output**: ``` battery_charging_optimizer.py hastrom_flex_extended.py ``` **If files are missing**: Copy them to the correct location --- ### ✅ 2. Check PyScript Integration Status **Via Home Assistant UI**: 1. Settings → Devices & Services 2. Search for "PyScript" 3. Check status - should show "Configured" **If not installed**: Install via HACS first **If error status**: Click for details, note the error message --- ### ✅ 3. Reload PyScript **Via Developer Tools**: 1. Developer Tools → Services 2. Service: `pyscript.reload` 3. Click "Call Service" **Watch for**: Error notifications in UI or logs --- ### ✅ 4. Check Home Assistant Logs Immediately After Reload **Via UI**: - Settings → System → Logs - Filter for "pyscript" **Look for these specific errors**: #### Error Type 1: Module Import Error ``` ModuleNotFoundError: No module named 'zoneinfo' ``` **Cause**: Python 3.9+ required for zoneinfo **Fix**: Update Home Assistant or use alternative (see Fix #1 below) --- #### Error Type 2: Task Executor Not Defined ``` NameError: name 'task' is not defined ``` **Cause**: PyScript not fully initialized or wrong PyScript version **Fix**: Update PyScript integration to latest version --- #### Error Type 3: Syntax Error ``` SyntaxError: invalid syntax (line XXX) ``` **Cause**: File corruption or copy error **Fix**: Re-copy files, ensure UTF-8 encoding --- #### Error Type 4: Entity Not Found ``` AttributeError: 'state' object has no attribute 'input_text' ``` **Cause**: Required helper entities don't exist **Fix**: Create missing entities (see Fix #2 below) --- ### ✅ 5. Verify Services Were Registered **Via Developer Tools**: 1. Developer Tools → Services 2. Search for "pyscript" **Expected Services**: - `pyscript.calculate_charging_schedule` - `pyscript.execute_charging_schedule` - `pyscript.getprices_extended` - `pyscript.reload` **If services missing**: PyScript failed to load files - check logs --- ### ✅ 6. Test Price Fetcher First **Manual Test**: ```yaml service: pyscript.getprices_extended ``` **Check Results**: 1. Developer Tools → States 2. Search for: `sensor.hastrom_flex_pro_ext` 3. Check attributes for: - `prices_today` (should be array of 24 prices) - `prices_tomorrow` (might be empty before 14:00) - `last_update` (should show recent timestamp) **If entity doesn't exist**: Script failed to run - check logs **If no data in attributes**: API call failed - check logs for HTTP errors --- ### ✅ 7. Test Optimizer **Manual Test**: ```yaml service: pyscript.calculate_charging_schedule ``` **Check Results**: 1. Developer Tools → States 2. Search for: `pyscript.battery_charging_schedule` 3. Check attributes for: - `schedule` (array of hour-by-hour plan) - `num_charges` (number of charging hours) - `last_update` (timestamp) **If state doesn't exist**: Optimizer failed to run completely **If schedule is empty**: Check log for calculation errors --- ## Common Error Scenarios & Fixes ### Scenario 1: "Cannot import zoneinfo" **Full Error**: ``` ModuleNotFoundError: No module named 'zoneinfo' ``` **Fix - Option A (Recommended)**: Update Home Assistant - Requires HA 2021.7+ (Python 3.9+) - Settings → System → Updates **Fix - Option B**: Use pytz fallback Edit both scripts, replace: ```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 reload PyScript. --- ### Scenario 2: Missing Input Helpers **Error**: ``` AttributeError: 'state' object has no attribute 'input_boolean' ``` **Required Entities - Input Booleans**: - `input_boolean.battery_optimizer_enabled` - `input_boolean.goodwe_manual_control` - `input_boolean.battery_optimizer_manual_override` **Required Entities - Input Numbers**: - `input_number.battery_capacity_kwh` (default: 10) - `input_number.battery_optimizer_min_soc` (default: 20) - `input_number.battery_optimizer_max_soc` (default: 100) - `input_number.battery_optimizer_max_charge_power` (default: 5000) - `input_number.battery_optimizer_price_threshold` (default: 28) - `input_number.battery_optimizer_reserve_capacity` (default: 2) - `input_number.battery_optimizer_pv_threshold` (default: 500) - `input_number.charge_power_battery` **Required Entities - Input Text**: - `input_text.battery_optimizer_status` **Create via UI**: 1. Settings → Devices & Services → Helpers 2. Click "Create Helper" 3. Choose "Number" or "Toggle" or "Text" 4. Set ID exactly as shown above **Or via configuration.yaml**: ```yaml input_boolean: battery_optimizer_enabled: name: Battery Optimizer Enabled initial: on goodwe_manual_control: name: GoodWe Manual Control initial: off battery_optimizer_manual_override: name: Battery Optimizer Manual Override initial: off input_number: battery_capacity_kwh: name: Battery Capacity (kWh) min: 0 max: 50 step: 0.1 initial: 10 unit_of_measurement: kWh battery_optimizer_min_soc: name: Min SOC min: 0 max: 100 step: 1 initial: 20 unit_of_measurement: '%' battery_optimizer_max_soc: name: Max SOC min: 0 max: 100 step: 1 initial: 100 unit_of_measurement: '%' battery_optimizer_max_charge_power: name: Max Charge Power min: 0 max: 10000 step: 100 initial: 5000 unit_of_measurement: W battery_optimizer_price_threshold: name: Price Threshold min: 0 max: 100 step: 0.1 initial: 28 unit_of_measurement: ct/kWh battery_optimizer_reserve_capacity: name: Reserve Capacity min: 0 max: 10 step: 0.1 initial: 2 unit_of_measurement: kWh battery_optimizer_pv_threshold: name: PV Threshold min: 0 max: 5000 step: 100 initial: 500 unit_of_measurement: Wh charge_power_battery: name: Charge Power Battery min: 0 max: 10000 step: 100 initial: 0 unit_of_measurement: W input_text: battery_optimizer_status: name: Battery Optimizer Status initial: "Initialisiert" max: 255 ``` --- ### Scenario 3: Time Triggers Not Firing **Symptom**: Manual calls work, but automated schedule doesn't run **Check 1**: Verify triggers are registered ```yaml # Developer Tools → Services service: pyscript.debug ``` Look in logs for registered triggers. **Check 2**: Verify system time and timezone **Fix**: Ensure Home Assistant timezone is set correctly: ```yaml # configuration.yaml homeassistant: time_zone: Europe/Berlin ``` **Check 3**: PyScript might not support cron syntax used Try alternative trigger in configuration.yaml: ```yaml automation: - alias: "Trigger Battery Optimizer Daily" trigger: - platform: time at: "14:05:00" action: - service: pyscript.calculate_charging_schedule - alias: "Execute Battery Schedule Hourly" trigger: - platform: time_pattern minutes: "05" action: - service: pyscript.execute_charging_schedule ``` --- ### Scenario 4: Sensors Not Created by hastrom_flex_extended.py **Symptom**: Service runs without error, but sensors don't appear **Check**: State must be set with a numeric value first In `hastrom_flex_extended.py`, ensure lines 87 and 109 execute: ```python state.set("sensor.hastrom_flex_ext", value=float(current_price)) state.set("sensor.hastrom_flex_pro_ext", value=float(current_price)) ``` **Problem**: If `current_price` is `None`, state.set won't create entity **Debug**: Add logging before state.set: ```python log.info(f"Current price: {current_price}, type: {type(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 - sensor not created") ``` --- ### Scenario 5: Schedule Executes at Wrong Time **Symptom**: Charging starts at wrong hour (e.g., 15:00 instead of 14:00) **Cause**: UTC/Local timezone mismatch **Check**: What timezone does PyScript use? Add debug logging in `execute_charging_schedule()`: ```python now = get_local_now() log.info(f"Current time: {now}") log.info(f"Current hour: {now.hour}") log.info(f"Timezone: {now.tzinfo}") log.info(f"UTC offset: {now.utcoffset()}") ``` **Fix**: Verify `get_local_now()` returns Europe/Berlin time - During winter: UTC+1 (CET) - During summer: UTC+2 (CEST) --- ### Scenario 6: State Attribute Size Too Large **Error**: ``` ValueError: State attributes exceed maximum size ``` **Cause**: Schedule with 48+ hours of detailed data **Fix - Option A**: Reduce schedule detail Store only charging hours, not all hours: ```python # In save_schedule(), filter before saving schedule_compact = [s for s in schedule if s['action'] == 'charge'] state.set(..., new_attributes={'schedule': schedule_compact, ...}) ``` **Fix - Option B**: Use separate entity for each day ```python # Save today and tomorrow separately schedule_today = [s for s in schedule if not s.get('is_tomorrow')] schedule_tomorrow = [s for s in schedule if s.get('is_tomorrow')] state.set('pyscript.battery_schedule_today', ...) state.set('pyscript.battery_schedule_tomorrow', ...) ``` --- ## Advanced Debugging ### Enable PyScript Debug Logging **configuration.yaml**: ```yaml logger: default: info logs: custom_components.pyscript: debug custom_components.pyscript.file.battery_charging_optimizer: debug custom_components.pyscript.file.hastrom_flex_extended: debug ``` Restart Home Assistant, then check logs. --- ### Add Comprehensive Error Handling Edit both scripts, wrap main logic in detailed try-catch: **battery_charging_optimizer.py**, line 38: ```python try: # Existing code... except Exception as e: log.error(f"EXCEPTION in calculate_charging_schedule: {e}") log.error(f"Exception type: {type(e).__name__}") import traceback log.error(f"Traceback:\n{traceback.format_exc()}") input_text.battery_optimizer_status = f"Error: {str(e)[:100]}" raise # Re-raise to see in HA logs ``` --- ### Manual Execution with Timing Test each component manually and time them: ```yaml # 1. Test price fetch (should take 1-3 seconds) service: pyscript.getprices_extended # Wait 5 seconds, then check logs # 2. Test optimization (should take < 1 second) service: pyscript.calculate_charging_schedule # Wait 5 seconds, then check logs # 3. Test execution (should be instant) service: pyscript.execute_charging_schedule # Check logs immediately ``` --- ### Check for Conflicting Automations Search for automations that might interfere: 1. Developer Tools → States 2. Filter: `automation.` 3. Look for automations controlling: - `input_boolean.goodwe_manual_control` - `input_number.charge_power_battery` If other automations are modifying these, they might conflict. --- ## Expected Successful Log Output When everything works, you should see: **After `pyscript.getprices_extended`**: ``` Lade Preise für 20251120 und 20251121 (lokale Zeit: 2025-11-20 15:00:00 CET) ✓ API-Abfrage erfolgreich: 48 Datenpunkte 📊 haStrom FLEX PRO Extended - Preise aktualisiert: ├─ Heute: 24 Stunden └─ Morgen: 24 Stunden (verfügbar: True) 📈 Heute: Min=18.50, Max=35.20, Avg=25.30 ct/kWh 📈 Morgen: Min=17.80, Max=34.50, Avg=24.80 ct/kWh ``` **After `pyscript.calculate_charging_schedule`**: ``` === Batterie-Optimierung gestartet (v3.2 - FIXED Timezones) === Konfiguration geladen: SOC 20-100%, Max 5000W ✓ Nutze Extended-Sensor: sensor.hastrom_flex_pro_ext Strompreise geladen: 48 Stunden (Tomorrow: True) PV-Prognose: Heute 12.5 kWh, Morgen 8.3 kWh Aktueller SOC: 45% Lokale Zeit: 2025-11-20 15:00:00 CET Planungsfenster: 45 Stunden (ab jetzt) Preise: Min=17.80, Max=35.20, Avg=25.05 ct/kWh Verfügbare Ladekapazität: 5.50 kWh 🎯 Benötigte Ladestunden: 2 (bei 5000W pro Stunde) ✓ Top 2 günstigste Stunden ausgewählt: - Preise: 17.80 - 18.20 ct/kWh - Durchschnitt: 18.00 ct/kWh - Ersparnis vs. Durchschnitt: 7.05 ct/kWh - Davon morgen: 1 - Zeiten: 02:00 heute (17.80ct), 03:00 morgen (18.20ct) ✓ Ladeplan gespeichert: 45 Stunden, 2 Ladungen (1 morgen) 📊 Statistik: - Planungsfenster: 45 Stunden - Tomorrow-Daten: ✓ Ja - Ladungen heute: 1 - Ladungen morgen: 1 - Energie heute: 5.0 kWh @ 17.80 ct/kWh - Energie morgen: 0.5 kWh @ 18.20 ct/kWh === Optimierung abgeschlossen === ``` **After `pyscript.execute_charging_schedule` (during charging hour)**: ``` Suche Ladeplan für 2025-11-20 02:00 Uhr (lokal) ✓ Gefunden: 2025-11-20T02:00:00+01:00 ⚡ Stunde 02:00 [heute]: action=charge, power=-5000W, price=17.80ct Grund: Rang 1/45: 17.80ct [heute] 🔋 AKTIVIERE LADEN mit 5000W ✓ Manuelles Laden aktiviert ``` **After `pyscript.execute_charging_schedule` (during auto hour)**: ``` Suche Ladeplan für 2025-11-20 15:00 Uhr (lokal) ✓ Gefunden: 2025-11-20T15:00:00+01:00 ⚡ Stunde 15:00 [heute]: action=auto, power=0W, price=28.50ct Grund: Rang 25 (nicht unter Top 2) ✓ Auto-Modus bereits aktiv ``` --- ## Final Checklist Before Requesting Help If you've tried everything above and still have issues, gather this info: 1. ✅ Home Assistant version: - Settings → System → Info 2. ✅ PyScript version: - Settings → Devices & Services → PyScript 3. ✅ Python version in HA: ```bash docker exec homeassistant python --version ``` 4. ✅ Complete error log: - Settings → System → Logs - Filter for "pyscript" - Copy last 50 lines 5. ✅ Entity status: - Check if these exist: `sensor.hastrom_flex_pro_ext`, `pyscript.battery_charging_schedule` 6. ✅ Service availability: - List all `pyscript.*` services 7. ✅ File locations confirmed: ```bash ls -la /config/pyscript/*.py ``` 8. ✅ Recent manual test results: - What happened when you called each service manually? --- ## Quick Reference Commands ```yaml # Reload PyScript service: pyscript.reload # Test price fetch service: pyscript.getprices_extended # Test optimizer service: pyscript.calculate_charging_schedule # Test executor service: pyscript.execute_charging_schedule # Enable optimizer service: input_boolean.turn_on data: entity_id: input_boolean.battery_optimizer_enabled # Disable optimizer service: input_boolean.turn_off data: entity_id: input_boolean.battery_optimizer_enabled # Check schedule state # Developer Tools → States → pyscript.battery_charging_schedule # Check price sensor # Developer Tools → States → sensor.hastrom_flex_pro_ext ``` --- ## Contact & Support If issues persist after following this guide: 1. Export logs: Settings → System → Advanced → Download Logs 2. Check PyScript GitHub issues: https://github.com/custom-components/pyscript 3. Home Assistant Community: https://community.home-assistant.io/ Include in your report: - HA version - PyScript version - Complete error logs - Output of validation script (`python3 validate_pyscript.py`) - Steps already tried from this guide