Files
dont-stop-folding/root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run
retr0 b48c3868e0 feat: add MQTT sensor publishing for Home Assistant
Adds a new s6 service (svc-foldingathome-mqtt) that polls the FAH 8 API
on port 7396 every 30 seconds and publishes 4 sensors to HA via MQTT
autodiscovery: Status, PPD, Work Unit Progress, and Credit estimate.

Requires the Mosquitto broker add-on; declared as mqtt:want so the
add-on remains functional without it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:50:49 +02:00

100 lines
3.6 KiB
Plaintext
Executable File

#!/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