chore: initial release v0.8.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1
root/etc/OpenCL/vendors/nvidia.icd
vendored
Normal file
1
root/etc/OpenCL/vendors/nvidia.icd
vendored
Normal file
@@ -0,0 +1 @@
|
||||
libnvidia-opencl.so.1
|
||||
6
root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run
Executable file
6
root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
echo "**** setting up config directory ****"
|
||||
mkdir -p /config
|
||||
chmod 755 /config
|
||||
@@ -0,0 +1 @@
|
||||
oneshot
|
||||
1
root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/up
Normal file
1
root/etc/s6-overlay/s6-rc.d/init-foldingathome-config/up
Normal file
@@ -0,0 +1 @@
|
||||
/etc/s6-overlay/s6-rc.d/init-foldingathome-config/run
|
||||
10
root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run
Executable file
10
root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run
Executable file
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
oneshot
|
||||
1
root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/up
Normal file
1
root/etc/s6-overlay/s6-rc.d/init-foldingathome-video/up
Normal file
@@ -0,0 +1 @@
|
||||
/etc/s6-overlay/s6-rc.d/init-foldingathome-video/run
|
||||
99
root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run
Executable file
99
root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/run
Executable file
@@ -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
|
||||
1
root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/type
Normal file
1
root/etc/s6-overlay/s6-rc.d/svc-foldingathome-mqtt/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
44
root/etc/s6-overlay/s6-rc.d/svc-foldingathome/run
Executable file
44
root/etc/s6-overlay/s6-rc.d/svc-foldingathome/run
Executable file
@@ -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[@]}"
|
||||
1
root/etc/s6-overlay/s6-rc.d/svc-foldingathome/type
Normal file
1
root/etc/s6-overlay/s6-rc.d/svc-foldingathome/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
Reference in New Issue
Block a user