import { exec, execAsync, GLib, interval, Variable } from "astal"; import { Gtk } from "astal/gtk4"; import AstalBattery from "gi://AstalBattery?version=0.1"; const FETCH_INTERVAL = 2000; const cpuUtil = Variable("0%"); const ramUtil = Variable("0%"); const ramUsed = Variable("0MiB"); const gpuUtil = Variable("0%"); let gpuName = "card1"; let enabled = false; const refreshStats = (): Stats => { gpuName = exec(`/bin/bash -c "ls /sys/class/drm/ | grep '^card[0-9]*$'"`); const cpuNameInSensors = "CPUTIN"; const stats = { kernel: exec("uname -sr"), netSpeed: exec( `/bin/bash -c "interface=$(ip route get 8.8.8.8 | awk '{print $5; exit}') && cat \"/sys/class/net/$interface/speed\""`, ), cpuTemp: exec( `/bin/bash -c "sensors | grep -m1 ${cpuNameInSensors} | awk '{print $2}'"`, ), cpuClk: exec( `awk '/cpu MHz/ {sum+=$4; ++n} END {print sum/n " MHz"}' /proc/cpuinfo`, ), gpuTemp: exec( `/bin/bash -c "sensors | grep -E 'edge' | awk '{print $2}'"`, ), gpuClk: exec( `/bin/bash -c "cat /sys/class/drm/${gpuName}/device/pp_dpm_sclk | grep '\\*' | awk '{print $2 $3}'"`, ), vram: Math.round( parseInt( exec( `cat /sys/class/drm/${gpuName}/device/mem_info_vram_used`, ), ) / 1024 / 1024, ) + "MiB", availableVRAM: Math.round( parseInt( exec( `cat /sys/class/drm/${gpuName}/device/mem_info_vram_total`, ), ) / 1024 / 1024, ) + "MiB", }; return stats; }; const systemStats: Variable = Variable(refreshStats()); const availableFeatures = { cpu: true, ram: true, }; const featureTest = () => { // Check if awk & sed are available try { exec("awk -V"); exec("sed --version"); enabled = true; } catch (e) { printerr( "[ SysInfo ] AWK or SED missing! No system info will be available", ); enabled = false; return; } // Check if mpstat is available try { exec("mpstat -V"); } catch (e) { availableFeatures.cpu = false; printerr( "[ SysInfo ] Feature Test for CPU info failed. mpstat from the sysstat package missing!", ); } }; const info = () => { return ( ); }; const SystemInformationPanel = () => { const popover = new Gtk.Popover(); popover.set_child(info()); return popover; }; const sysInfoFetcher = () => { if (enabled) { if (availableFeatures.cpu) { cpuUtil.set( "" + Math.round( parseFloat(exec(`/bin/fish -c cpu-utilization`)), ), ); } if (availableFeatures.ram) { ramUtil.set( "" + Math.round( parseFloat( exec( `/bin/bash -c "free | awk '/Mem/ { printf(\\"%.2f\\\\n\\", ($3/$2)*100) }'"`, ), ), ), ); ramUsed.set( exec( `/bin/bash -c \"free -h | awk '/^Mem:/ {print $3 \\" used of \\" $2}'\"`, ) .replaceAll("Gi", "GiB") .replaceAll("Mi", "MiB"), ); } gpuUtil.set(exec("cat /sys/class/drm/card1/device/gpu_busy_percent")); } }; const panel = SystemInformationPanel(); const SystemInfo = () => { featureTest(); const openSysInfo = async () => { panel.popup(); systemStats.set(refreshStats()); }; if (enabled) { sysInfoFetcher(); interval(FETCH_INTERVAL, sysInfoFetcher); return ( ); } else { return ; } }; export default { SystemInfo, panel, };