#!/usr/bin/env bash # homeai-esp32/setup.sh — P6: ESPHome firmware for ESP32-S3-BOX-3 # # Usage: # ./setup.sh — check environment + validate config # ./setup.sh flash — compile + flash via USB (first time) # ./setup.sh ota — compile + flash via OTA (wireless) # ./setup.sh logs — stream device logs # ./setup.sh validate — validate YAML without compiling # # Prerequisites: # - ~/homeai-esphome-env — Python 3.12 venv with ESPHome # - Home Assistant running on 10.0.0.199 # - Wyoming STT/TTS running on Mac Mini (ports 10300/10301) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" ESPHOME_VENV="${HOME}/homeai-esphome-env" ESPHOME="${ESPHOME_VENV}/bin/esphome" ESPHOME_DIR="${SCRIPT_DIR}/esphome" DEFAULT_CONFIG="${ESPHOME_DIR}/homeai-living-room.yaml" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } log_ok() { echo -e "${GREEN}[OK]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; } # ─── Environment checks ────────────────────────────────────────────────────── check_env() { local ok=true log_info "Checking environment..." # ESPHome venv if [[ -x "${ESPHOME}" ]]; then local version version=$("${ESPHOME}" version 2>/dev/null) log_ok "ESPHome: ${version}" else log_error "ESPHome not found at ${ESPHOME}" echo " Install: /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv ${ESPHOME_VENV}" echo " ${ESPHOME_VENV}/bin/pip install 'esphome>=2025.5.0'" ok=false fi # secrets.yaml if [[ -f "${ESPHOME_DIR}/secrets.yaml" ]]; then if grep -q "YOUR_" "${ESPHOME_DIR}/secrets.yaml" 2>/dev/null; then log_warn "secrets.yaml contains placeholder values — edit before flashing" ok=false else log_ok "secrets.yaml configured" fi else log_error "secrets.yaml not found at ${ESPHOME_DIR}/secrets.yaml" ok=false fi # Config file if [[ -f "${DEFAULT_CONFIG}" ]]; then log_ok "Config: $(basename "${DEFAULT_CONFIG}")" else log_error "Config not found: ${DEFAULT_CONFIG}" ok=false fi # Illustrations local illust_dir="${ESPHOME_DIR}/illustrations" local illust_count illust_count=$(find "${illust_dir}" -name "*.png" 2>/dev/null | wc -l | tr -d ' ') if [[ "${illust_count}" -ge 7 ]]; then log_ok "Illustrations: ${illust_count} PNGs in illustrations/" else log_warn "Missing illustrations (found ${illust_count}, need 7)" fi # Wyoming services on Mac Mini if curl -sf "http://localhost:10300" -o /dev/null 2>/dev/null || nc -z localhost 10300 2>/dev/null; then log_ok "Wyoming STT (port 10300) reachable" else log_warn "Wyoming STT (port 10300) not reachable" fi if curl -sf "http://localhost:10301" -o /dev/null 2>/dev/null || nc -z localhost 10301 2>/dev/null; then log_ok "Wyoming TTS (port 10301) reachable" else log_warn "Wyoming TTS (port 10301) not reachable" fi # Home Assistant if curl -sk "https://10.0.0.199:8123" -o /dev/null 2>/dev/null; then log_ok "Home Assistant (10.0.0.199:8123) reachable" else log_warn "Home Assistant not reachable — ESP32 won't be able to connect" fi if $ok; then log_ok "Environment ready" else log_warn "Some issues found — fix before flashing" fi } # ─── Commands ───────────────────────────────────────────────────────────────── cmd_flash() { local config="${1:-${DEFAULT_CONFIG}}" log_info "Compiling + flashing via USB: $(basename "${config}")" log_info "First compile downloads ESP-IDF toolchain (~500MB), takes 5-10 min..." cd "${ESPHOME_DIR}" "${ESPHOME}" run "$(basename "${config}")" } cmd_ota() { local config="${1:-${DEFAULT_CONFIG}}" log_info "Compiling + OTA upload: $(basename "${config}")" cd "${ESPHOME_DIR}" "${ESPHOME}" run "$(basename "${config}")" } cmd_logs() { local config="${1:-${DEFAULT_CONFIG}}" log_info "Streaming logs for: $(basename "${config}")" cd "${ESPHOME_DIR}" "${ESPHOME}" logs "$(basename "${config}")" } cmd_validate() { local config="${1:-${DEFAULT_CONFIG}}" log_info "Validating: $(basename "${config}")" cd "${ESPHOME_DIR}" "${ESPHOME}" config "$(basename "${config}")" log_ok "Config valid" } # ─── Main ───────────────────────────────────────────────────────────────────── case "${1:-}" in flash) check_env echo "" cmd_flash "${2:-}" ;; ota) check_env echo "" cmd_ota "${2:-}" ;; logs) cmd_logs "${2:-}" ;; validate) cmd_validate "${2:-}" ;; *) check_env echo "" echo "Usage: $0 {flash|ota|logs|validate} [config.yaml]" echo "" echo " flash Compile + flash via USB (first time)" echo " ota Compile + flash via OTA (wireless, after first flash)" echo " logs Stream device logs" echo " validate Validate YAML config without compiling" echo "" echo "Default config: $(basename "${DEFAULT_CONFIG}")" ;; esac