Update sab_speed_control.sh

This commit is contained in:
Admin9705
2025-03-01 11:39:17 -05:00
committed by GitHub
parent 5ad046bf4d
commit a52c912a27

View File

@@ -1,80 +1,159 @@
#!/bin/bash
# Adjust SABnzbd Speed Limit Based on Tautulli Remote Bandwidth Usage (Looping)
# -------------------------------------------------------------------
# This script continuously queries Tautulli for Plex activity, counts remote
# sessions, sums their total bandwidth usage, rounds the total up to the nearest MB,
# and adjusts SABnzbds speed limit accordingly.
#
# It also verifies Tautulli returns a valid JSON structure. If Tautulli is
# unreachable or the address is fake, it will log an error instead of claiming success.
#
# -------------------------------------------------------------------
# Configuration Variables:
# -------------------------------------------------------------------
# ============================================================
# Script Name: SAB Speed Control
# Author: Admin9705
# ============================================================
# NOTE: Control DL speeds while others are watching PLEX
# ============================================================
# v1 - Initial Script | v2 - Added Night Speeds
# Configuration
SABNZBD_API_KEY="60x7fega60f642d489ed89f08c4f8a80fake"
SABNZBD_URL="http://10.0.0.10:8081/sabnzbd/api"
SLOW_SPEED="65000000" # DL Speed when Plex IS playing for a user
NORMAL_SPEED="85000000" # DL Speed when Plex is NOT playing for a user
NIGHT_SPEED="125000000" # DL Speed when not using Internet and when Plex NOT playing for a user (such as Night)
# 125000000 is 118.2 MB | 80000000 is 76.3 MB
NIGHT_START="01" # Start hour for nighttime speed (24-hour format) (01 is 0100 AM or 0100hrs)
NIGHT_END="07" # End hour for nighttime speed (24-hour format) (07 is 0700 AM or 0700hrs)
# Type Date in CMD Line to ENSURE that SERVER TIME matches/aligns as a test
CHECK_INTERVAL=10 # Seconds between checks
# Tautulli API configuration:
TAUTULLI_API_KEY="dad9bbb78bde43249754b630b58fbf7c"
TAUTULLI_URL="http://10.0.0.10:8181/api/v2"
TAUTULLI_URL="http://10.0.0.10:8181/api/v2" # Make sure protocol & domain are correct!
# Function to set SABnzbd speed limit
set_sab_speed() {
local speed=$1
local full_url="${SABNZBD_URL}?mode=config&name=speedlimit&value=${speed}&apikey=${SABNZBD_API_KEY}"
# SABnzbd API configuration:
SAB_ADDRESS="http://10.0.0.10:8080"
SAB_API_KEY="86a11e19dcb1400a869773be38abc9bf"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Sending request to set SABnzbd speed to ${speed} KB/s"
response=$(curl -s "${full_url}")
# Speed limit settings:
BASE_SPEED_LIMIT_MB=50 # Base SABnzbd speed limit in MB/s
OFFSET_PER_USER_MB=5 # Reduce speed by X MB/s for each remote user
MIN_SPEED_MB=10 # Minimum speed limit in MB/s
if [[ -z $response ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - No response received from SABnzbd API."
else
echo "$(date '+%Y-%m-%d %H:%M:%S') - SABnzbd API response: ${response}"
fi
# Local network configuration:
LOCAL_IP_PREFIX="10.0.0."
# Loop interval:
WAIT_INTERVAL=3 # Seconds between checks
# -------------------------------------------------------------------
# Logging Function
# -------------------------------------------------------------------
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
}
# Function to check if Plex is playing a file via Tautulli API
is_plex_playing() {
local full_url="${TAUTULLI_URL}?apikey=${TAUTULLI_API_KEY}&cmd=get_activity"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Checking Plex activity via Tautulli API"
# -------------------------------------------------------------------
# check_tautulli_connection:
# Confirms Tautulli returns HTTP 200 and valid JSON with .response.data.sessions
# -------------------------------------------------------------------
check_tautulli_connection() {
log_message "Checking connection to Tautulli API at ${TAUTULLI_URL}"
response=$(curl -s "${full_url}" | jq -r '.response.data.sessions | length')
# Make a request, capture HTTP status & body separately
http_response=$(curl -s -w "HTTPSTATUS:%{http_code}" -o /tmp/tautulli_check.json \
"${TAUTULLI_URL}?apikey=${TAUTULLI_API_KEY}&cmd=get_activity")
if [[ "$response" -gt 0 ]]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Plex is currently playing $response file(s)"
return 0
else
echo "$(date '+%Y-%m-%d %H:%M:%S') - No Plex playback detected"
# Extract the status code
status_code=$(echo "$http_response" | sed -n 's/.*HTTPSTATUS://p')
# Read the response body from the temp file
body=$(cat /tmp/tautulli_check.json)
if [ "$status_code" -ne 200 ]; then
log_message "ERROR: Tautulli returned HTTP status $status_code. Check your URL or API key."
return 1
fi
# Ensure we have the key .response.data.sessions in the JSON
if ! echo "$body" | jq -e '.response.data.sessions' >/dev/null 2>&1; then
log_message "ERROR: Tautulli's JSON is missing .response.data.sessions. Possibly an invalid response."
return 1
fi
log_message "Successfully connected to Tautulli."
return 0
}
# Monitoring loop
while true; do
if is_plex_playing; then
# If Plex is playing/transcoding, use SLOW_SPEED
set_sab_speed "${SLOW_SPEED}"
else
# If Plex is not playing/transcoding, check the current hour
current_hour=$(date +%H)
# -------------------------------------------------------------------
# adjust_sab_speed_limit:
# Retrieves current Tautulli data, calculates new SAB speed,
# and updates SABnzbd using the 4.4 API format.
# -------------------------------------------------------------------
adjust_sab_speed_limit() {
# Make a fresh request for current Tautulli data
http_response=$(curl -s -w "HTTPSTATUS:%{http_code}" -o /tmp/tautulli_data.json \
"${TAUTULLI_URL}?apikey=${TAUTULLI_API_KEY}&cmd=get_activity")
# Compare current hour to NIGHT_START and NIGHT_END
if [ "${current_hour}" -ge "${NIGHT_START}" ] && [ "${current_hour}" -lt "${NIGHT_END}" ]; then
# If current time is between NIGHT_START and NIGHT_END (exclusive of NIGHT_END), use NIGHT_SPEED
set_sab_speed "${NIGHT_SPEED}"
else
# Otherwise, use NORMAL_SPEED
set_sab_speed "${NORMAL_SPEED}"
fi
status_code=$(echo "$http_response" | sed -n 's/.*HTTPSTATUS://p')
body=$(cat /tmp/tautulli_data.json)
if [ "$status_code" -ne 200 ]; then
log_message "ERROR: Tautulli returned HTTP status $status_code. Skipping SABnzbd update."
return
fi
sleep "${CHECK_INTERVAL}"
# Check that the JSON structure is correct
if ! echo "$body" | jq -e '.response.data.sessions' >/dev/null 2>&1; then
log_message "ERROR: Tautulli's JSON is missing .response.data.sessions. Skipping SABnzbd update."
return
fi
# Count remote sessions (where IP does not start with LOCAL_IP_PREFIX)
remote_count=$(echo "$body" | jq "[.response.data.sessions[]?
| select(.ip_address | startswith(\"${LOCAL_IP_PREFIX}\") | not)]
| length")
# Sum the remote sessions' bandwidth
total_bandwidth=$(echo "$body" | jq "[.response.data.sessions[]?
| select(.ip_address | startswith(\"${LOCAL_IP_PREFIX}\") | not)
| .bandwidth]
| add")
if [ -z "$total_bandwidth" ] || [ "$total_bandwidth" = "null" ]; then
total_bandwidth=0
fi
# Round up to the nearest integer
rounded_bandwidth=$(echo "$total_bandwidth" | awk '{if($1==int($1)){print $1}else{print int($1)+1}}')
log_message "Detected ${remote_count} remote streaming session(s) with a total bandwidth of ${rounded_bandwidth} MB/s."
# Subtract both the per-user offset and the total remote bandwidth
reduction=$(( remote_count * OFFSET_PER_USER_MB ))
new_speed=$(( BASE_SPEED_LIMIT_MB - reduction - rounded_bandwidth ))
if [ "$new_speed" -lt "$MIN_SPEED_MB" ]; then
new_speed=$MIN_SPEED_MB
fi
# Log the calculation details first
log_message "(Base: ${BASE_SPEED_LIMIT_MB} MB/s, Offset: ${remote_count} x ${OFFSET_PER_USER_MB} MB/s, Remote BW: ${rounded_bandwidth} MB/s)"
# Then log the final speed
log_message "Calculated new SABnzbd speed limit: ${new_speed} MB/s"
# Update SABnzbd
sab_api_url="${SAB_ADDRESS}/api?mode=config&name=speedlimit&apikey=${SAB_API_KEY}&value=${new_speed}M"
log_message "Sending SABnzbd API request: ${sab_api_url}"
sab_response=$(curl -s -w "HTTPSTATUS:%{http_code}" "$sab_api_url")
sab_body=$(echo "$sab_response" | sed -e 's/HTTPSTATUS\:.*//g')
sab_status=$(echo "$sab_response" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if [ "$sab_status" -eq 200 ]; then
log_message "SABnzbd speed limit successfully updated. Response: ${sab_body}"
else
log_message "Error updating SABnzbd speed limit. HTTP status: ${sab_status}, Response: ${sab_body}"
fi
}
# -------------------------------------------------------------------
# Main Execution Loop
# -------------------------------------------------------------------
while true; do
# First confirm Tautulli is actually reachable & returning valid JSON
if ! check_tautulli_connection; then
log_message "Skipping speed adjustment due to Tautulli connection error."
else
# If Tautulli is valid, do the speed adjustment
adjust_sab_speed_limit
fi
log_message "Waiting for ${WAIT_INTERVAL} seconds before next check..."
echo ""
sleep "${WAIT_INTERVAL}"
done