#!/bin/bash # # detect-device.sh - Detect which doorbell board is connected # # Uses two methods: # 1. Firmware query (if flashed): sends "board" command, expects "[BOARD] xxx" # 2. Hardware probe (fallback): uses esptool to query chip type and flash size # # Usage: ./scripts/detect-device.sh [port] # If no port specified, tries common ports: /dev/ttyUSB0 /dev/ttyACM0 set -e # Configuration TIMEOUT_FIRMWARE=2 TIMEOUT_HARDWARE=5 # Known boards and their characteristics declare -A BOARD_CHIP=( ["esp32-s3-lcd-43"]="ESP32-S3" ["esp32-32e"]="ESP32" ["esp32-32e-4"]="ESP32" ) # Find available serial ports find_ports() { local ports=() for p in /dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyACM0 /dev/ttyACM1; do if [ -e "$p" ]; then ports+=("$p") fi done printf '%s\n' "${ports[@]}" } # Query firmware for board name query_firmware() { local port="$1" # Try using Python for more reliable serial communication local output output=$(python3 -c " import serial import time try: s = serial.Serial('$port', 115200, timeout=$TIMEOUT_FIRMWARE) time.sleep(0.5) s.write(b'board\r\n') time.sleep($TIMEOUT_FIRMWARE) print(s.read(200).decode('utf-8', errors='ignore')) s.close() except: pass " 2>/dev/null || true) # Look for [BOARD] xxx pattern if echo "$output" | grep -q '\[BOARD\]'; then local board board=$(echo "$output" | grep '\[BOARD\]' | sed 's/.*\[BOARD\] //' | tr -d '\r\n') if [ -n "$board" ]; then echo "$board" return 0 fi fi return 1 } # Hardware probe using esptool probe_hardware() { local port="$1" # Get chip info local chip_info chip_info=$(timeout "$TIMEOUT_HARDWARE" esptool --port "$port" chip_id 2>/dev/null || true) if [ -z "$chip_info" ]; then return 1 fi # Check for ESP32-S3 if echo "$chip_info" | grep -q "ESP32-S3"; then echo "esp32-s3-lcd-43" return 0 fi # For ESP32, check flash size if echo "$chip_info" | grep -q "ESP32"; then local flash_size flash_size=$(echo "$chip_info" | grep -i "flash size" | grep -oE '[0-9]+' | head -1 || echo "0") if [ -n "$flash_size" ] && [ "$flash_size" -ge 8 ]; then # 8MB+ flash - likely esp32-32e-4 echo "esp32-32e-4 (or esp32-32e)" return 0 else # 4MB or less - likely esp32-32e echo "esp32-32e (or esp32-32e-4)" return 0 fi fi return 1 } # Main detection logic detect() { local port="$1" # Try firmware query first (100% accurate if firmware responds) echo "Trying firmware query on $port..." >&2 local result result=$(query_firmware "$port" || true) if [ -n "$result" ]; then echo "Detected via firmware: $result" return 0 fi # Fall back to hardware probe echo "Trying hardware probe on $port..." >&2 result=$(probe_hardware "$port" || true) if [ -n "$result" ]; then echo "Detected via hardware: $result" return 0 fi echo "No device detected on $port" >&2 return 1 } # Entry point main() { local target_port="$1" if [ -n "$target_port" ]; then # Specific port requested if [ ! -e "$target_port" ]; then echo "Error: Port $target_port does not exist" >&2 exit 1 fi detect "$target_port" else # Auto-detect: try all available ports local found=0 for port in $(find_ports); do if detect "$port"; then found=1 break fi done if [ "$found" -eq 0 ]; then echo "No doorbell device detected" >&2 exit 1 fi fi } main "$@"