commit 94f5803141e178b07006200f92bff195e971a54c Author: retr0 Date: Thu Jul 17 21:23:35 2025 +0200 chore: initial release v0.8.2 Co-Authored-By: Claude Sonnet 4.6 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7347a7f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/bin +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76c3fa8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Docker +*.tar.gz +*.log + +# Editor-Dateien +.vscode/ +*.swp \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d7d027e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +## 0.8.2 +- Add-on-Optionen werden jetzt korrekt über `bashio::config` ausgelesen (statt fehlerhafter Env-Var-Substitution) +- `--power`-Flag entfernt (wird von FAH 8 nicht unterstützt, Leistung über Web-Interface steuerbar) +- Neues Add-on-Icon +- README ausführlich erweitert (Installation, Konfiguration, Troubleshooting) +- DOCS.md bereinigt (veraltete `power`-Option entfernt) + +## 0.8.1 +- Dockerfile auf HAOS-kompatible Build-Basis umgestellt (`ARG BUILD_FROM`) +- FAH-Download-Logik korrigiert (arch-spezifisch, kein fehlerhafter "debian"-Filter) +- s6-overlay: LinuxServer-spezifische Abhängigkeiten entfernt (`init-config-end`, `init-config`, `init-services`) +- s6-overlay: Abhängigkeitskette korrigiert (`base → config → video → service`) +- Service-Skript: Syntax-Fehler behoben, alle CLI-Argumente (user, team, passkey, power) ergänzt +- Env-Variable `USER` → `FAH_USER` (Konflikt mit Shell-Variable vermieden) +- Architektur-Support auf `amd64` und `aarch64` beschränkt (FAH 8 unterstützt kein armhf/armv7) +- Dokumentation vollständig überarbeitet + +## 0.8.0 +- Aktualisiert auf Folding@home 8.4 +- Initiale Version des Forks diff --git a/DOCS.md b/DOCS.md new file mode 100644 index 0000000..fc27e85 --- /dev/null +++ b/DOCS.md @@ -0,0 +1,140 @@ +# Folding@home Add-on Dokumentation + +## Über dieses Add-on + +Dieses Add-on führt den [Folding@home](https://foldingathome.org/) Client (Version 8.x) als +Home Assistant Add-on aus. Folding@home ist ein verteiltes Rechenprojekt, das die Rechenleistung +deines Computers nutzt, um Proteinfaltungssimulationen für medizinische Forschung durchzuführen +(z. B. Alzheimer, Krebs, COVID-19). + +--- + +## Installation + +1. Öffne Home Assistant und gehe zu: + **Einstellungen → Add-ons → Add-on Store** +2. Klicke oben rechts auf **⋮ → Repositories** +3. Füge folgende URL hinzu: + ``` + https://gitea.bitfire.work/retr0/dont-stop-folding + ``` +4. Schließe den Dialog – das Add-on „Folding@home" erscheint nun im Store +5. Klicke auf das Add-on und dann auf **Installieren** +6. Konfiguriere die gewünschten Optionen (siehe unten) +7. Klicke auf **Starten** + +--- + +## Konfiguration + +### Optionen + +| Option | Typ | Standard | Beschreibung | +|-----------------|--------|-----------|--------------| +| `user` | string | _(leer)_ | Dein Folding@home-Benutzername. Wird für die Statistikseite verwendet. | +| `team` | string | `247478` | Team-ID. `247478` ist das offizielle Home Assistant Team. | +| `passkey` | string | _(leer)_ | Dein persönlicher Passkey von foldingathome.org. Aktiviert Bonus-Punkte. | +| `account_token` | string | _(leer)_ | Token für das neue FAH 8 Online-Konto (von foldingathome.org). | +| `machine_name` | string | _(leer)_ | Anzeigename dieser Maschine im FAH-Online-Konto. | + +### Beispielkonfiguration + +```yaml +user: "mein_benutzername" +team: "247478" +passkey: "abc123..." +``` + +Mit FAH 8 Online-Konto: +```yaml +account_token: "eyJ..." +machine_name: "homeassistant" +``` + +> Die Leistungsstufe lässt sich nach dem Start im Web-Interface unter `http://:7396` anpassen. + +--- + +## Web-Interface + +Nach dem Start ist die Folding@home Web-UI erreichbar unter: + +``` +http://:7396 +``` + +Dort kannst du: +- Aktuelle Work Units und Fortschritt einsehen +- Die Leistungsstufe manuell anpassen +- Folding pausieren oder fortsetzen +- Statistiken abrufen + +--- + +## Zwei Kontosysteme + +Folding@home bietet zwei Möglichkeiten, Punkte zu sammeln: + +### Klassisch (user + passkey) +Das bewährte System – erstelle einen Account auf [foldingathome.org](https://foldingathome.org/), +trage Benutzernamen und optional einen Passkey ein. + +### FAH 8 Online-Konto (account_token) +Das neue System seit Version 8. Erstelle ein Konto auf +[foldingathome.org](https://foldingathome.org/), generiere einen Token und trage +ihn unter `account_token` ein. `machine_name` gibt der Maschine einen erkennbaren Namen +in deinem Konto-Dashboard. + +> Hinweis: Beide Systeme können nicht gleichzeitig aktiv sein. Wenn `account_token` +> gesetzt ist, wird er bevorzugt. Ohne beides wird anonym gefaltet. + +--- + +## Datenspeicherung + +Der FAH Client speichert seine Konfiguration und Work-Unit-Daten im +Home Assistant Konfigurationsverzeichnis unter: + +``` +/config/ (innerhalb des Containers) +``` + +Die Daten bleiben bei Neustarts und Updates des Add-ons erhalten. + +--- + +## Unterstützte Architekturen + +| Architektur | Unterstützt | +|-------------|-------------| +| `amd64` | ✓ | +| `aarch64` | ✓ | +| `armhf` | ✗ (vom FAH 8 Client nicht unterstützt) | +| `armv7` | ✗ (vom FAH 8 Client nicht unterstützt) | + +--- + +## Problembehandlung + +### Add-on startet nicht +- Prüfe im Log-Tab des Add-ons auf Fehlermeldungen +- Stelle sicher, dass Port `7396` nicht von einem anderen Dienst belegt ist + +### Web-Interface nicht erreichbar +- Warte 30–60 Sekunden nach dem Start – der FAH Client benötigt etwas Zeit zum Initialisieren +- Prüfe, ob das Add-on im Status „Läuft" angezeigt wird + +### Keine Punkte / kein Fortschritt +- Der FAH Server weist Work Units zu – bei geringer Auslastung der Server kann es zu Wartezeiten kommen +- Prüfe im Web-Interface unter `http://:7396`, ob aktiv gefaltet wird +- Stelle sicher, dass `user` und `team` korrekt eingetragen sind + +### „No appropriate assignment" im Log (Raspberry Pi / ARM) +Meldungen wie `HTTP_SERVICE_UNAVAILABLE: {"error":"No appropriate assignment"}` sind auf ARM-Geräten ohne GPU (z. B. Raspberry Pi) normal. FAH 8 priorisiert GPU- und x86-Clients – für reine ARM-CPUs sind schlicht weniger Arbeitspakete verfügbar. + +Der Client wiederholt die Anfrage automatisch mit exponentiell steigendem Abstand. Es ist keine Aktion erforderlich – nach einigen Stunden wird in der Regel eine Work Unit zugeteilt. Das Add-on muss **nicht** neu gestartet werden. + +### Anonym falten +Wenn weder `user` noch `account_token` gesetzt sind, werden Beiträge unter dem +anonymen Benutzer gesammelt. Die Leistung ist identisch, nur die Statistiken werden +keinem Konto zugeordnet. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..94005e7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +# syntax=docker/dockerfile:1 + +ARG BUILD_FROM +FROM $BUILD_FROM + +ARG BUILD_DATE +ARG BUILD_REF +ARG BUILD_VERSION +ARG BUILD_ARCH + +LABEL \ + io.hass.name="Folding@home" \ + io.hass.description="Run Folding@home to contribute to scientific research" \ + io.hass.arch="${BUILD_ARCH}" \ + io.hass.type="addon" \ + io.hass.version=${BUILD_VERSION} \ + maintainer="retr0" + +# Add needed NVIDIA environment variables for container toolkit +ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility" + +# Prevent interactive prompts during package installation +ENV DEBIAN_FRONTEND="noninteractive" + +RUN \ + echo "**** install runtime packages ****" && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + bzip2 \ + curl \ + jq \ + libexpat1 \ + mosquitto-clients \ + netcat-openbsd && \ + echo "**** install foldingathome ****" && \ + if [ "${BUILD_ARCH}" = "aarch64" ]; then \ + FAH_WORKER="debian-stable-arm64"; \ + else \ + FAH_WORKER="debian-10-64bit"; \ + fi && \ + DOWNLOAD_PATH=$(curl -fsSL "https://download.foldingathome.org/releases/public/fah-client/meta.json" | \ + jq -r --arg worker "${FAH_WORKER}" \ + '.[] | select(.worker == $worker and .mode == "release" and (.package | endswith(".tar.bz2"))) | .package' \ + | head -1) && \ + echo "Downloading FAH client: ${DOWNLOAD_PATH}" && \ + curl -fsSL "https://download.foldingathome.org/releases/public/fah-client/${DOWNLOAD_PATH}" \ + -o /tmp/fah.tar.bz2 && \ + mkdir -p /app && \ + tar xf /tmp/fah.tar.bz2 -C /app --strip-components=1 && \ + echo "**** cleanup ****" && \ + apt-get clean && \ + rm -rf \ + /tmp/* \ + /var/lib/apt/lists/* \ + /var/tmp/* \ + /var/log/* + +# Add local files +COPY root/ / + +EXPOSE 7396 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..df993ab --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,5 @@ +MIT License + +Copyright (c) 2020-2025 Retr0 + +Permission is hereby granted, free of charge, to any person obtaining a copy... \ No newline at end of file diff --git a/build.yaml b/build.yaml new file mode 100644 index 0000000..030fdcb --- /dev/null +++ b/build.yaml @@ -0,0 +1,4 @@ +build_from: + amd64: ghcr.io/hassio-addons/debian-base/amd64:7.3.1 + aarch64: ghcr.io/hassio-addons/debian-base/aarch64:7.3.1 +squash: false diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..ca0463e --- /dev/null +++ b/config.yaml @@ -0,0 +1,29 @@ +name: Folding@home +version: 0.8.2 +slug: foldingathome +description: Run Folding@home to contribute to scientific research +url: https://gitea.bitfire.work/retr0/dont-stop-folding +arch: + - amd64 + - aarch64 +init: false +ports: + 7396/tcp: 7396 +ports_description: + 7396/tcp: Folding@home Web Interface +map: + - config:rw +services: + - mqtt:want +options: + user: "" + team: "247478" + passkey: "" + account_token: "" + machine_name: "" +schema: + user: str? + team: str + passkey: str? + account_token: str? + machine_name: str? diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cdb1058 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,6 @@ +services: + dontstopfolding: + image: dontstopfolding + build: + context: . + dockerfile: ./Dockerfile diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..d54f706 Binary files /dev/null and b/icon.png differ diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..d895b15 --- /dev/null +++ b/readme.md @@ -0,0 +1,175 @@ +# dont-stop-folding + +![dont-stop-folding](icon.png) + +> Home Assistant Add-on für [Folding@home](https://foldingathome.org/) – nutze die Rechenleistung +> deines Home Assistant Servers, um zur wissenschaftlichen Forschung beizutragen. + +--- + +## Was ist Folding@home? + +[Folding@home](https://foldingathome.org/) ist ein verteiltes Rechenprojekt der Washington University in St. Louis. +Es simuliert die Faltung von Proteinen – also den Prozess, durch den sich Eiweißmoleküle zu ihrer +dreidimensionalen Funktionsform falten. Fehler in diesem Prozess stehen im Zusammenhang mit +Krankheiten wie Alzheimer, Parkinson, Krebs und COVID-19. + +Jeder Computer, der am Projekt teilnimmt, berechnet kleine Simulationsaufgaben (sogenannte *Work Units*) +und sendet die Ergebnisse an die Forschungsserver zurück. Mit diesem Add-on läuft der Folding@home +Client direkt auf deinem Home Assistant Server – vollständig im Hintergrund, ohne separate Hardware. + +--- + +## Features + +- **Folding@home Client 8.x** – aktuelle Version mit verbesserter Effizienz +- **Web-Interface** auf Port 7396 – Fortschritt, Statistiken und Steuerung direkt im Browser +- **Zwei Kontosysteme** – klassisch (Benutzername + Passkey) oder FAH 8 Online-Konto (Account Token) +- **Team-Support** – standardmäßig im Home Assistant Community Team (247478) +- **Persistenz** – Work-Unit-Daten und Konfiguration bleiben bei Updates erhalten +- **Unterstützte Architekturen:** `amd64`, `aarch64` + +--- + +## Installation + +1. Öffne Home Assistant und navigiere zu: + **Einstellungen → Add-ons → Add-on Store** + +2. Klicke oben rechts auf **⋮ → Repositories** und füge folgende URL hinzu: + ``` + https://gitea.bitfire.work/retr0/dont-stop-folding + ``` + +3. Schließe den Dialog – das Add-on **Folding@home** erscheint nun im Store. + +4. Klicke auf das Add-on und dann auf **Installieren**. + +5. Wechsle in den Tab **Konfiguration** und trage deine Daten ein (siehe unten). + +6. Klicke auf **Starten**. + +--- + +## Konfiguration + +### Optionen + +| Option | Typ | Standard | Beschreibung | +|-----------------|--------|-----------|--------------| +| `user` | string | _(leer)_ | Dein Folding@home-Benutzername für die Statistikseite. | +| `team` | string | `247478` | Team-ID. `247478` ist das offizielle Home Assistant Community Team. | +| `passkey` | string | _(leer)_ | Persönlicher Passkey von foldingathome.org. Aktiviert Bonus-Punkte (Quick Return Bonus). | +| `account_token` | string | _(leer)_ | Token für das FAH 8 Online-Konto. Empfohlen für neue Nutzer. | +| `machine_name` | string | _(leer)_ | Anzeigename dieser Maschine im FAH-Konto-Dashboard. | + +### Beispielkonfigurationen + +**Klassisches Konto (user + passkey):** +```yaml +user: "mein_benutzername" +team: "247478" +passkey: "abc123..." +``` + +**FAH 8 Online-Konto:** +```yaml +account_token: "eyJ..." +machine_name: "homeassistant" +``` + +**Anonym falten** (keine Einträge nötig – einfach leer lassen): +```yaml +team: "247478" +``` + +> **Hinweis:** `account_token` und `user`/`passkey` schließen sich gegenseitig aus. +> Wenn `account_token` gesetzt ist, wird er bevorzugt. Ohne beides wird anonym gefaltet. + +--- + +## Web-Interface + +Nach dem Start ist die Folding@home Web-UI erreichbar unter: + +``` +http://:7396 +``` + +Über das Web-Interface kannst du: + +- Aktuelle Work Units und deren Fortschritt einsehen +- Folding pausieren und fortsetzen +- Die Leistungsstufe (light / medium / full) anpassen +- CPU- und GPU-Slots konfigurieren +- Statistiken und deinen Beitrag abrufen + +--- + +## Kontosysteme im Vergleich + +Folding@home bietet zwei Möglichkeiten, Beiträge einem Konto zuzuordnen: + +### Klassisch – Benutzername + Passkey + +Das bewährte System. Erstelle einen Account auf [foldingathome.org](https://foldingathome.org/), +trage deinen Benutzernamen unter `user` ein. Mit einem optionalen `passkey` werden +Bonus-Punkte freigeschaltet (Quick Return Bonus), die vergeben werden, wenn Work Units +pünktlich abgegeben werden. + +### FAH 8 Online-Konto – Account Token + +Das neue System ab Version 8. Nach der Registrierung auf +[foldingathome.org](https://foldingathome.org/) generierst du einen Token im +Web-Dashboard und trägst ihn unter `account_token` ein. Optional kannst du unter +`machine_name` einen Namen vergeben, damit du mehrere Maschinen im Dashboard unterscheiden kannst. + +--- + +## Unterstützte Architekturen + +| Architektur | Status | +|-------------|--------| +| `amd64` | ✅ Unterstützt | +| `aarch64` | ✅ Unterstützt (z. B. Raspberry Pi 4/5 mit 64-Bit-OS) | +| `armhf` | ❌ Nicht unterstützt (FAH 8 Client nicht verfügbar) | +| `armv7` | ❌ Nicht unterstützt (FAH 8 Client nicht verfügbar) | + +--- + +## Datenspeicherung + +Der FAH Client speichert Konfiguration und Work-Unit-Daten persistent im +Home Assistant Konfigurationsverzeichnis. Die Daten bleiben bei Neustarts +und Add-on-Updates vollständig erhalten. + +--- + +## Problembehandlung + +### Add-on startet nicht +- Prüfe den **Log-Tab** des Add-ons auf Fehlermeldungen. +- Stelle sicher, dass Port `7396` nicht von einem anderen Dienst belegt ist. + +### Web-Interface nicht erreichbar +- Warte 30–60 Sekunden nach dem Start – der FAH Client benötigt etwas Zeit zur Initialisierung. +- Prüfe, ob das Add-on im Status **Läuft** angezeigt wird. + +### Kein Fortschritt / keine Work Units +- Der FAH-Server weist Work Units zu. Bei hoher Auslastung der Forschungsserver + kann es zu Wartezeiten kommen – das ist normal. +- Prüfe im Web-Interface, ob der Client verbunden ist. +- Stelle sicher, dass `user` und `team` korrekt eingetragen sind. +- Für FAH 8: Ohne gültigen `account_token` werden keine Work Units zugeteilt. + Anonymes Falten funktioniert in FAH 8 nur eingeschränkt. + +### Beiträge erscheinen nicht in der Statistik +- Statistiken werden verzögert aktualisiert (bis zu mehrere Stunden). +- Stelle sicher, dass `user` korrekt geschrieben ist (Groß-/Kleinschreibung zählt). +- Mit einem `passkey` werden Punkte zuverlässiger zugeordnet. + +--- + +## Lizenz + +MIT License – siehe [LICENSE.txt](LICENSE.txt) diff --git a/repository.json b/repository.json new file mode 100644 index 0000000..ba4744a --- /dev/null +++ b/repository.json @@ -0,0 +1,5 @@ +{ + "name": "dont-stop-folding", + "url": "https://gitea.bitfire.work/retr0/dont-stop-folding", + "maintainer": "retr0" +} diff --git a/root/etc/OpenCL/vendors/nvidia.icd b/root/etc/OpenCL/vendors/nvidia.icd new file mode 100644 index 0000000..9712af9 --- /dev/null +++ b/root/etc/OpenCL/vendors/nvidia.icd @@ -0,0 +1 @@ +libnvidia-opencl.so.1 diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/dependencies.d/base b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/dependencies.d/base new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run new file mode 100755 index 0000000..fd6d050 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run @@ -0,0 +1,6 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash + +echo "**** setting up config directory ****" +mkdir -p /config +chmod 755 /config diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/type b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/type new file mode 100644 index 0000000..bdd22a1 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/up b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/up new file mode 100644 index 0000000..c136ca7 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/dependencies.d/init-foldingathome-config b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/dependencies.d/init-foldingathome-config new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run new file mode 100755 index 0000000..8bbb07f --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run @@ -0,0 +1,10 @@ +#!/usr/bin/with-contenv bash +# shellcheck shell=bash + +# Make GPU devices accessible if present (running as root in HAOS) +FILES=$(find /dev/dri /dev/dvb -type c -print 2>/dev/null) + +for i in $FILES; do + echo "**** found GPU device: ${i} ****" + chmod a+rw "${i}" 2>/dev/null || true +done diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/type b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/type new file mode 100644 index 0000000..bdd22a1 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/type @@ -0,0 +1 @@ +oneshot diff --git a/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/up b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/up new file mode 100644 index 0000000..a488a77 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/dependencies.d/svc-foldingathome b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/dependencies.d/svc-foldingathome new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run new file mode 100755 index 0000000..f750d15 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run @@ -0,0 +1,99 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +FAH_API="http://localhost:7396/api" +POLL_INTERVAL=30 +STATE_TOPIC="foldingathome/state" +DISCOVERY_PREFIX="homeassistant" + +# Abort cleanly if MQTT service is not available +if ! bashio::services.mqtt; then + bashio::log.info "MQTT not available — skipping sensor publishing. Install the Mosquitto broker add-on to enable HA sensors." + exec sleep infinity +fi + +MQTT_HOST=$(bashio::services.mqtt 'host') +MQTT_PORT=$(bashio::services.mqtt 'port') +MQTT_USER=$(bashio::services.mqtt 'username') +MQTT_PASS=$(bashio::services.mqtt 'password') +UNIQUE_ID="foldingathome_$(hostname | tr -cd '[:alnum:]_')" + +mqtt_publish() { + mosquitto_pub \ + -h "$MQTT_HOST" -p "$MQTT_PORT" \ + -u "$MQTT_USER" -P "$MQTT_PASS" \ + -t "$1" -m "$2" -r -q 1 +} + +publish_discovery() { + local device + device=$(jq -n \ + --arg id "$UNIQUE_ID" \ + '{identifiers: [$id], name: "Folding@home", model: "FAH 8", manufacturer: "foldingathome.org"}') + + declare -A sensors + sensors=( + ["status"]='{"name":"Folding@home Status","value_template":"{{ value_json.status }}","icon":"mdi:dna"}' + ["ppd"]='{"name":"Folding@home PPD","value_template":"{{ value_json.ppd }}","unit_of_measurement":"PPD","icon":"mdi:speedometer","state_class":"measurement"}' + ["progress"]='{"name":"Folding@home Progress","value_template":"{{ value_json.progress }}","unit_of_measurement":"%","icon":"mdi:progress-clock","state_class":"measurement"}' + ["credit"]='{"name":"Folding@home Credit","value_template":"{{ value_json.credit }}","unit_of_measurement":"points","icon":"mdi:star","state_class":"total_increasing"}' + ) + + for key in "${!sensors[@]}"; do + local config + config=$(echo "${sensors[$key]}" | jq \ + --arg uid "${UNIQUE_ID}_${key}" \ + --arg topic "$STATE_TOPIC" \ + --argjson device "$device" \ + '. + {unique_id: $uid, state_topic: $topic, device: $device}') + mqtt_publish "${DISCOVERY_PREFIX}/sensor/${UNIQUE_ID}_${key}/config" "$config" + done + + bashio::log.info "HA sensor discovery published (${#sensors[@]} sensors)" +} + +# Wait for FAH API to become ready +bashio::log.info "Waiting for Folding@home API on port 7396..." +until curl -sf "${FAH_API}/info" > /dev/null 2>&1; do + sleep 5 +done +bashio::log.info "Folding@home API ready — starting MQTT sensor publisher" + +publish_discovery + +while true; do + UNITS=$(curl -sf "${FAH_API}/units" 2>/dev/null || echo "[]") + UNIT_COUNT=$(echo "$UNITS" | jq 'length') + + if [ "$UNIT_COUNT" -gt 0 ]; then + RAW_STATE=$(echo "$UNITS" | jq -r '.[0].state // "unknown"') + case "$RAW_STATE" in + RUN) STATUS="Running" ;; + PAUSE) STATUS="Paused" ;; + FINISH) STATUS="Finishing" ;; + ASSIGN) STATUS="Assigning" ;; + DOWNLOAD) STATUS="Downloading" ;; + SEND) STATUS="Sending" ;; + *) STATUS="Idle" ;; + esac + PPD=$(echo "$UNITS" | jq '[.[].ppd // 0] | add // 0 | round') + PROGRESS=$(echo "$UNITS" | jq '.[0].progress // 0 | . * 100 | round') + CREDIT=$(echo "$UNITS" | jq '[.[].credit // 0] | add // 0 | round') + else + STATUS="Idle" + PPD=0 + PROGRESS=0 + CREDIT=0 + fi + + PAYLOAD=$(jq -n \ + --arg status "$STATUS" \ + --argjson ppd "$PPD" \ + --argjson progress "$PROGRESS" \ + --argjson credit "$CREDIT" \ + '{status: $status, ppd: $ppd, progress: $progress, credit: $credit}') + + mqtt_publish "$STATE_TOPIC" "$PAYLOAD" + + sleep "$POLL_INTERVAL" +done diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/type b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/type @@ -0,0 +1 @@ +longrun diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/dependencies.d/init-foldingathome-video b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/dependencies.d/init-foldingathome-video new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/run b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/run new file mode 100755 index 0000000..2d51b62 --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/run @@ -0,0 +1,44 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +declare -a args + +# Network: bind to all interfaces, allow all connections +args+=(--http-addresses "0.0.0.0:7396") +args+=(--allow "0/0") + +# FAH account credentials +FAH_USER=$(bashio::config 'user') +TEAM=$(bashio::config 'team') +PASSKEY=$(bashio::config 'passkey') +ACCOUNT_TOKEN=$(bashio::config 'account_token') +MACHINE_NAME=$(bashio::config 'machine_name') + +if bashio::config.has_value 'user'; then + args+=(--user "${FAH_USER}") +fi + +if bashio::config.has_value 'team'; then + args+=(--team "${TEAM}") +fi + +if bashio::config.has_value 'passkey'; then + args+=(--passkey "${PASSKEY}") +fi + +if bashio::config.has_value 'account_token'; then + args+=(--account-token "${ACCOUNT_TOKEN}") + if bashio::config.has_value 'machine_name'; then + args+=(--machine-name "${MACHINE_NAME}") + fi +fi + +if ! bashio::config.has_value 'user' && ! bashio::config.has_value 'account_token'; then + bashio::log.info "No user or account_token set — folding anonymously." +fi + +# Run from /config so fah-client stores its data there +mkdir -p /config +cd /config || exit 1 + +exec /app/fah-client "${args[@]}" diff --git a/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/type b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/root/etc/s6-overlay/s6-rc.d/svc-foldingathome/type @@ -0,0 +1 @@ +longrun diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-foldingathome-config b/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-foldingathome-config new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-foldingathome-video b/root/etc/s6-overlay/s6-rc.d/user/contents.d/init-foldingathome-video new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-foldingathome b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-foldingathome new file mode 100644 index 0000000..e69de29 diff --git a/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-foldingathome-mqtt b/root/etc/s6-overlay/s6-rc.d/user/contents.d/svc-foldingathome-mqtt new file mode 100644 index 0000000..e69de29