Files
dashboard/widgets/system-widget.sh
Francisco 7b2949e739 Initial commit: conky dashboard + DogeBot
Three conky panels (main, dayz, doge) plus all widgets, NUT config templates,
and the systemd timer that drives the qwen2.5:1.5b vibe report on maeth-storage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:16:54 -04:00

107 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/home-assistant-energy-widget"
CACHE_FILE="$CACHE_DIR/system-cpu.stat"
mkdir -p "$CACHE_DIR"
read _ user nice system idle iowait irq softirq steal _ _ < /proc/stat
total=$((user + nice + system + idle + iowait + irq + softirq + steal))
idle_all=$((idle + iowait))
cpu_percent="--"
if [[ -f "$CACHE_FILE" ]]; then
read -r prev_idle prev_total < "$CACHE_FILE" || true
if [[ -n "${prev_idle:-}" && -n "${prev_total:-}" && "$total" -gt "$prev_total" ]]; then
delta_idle=$((idle_all - prev_idle))
delta_total=$((total - prev_total))
cpu_percent="$((100 * (delta_total - delta_idle) / delta_total))"
fi
fi
printf '%s %s\n' "$idle_all" "$total" > "$CACHE_FILE"
read mem_total mem_available <<< "$(awk '/MemTotal/{t=$2} /MemAvailable/{a=$2} END {print t, a}' /proc/meminfo)"
mem_used=$((mem_total - mem_available))
mem_percent=$((100 * mem_used / mem_total))
mem_used_gib="$(awk -v kb="$mem_used" 'BEGIN {printf "%.1f", kb / 1024 / 1024}')"
mem_total_gib="$(awk -v kb="$mem_total" 'BEGIN {printf "%.1f", kb / 1024 / 1024}')"
bar() {
local pct="$1" filled total=26
filled=$(( pct * total / 100 ))
(( filled < 0 )) && filled=0
(( filled > total )) && filled=$total
local out="" i
for ((i = 0; i < total; i++)); do
if (( i < filled )); then out+="▰"; else out+="▱"; fi
done
printf '%s' "$out"
}
printf '${color 34D399}▎${color} ${color F1F5F9}${font Inter:bold:size=9}MAETH-PC${font}${color}${alignr}${color 34D399}●${color}\n'
if [[ "$cpu_percent" == "--" ]]; then
printf '${color 64748B}cpu${color}${alignr}${color 475569}${font Adwaita Mono:size=9}warming up${font}${color}\n'
else
printf '${color 64748B}cpu${color}${goto 60}${color E2E8F0}${font Adwaita Mono:size=9}%3s%%${font}${color}${alignr}${color 34D399}${font Adwaita Mono:size=11}%s${font}${color}\n' "$cpu_percent" "$(bar "$cpu_percent")"
fi
printf '${color 64748B}mem${color}${goto 60}${color E2E8F0}${font Adwaita Mono:size=9}%3s%%${font}${color}${alignr}${color 34D399}${font Adwaita Mono:size=11}%s${font}${color}\n' "$mem_percent" "$(bar "$mem_percent")"
printf '${color 475569}${font Inter:size=8}%s / %s GiB${font}${color}\n' "$mem_used_gib" "$mem_total_gib"
if command -v upsc >/dev/null 2>&1; then
ups_out="$(upsc hikvision@localhost 2>/dev/null || true)"
if [[ -n "$ups_out" ]]; then
ups_status="$(printf '%s\n' "$ups_out" | awk -F': ' '$1=="ups.status"{print $2}')"
ups_load="$(printf '%s\n' "$ups_out" | awk -F': ' '$1=="ups.load"{print $2}')"
batt_charge="$(printf '%s\n' "$ups_out" | awk -F': ' '$1=="battery.charge"{print $2}')"
batt_runtime="$(printf '%s\n' "$ups_out" | awk -F': ' '$1=="battery.runtime"{print $2}')"
in_volt="$(printf '%s\n' "$ups_out" | awk -F': ' '$1=="input.voltage"{print $2}')"
case "${ups_status:-}" in
*OL*) status_label="online"; status_color=34D399 ;;
*OB*) status_label="on battery"; status_color=FBBF24 ;;
*LB*) status_label="LOW BATT"; status_color=FB7185 ;;
*) status_label="${ups_status:-?}"; status_color=64748B ;;
esac
printf '${color 64748B}ups${color}${goto 60}${color %s}${font Adwaita Mono:size=9}%s${font}${color}' "$status_color" "$status_label"
if [[ -n "${batt_charge:-}" ]]; then
pct=$(printf '%.0f' "$batt_charge")
bar_color=34D399
(( pct < 50 )) && bar_color=FBBF24
(( pct < 20 )) && bar_color=FB7185
printf '${alignr}${color %s}${font Adwaita Mono:size=11}%s${font}${color}' "$bar_color" "$(bar "$pct")"
fi
printf '\n'
meta=()
[[ -n "${batt_charge:-}" ]] && meta+=("batt $(printf '%.0f' "$batt_charge")%")
[[ -n "${ups_load:-}" ]] && meta+=("load $(printf '%.0f' "$ups_load")%")
[[ -n "${batt_runtime:-}" ]] && meta+=("$((batt_runtime/60)) min")
[[ -n "${in_volt:-}" ]] && meta+=("$(printf '%.0f' "$in_volt") V")
if (( ${#meta[@]} > 0 )); then
meta_str="$(IFS=$'\n'; printf '%s\n' "${meta[@]}" | paste -sd '|' - | sed 's/|/ · /g')"
printf '${color 475569}${font Inter:size=8}%s${font}${color}\n' "$meta_str"
fi
fi
fi
if command -v nvidia-smi >/dev/null 2>&1; then
query='index,name,utilization.gpu,memory.used,memory.total,temperature.gpu,power.draw,power.limit'
if gpu_output="$(nvidia-smi --query-gpu="$query" --format=csv,noheader,nounits 2>/dev/null)"; then
printf '%s\n' "$gpu_output" | awk -F', *' '
{
name=$2
gsub(/^NVIDIA GeForce /, "", name)
gsub(/^GeForce /, "", name)
gsub(/^NVIDIA /, "", name)
power=$7; limit=$8
if (power == "[N/A]" || limit == "[N/A]") {
meta=sprintf("%s°C", $6)
} else {
meta=sprintf("%s°C · %s/%s W", $6, power, limit)
}
printf "${color 64748B}%s${color}${alignr}${color E2E8F0}${font Adwaita Mono:size=9}%s%%${font}${color}\n", name, $3
printf "${color 475569}${font Inter:size=8}%s / %s MiB${font}${color}${alignr}${color 475569}${font Inter:size=8}%s${font}${color}\n", $4, $5, meta
}
'
fi
fi