# Loads default set of integrations. Do not remove.
default_config:

# Keep OctoPrint's job-list sensor out of the history DB (large JSON attribute, refreshed every 5 min)
recorder:
  exclude:
    entities:
      - sensor.octoprint_recent_prints

# Core Utility Meter Engine (Required for Hilo to generate compatible energy dashboard metrics)
utility_meter:

# Shell Commands
shell_command:
  cleanup_blink_snapshots: "find /media /config/www -name 'blink_*.jpg' -mmin +360 -delete"
  # IPv6 workaround: static address, no gateway -> v6 internet fails fast, Matter link-local unaffected
  ipv6_static_nogw: "sh /config/netfix_ipv6.sh"

# Rest Commands (OctoPrint nozzle extrusion)
rest_command:
  octoprint_extrude_10:
    url: "https://ender5pro.duckdns.org/api/printer/command"
    method: POST
    content_type: "application/json"
    headers:
      X-Api-Key: !secret octoprint_api_key
    payload: '{"commands": ["G91", "G1 E10 F300", "G90"]}'

# Load ffmpeg
ffmpeg:

# Enable Streams
stream:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

panel_custom:
  - name: developer-tools
    sidebar_title: Developer Tools
    sidebar_icon: mdi:hammer-wrench
    url_path: developer-tools/yaml
    embed_iframe: true
    require_admin: true

# Combined Template Section
template:
  # Nest Camera Event Trigger
  - trigger:
      - platform: event
        event_type: nest_event
        event_data:
          type: camera_motion
    binary_sensor:
      - name: "Nest Camera Motion"
        state: "true"
        auto_off: 10
        device_class: motion

  # Time-Pattern Trigger (Forces calculation updates every minute)
  - trigger:
      - platform: time_pattern
        minutes: "/1"
    sensor:
      - name: "Hydro Quebec Active Rate"
        unique_id: hydro_quebec_active_rate
        unit_of_measurement: "CAD/kWh"
        state: >
          {% set daily_consumption = states('sensor.meter00_daily_grid_energy') | float(999) %}
          {% set low_rate = states('sensor.hilo_rate_low') | float(0.07065) %}
          {% set medium_rate = states('sensor.hilo_rate_medium') | float(0.11142) %}

          {% if daily_consumption < 40.0 %}
            {{ low_rate }}
          {% else %}
            {{ medium_rate }}
          {% endif %}

      # AUTOMATIC LOOKUP SENSOR: Dynamically extracts the active living room climate entity ID
      - name: "HVAC Real-Time Power Draw"
        unique_id: hvac_real_time_power_draw
        unit_of_measurement: "kW"
        device_class: power
        state_class: measurement
        state: >
          {% set hvac = 'climate.living_room_living_room' %}
          {% if states(hvac) not in ['unknown', 'unavailable'] %}
            {% set action = state_attr(hvac, 'hvac_action') | string | lower %}
            {% if action == 'cooling' %}
              2.12
            {% elif action == 'heating' %}
              {% if is_state_attr(hvac, 'preset_mode', 'eco') or is_state_attr(hvac, 'aux_heat', 'on') %}
                20.5
              {% else %}
                2.5
              {% endif %}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}

      # ADJUSTED SENSOR: Scaled down from 1.50 to 1.35 to fix Energy Dashboard overlap
      - name: "Pool Pump Estimated Power Draw"
        unique_id: pool_pump_estimated_power_draw
        unit_of_measurement: "kW"
        device_class: power
        state_class: measurement
        state: >
          {% if is_state('input_boolean.pool_pump_in_use', 'on') %}
            1.25
          {% else %}
            0
          {% endif %}

      # FIXED SENSOR: Pulls true variable watts from sensor.basement_power and converts to kW
      - name: "Basement Heater Power Draw"
        unique_id: basement_heater_power_draw
        unit_of_measurement: "kW"
        device_class: power
        state_class: measurement
        state: >
          {% set raw_watts = states('sensor.basement_power') | float(0) %}
          {{ (raw_watts / 1000) | round(2) }}

      # WATER HEATER SENSOR: Pulls hardware power from Hilo water heater switch and converts W to kW
      - name: "Water Heater Power Draw"
        unique_id: water_heater_power_draw
        unit_of_measurement: "kW"
        device_class: power
        state_class: measurement
        state: >
          {% set raw_watts = states('sensor.water_heater_power') | float(0) %}
          {{ (raw_watts / 1000) | round(2) }}

  # State-based Template Sensors (Blink Temperature Dropout Filtering for all 4 cameras)
  - sensor:
      - name: "Blink Front Temperature Clean"
        unique_id: blink_front_temperature_clean
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        state: >
          {% set raw = states('sensor.blink_front_temperature') | float(default=-999) %}
          {% if raw > -40 and raw < 60 %}
            {{ raw }}
          {% else %}
            {{ states('sensor.blink_front_temperature_clean') }}
          {% endif %}

      - name: "Blink Backyard Shed Temperature Clean"
        unique_id: blink_backyard_shed_temperature_clean
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        state: >
          {% set raw = states('sensor.blink_backyard_shed_temperature') | float(default=-999) %}
          {% if raw > -40 and raw < 60 %}
            {{ raw }}
          {% else %}
            {{ states('sensor.blink_backyard_shed_temperature_clean') }}
          {% endif %}

      - name: "Blink Backyard Tree Temperature Clean"
        unique_id: blink_backyard_tree_temperature_clean
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        state: >
          {% set raw = states('sensor.blink_backyard_tree_temperature') | float(default=-999) %}
          {% if raw > -40 and raw < 60 %}
            {{ raw }}
          {% else %}
            {{ states('sensor.blink_backyard_tree_temperature_clean') }}
          {% endif %}

      - name: "Blink Backyard Temperature Clean"
        unique_id: blink_backyard_temperature_clean
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        state: >
          {% set raw = states('sensor.blink_backyard_temperature') | float(default=-999) %}
          {% if raw > -40 and raw < 60 %}
            {{ raw }}
          {% else %}
            {{ states('sensor.blink_backyard_temperature_clean') }}
          {% endif %}

      # POOL PUMP SENSOR: Converts kW sensor to Watts for Watt-based gauge cards
      - name: "Pool Pump Estimated Power Draw Watts"
        unique_id: pool_pump_estimated_power_draw_watts
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >
          {% set kw = states('sensor.pool_pump_estimated_power_draw') | float(0) %}
          {{ (kw * 1000) | round(0) }}

      # HVAC SENSOR: Converts kW sensor to Watts for Watt-based gauge cards
      - name: "HVAC Real-Time Power Draw Watts"
        unique_id: hvac_real_time_power_draw_watts
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >
          {% set kw = states('sensor.hvac_real_time_power_draw') | float(0) %}
          {{ (kw * 1000) | round(0) }}

      # BASEMENT HEATER: Converts kW sensor to Watts for Watt-based gauge cards
      - name: "Basement Heater Power Draw Watts"
        unique_id: basement_heater_power_draw_watts
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >
          {% set kw = states('sensor.basement_heater_power_draw') | float(0) %}
          {{ (kw * 1000) | round(0) }}

      # WATER HEATER: Converts kW sensor to Watts for Watt-based gauge cards
      - name: "Water Heater Power Draw Watts"
        unique_id: water_heater_power_draw_watts
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >
          {% set kw = states('sensor.water_heater_power_draw') | float(0) %}
          {{ (kw * 1000) | round(0) }}

      # OCTOPRINT: Most recent print's filament usage (mm), from PrintHistory plugin
      - name: "OctoPrint Last Print Filament"
        unique_id: octoprint_last_print_filament
        unit_of_measurement: "mm"
        icon: mdi:spool
        state: >-
          {% set fm = state_attr('sensor.octoprint_filament_used_total', 'filamentModels') %}
          {% set total = fm.get('total', {}) if fm else {} %}
          {{ total.get('usedLength', 0) | float | round(2) }}

# Legacy and Integration Sensor Section
sensor:
  - platform: torque
    email: torque-car@asuscomm.com
    name: MyCar

  # RE-ADDED INTEGRATION ENGINE: Converts your pool pump kW into valid long-term energy stats
  - platform: integration
    source: sensor.pool_pump_estimated_power_draw
    name: Pool Pump Total Energy
    unique_id: pool_pump_total_energy_riemann_sum
    method: left
    round: 2

  # NEW INTEGRATION SENSOR: Converts HVAC kW into valid long-term energy stats (kWh)
  - platform: integration
    source: sensor.hvac_real_time_power_draw
    name: HVAC Total Energy
    unique_id: hvac_total_energy_riemann_sum
    method: left
    round: 2

# OctoPrint PrintHistory - filament usage from https://ender5pro.duckdns.org
rest:
  - resource: "https://ender5pro.duckdns.org/plugin/PrintJobHistory/loadPrintJobHistoryByQuery?from=0&to=100000&sortColumn=printStartDateTime&sortOrder=desc&filterName="
    method: GET
    headers:
      X-Api-Key: !secret octoprint_api_key
    scan_interval: 300
    sensor:
      - name: "OctoPrint Filament Used Total"
        unique_id: octoprint_filament_used_total
        unit_of_measurement: "mm"
        device_class: distance
        state_class: total
        icon: mdi:spool
        value_template: >-
          {{
            value_json.allPrintJobs
            | map(attribute='filamentModels')
            | select('defined')
            | map(attribute='total')
            | select('defined')
            | map(attribute='usedLength')
            | select('is_number')
            | sum
            | round(2)
          }}
        json_attributes_path: "$.allPrintJobs[0]"
        json_attributes:
          - "fileName"
          - "filamentModels"
          - "printStatusResult"
          - "duration"
          - "printStartDateTimeFormatted"
      # TOTAL FILAMENT MASS: sums PrintJobHistory's own per-job weight (density-aware), in grams
      - name: "OctoPrint Filament Used Weight Total"
        unique_id: octoprint_filament_used_weight_total
        unit_of_measurement: "g"
        device_class: weight
        state_class: total
        icon: mdi:spool
        value_template: >-
          {% set ns = namespace(weight=0) %}
          {% for job in value_json.allPrintJobs | default([]) %}
            {% set models = job.get('filamentModels') or {} %}
            {% set ns.weight = ns.weight + (models.get('total', {}).get('usedWeight') or 0) | float(0) %}
          {% endfor %}
          {{ ns.weight | round(2) }}
      - name: "OctoPrint Recent Prints"
        unique_id: octoprint_recent_prints
        icon: mdi:history
        value_template: >-
          {{ value_json.allPrintJobs | length }}
        json_attributes:
          - "allPrintJobs"
  - resource: "https://ender5pro.duckdns.org/api/job"
    method: GET
    headers:
      X-Api-Key: !secret octoprint_api_key
    scan_interval: 30
    sensor:
      - name: "OctoPrint Print Progress Live"
        unique_id: octoprint_print_progress_live
        unit_of_measurement: "%"
        state_class: measurement
        icon: mdi:printer-3d-nozzle
        value_template: >-
          {{
            value_json.progress.completion | float(0) | round(2)
          }}
        json_attributes_path: "$.progress"
        json_attributes:
          - "filepos"
          - "printTime"
          - "printTimeLeft"
          - "printTimeLeftOrigin"
      - name: "OctoPrint Print Time Left Live"
        unique_id: octoprint_print_time_left_live
        device_class: duration
        unit_of_measurement: "s"
        state_class: measurement
        icon: mdi:timer-outline
        value_template: >-
          {{
            value_json.progress.printTimeLeft | int(-1)
          }}
      - name: "OctoPrint Print State Live"
        unique_id: octoprint_print_state_live
        icon: mdi:printer-3d
        value_template: "{{ value_json.state }}"

# OctoPrint physical position (holds last value when idle; raw discovery sensor zeroes on currentZ:null)
mqtt:
  sensor:
    - name: "Position Z"
      unique_id: octoprint_position_z
      state_topic: "octoPrint/event/PositionUpdate"
      value_template: "{{ value_json.z }}"
      unit_of_measurement: "mm"
      device_class: distance
      icon: mdi:axis-z-arrow
      availability:
        - topic: "octoPrint/mqtt"
          payload_available: "connected"
          payload_not_available: "disconnected"
      device:
        identifiers:
          - "041acd1efce0452ca0a0360eeb89c3b4"
        name: "OctoPrint"

    - name: "Print File Size"
      unique_id: octoprint_print_file_size
      state_topic: "octoPrint/progress/printing"
      value_template: "{{ value_json.printer_data.job.file.size | int(0) }}"
      unit_of_measurement: "B"
      device_class: data_size
      icon: mdi:file-code
      availability:
        - topic: "octoPrint/mqtt"
          payload_available: "connected"
          payload_not_available: "disconnected"
      device:
        identifiers:
          - "041acd1efce0452ca0a0360eeb89c3b4"
        name: "OctoPrint"

    - name: "Print User"
      unique_id: octoprint_print_user
      state_topic: "octoPrint/progress/printing"
      value_template: "{{ value_json.printer_data.job.user | default('') }}"
      icon: mdi:account
      availability:
        - topic: "octoPrint/mqtt"
          payload_available: "connected"
          payload_not_available: "disconnected"
      device:
        identifiers:
          - "041acd1efce0452ca0a0360eeb89c3b4"
        name: "OctoPrint"

emulated_hue:
  host_ip: 192.168.1.140
  advertise_ip: 192.168.1.140
  listen_port: 80
  expose_by_default: true
  entities:
    input_boolean.cync_motion_bridge:
      name: "Cync Motion Bridge"
      hidden: false

nest_snapshot:

# G-code proxy for the 3D toolpath viewer card (www/gcode_viewer_card.js)
octoprint_gcode_proxy: