mirror of
https://github.com/lildude/ha-addon-teslamate.git
synced 2026-10-13 21:19:16 -04:00
Merge branch 'debug-setup-ha' into improve-dev-test
This commit is contained in:
+77
-19
@@ -12,11 +12,21 @@
|
|||||||
# broker / Grafana instance is available.
|
# broker / Grafana instance is available.
|
||||||
#
|
#
|
||||||
# Usage: bash .devcontainer/setup-ha.sh
|
# Usage: bash .devcontainer/setup-ha.sh
|
||||||
|
# DEBUG=1 bash .devcontainer/setup-ha.sh # verbose output + error details
|
||||||
#
|
#
|
||||||
# Safe to run multiple times (idempotent).
|
# Safe to run multiple times (idempotent).
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# DEBUG: when set to a truthy value (1/true/yes/on), print verbose diagnostics
|
||||||
|
# and surface API responses/errors that are normally hidden. Unset (or 0/false)
|
||||||
|
# keeps the default, quiet output.
|
||||||
|
DEBUG="${DEBUG:-0}"
|
||||||
|
case "${DEBUG,,}" in
|
||||||
|
1 | true | yes | on) DEBUG=1 ;;
|
||||||
|
*) DEBUG=0 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
HA_URL="http://localhost:8123"
|
HA_URL="http://localhost:8123"
|
||||||
ALEXBELGIUM_REPO="https://github.com/alexbelgium/hassio-addons"
|
ALEXBELGIUM_REPO="https://github.com/alexbelgium/hassio-addons"
|
||||||
ADMIN_USER="admin"
|
ADMIN_USER="admin"
|
||||||
@@ -47,6 +57,7 @@ GREEN='\033[0;32m'
|
|||||||
YELLOW='\033[0;33m'
|
YELLOW='\033[0;33m'
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
CYAN='\033[0;36m'
|
CYAN='\033[0;36m'
|
||||||
|
DIM='\033[2m'
|
||||||
BOLD='\033[1m'
|
BOLD='\033[1m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
@@ -54,20 +65,62 @@ log() { echo -e "${CYAN}==>${NC} ${BOLD}$*${NC}"; }
|
|||||||
warn() { echo -e "${YELLOW}WARNING:${NC} $*" >&2; }
|
warn() { echo -e "${YELLOW}WARNING:${NC} $*" >&2; }
|
||||||
err() { echo -e "${RED}ERROR:${NC} $*" >&2; exit 1; }
|
err() { echo -e "${RED}ERROR:${NC} $*" >&2; exit 1; }
|
||||||
ok() { echo -e "${CYAN}==>${NC} ${GREEN}$*${NC}"; }
|
ok() { echo -e "${CYAN}==>${NC} ${GREEN}$*${NC}"; }
|
||||||
|
# debug() prints only when DEBUG is enabled and writes to stderr, so it never
|
||||||
|
# pollutes function output captured via $(...).
|
||||||
|
debug() {
|
||||||
|
[ "$DEBUG" = "1" ] || return 0
|
||||||
|
echo -e "${DIM}DEBUG:${NC} $*" >&2
|
||||||
|
}
|
||||||
|
# debug_response() logs an API response when debugging, truncated so large
|
||||||
|
# payloads (e.g. addon logs) stay readable.
|
||||||
|
debug_response() {
|
||||||
|
[ "$DEBUG" = "1" ] || return 0
|
||||||
|
local resp="$1" max=800
|
||||||
|
if [ "${#resp}" -gt "$max" ]; then
|
||||||
|
debug "response (truncated): ${resp:0:$max}..."
|
||||||
|
else
|
||||||
|
debug "response: ${resp}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Run Supervisor API call via hassio_cli container
|
# Run Supervisor API call via hassio_cli container
|
||||||
# IMPORTANT: Use single quotes for outer sh -c argument so $SUPERVISOR_TOKEN
|
# IMPORTANT: Use single quotes for outer sh -c argument so $SUPERVISOR_TOKEN
|
||||||
# is expanded by the inner shell (where the env var exists), not the outer bash.
|
# is expanded by the inner shell (where the env var exists), not the outer bash.
|
||||||
supervisor_api() {
|
supervisor_api() {
|
||||||
local method="$1" endpoint="$2"
|
local method="$1" endpoint="$2"
|
||||||
docker exec hassio_cli sh -c \
|
debug "API ${method} ${endpoint}"
|
||||||
'curl -s -X '"${method}"' -H "Authorization: Bearer $SUPERVISOR_TOKEN" -H "Content-Type: application/json" http://supervisor'"${endpoint}"
|
local resp
|
||||||
|
resp=$(docker exec hassio_cli sh -c \
|
||||||
|
'curl -s -X '"${method}"' -H "Authorization: Bearer $SUPERVISOR_TOKEN" -H "Content-Type: application/json" http://supervisor'"${endpoint}")
|
||||||
|
debug_response "$resp"
|
||||||
|
printf '%s\n' "$resp"
|
||||||
}
|
}
|
||||||
|
|
||||||
supervisor_api_with_body() {
|
supervisor_api_with_body() {
|
||||||
local method="$1" endpoint="$2" body="$3"
|
local method="$1" endpoint="$2" body="$3"
|
||||||
docker exec -e "BODY=${body}" hassio_cli sh -c \
|
debug "API ${method} ${endpoint} body=${body}"
|
||||||
'curl -s -X '"${method}"' -H "Authorization: Bearer $SUPERVISOR_TOKEN" -H "Content-Type: application/json" -d "$BODY" http://supervisor'"${endpoint}"
|
local resp
|
||||||
|
resp=$(docker exec -e "BODY=${body}" hassio_cli sh -c \
|
||||||
|
'curl -s -X '"${method}"' -H "Authorization: Bearer $SUPERVISOR_TOKEN" -H "Content-Type: application/json" -d "$BODY" http://supervisor'"${endpoint}")
|
||||||
|
debug_response "$resp"
|
||||||
|
printf '%s\n' "$resp"
|
||||||
|
}
|
||||||
|
|
||||||
|
# POST to the local HA API for an optional onboarding step. Failures are
|
||||||
|
# non-fatal; the request and any response/error are shown only when debugging.
|
||||||
|
ha_post_optional() {
|
||||||
|
local token="$1" endpoint="$2" data="$3"
|
||||||
|
debug "POST ${endpoint} ${data}"
|
||||||
|
local resp rc=0
|
||||||
|
resp=$(curl -sS -X POST "${HA_URL}${endpoint}" \
|
||||||
|
-H "Authorization: Bearer ${token}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$data" 2>&1) || rc=$?
|
||||||
|
if [ "$rc" -ne 0 ]; then
|
||||||
|
debug "${endpoint} failed (rc=${rc}): ${resp}"
|
||||||
|
elif [ -n "$resp" ]; then
|
||||||
|
debug "${endpoint} response: ${resp}"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Query a specific jq field from a Supervisor API response
|
# Query a specific jq field from a Supervisor API response
|
||||||
@@ -96,6 +149,7 @@ wait_for_ha() {
|
|||||||
ok "Home Assistant is ready"
|
ok "Home Assistant is ready"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: Home Assistant not ready yet"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -122,6 +176,7 @@ complete_onboarding() {
|
|||||||
auth_response=$(curl -sf -X POST "${HA_URL}/api/onboarding/users" \
|
auth_response=$(curl -sf -X POST "${HA_URL}/api/onboarding/users" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"client_id\":\"${CLIENT_ID}\",\"name\":\"Admin\",\"username\":\"${ADMIN_USER}\",\"password\":\"${ADMIN_PASS}\",\"language\":\"en\"}")
|
-d "{\"client_id\":\"${CLIENT_ID}\",\"name\":\"Admin\",\"username\":\"${ADMIN_USER}\",\"password\":\"${ADMIN_PASS}\",\"language\":\"en\"}")
|
||||||
|
debug "users response: ${auth_response}"
|
||||||
|
|
||||||
local auth_code
|
local auth_code
|
||||||
auth_code=$(echo "$auth_response" | jq -r '.auth_code')
|
auth_code=$(echo "$auth_response" | jq -r '.auth_code')
|
||||||
@@ -136,6 +191,7 @@ complete_onboarding() {
|
|||||||
--data-urlencode "grant_type=authorization_code" \
|
--data-urlencode "grant_type=authorization_code" \
|
||||||
--data-urlencode "code=${auth_code}" \
|
--data-urlencode "code=${auth_code}" \
|
||||||
--data-urlencode "client_id=${CLIENT_ID}")
|
--data-urlencode "client_id=${CLIENT_ID}")
|
||||||
|
debug "token response: ${token_response}"
|
||||||
|
|
||||||
local access_token
|
local access_token
|
||||||
access_token=$(echo "$token_response" | jq -r '.access_token')
|
access_token=$(echo "$token_response" | jq -r '.access_token')
|
||||||
@@ -144,22 +200,12 @@ complete_onboarding() {
|
|||||||
err "Failed to get access token: ${token_response}"
|
err "Failed to get access token: ${token_response}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Complete remaining onboarding steps
|
# Complete remaining onboarding steps (best-effort; failures are non-fatal)
|
||||||
log "Completing onboarding steps..."
|
log "Completing onboarding steps..."
|
||||||
curl -sf -X POST "${HA_URL}/api/onboarding/core_config" \
|
ha_post_optional "$access_token" "/api/onboarding/core_config" "{}"
|
||||||
-H "Authorization: Bearer ${access_token}" \
|
ha_post_optional "$access_token" "/api/onboarding/analytics" "{}"
|
||||||
-H "Content-Type: application/json" \
|
ha_post_optional "$access_token" "/api/onboarding/integration" \
|
||||||
-d "{}" > /dev/null 2>&1 || true
|
"{\"client_id\":\"${CLIENT_ID}\",\"redirect_uri\":\"${HA_URL}/\"}"
|
||||||
|
|
||||||
curl -sf -X POST "${HA_URL}/api/onboarding/analytics" \
|
|
||||||
-H "Authorization: Bearer ${access_token}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{}" > /dev/null 2>&1 || true
|
|
||||||
|
|
||||||
curl -sf -X POST "${HA_URL}/api/onboarding/integration" \
|
|
||||||
-H "Authorization: Bearer ${access_token}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"client_id\":\"${CLIENT_ID}\",\"redirect_uri\":\"${HA_URL}/\"}" > /dev/null 2>&1 || true
|
|
||||||
|
|
||||||
ok "Onboarding complete"
|
ok "Onboarding complete"
|
||||||
}
|
}
|
||||||
@@ -187,6 +233,7 @@ add_addon_repo() {
|
|||||||
ok "Store refreshed successfully"
|
ok "Store refreshed successfully"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: postgres addon not in store yet"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -222,6 +269,7 @@ install_postgres() {
|
|||||||
ok "PostgreSQL addon installed (version: ${version})"
|
ok "PostgreSQL addon installed (version: ${version})"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: PostgreSQL not installed yet"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -267,6 +315,7 @@ configure_and_start_postgres() {
|
|||||||
sleep 10
|
sleep 10
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: PostgreSQL state=${state}"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -323,6 +372,7 @@ install_teslamate() {
|
|||||||
ok "TeslaMate addon installed (version: ${version})"
|
ok "TeslaMate addon installed (version: ${version})"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: TeslaMate not installed yet"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -351,6 +401,7 @@ configure_and_start_teslamate() {
|
|||||||
--arg tz "$TIMEZONE" \
|
--arg tz "$TIMEZONE" \
|
||||||
'{database_user: $user, database_pass: $pass, database_port: $port, database_host: $host, database_name: $db, database_ssl: false, disable_mqtt: true, grafana_import_dashboards: false, timezone: $tz}')
|
'{database_user: $user, database_pass: $pass, database_port: $port, database_host: $host, database_name: $db, database_ssl: false, disable_mqtt: true, grafana_import_dashboards: false, timezone: $tz}')
|
||||||
options_json=$(jq -n --argjson cur "$current_options" --argjson ovr "$overrides" '{options: ($cur + $ovr)}')
|
options_json=$(jq -n --argjson cur "$current_options" --argjson ovr "$overrides" '{options: ($cur + $ovr)}')
|
||||||
|
debug "options payload: ${options_json}"
|
||||||
|
|
||||||
local response
|
local response
|
||||||
response=$(supervisor_api_with_body POST "/addons/${TESLAMATE_SLUG}/options" "${options_json}")
|
response=$(supervisor_api_with_body POST "/addons/${TESLAMATE_SLUG}/options" "${options_json}")
|
||||||
@@ -380,6 +431,7 @@ configure_and_start_teslamate() {
|
|||||||
if [ "$state" = "started" ]; then
|
if [ "$state" = "started" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: TeslaMate state=${state}"
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -402,6 +454,9 @@ wait_for_teslamate_ready() {
|
|||||||
ok "TeslaMate is ready"
|
ok "TeslaMate is ready"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if [ "$DEBUG" = "1" ]; then
|
||||||
|
debug "Attempt $((attempt + 1))/${max_attempts}: endpoint not up yet; last log: $(echo "$logs" | tail -n 1)"
|
||||||
|
fi
|
||||||
sleep 5
|
sleep 5
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
@@ -414,6 +469,9 @@ main() {
|
|||||||
log "Setting up Home Assistant for TeslaMate development"
|
log "Setting up Home Assistant for TeslaMate development"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
debug "Verbose debug output enabled"
|
||||||
|
debug "HA_URL=${HA_URL} POSTGRES_SLUG=${POSTGRES_SLUG} TESLAMATE_SLUG=${TESLAMATE_SLUG}"
|
||||||
|
|
||||||
wait_for_ha
|
wait_for_ha
|
||||||
complete_onboarding
|
complete_onboarding
|
||||||
add_addon_repo
|
add_addon_repo
|
||||||
|
|||||||
Reference in New Issue
Block a user