Update sab_speed_control.sh
This commit is contained in:
@@ -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 SABnzbd’s 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
|
||||
|
||||
Reference in New Issue
Block a user