Advanced Home Energy Management System for Portugal

I’ll create a comprehensive plan for your renewable energy system that optimizes all components within Portugal’s specific context. Let’s integrate your GoodWe system, Tesla, heat pumps, and dehumidifiers into an intelligent Home Assistant setup.

1. System Architecture Overview

Your home energy ecosystem consists of several key components that need to be integrated into a cohesive system:

┌─────────────────────────────────────────────────────────────────────┐
│                       External Data Sources                          │
│  ┌──────────────┐  ┌───────────────┐  ┌────────────┐  ┌──────────┐  │
│  │Weather API   │  │Electricity    │  │Solar       │  │Tesla     │  │
│  │(forecast)    │  │Price API      │  │Forecast API│  │API       │  │
│  └──────┬───────┘  └───────┬───────┘  └─────┬──────┘  └────┬─────┘  │
└────────┼────────────────────┼───────────────┼────────────┼─────────┘
         │                    │               │            │
         ▼                    ▼               ▼            ▼
┌─────────────────────────────────────────────────────────────────────┐
│                          Home Assistant                              │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │                Core Integration Layer                         │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌───────────┐  │   │
│  │  │GoodWe       │ │Tesla        │ │Heat Pump │ │Dehumidifier│  │   │
│  │  │Integration  │ │Integration  │ │Integration│ │Integration │  │   │
│  │  └─────────────┘ └─────────────┘ └──────────┘ └───────────┘  │   │
│  └──────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │                   Energy Management Layer                     │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐    │   │
│  │  │Energy       │ │Predictive   │ │Optimization          │    │   │
│  │  │Monitoring   │ │Models       │ │Algorithms            │    │   │
│  │  └─────────────┘ └─────────────┘ └──────────────────────┘    │   │
│  └──────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │                      Automation Layer                         │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌───────────┐  │   │
│  │  │Solar        │ │Battery      │ │Load      │ │Device     │  │   │
│  │  │Optimization │ │Management   │ │Balancing │ │Scheduling  │  │   │
│  │  └─────────────┘ └─────────────┘ └──────────┘ └───────────┘  │   │
│  └──────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │                 User Interface Layer                          │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌───────────┐  │   │
│  │  │Real-time    │ │Historical   │ │Control   │ │Predictive │  │   │
│  │  │Dashboard    │ │Analytics    │ │Panel     │ │Insights   │  │   │
│  │  └─────────────┘ └─────────────┘ └──────────┘ └───────────┘  │   │
│  └──────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────┘
         │            │             │              │
         ▼            ▼             ▼              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                      Physical Energy Systems                         │
│  ┌──────────────┐  ┌───────────────┐  ┌────────────┐  ┌──────────┐  │
│  │4.92kW Solar  │  │GoodWe Inverter│  │Tesla       │  │Heat Pumps/│  │
│  │Array         │◄─►│& Battery      │◄─►│Model Y    │◄─►│Dehumidifiers│
│  └──────────────┘  └───────────────┘  └────────────┘  └──────────┘  │
└─────────────────────────────────────────────────────────────────────┘

Data Flow:

  1. Energy Production: Solar panels → GoodWe inverter → Home consumption/Battery/Grid
  2. Energy Consumption: Home devices ← GoodWe inverter ← Battery/Grid
  3. Data Collection: All components → Home Assistant → Monitoring & Analytics
  4. Control Signals: Home Assistant → Smart devices → Optimized operation

Key Integration Points:

  • GoodWe inverter with Home Assistant via Modbus or API
  • Tesla Model Y via Tesla API
  • Heat pumps and dehumidifiers via smart plugs or direct integration
  • External data sources (weather, electricity prices) via APIs

2. Integration Guide

2.1 GoodWe Integration

The GoodWe system is the cornerstone of your setup. We’ll use the HACS GoodWe integration for reliable data collection and control.

# configuration.yaml
goodwe:
  inverter_host: 192.168.1.x  # Replace with your GoodWe inverter IP
  inverter_port: 502  # Default Modbus port
  inverter_type: GW10K-ET  # Replace with your specific model
  scan_interval: 10  # Update frequency in seconds

For more advanced control, we’ll add template sensors:

# configuration.yaml
template:
  - sensor:
      - name: "Battery SOC"
        state: "{{ state_attr('sensor.goodwe_battery', 'soc') }}"
        unit_of_measurement: "%"
        
      - name: "Battery Charge Power"
        state: "{{ state_attr('sensor.goodwe_battery', 'charge_power') | float }}"
        unit_of_measurement: "W"
        
      - name: "Battery Discharge Power"
        state: "{{ state_attr('sensor.goodwe_battery', 'discharge_power') | float }}"
        unit_of_measurement: "W"
        
      - name: "Solar Production"
        state: "{{ states('sensor.goodwe_pv_power') | float }}"
        unit_of_measurement: "W"

2.2 Tesla Model Y Integration

For the Tesla integration, we’ll use the excellent HACS Tesla Custom Component:

# configuration.yaml
tesla_custom:
  username: your_tesla_account_email
  password: your_tesla_account_password
  scan_interval: 660  # 11 minutes to avoid API rate limits
  enable_websocket: true  # For real-time updates

To enable better energy management, let’s create template sensors for the Tesla:

# configuration.yaml
template:
  - sensor:
      - name: "Tesla SOC"
        state: "{{ state_attr('sensor.tesla_model_y_battery', 'level') }}"
        unit_of_measurement: "%"
        
      - name: "Tesla Charging Power"
        state: %3E
          {% if is_state('binary_sensor.tesla_model_y_charger', 'on') %}
            {{ state_attr('sensor.tesla_model_y_charger', 'power') | float }}
          {% else %}
            0
          {% endif %}
        unit_of_measurement: "W"
        
      - name: "Tesla Energy Available"
        state: >
          {% set capacity = 75 %}  # Model Y capacity in kWh
          {% set soc = states('sensor.tesla_soc') | float %}
          {{ (capacity * soc / 100) | round(2) }}
        unit_of_measurement: "kWh"

2.3 Heat Pump and Dehumidifier Integration

For these devices, we’ll use smart plugs with power monitoring:

# configuration.yaml
# Assuming smart plugs are using Tasmota, Shelly, or similar
switch:
  - platform: mqtt
    name: "Water Heater Heat Pump"
    state_topic: "stat/heater_plug/POWER"
    command_topic: "cmnd/heater_plug/POWER"
    payload_on: "ON"
    payload_off: "OFF"
    
  - platform: mqtt
    name: "Home Heat Pump"
    state_topic: "stat/home_heating_plug/POWER"
    command_topic: "cmnd/home_heating_plug/POWER"
    payload_on: "ON"
    payload_off: "OFF"
    
  # Repeat for dehumidifiers

Add power monitoring sensors:

sensor:
  - platform: mqtt
    name: "Water Heater Power"
    state_topic: "tele/heater_plug/SENSOR"
    value_template: "{{ value_json.ENERGY.Power }}"
    unit_of_measurement: "W"
    
  - platform: mqtt
    name: "Home Heat Pump Power"
    state_topic: "tele/home_heating_plug/SENSOR"
    value_template: "{{ value_json.ENERGY.Power }}"
    unit_of_measurement: "W"
    
  # Repeat for dehumidifiers

2.4 External Data Integration

For Portugal’s specific context, we need energy price and weather data:

# configuration.yaml
# Portuguese Energy Price API (OMIE)
rest:
  - resource: https://api.esios.ree.es/archives/70/download_json
    scan_interval: 3600  # Hourly updates
    sensor:
      name: energy_price_tomorrow
      value_template: "{{ value_json.PVPC[0].price }}"
      unit_of_measurement: "€/kWh"
 
# Weather forecast for solar prediction
weather:
  - platform: openweathermap
    api_key: your_openweathermap_api_key
    latitude: !secret home_latitude
    longitude: !secret home_longitude
    mode: daily

2.5 Energy Dashboard Configuration

Enable Home Assistant’s Energy Dashboard for baseline monitoring:

# configuration.yaml
energy:
  # Solar panel feed
  solar_production_entity_ids:
    - sensor.goodwe_pv_power
  # Grid consumption/feed-in
  grid_consumption_entity_ids:
    - sensor.goodwe_grid_consumption
  grid_return_entity_ids:
    - sensor.goodwe_grid_feed_in
  # Battery storage
  battery_consumption_entity_ids:
    - sensor.battery_discharge_power
  battery_production_entity_ids:
    - sensor.battery_charge_power
  # Device consumption tracking
  device_consumption_entity_ids:
    - sensor.water_heater_power
    - sensor.home_heat_pump_power
    - sensor.dehumidifier_1_power
    - sensor.dehumidifier_2_power
    - sensor.dehumidifier_3_power
    - sensor.dehumidifier_4_power
    - sensor.tesla_charging_power

3. Automation Strategy

3.1 Solar Self-Consumption Optimization

# automations.yaml
- alias: "Prioritize Solar Self-Consumption"
  trigger:
    - platform: numeric_state
      entity_id: sensor.solar_production
      above: 1000  # When solar production exceeds 1kW
  condition:
    - condition: time
      after: '09:00:00'
      before: '16:00:00'
  action:
    - service: script.turn_on
      entity_id: script.activate_high_consumption_devices

Script to activate high-consumption devices:

# scripts.yaml
activate_high_consumption_devices:
  sequence:
    # Decision tree logic based on solar production level
    - choose:
        # High solar production scenario
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 3000  # 3kW+
          sequence:
            - service: switch.turn_on
              target:
                entity_id: 
                  - switch.dehumidifier_1
                  - switch.dehumidifier_2
                  - switch.dehumidifier_3
                  - switch.dehumidifier_4
            - service: switch.turn_on
              entity_id: switch.water_heater_heat_pump
            # If Tesla is home and needs charging
            - condition: and
              conditions:
                - condition: state
                  entity_id: device_tracker.tesla_model_y
                  state: 'home'
                - condition: numeric_state
                  entity_id: sensor.tesla_soc
                  below: 90
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: charge_start
                
        # Medium solar production scenario
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 2000  # 2-3kW
              below: 3000
          sequence:
            - service: switch.turn_on
              target:
                entity_id: 
                  - switch.dehumidifier_1
                  - switch.dehumidifier_2
            - service: switch.turn_on
              entity_id: switch.water_heater_heat_pump
              
        # Lower solar production scenario
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 1000  # 1-2kW
              below: 2000
          sequence:
            - service: switch.turn_on
              entity_id: switch.dehumidifier_1

3.2 Battery Management Strategy

This strategy applies to both your home battery and Tesla:

# automations.yaml
- alias: "Battery Smart Charging/Discharging"
  trigger:
    - platform: time_pattern
      minutes: "/10"  # Check every 10 minutes
  action:
    - service: script.battery_management

Script for intelligent battery management:

# scripts.yaml
battery_management:
  sequence:
    # Get current electricity price tier (vazio/cheio/ponta)
    - variables:
        current_hour: "{{ now().hour }}"
        is_weekend: "{{ now().weekday() in [5, 6] }}"  # Saturday, Sunday
        price_tier: >
          {% if is_weekend %}
            vazio
          {% elif current_hour %3C 8 or current_hour >= 22 %}
            vazio
          {% elif current_hour >= 8 and current_hour < 10 or current_hour >= 20 and current_hour < 22 %}
            cheio
          {% elif current_hour >= 10 and current_hour < 13 or current_hour >= 18 and current_hour < 20 %}
            ponta
          {% elif current_hour >= 13 and current_hour < 18 %}
            cheio
          {% endif %}
        home_battery_soc: "{{ states('sensor.battery_soc') | float }}"
        tesla_soc: "{{ states('sensor.tesla_soc') | float }}"
        solar_forecast_next_hour: "{{ states('sensor.forecast_solar_next_hour') | float }}"
        current_consumption: "{{ states('sensor.home_consumption') | float }}"
        
    # Decision tree for battery management
    - choose:
        # High price period (ponta) - Discharge batteries
        - conditions:
            - condition: template
              value_template: "{{ price_tier == 'ponta' }}"
          sequence:
            # If home battery has sufficient charge, use it
            - condition: numeric_state
              entity_id: sensor.battery_soc
              above: 20  # Keep 20% minimum
            - service: script.set_goodwe_discharge_mode
            
        # Low price period (vazio) - Charge batteries
        - conditions:
            - condition: template
              value_template: "{{ price_tier == 'vazio' }}"
          sequence:
            # Charge home battery to 100% during low price
            - condition: numeric_state
              entity_id: sensor.battery_soc
              below: 100
            - service: script.set_goodwe_charge_mode
            
            # Charge Tesla if home and SOC is below threshold
            - condition: and
              conditions:
                - condition: state
                  entity_id: device_tracker.tesla_model_y
                  state: 'home'
                - condition: numeric_state
                  entity_id: sensor.tesla_soc
                  below: 70  # Adjust based on daily driving needs
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: charge_start
                
        # Medium price (cheio) - Base decisions on solar forecast
        - conditions:
            - condition: template
              value_template: "{{ price_tier == 'cheio' }}"
          sequence:
            - choose:
                # If good solar production is expected soon, preserve battery
                - conditions:
                    - condition: numeric_state
                      entity_id: sensor.forecast_solar_next_hour
                      above: 2000  # 2kW+ expected
                  sequence:
                    - service: script.set_goodwe_self_consumption_mode
                
                # If poor solar expected and battery is charged
                - conditions:
                    - condition: numeric_state
                      entity_id: sensor.forecast_solar_next_hour
                      below: 1000  # Poor solar expected
                    - condition: numeric_state
                      entity_id: sensor.battery_soc
                      above: 50  # Battery has decent charge
                  sequence:
                    - service: script.set_goodwe_self_consumption_mode
                
                # Otherwise charge from grid (still cheaper than ponta)
                - conditions:
                    - condition: numeric_state
                      entity_id: sensor.battery_soc
                      below: 40  # Battery needs charge for evening peak
                  sequence:
                    - service: script.set_goodwe_charge_mode

Helper scripts for GoodWe mode control:

# scripts.yaml
set_goodwe_discharge_mode:
  sequence:
    - service: goodwe.set_operation_mode
      data:
        operation_mode: "Time of Use"
        battery_power_mode: "Force Discharge"
        battery_discharge_time: "{{ now().hour }}:00"
        battery_discharge_power: 2500  # Adjust based on consumption needs
 
set_goodwe_charge_mode:
  sequence:
    - service: goodwe.set_operation_mode
      data:
        operation_mode: "Time of Use"
        battery_power_mode: "Force Charge"
        battery_charge_time: "{{ now().hour }}:00"
        battery_charge_power: 2000  # Adjust based on grid capacity
 
set_goodwe_self_consumption_mode:
  sequence:
    - service: goodwe.set_operation_mode
      data:
        operation_mode: "Self-consumption"

3.3 Dehumidifier Management

Dehumidifiers should run based on energy availability and humidity levels:

# automations.yaml
- alias: "Smart Dehumidifier Control"
  trigger:
    - platform: time_pattern
      minutes: "/15"  # Check every 15 minutes
  condition:
    - condition: numeric_state
      entity_id: sensor.home_humidity
      above: 60  # Only run if humidity is high
  action:
    - service: script.manage_dehumidifiers

Script for dehumidifier management:

# scripts.yaml
manage_dehumidifiers:
  sequence:
    - variables:
        solar_available: "{{ states('sensor.solar_production') | float }}"
        battery_soc: "{{ states('sensor.battery_soc') | float }}"
        electricity_price: "{{ states('sensor.energy_price_current') | float }}"
        current_hour: "{{ now().hour }}"
        
    # Decision logic for dehumidifiers
    - choose:
        # Solar excess available - run all needed dehumidifiers
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 1500  # Significant solar production
          sequence:
            # Check humidity in different zones and turn on accordingly
            - service: switch.turn_on
              target:
                entity_id: >
                  {% set dehumidifiers = [] %}
                  {% if states('sensor.living_room_humidity') | float > 60 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_1'] %}
                  {% endif %}
                  {% if states('sensor.bedroom_humidity') | float > 60 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_2'] %}
                  {% endif %}
                  {% if states('sensor.basement_humidity') | float > 65 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_3'] %}
                  {% endif %}
                  {% if states('sensor.bathroom_humidity') | float > 70 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_4'] %}
                  {% endif %}
                  {{ dehumidifiers }}
        
        # Low electricity price period but no solar
        - conditions:
            - condition: template
              value_template: >
                {% set is_low_price = current_hour < 8 or current_hour >= 22 or now().weekday() in [5, 6] %}
                {{ is_low_price and battery_soc > 40 }}
          sequence:
            # Run high-priority dehumidifiers only
            - service: switch.turn_on
              target:
                entity_id: >
                  {% set dehumidifiers = [] %}
                  {% if states('sensor.basement_humidity') | float > 70 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_3'] %}
                  {% endif %}
                  {% if states('sensor.bathroom_humidity') | float > 75 %}
                    {% set dehumidifiers = dehumidifiers + ['switch.dehumidifier_4'] %}
                  {% endif %}
                  {{ dehumidifiers }}
                  
        # All other scenarios - only run if critical humidity
        - conditions:
            - condition: numeric_state
              entity_id: sensor.home_humidity
              above: 75  # Very high humidity
          sequence:
            - service: switch.turn_on
              entity_id: switch.dehumidifier_1  # Run just one for emergency

3.4 Heat Pump Water Heater Optimization

# automations.yaml
- alias: "Smart Water Heating"
  trigger:
    - platform: time_pattern
      hours: "/1"  # Check hourly
  action:
    - service: script.manage_water_heating

Water heating management script:

# scripts.yaml
manage_water_heating:
  sequence:
    - variables:
        hot_water_temp: "{{ states('sensor.hot_water_temperature') | float }}"
        solar_available: "{{ states('sensor.solar_production') | float }}"
        current_hour: "{{ now().hour }}"
        is_weekend: "{{ now().weekday() in [5, 6] }}"
        price_tier: >
          {% if is_weekend %}
            vazio
          {% elif current_hour < 8 or current_hour >= 22 %}
            vazio
          {% elif current_hour >= 8 and current_hour < 10 or current_hour >= 20 and current_hour < 22 %}
            cheio
          {% elif current_hour >= 10 and current_hour < 13 or current_hour >= 18 and current_hour < 20 %}
            ponta
          {% elif current_hour >= 13 and current_hour < 18 %}
            cheio
          {% endif %}
        
    # Decision tree for water heating
    - choose:
        # Hot water temperature is low - needs immediate heating
        - conditions:
            - condition: numeric_state
              entity_id: sensor.hot_water_temperature
              below: 45  # Minimum acceptable temperature
          sequence:
            - service: switch.turn_on
              entity_id: switch.water_heater_heat_pump
              
        # Excess solar available - perfect time to heat water
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 2500  # Good solar production
            - condition: numeric_state
              entity_id: sensor.hot_water_temperature
              below: 60  # Not fully heated yet
          sequence:
            - service: switch.turn_on
              entity_id: switch.water_heater_heat_pump
              
        # Low price period (vazio) - good time to heat water
        - conditions:
            - condition: template
              value_template: "{{ price_tier == 'vazio' }}"
            - condition: numeric_state
              entity_id: sensor.hot_water_temperature
              below: 55  # Below optimal temperature
          sequence:
            - service: switch.turn_on
              entity_id: switch.water_heater_heat_pump
              
      # Default action if no conditions match
      default:
        - service: switch.turn_off
          entity_id: switch.water_heater_heat_pump

3.5 Tesla Charging Strategy

# automations.yaml
- alias: "Tesla Intelligent Charging"
  trigger:
    - platform: state
      entity_id: device_tracker.tesla_model_y
      to: 'home'  # When Tesla arrives home
    - platform: time_pattern
      hours: "/1"  # Check hourly for optimization
  action:
    - service: script.optimize_tesla_charging

Tesla charging optimization script:

# scripts.yaml
optimize_tesla_charging:
  sequence:
    - variables:
        solar_available: "{{ states('sensor.solar_production') | float }}"
        battery_soc: "{{ states('sensor.battery_soc') | float }}"
        tesla_soc: "{{ states('sensor.tesla_soc') | float }}"
        is_tesla_home: "{{ is_state('device_tracker.tesla_model_y', 'home') }}"
        current_hour: "{{ now().hour }}"
        is_weekend: "{{ now().weekday() in [5, 6] }}"
        next_trip_time: "{{ states('input_datetime.next_car_trip') }}"
        price_tier: >
          {% if is_weekend %}
            vazio
          {% elif current_hour < 8 or current_hour >= 22 %}
            vazio
          {% elif current_hour >= 8 and current_hour < 10 or current_hour >= 20 and current_hour < 22 %}
            cheio
          {% elif current_hour >= 10 and current_hour < 13 or current_hour >= 18 and current_hour < 20 %}
            ponta
          {% elif current_hour >= 13 and current_hour < 18 %}
            cheio
          {% endif %}
        
    # Only proceed if Tesla is home
    - condition: template
      value_template: "{{ is_tesla_home }}"
      
    # Decision tree for Tesla charging
    - choose:
        # High solar production available
        - conditions:
            - condition: numeric_state
              entity_id: sensor.solar_production
              above: 3000  # Only charge from solar if significant excess
            - condition: numeric_state
              entity_id: sensor.tesla_soc
              below: 90  # Not already fully charged
          sequence:
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: set_charging_amps
                params:
                  charging_amps: 16  # Adjust based on excess solar
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: charge_start
                
        # Low price period overnight
        - conditions:
            - condition: template
              value_template: "{{ price_tier == 'vazio' }}"
            - condition: numeric_state
              entity_id: sensor.tesla_soc
              below: 80  # Charge to 80% during low price
          sequence:
            # Set charge limit to 80%
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: set_charge_limit
                params:
                  charge_limit: 80
            # Set charging amps
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: set_charging_amps
                params:
                  charging_amps: 32  # Maximum charging speed
            # Start charging
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: charge_start
                
        # Trip planned soon and charge needed
        - conditions:
            - condition: template
              value_template: >
                {% set trip_hour = strptime(states('input_datetime.next_car_trip'), '%Y-%m-%d %H:%M:%S').hour %}
                {% set hours_until_trip = (trip_hour - current_hour) % 24 %}
                {{ hours_until_trip < 3 and tesla_soc < 70 }}
          sequence:
            # Emergency charging regardless of price
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: set_charge_limit
                params:
                  charge_limit: 90
            - service: tesla_custom.api_command
              data:
                device_id: !secret tesla_device_id
                command: charge_start
                
      # Default action - stop charging if no conditions match
      default:
        - service: tesla_custom.api_command
          data:
            device_id: !secret tesla_device_id
            command: charge_stop

4. Custom Dashboards

Let’s create specialized dashboards that give you complete visibility into your system.

4.1 Energy Overview Dashboard

# lovelace configuration - energy_overview.yaml
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Current Status"
          - type: glance
            title: System Status
            entities:
              - entity: sensor.solar_production
                name: Solar
                icon: mdi:solar-power
              - entity: sensor.home_consumption
                name: Consumption
                icon: mdi:power-socket-eu
              - entity: sensor.battery_soc
                name: Home Battery
                icon: mdi:battery-high
              - entity: sensor.tesla_soc
                name: Tesla Battery
                icon: mdi:car-electric
          
          - type: custom:mini-graph-card
            name: Power Flow (Last 24h)
            hours_to_show: 24
            points_per_hour: 4
            line_width: 2
            entities:
              - entity: sensor.solar_production
                name: Solar
                color: '#ffd700'
              - entity: sensor.home_consumption
                name: Home
                color: '#3498db'
              - entity: sensor.battery_power
                name: Battery 
                color: '#2ecc71'
      
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Current Electricity Pricing"
          - type: custom:apexcharts-card
            header:
              title: Price Forecast (24h)
              show: true
            graph_span: 24h
            span:
              start: day
            series:
              - entity: sensor.energy_price_current
                name: "€/kWh"
                stroke_width: 2
                color: var(--accent-color)
            
          - type: entity
            name: Current Rate Tier
            entity: sensor.current_price_tier
            icon: mdi:currency-eur

4.2 Device Control Dashboard

# lovelace configuration - device_control.yaml
title: Device Control
views:
  - title: Smart Devices
    path: devices
    icon: mdi:power-plug
    badges: []
    cards:
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Heat Pumps"
          - type: entities
            title: Heat Pump Control
            entities:
              - entity: switch.water_heater_heat_pump
                name: Water Heater
                secondary_info: last-changed
              - entity: sensor.hot_water_temperature
                name: Water Temperature
              - entity: sensor.water_heater_power
                name: Power Consumption
              - entity: switch.home_heat_pump
                name: Home Heating
                secondary_info: last-changed
              - entity: sensor.home_heat_pump_power
                name: Power Consumption
              - entity: sensor.room_temperature
                name: Room Temperature
          
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Dehumidifiers"
          - type: entities
            title: Dehumidifier Control
            entities:
              - entity: switch.dehumidifier_1
                name: Living Room
                secondary_info: last-changed
              - entity: sensor.living_room_humidity
                name: Humidity
              - entity: switch.dehumidifier_2
                name: Bedroom
                secondary_info: last-changed
              - entity: sensor.bedroom_humidity
                name: Humidity
              - entity: switch.dehumidifier_3
                name: Basement
                secondary_info: last-changed
              - entity: sensor.basement_humidity
                name: Humidity
              - entity: switch.dehumidifier_4
                name: Bathroom
                secondary_info: last-changed
              - entity: sensor.bathroom_humidity
                name: Humidity
                
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Tesla Model Y"
          - type: entities
            title: Tesla Status
            entities:
              - entity: sensor.tesla_soc
                name: Battery Level
              - entity: sensor.tesla_range
                name: Range
              - entity: binary_sensor.tesla_model_y_charger
                name: Charging Status
              - entity: sensor.tesla_charging_power
                name: Charging Power
              - entity: device_tracker.tesla_model_y
                name: Location
          - type: custom:button-card
            name: Start Charging
            icon: mdi:ev-station
            show_name: true
            tap_action:
              action: call-service
              service: tesla_custom.api_command
              service_data:
                device_id: !secret tesla_device_id
                command: charge_start
          - type: custom:button-card
            name: Stop Charging
            icon: mdi:power-plug-off
            show_name: true
            tap_action:
              action: call-service
              service: tesla_custom.api_command
              service_data:
                device_id: !secret tesla_device_id
                command: charge_stop

4.3 Analytics Dashboard

# lovelace configuration - analytics.yaml
title: Energy Analytics
views:
  - title: Analytics
    path: analytics
    icon: mdi:chart-line
    badges: []
    cards:
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Daily Energy Balance"
          - type: custom:apexcharts-card
            header:
              title: Energy Production vs Consumption
              show: true
            graph_span: 7d
            span:
              start: week
            series:
              - entity: sensor.daily_energy_production
                name: Production (kWh)
                stroke_width: 2
                color: '#2ecc71'
                type: column
              - entity: sensor.daily_energy_consumption
                name: Consumption (kWh)
                stroke_width: 2
                color: '#e74c3c'
                type: column
              - entity: sensor.daily_grid_import
                name: Grid Import (kWh)
                stroke_width: 2
                color: '#3498db'
                type: column
              - entity: sensor.daily_grid_export
                name: Grid Export (kWh)
                stroke_width: 2
                color: '#f39c12'
                type: column
                
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Battery Utilization"
          - type: custom:mini-graph-card
            name: Home Battery SOC
            hours_to_show: 48
            points_per_hour: 2
            line_width: 2
            entities:
              - entity: sensor.battery_soc
                name: Battery Level
                
          - type: custom:apexcharts-card
            header:
              title: Tesla Charging Pattern
              show: true
            graph_span: 7d
            series:
              - entity: sensor.tesla_daily_energy_added
                name: Charge Added (kWh)
                stroke_width: 2
                color: '#9b59b6'
                type: column
                
      - type: vertical-stack
        cards:
          - type: markdown
            content: "## Energy Cost Savings"
          - type: custom:apexcharts-card
            header:
              title: Daily Energy Costs
              show: true
            graph_span: 30d
            span:
              start: month
            series:
              - entity: sensor.daily_energy_cost
                name: Actual Cost (€)
                stroke_width: 2
                color: '#e74c3c'
              - entity: sensor.daily_energy_cost_without_optimization
                name: Estimated Cost Without System (€)
                stroke_width: 2
                color: '#7f8c8d'
                curve: smooth

5. Predictive Energy Model

Let’s create a predictive model using the Python integration in Home Assistant to forecast energy production and consumption.

# configuration.yaml
python_script:

Create a new file: /config/python_scripts/energy_prediction.py:

# energy_prediction.py
import datetime
import numpy as np
from sklearn.ensemble import RandomForestRegressor
import pickle
import os
 
# Define path for model storage
MODEL_PATH = "/config/python_scripts/energy_models/"
if not os.path.exists(MODEL_PATH):
    os.makedirs(MODEL_PATH)
 
# Get Home Assistant API and states
hass = hass  # noqa
now = datetime.datetime.now()
 
# Collect weather forecast data
try:
    weather_forecast = []
    cloud_cover = []
    temperature = []
    
    for day in range(2):  # Today and tomorrow
        for hour in range(24):
            forecast_time = now.replace(hour=hour, minute=0, second=0, microsecond=0) + datetime.timedelta(days=day)
            forecast_str = forecast_time.strftime("%Y-%m-%d_%H")
            
            # Get forecast entities for each hour
            cloud_entity = f"sensor.forecast_cloud_cover_{forecast_str}"
            temp_entity = f"sensor.forecast_temperature_{forecast_str}"
            
            if cloud_entity in hass.states.entity_ids("sensor"):
                cloud_cover.append(float(hass.states.get(cloud_entity).state))
            else:
                cloud_cover.append(50)  # Default value
                
            if temp_entity in hass.states.entity_ids("sensor"):
                temperature.append(float(hass.states.get(temp_entity).state))
            else:
                temperature.append(20)  # Default value
    
    # Get historical production data for the last 30 days
    production_history = []
    consumption_history = []
    weather_history = []
    day_of_week_history = []
    hour_of_day_history = []
    
    # Load existing data if available
    history_file = f"{MODEL_PATH}energy_history.pkl"
    if os.path.exists(history_file):
        with open(history_file, 'rb') as f:
            history_data = pickle.load(f)
            production_history = history_data.get('production', [])
            consumption_history = history_data.get('consumption', [])
            weather_history = history_data.get('weather', [])
            day_of_week_history = history_data.get('day_of_week', [])
            hour_of_day_history = history_data.get('hour_of_day', [])
    
    # Add today's actual values to history
    for hour in range(now.hour):
        timestamp = now.replace(hour=hour, minute=0, second=0, microsecond=0)
        history_time_str = timestamp.strftime("%Y-%m-%d_%H")
        
        prod_entity = f"sensor.solar_production_{history_time_str}"
        cons_entity = f"sensor.home_consumption_{history_time_str}"
        weather_entity = f"sensor.cloud_cover_{history_time_str}"
        
        if prod_entity in hass.states.entity_ids("sensor"):
            production_history.append(float(hass.states.get(prod_entity).state))
            consumption_history.append(float(hass.states.get(cons_entity).state))
            weather_history.append(float(hass.states.get(weather_entity).state))
            day_of_week_history.append(timestamp.weekday())
            hour_of_day_history.append(timestamp.hour)
    
    # Ensure we have enough data
    if len(production_history) > 48:  # At least 48 hours of data
        # Train production model
        X_prod = np.column_stack((weather_history, day_of_week_history, hour_of_day_history))
        y_prod = np.array(production_history)
        
        # Train consumption model
        X_cons = np.column_stack((day_of_week_history, hour_of_day_history, production_history))
        y_cons = np.array(consumption_history)
        
        # Create and train models
        prod_model = RandomForestRegressor(n_estimators=50, random_state=42)
        prod_model.fit(X_prod, y_prod)
        
        cons_model = RandomForestRegressor(n_estimators=50, random_state=42)
        cons_model.fit(X_cons, y_cons)
        
        # Save models
        with open(f"{MODEL_PATH}production_model.pkl", 'wb') as f:
            pickle.dump(prod_model, f)
        
        with open(f"{MODEL_PATH}consumption_model.pkl", 'wb') as f:
            pickle.dump(cons_model, f)
        
        # Save updated history
        history_data = {
            'production': production_history[-720:],  # Keep last 30 days
            'consumption': consumption_history[-720:],
            'weather': weather_history[-720:],
            'day_of_week': day_of_week_history[-720:],
            'hour_of_day': hour_of_day_history[-720:]
        }
        with open(history_file, 'wb') as f:
            pickle.dump(history_data, f)
        
        # Generate predictions for next 48 hours
        forecast_production = []
        forecast_consumption = []
        
        for day in range(2):  # Today and tomorrow
            for hour in range(24):
                forecast_time = now.replace(hour=hour, minute=0, second=0, microsecond=0) + datetime.timedelta(days=day)
                
                # Skip hours that have already passed today
                if day == 0 and hour < now.hour:
                    continue
                
                hour_idx = day * 24 + hour
                if hour_idx < len(cloud_cover):
                    # Production forecast
                    X_prod_pred = np.array([[
                        cloud_cover[hour_idx],
                        forecast_time.weekday(),
                        hour
                    ]])
                    
                    prod_pred = prod_model.predict(X_prod_pred)[0]
                    prod_pred = max(0, prod_pred)  # Production can't be negative
                    
                    # Consumption forecast based on production prediction
                    X_cons_pred = np.array([[
                        forecast_time.weekday(),
                        hour,
                        prod_pred
                    ]])
                    
                    cons_pred = cons_model.predict(X_cons_pred)[0]
                    cons_pred = max(100, cons_pred)  # Base consumption
                    
                    # Store predictions
                    time_str = forecast_time.strftime("%Y-%m-%d %H:%M")
                    forecast_production.append((time_str, prod_pred))
                    forecast_consumption.append((time_str, cons_pred))
                    
                    # Create/update sensor states
                    time_key = forecast_time.strftime("%Y%m%d%H")
                    hass.states.set(f"sensor.forecast_production_{time_key}", prod_pred, {
                        "unit_of_measurement": "W",
                        "friendly_name": f"Forecast Production {forecast_time.strftime('%d/%m %H:%M')}",
                        "icon": "mdi:solar-power"
                    })
                    
                    hass.states.set(f"sensor.forecast_consumption_{time_key}", cons_pred, {
                        "unit_of_measurement": "W",
                        "friendly_name": f"Forecast Consumption {forecast_time.strftime('%d/%m %H:%M')}",
                        "icon": "mdi:power-socket-eu"
                    })
        
        # Calculate daily totals
        tomorrow = now.date() + datetime.timedelta(days=1)
        tomorrow_prod_total = sum(prod for time_str, prod in forecast_production if tomorrow.strftime("%Y-%m-%d") in time_str) / 1000  # Convert to kWh
        tomorrow_cons_total = sum(cons for time_str, cons in forecast_consumption if tomorrow.strftime("%Y-%m-%d") in time_str) / 1000  # Convert to kWh
        
        # Update daily forecast sensors
        hass.states.set("sensor.tomorrow_production_forecast", tomorrow_prod_total, {
            "unit_of_measurement": "kWh",
            "friendly_name": "Tomorrow's Production Forecast",
            "icon": "mdi:solar-power"
        })
        
        hass.states.set("sensor.tomorrow_consumption_forecast", tomorrow_cons_total, {
            "unit_of_measurement": "kWh",
            "friendly_name": "Tomorrow's Consumption Forecast",
            "icon": "mdi:power-socket-eu"
        })
        
        # Calculate surplus/deficit forecast
        surplus = tomorrow_prod_total - tomorrow_cons_total
        hass.states.set("sensor.tomorrow_energy_balance", surplus, {
            "unit_of_measurement": "kWh",
            "friendly_name": "Tomorrow's Energy Balance",
            "icon": "mdi:scale-balance"
        })
        
        # Success message
        hass.states.set("sensor.energy_prediction_status", "Success", {
            "last_run": now.isoformat(),
            "friendly_name": "Energy Prediction Status"
        })
    else:
        # Not enough data yet
        hass.states.set("sensor.energy_prediction_status", "Insufficient Data", {
            "last_run": now.isoformat(),
            "friendly_name": "Energy Prediction Status",
            "required_hours": 48,
            "current_hours": len(production_history)
        })
 
except Exception as e:
    # Error handling
    hass.states.set("sensor.energy_prediction_status", "Error", {
        "last_run": now.isoformat(),
        "friendly_name": "Energy Prediction Status",
        "error": str(e)
    })

Set up an automation to run the prediction model:

# automations.yaml
- alias: "Run Energy Prediction Model"
  trigger:
    - platform: time
      at: "00:05:00"  # Run shortly after midnight
    - platform: time
      at: "12:05:00"  # Update mid-day
  action:
    - service: python_script.energy_prediction

6. Implementation Roadmap

Here’s a prioritized implementation plan:

Phase 1: Foundation (Week 1-2)

  • Install Home Assistant if not already done
  • Set up GoodWe integration and verify data flow
  • Configure basic energy monitoring
  • Create initial Energy dashboard
  • Set up external data sources (weather, electricity prices)

Phase 2: Device Integration (Week 3-4)

  • Configure Tesla integration
  • Add smart plugs for heat pumps and dehumidifiers
  • Verify all devices are reporting correctly
  • Implement basic manual control via Home Assistant

Phase 3: Basic Automation (Week 5-6)

  • Implement solar self-consumption optimization
  • Configure basic battery charging/discharging based on time-of-use
  • Set up dehumidifier scheduling during solar production
  • Implement water heater optimization

Phase 4: Advanced Automation (Week 7-8)

  • Implement Tesla charging optimization
  • Create predictive energy model
  • Fine-tune battery management strategy
  • Advanced heat pump controls based on forecasts

Phase 5: Optimization & Refinement (Week 9-10)

  • Create comprehensive dashboards
  • Fine-tune automation parameters
  • Implement energy cost tracking
  • Test extreme scenarios (very cloudy days, grid outages)

Phase 6: Advanced Features (Week 11-12)

  • Implement voice control if desired
  • Add mobile notifications for key events
  • Configure backup systems for critical functions
  • Integrate with additional services

7. Troubleshooting Guide

GoodWe Integration Issues

ProblemCauseSolution
No data from GoodWeConnection issueVerify IP address and port. Check if inverter is accessible from Home Assistant network.
Intermittent dataNetwork stabilityConsider connecting via Ethernet instead of Wi-Fi. Reduce polling frequency.
Unexpected readingsModbus register mappingUse correct inverter model in configuration, or manually map registers.
Battery data missingIntegration version issueUpdate to latest HACS GoodWe integration.

Tesla API Issues

ProblemCauseSolution
Authentication failsPassword/token issueRegenerate token, verify credentials.
”Vehicle unavailable”Car in sleep modeUse wake_up command before other commands.
API rate limitingToo frequent pollingIncrease scan_interval to at least 10 minutes.
Charging commands failVehicle state mismatchCheck if car is plugged in. Use vehicle.update() before commands.

Heat Pumps and Dehumidifiers

ProblemCauseSolution
Devices not respondingSmart plug connectivityVerify Wi-Fi coverage, restart plugs.
Power readings inaccurateCalibration issueSet correct wattage in device configuration.
Unexpected device stateAutomation conflictsReview automation trigger conditions for overlaps.
Device switching too oftenThreshold too tightAdd hysteresis to decision logic (5-10% buffer zones).

Energy Model Issues

ProblemCauseSolution
Prediction failingMissing requirementsInstall scikit-learn via HACS Python Script dependencies.
Inaccurate predictionsNot enough training dataLet system collect at least 2 weeks of data.
Model not updatingFile permission issueCheck permissions for model directory in Home Assistant.
Seasonal changes affect accuracyOutdated modelForce model rebuild with full history monthly.

8. Future Expansion Options

Demand Response Integration

  • Integrate with Portuguese grid demand response programs (when available)
  • Prepare system for future virtual power plant participation
  • Set up automatic response to grid frequency signals

Enhanced Predictions

  • Add machine learning models for more precise consumption forecasting
  • Integrate holiday and occupancy prediction into energy model
  • Connect to grid congestion prediction APIs (when available in Portugal)

Additional Hardware

  • Add smart blinds/shutters to help with thermal management
  • Install EV charger with dynamic load balancing
  • Add energy consumption monitoring for major appliances

System Intelligence

  • Implement fully predictive battery management that learns from usage patterns
  • Create seasonal optimization strategies specific to Portuguese climate
  • Develop voice assistant integration for energy status reports

Grid Export Optimization

  • Monitor Portugal’s grid export policies and optimize for maximum revenue
  • Implement dynamic export limiting based on grid needs and prices
  • Prepare for peer-to-peer energy trading when regulations allow

9. Resource List

Home Assistant Resources

Portugal-Specific Resources

Technical Documentation

Portuguese Home Automation Communities

This implementation plan provides a comprehensive approach to optimizing your home energy system in Portugal. By following this roadmap, you’ll create an advanced setup that maximizes solar self-consumption, minimizes electricity costs, and provides intelligent control of all your energy-consuming devices. The step-by-step implementation allows you to build the system progressively, ensuring each component works correctly before moving to the next level of complexity.

Would you like me to elaborate on any specific section or provide more details on a particular component of the system?