#:########################################################################################:#
# Package: BYD Charging Schedule At Home
# File:    byd_charging_schedule_athome.yaml
# Version: v1.1.0
# Date:    2026-07-23
#
# Purpose:
#   Enables the BYD Atto 3 charging schedule when the car arrives home.
#   Disables the schedule only after the car has been confirmed away for a
#   configurable delay, to avoid rapid toggling from uncertain presence detection.
#
# Behaviour:
#   - Confirmed arrival home:
#       Sets the schedule to 9:00 PM through midnight with charge-to-full disabled,
#       enables it, and retries cloud reconciliation once per minute.
#
#   - Confirmed away:
#       After away_confirm_minutes, disables the schedule and retries cloud
#       reconciliation once per minute.
#
#   - Manual control:
#       If the car is already home and the user or another HA automation turns
#       the schedule OFF manually, this package will not turn it back ON unless
#       the car is later confirmed away and then arrives home again.
#
# Notes:
#   - Home Assistant usually stores the device_tracker home state as "home",
#     even if the UI displays "At Home".
#   - Change away_confirm_minutes below if you want a longer/shorter debounce.
#:########################################################################################:#

input_boolean:
  byd_atto3_charging_schedule_confirmed_away:
    name: "BYD Atto 3 Charging Schedule - Confirmed Away"
    icon: mdi:car-off

automation:
  #:######################################################################################:#
  # ARRIVAL - Reconcile and enable schedule after a confirmed away period
  #:######################################################################################:#
  - id: byd_atto3_charging_schedule_arrival_enable
    alias: "BYD Atto 3 Charging Schedule - Arrival Enable"
    description: >
      Reconciles the BYD charging schedule to 9:00 PM through midnight and turns
      it ON when the car arrives home after a confirmed away period. Rechecks the
      cloud-confirmed state once per minute and retries failed updates.
    mode: single
    variables: &byd_charging_schedule_vars
      tracker_entity: device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker
      schedule_switch_entity: switch.atto_3_schedule_enabled
      schedule_start_time_entity: time.atto_3_start_time
      schedule_end_time_entity: time.atto_3_end_time
      schedule_charge_to_full_entity: switch.atto_3_charge_to_full

      # HA normally stores "At Home" as "home".
      home_state: "home"

      # Required charging schedule settings.
      expected_start_time: "21:00:00"
      expected_end_time: "00:00:00"

      # Adjustable YAML-only delay before the car is treated as truly away.
      away_confirm_minutes: 10

      # Verify cloud-confirmed schedule state at one-minute intervals.
      schedule_verify_attempts: 6
      schedule_verify_interval: "00:01:00"

      # These states will not be treated as confirmed away.
      ignored_tracker_states:
        - "unknown"
        - "unavailable"

    triggers:
      - trigger: state
        entity_id: device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker

    conditions:
      - condition: template
        value_template: >-
          {{ trigger.to_state is not none
             and trigger.from_state is not none
             and trigger.to_state.state == home_state
             and trigger.from_state.state == 'not_home' }}

    actions:
      - choose:
          - conditions:
              - condition: state
                entity_id: input_boolean.byd_atto3_charging_schedule_confirmed_away
                state: "on"
            sequence:
              - action: input_boolean.turn_off
                target:
                  entity_id: input_boolean.byd_atto3_charging_schedule_confirmed_away

              - repeat:
                  count: "{{ schedule_verify_attempts | int(6) }}"
                  sequence:
                    - if:
                        - condition: template
                          value_template: "{{ is_state(tracker_entity, home_state) }}"
                      then:
                        - if:
                            - condition: template
                              value_template: >-
                                {{ states(schedule_start_time_entity) != expected_start_time }}
                          then:
                            - action: time.set_value
                              continue_on_error: true
                              target:
                                entity_id: "{{ schedule_start_time_entity }}"
                              data:
                                time: "{{ expected_start_time }}"

                        - if:
                            - condition: template
                              value_template: >-
                                {{ states(schedule_end_time_entity) != expected_end_time }}
                          then:
                            - action: time.set_value
                              continue_on_error: true
                              target:
                                entity_id: "{{ schedule_end_time_entity }}"
                              data:
                                time: "{{ expected_end_time }}"

                        - if:
                            - condition: template
                              value_template: >-
                                {{ not is_state(schedule_charge_to_full_entity, 'off') }}
                          then:
                            - action: switch.turn_off
                              continue_on_error: true
                              target:
                                entity_id: "{{ schedule_charge_to_full_entity }}"

                        - if:
                            - condition: template
                              value_template: >-
                                {{ not is_state(schedule_switch_entity, 'on') }}
                          then:
                            - action: switch.turn_on
                              continue_on_error: true
                              target:
                                entity_id: "{{ schedule_switch_entity }}"

                    - delay: "{{ schedule_verify_interval }}"

  #:######################################################################################:#
  # DEPARTURE - Disable schedule after confirmed away timeout
  #:######################################################################################:#
  - id: byd_atto3_charging_schedule_departure_disable_after_timeout
    alias: "BYD Atto 3 Charging Schedule - Departure Disable After Timeout"
    description: >
      When the car leaves home, waits for the configured away timeout. If the car
      is still away, marks it confirmed away, turns the BYD charging schedule OFF,
      and retries failed cloud updates once per minute.
    mode: restart
    variables: *byd_charging_schedule_vars

    triggers:
      - trigger: state
        entity_id: device_tracker.byd_atto3_ibeacon_bur4c2a_bermuda_tracker

    conditions:
      - condition: template
        value_template: >-
          {% set new_state = trigger.to_state.state if trigger.to_state is not none else '' %}
          {{ new_state != home_state
             and new_state not in ignored_tracker_states }}

    actions:
      - delay:
          minutes: "{{ away_confirm_minutes | int(10) }}"

      - condition: template
        value_template: >-
          {% set current_state = states(tracker_entity) %}
          {{ current_state != home_state
             and current_state not in ignored_tracker_states }}

      - action: input_boolean.turn_on
        target:
          entity_id: input_boolean.byd_atto3_charging_schedule_confirmed_away

      - repeat:
          count: "{{ schedule_verify_attempts | int(6) }}"
          sequence:
            - if:
                - condition: template
                  value_template: >-
                    {% set current_state = states(tracker_entity) %}
                    {{ current_state != home_state
                       and current_state not in ignored_tracker_states
                       and not is_state(schedule_switch_entity, 'off') }}
              then:
                - action: switch.turn_off
                  continue_on_error: true
                  target:
                    entity_id: "{{ schedule_switch_entity }}"

            - delay: "{{ schedule_verify_interval }}"

  #:######################################################################################:#
  # STARTUP SAFETY - If HA restarts while the car is away, re-arm arrival logic
  #:######################################################################################:#
  - id: byd_atto3_charging_schedule_startup_away_check
    alias: "BYD Atto 3 Charging Schedule - Startup Away Check"
    description: >
      On Home Assistant startup, if the car is already away and remains away
      beyond the configured timeout, mark it confirmed away and reconcile the
      charging schedule OFF so the next confirmed arrival can enable it.
    mode: single
    variables: *byd_charging_schedule_vars

    triggers:
      - trigger: homeassistant
        event: start

    actions:
      - delay: "00:01:00"

      - condition: template
        value_template: >-
          {% set current_state = states(tracker_entity) %}
          {{ current_state != home_state
             and current_state not in ignored_tracker_states }}

      - delay:
          minutes: "{{ away_confirm_minutes | int(10) }}"

      - condition: template
        value_template: >-
          {% set current_state = states(tracker_entity) %}
          {{ current_state != home_state
             and current_state not in ignored_tracker_states }}

      - action: input_boolean.turn_on
        target:
          entity_id: input_boolean.byd_atto3_charging_schedule_confirmed_away

      - repeat:
          count: "{{ schedule_verify_attempts | int(6) }}"
          sequence:
            - if:
                - condition: template
                  value_template: >-
                    {% set current_state = states(tracker_entity) %}
                    {{ current_state != home_state
                       and current_state not in ignored_tracker_states
                       and not is_state(schedule_switch_entity, 'off') }}
              then:
                - action: switch.turn_off
                  continue_on_error: true
                  target:
                    entity_id: "{{ schedule_switch_entity }}"

            - delay: "{{ schedule_verify_interval }}"
