63a45d4ee2
Der Erweiterung fehlte CFBundleVersion - eine Pflichtangabe, ohne die iOS
die Installation der ganzen App verweigert ("kann nicht installiert werden").
Verursacht von der Versionsangleichung vom Vortag: das Skript reichte den
Platzhalter $(CURRENT_PROJECT_VERSION) statt einer Zahl weiter, und das per
Skript angelegte Ziel der Erweiterung kennt diese Build-Einstellung nicht.
An den entpackten .ipa nachgemessen, 2026.9.3.3 gegen 2026.9.4.5.
ios-signieren.sh reicht nur noch echte Zahlen weiter, das Gegenlesen der
fertigen .ipa bricht ab statt zu warnen, und abgelegt wird erst danach -
eine Datei, die die Pruefung nicht besteht, darf nicht in auslieferung/
landen.
Dazu:
- Kopfmarke statt Firmierung des Betreibers in der Tankstellen-Zeile
- dritter Suchbegriff: der Name ohne fuehrende Marke. Gemessen: Nominatim
findet "Shell, Pascalstr. 8, Ingolstadt" nicht, "Pascalstr. 8, Ingolstadt"
schon - daran blieb die Belegkarte der realen Instanz leer
- der Tankstellen-Verweis zeigt die Tankstelle, statt eine Route zu rechnen
- Cache-Brecher auf .ipa, Symbolen und manifest.plist
- QR-Scanner fuer den Zugangs-Token bei der Ersteinrichtung (jsQR statt
GoogleMLKit, damit der Xcode-Lauf kein pod install riskiert)
214/214 Tests, Panel als Modul geparst, live gegen audi_ha_test geprueft.
142 lines
6.0 KiB
Bash
Executable File
142 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Bereitet die Installation ueber die Luft vor: legt neben der signierten .ipa
|
|
# die manifest.plist und eine kleine Installationsseite ab.
|
|
#
|
|
# bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net
|
|
#
|
|
# Warum das noetig ist: iOS installiert eine App nur dann ueber die Luft, wenn
|
|
# ein itms-services-Link auf eine manifest.plist zeigt, die wiederum die
|
|
# Adresse der .ipa enthaelt. Beide Adressen muessen ueber **HTTPS mit einem
|
|
# oeffentlich vertrauenswuerdigen Zertifikat** erreichbar sein - einfaches HTTP
|
|
# und selbstsignierte Zertifikate lehnt iOS kommentarlos ab. Home Assistant
|
|
# unter /local/ genuegt dafuer nicht, das laeuft im Tailnet unverschluesselt.
|
|
#
|
|
# Passend dazu und ohne offenen Port: `tailscale serve` liefert ein echtes
|
|
# Let's-Encrypt-Zertifikat auf <maschine>.<tailnet>.ts.net aus. Voraussetzung
|
|
# ist, dass in der Tailscale-Verwaltung HTTPS-Zertifikate aktiviert sind.
|
|
#
|
|
# tailscale serve --bg ios/build/luftweg
|
|
#
|
|
# Danach den ausgegebenen Link auf dem iPhone in **Safari** oeffnen (andere
|
|
# Browser reichen itms-services nicht an das System weiter).
|
|
set -euo pipefail
|
|
|
|
if [ $# -lt 1 ]; then
|
|
echo "Aufruf: bash scripts/ios-luftweg.sh <basis-url> [zielordner]" >&2
|
|
echo "Beispiel: bash scripts/ios-luftweg.sh https://mein-mac.tailnetname.ts.net" >&2
|
|
echo "Gitea: bash scripts/ios-luftweg.sh \\" >&2
|
|
echo " https://gitea.nothaft.cloud/paul/audi-app/raw/branch/main/companion-app/auslieferung \\" >&2
|
|
echo " auslieferung" >&2
|
|
exit 1
|
|
fi
|
|
|
|
BASIS="${1%/}"
|
|
if [ "${BASIS#https://}" = "$BASIS" ]; then
|
|
echo "FEHLER: Die Basis-Adresse muss mit https:// beginnen." >&2
|
|
echo "iOS verweigert die Installation ueber die Luft ueber unverschluesseltes HTTP." >&2
|
|
exit 1
|
|
fi
|
|
|
|
HIER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
APP="$(dirname "$HIER")"
|
|
IPA="$APP/auslieferung/App.ipa"
|
|
# Zweites Argument erlaubt es, direkt in den versionierten Ordner zu schreiben -
|
|
# noetig, wenn nicht ein eigener Host ausliefert, sondern das Repository selbst.
|
|
ZIEL="$APP/${2:-ios/build/luftweg}"
|
|
|
|
[ -f "$IPA" ] || { echo "FEHLER: $IPA fehlt - erst scripts/ios-signieren.sh laufen lassen." >&2; exit 1; }
|
|
|
|
# Version aus der .ipa selbst lesen statt sie hier zu wiederholen: zwei Quellen
|
|
# fuer dieselbe Angabe waeren eine zu viel.
|
|
AUSPACK="$(mktemp -d)"
|
|
trap 'rm -rf "$AUSPACK"' EXIT
|
|
unzip -q "$IPA" -d "$AUSPACK"
|
|
PLIST="$(find "$AUSPACK/Payload" -maxdepth 2 -name Info.plist | head -1)"
|
|
KENNUNG="$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$PLIST")"
|
|
VERSION="$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$PLIST")"
|
|
|
|
mkdir -p "$ZIEL"
|
|
[ "$IPA" -ef "$ZIEL/App.ipa" ] || cp "$IPA" "$ZIEL/App.ipa"
|
|
cp "$APP/public/symbol-192.png" "$ZIEL/symbol-192.png"
|
|
cp "$APP/public/symbol-512.png" "$ZIEL/symbol-512.png"
|
|
|
|
# Die Adressen tragen die Version als Anhaengsel (?v=...). Sie zeigen sonst bei
|
|
# jedem Bau auf dieselbe Zeichenkette, und der Installations-Dienst von iOS haelt
|
|
# eine einmal geholte .ipa dann fuer schon bekannt - sichtbar als Wolke mit Pfeil,
|
|
# die nie fertig wird, oder als "kann nicht installiert werden". Dieselbe Vorsorge
|
|
# trifft das Panel seit jeher fuer sein eigenes Buendel (siehe ota.ts).
|
|
cat > "$ZIEL/manifest.plist" <<PLISTENDE
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>items</key>
|
|
<array>
|
|
<dict>
|
|
<key>assets</key>
|
|
<array>
|
|
<dict>
|
|
<key>kind</key><string>software-package</string>
|
|
<key>url</key><string>$BASIS/App.ipa?v=$VERSION</string>
|
|
</dict>
|
|
<dict>
|
|
<key>kind</key><string>display-image</string>
|
|
<key>url</key><string>$BASIS/symbol-192.png?v=$VERSION</string>
|
|
</dict>
|
|
<dict>
|
|
<key>kind</key><string>full-size-image</string>
|
|
<key>url</key><string>$BASIS/symbol-512.png?v=$VERSION</string>
|
|
</dict>
|
|
</array>
|
|
<key>metadata</key>
|
|
<dict>
|
|
<key>bundle-identifier</key><string>$KENNUNG</string>
|
|
<key>bundle-version</key><string>$VERSION</string>
|
|
<key>kind</key><string>software</string>
|
|
<key>title</key><string>DataMetric360</string>
|
|
</dict>
|
|
</dict>
|
|
</array>
|
|
</dict>
|
|
</plist>
|
|
PLISTENDE
|
|
|
|
# Das kaufmaennische Und muss in HTML maskiert werden, sonst schneidet Safari
|
|
# den Link hinter dem url-Parameter ab.
|
|
cat > "$ZIEL/index.html" <<HTMLENDE
|
|
<!doctype html>
|
|
<html lang="de">
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>DataMetric360 installieren</title>
|
|
<style>
|
|
body { font-family: -apple-system, sans-serif; background: #161b23; color: #eef1f6;
|
|
margin: 0; display: grid; place-items: center; min-height: 100vh; }
|
|
main { text-align: center; padding: 2rem; }
|
|
h1 { font-weight: 300; font-size: 1.5rem; }
|
|
a { display: inline-block; margin-top: 1.5rem; padding: 0.9rem 2rem; border-radius: 999px;
|
|
background: #eef1f6; color: #161b23; text-decoration: none; font-size: 1.1rem; }
|
|
p { color: #8a94a3; font-size: 0.9rem; line-height: 1.5; }
|
|
</style>
|
|
<main>
|
|
<h1>DataMetric360</h1>
|
|
<p>Version $VERSION</p>
|
|
<a href="itms-services://?action=download-manifest&url=$BASIS/manifest.plist?v=$VERSION">Installieren</a>
|
|
<p>In Safari oeffnen. Nach dem Antippen fragt iOS einmal nach,<br>danach erscheint die App auf dem Startbildschirm.</p>
|
|
</main>
|
|
</html>
|
|
HTMLENDE
|
|
|
|
echo "Ordner fertig: $ZIEL"
|
|
echo
|
|
echo "Wenn ein eigener Host ausliefert:"
|
|
echo " tailscale serve --bg $ZIEL"
|
|
echo " dann auf dem iPhone in Safari oeffnen: $BASIS/"
|
|
echo
|
|
# Gitea liefert rohe Dateien grundsaetzlich als text/plain aus - die
|
|
# index.html wird dort also als Quelltext angezeigt statt gerendert. Deshalb
|
|
# hier zusaetzlich der fertige Link zum Einfuegen in die Safari-Adresszeile;
|
|
# der funktioniert unabhaengig davon, ob eine Seite drumherum existiert.
|
|
echo "Ohne Seite (z. B. aus dem Repository heraus) direkt in Safari einfuegen:"
|
|
echo " itms-services://?action=download-manifest&url=$BASIS/manifest.plist?v=$VERSION"
|