#!/usr/bin/env bash set -e source .env ## Spore Control Script ## Usage: ./ctl.sh [options] ## ## Commands: ## build [target] - Build firmware for target (base, d1_mini, etc.) ## flash [target] - Flash firmware to device ## uploadfs [target] - Upload filesystem to device ## ota update - OTA update specific node ## ota all - OTA update all nodes in cluster ## cluster members - List cluster members ## node wifi [ip] - Configure WiFi on node ## monitor - Monitor serial output ## ## Examples: ## ./ctl.sh build base ## ./ctl.sh flash d1_mini ## ./ctl.sh node wifi "MyNetwork" "MyPassword" ## ./ctl.sh node wifi "MyNetwork" "MyPassword" 192.168.1.100 function info { sed -n 's/^##//p' ctl.sh } function build { function target { echo "Building project for $1..." pio run -e $1 } function all { pio run } ${@:-all} } function flash { function target { echo "Flashing firmware for $1..." pio run --target upload -e $1 } ${@:-info} } function mkfs { ~/bin/mklittlefs -c data \ -s 0x9000 \ -b 4096 \ -p 256 \ littlefs.bin } function flashfs { esptool.py --port /dev/ttyUSB0 \ --baud 115200 \ write_flash 0xbb000 littlefs.bin } function uploadfs { echo "Uploading files to LittleFS..." pio run -e $1 -t uploadfs } function ota { function update { echo "Updating node at $1 with $2... " curl -X POST \ -F "file=@.pio/build/$2/firmware.bin" \ http://$1/api/node/update | jq -r '.status' } function all { echo "Updating all nodes..." curl -s http://$API_NODE/api/cluster/members | jq -r '.members.[].ip' | while read -r ip; do ota update $ip $1 done } ${@:-info} } function cluster { function members { curl -s http://$API_NODE/api/cluster/members | jq -r '.members[] | "\(.hostname) \(.ip)"' } ${@:-info} } function node { function wifi { if [ $# -lt 2 ]; then echo "Usage: $0 node wifi [node_ip]" echo " ssid: WiFi network name" echo " password: WiFi password" echo " node_ip: Optional IP address (defaults to API_NODE from .env)" return 1 fi local ssid="$1" local password="$2" local node_ip="${3:-$API_NODE}" echo "Configuring WiFi on node $node_ip..." echo "SSID: $ssid" # Configure WiFi using the API endpoint response=$(curl -s -w "\n%{http_code}" -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "ssid=$ssid&password=$password" \ "http://$node_ip/api/network/wifi/config" 2>/dev/null || echo -e "\n000") # Extract HTTP status code and response body http_code=$(echo "$response" | tail -n1) response_body=$(echo "$response" | head -n -1) # Check if curl succeeded if [ "$http_code" = "000" ] || [ -z "$response_body" ]; then echo "Error: Failed to connect to node at $node_ip" echo "Please check:" echo " - Node is powered on and connected to network" echo " - IP address is correct" echo " - Node is running Spore firmware" return 1 fi # Check HTTP status code if [ "$http_code" != "200" ]; then echo "Error: HTTP $http_code - Server error" echo "Response: $response_body" return 1 fi # Parse and display the response status=$(echo "$response_body" | jq -r '.status // "unknown"') message=$(echo "$response_body" | jq -r '.message // "No message"') config_saved=$(echo "$response_body" | jq -r '.config_saved // false') restarting=$(echo "$response_body" | jq -r '.restarting // false') connected=$(echo "$response_body" | jq -r '.connected // false') ip=$(echo "$response_body" | jq -r '.ip // "N/A"') echo "Status: $status" echo "Message: $message" echo "Config saved: $config_saved" if [ "$restarting" = "true" ]; then echo "Restarting: true" echo "Note: Node will restart to apply new WiFi settings" fi echo "Connected: $connected" if [ "$connected" = "true" ]; then echo "IP Address: $ip" fi # Return appropriate exit code if [ "$status" = "success" ]; then echo "WiFi configuration completed successfully!" return 0 else echo "WiFi configuration failed!" return 1 fi } ${@:-info} } function monitor { pio run --target monitor } ${@:-info}