Files
homeai/homeai-esp32/setup.sh
Aodhan Collins c4cecbd8dc feat: ESP32-S3-BOX-3 room satellite — ESPHome config, OTA deploy, placeholder faces
Living room unit fully working: on-device wake word (hey_jarvis), voice pipeline
via HA (Wyoming STT → OpenClaw → Wyoming TTS), static PNG display states, OTA
updates. Includes deploy.sh for quick OTA with custom image support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 20:48:03 +00:00

178 lines
5.4 KiB
Bash

#!/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