#:########################################################################################:#
# TITLE: COMMON NETWORK STATIC
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# PURPOSE:
# Common ESPHome WiFi/network package using static IP addressing.
#
# Intended for fixed devices on the main Home Assistant / IoT WiFi network.
#:########################################################################################:#
# OPERATION NOTES:
# - Uses configured WiFi SSID/password from secrets.
# - Uses static IP settings supplied by the including device YAML.
# - Provides fallback AP if configured WiFi fails.
# - Captive portal allows WiFi settings to be manually overridden.
# - Safe Mode is enabled to help recover from boot loops.
# - OTA updates are enabled.
# - IPv6 can be enabled/disabled by substitution.
#:########################################################################################:#
# REQUIRED PACKAGE VARS:
# These are normally passed in by the device YAML package include.
#
# local_device_name:
#   Device name used for fallback AP SSID.
#
# local_static_ip_address:
#   Static IP address for this specific device.
#
# local_current_ip_address:
#   Address ESPHome should use for upload/reconnect.
#   Usually the same as local_static_ip_address.
#
# local_ota_pass:
#   OTA password.
#:########################################################################################:#
# OPTIONAL NOTES:
# - For portable devices, use common/network_common_dhcp.yaml instead.
# - If changing a device IP address, update local_current_ip_address during the transition.
# - After the device is reachable at the new address, set local_current_ip_address back to
#   local_static_ip_address.
#:########################################################################################:#


#:########################################################################################:#
# SUBSTITUTIONS:
# Common network variable substitutions
#:########################################################################################:#
substitutions:
  # WiFi Credentials
  wifi_ssid: !secret ha_wifi_ssid
  wifi_password: !secret ha_wifi_password
  fallback_ap_password: !secret fallback_ap_password

  # Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken
  wifi_fast_connect: "false"

  # Define a domain for this device to use
  # Example: iot.home.lan means the device appears as device-name.iot.home.lan in DNS/DHCP logs
  dns_domain: ".local"

  # Automatically add the MAC address to the device name
  # Useful if using a single firmware image for multiple devices
  add_mac_suffix: "false"

  # Enable or disable IPv6 networking on the device
  ipv6_enable: "false"

  # Static IP Network Settings
  static_ip_subnet: !secret ha_wifi_subnet
  static_ip_gateway: !secret ha_wifi_gateway
  static_ip_dns1: !secret ha_wifi_dns1
  static_ip_dns2: !secret ha_wifi_dns2

  # Fallback AP Timing
  fallback_ap_timeout: "10min"

  # Network reconnect every x hours to ensure best access point
  base_interval_hours: "23"
  random_offset_max_minutes: "59"


#:########################################################################################:#
# WIFI:
# Static IP WiFi configuration with fallback AP and captive portal
# https://esphome.io/components/wifi.html
#:########################################################################################:#
wifi:
  ssid: ${wifi_ssid}
  password: ${wifi_password}

  # ESP8266 default is NONE. Power save can reduce WiFi reliability.
  power_save_mode: none

  # Static IP address
  manual_ip:
    static_ip: ${local_static_ip_address}
    gateway: ${static_ip_gateway}
    subnet: ${static_ip_subnet}
    dns1: ${static_ip_dns1}
    dns2: ${static_ip_dns2}

  # Address ESPHome should use when connecting/uploading
  use_address: ${local_current_ip_address}

  # Fallback hotspot in case configured WiFi connection fails
  ap:
    ssid: ${local_device_name}
    password: ${fallback_ap_password}
    ap_timeout: ${fallback_ap_timeout}

  # Allow rapid re-connection to previously connected WiFi SSID, skipping scan of all SSIDs
  fast_connect: ${wifi_fast_connect}

  # Define DNS domain / suffix to add to hostname
  domain: ${dns_domain}

  min_auth_mode: WPA2

  # Reboot eventually when WiFi is down
  reboot_timeout: 56h


#:########################################################################################:#
# CAPTIVE PORTAL:
# Fallback mechanism for changing WiFi if the configured WiFi fails
# https://esphome.io/components/captive_portal.html
#:########################################################################################:#
captive_portal:


#:########################################################################################:#
# OTA:
# Enable Over the Air update capability
# https://esphome.io/components/ota.html
#:########################################################################################:#
ota:
  - platform: esphome
    password: ${local_ota_pass}
    version: 2

  # Optional: uncomment if you want OTA uploads through the web interface
  #- platform: web_server


#:########################################################################################:#
# SAFE MODE:
# Safe mode will detect boot loops
# https://esphome.io/components/safe_mode
#:########################################################################################:#
safe_mode:


#:########################################################################################:#
# NETWORK:
# Global configuration for all network types
# https://esphome.io/components/network.html
#:########################################################################################:#
network:
  enable_ipv6: ${ipv6_enable}


#:########################################################################################:#
# SCRIPT:
# Optional network reconnect every x hours + random minutes
#
# This can be enabled if a device tends to stay connected to a weaker AP after roaming.
#:########################################################################################:#
#script:
#  - id: random_reconnect
#    mode: restart
#    then:
#      - lambda: |-
#          // Compute total delay: base hours + random offset minutes
#          uint32_t extra;
#
#          #if defined(ESP32)
#          // ESP32 uses esp_random()
#          extra = esp_random() % (${random_offset_max_minutes} + 1);
#          #elif defined(ESP8266)
#          // ESP8266 Arduino core uses os_random()
#          extra = os_random() % (${random_offset_max_minutes} + 1);
#          #else
#          // Fallback
#          extra = esp_random() % (${random_offset_max_minutes} + 1);
#          #endif
#
#          uint32_t total_s = ${base_interval_hours} * 3600 + extra * 60;
#          ESP_LOGI("random_reconnect", "Next reconnect in %u seconds", total_s);
#
#          // Delay inside lambda blocks script execution, but is OK for reconnect timing
#          delay(total_s * 1000);
#
#      - logger.log: "network_check: performing reconnect"
#      - wifi.disable: {}
#      - delay: 1s
#      - wifi.enable: {}
#      - script.execute: random_reconnect