import { exec, 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 }