This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

eww: show tdp graph

+113
+113
2configs/desktops/sway/eww.nix
··· 19 19 (defpoll cpu-freq :interval "2s" :initial 0 "${lib.getExe cpuFreqScript}") 20 20 (defpoll cpu-load :interval "2s" :initial "0.00" "cut -d' ' -f1 /proc/loadavg") 21 21 (defpoll temperature :interval "2s" :initial '{"temp": 0, "fan": 0}' "${lib.getExe tempScript}") 22 + (defpoll power :interval "2s" :initial '{"watts": 0, "charging": false}' "${lib.getExe powerScript}") 22 23 (defpoll battery :interval "10s" :initial '{"capacity": "100", "icon": "󰁹", "watts": "0", "time_remaining": "--", "status": "Full"}' "${lib.getExe batteryScript}") 23 24 (defpoll volume :interval "1s" :initial '{"level": "0", "icon": "󰕿"}' "${lib.getExe volumeScript}") 24 25 (defpoll network :interval "5s" :initial "󰖪 ..." "${lib.getExe networkScript}") ··· 48 49 (graph-widget :value {EWW_CPU.avg} :icon "󰍛" :class "cpu" :unit "%" :tooltip "Load: ''${cpu-load} | ''${cpu-freq} MHz") 49 50 (graph-widget :value {EWW_RAM.used_mem_perc} :icon "󰘚" :class "memory" :unit "%") 50 51 (graph-widget :value {temperature.temp} :icon "󰔏" :class "temp" :unit "°" :tooltip "Fan: ''${temperature.fan} RPM") 52 + (power-graph-widget) 51 53 (brightness-widget) 52 54 (battery-widget) 53 55 (idle-inhibitor) ··· 79 81 (box :class "battery" :orientation "h" :space-evenly false 80 82 :tooltip "''${battery.watts}W | ''${battery.time_remaining} ''${battery.status == 'Charging' ? 'to full' : 'remaining'}" 81 83 (label :text "''${battery.capacity}% ''${battery.icon}"))) 84 + 85 + (defwidget power-graph-widget [] 86 + (box :class {power.charging ? "graph-module power charging" : "graph-module power"} :orientation "h" :space-evenly false :spacing 4 87 + :tooltip "''${battery.time_remaining} ''${battery.status == 'Charging' ? 'to full' : 'remaining'}" 88 + (graph :class "graph" 89 + :value {power.watts} 90 + :thickness 3 91 + :time-range "60s" 92 + :min 0 93 + :max 45 94 + :dynamic false 95 + :line-style "round" 96 + :width 75) 97 + (label :text "''${round(power.watts, 1)}W ''${power.charging ? '󰂄' : '󰁹'}"))) 82 98 83 99 (defwidget volume-widget [] 84 100 (box :class "volume" :orientation "h" :space-evenly false ··· 164 180 background-color: #ff9e64; 165 181 color: #1a1b26; 166 182 } 183 + &.power { 184 + background-color: #f7768e; 185 + color: #1a1b26; 186 + &.charging { 187 + background-color: #9ece6a; 188 + } 189 + } 167 190 } 168 191 169 192 .graph { ··· 246 269 ''; 247 270 }; 248 271 272 + powerScript = pkgs.writeShellApplication { 273 + name = "eww-power"; 274 + runtimeInputs = [ 275 + pkgs.jq 276 + pkgs.bc 277 + ]; 278 + text = '' 279 + # Use RAPL for actual system power consumption (works on Intel and AMD Zen) 280 + # Falls back to battery power_now if RAPL unavailable 281 + 282 + state_file="/tmp/eww-power-state" 283 + rapl_path="/sys/class/powercap/intel-rapl:0/energy_uj" 284 + 285 + # Check charging status 286 + charging="false" 287 + for p in /sys/class/power_supply/BAT* /sys/class/power_supply/BATT*; do 288 + if [ -f "$p/status" ]; then 289 + status=$(cat "$p/status" 2>/dev/null || echo "Unknown") 290 + if [ "$status" = "Charging" ]; then 291 + charging="true" 292 + fi 293 + break 294 + fi 295 + done 296 + 297 + # Try RAPL first (gives actual system power regardless of charging state) 298 + if [ -r "$rapl_path" ]; then 299 + current_energy=$(cat "$rapl_path") 300 + current_time=$(date +%s%N) 301 + 302 + if [ -f "$state_file" ]; then 303 + read -r prev_energy prev_time < "$state_file" 304 + 305 + # Calculate power from energy difference 306 + energy_diff=$((current_energy - prev_energy)) 307 + time_diff=$((current_time - prev_time)) 308 + 309 + # Handle counter wrap-around 310 + if [ "$energy_diff" -lt 0 ]; then 311 + max_energy=$(cat /sys/class/powercap/intel-rapl:0/max_energy_range_uj 2>/dev/null || echo 0) 312 + energy_diff=$((energy_diff + max_energy)) 313 + fi 314 + 315 + if [ "$time_diff" -gt 0 ]; then 316 + # energy_diff is in microjoules, time_diff is in nanoseconds 317 + # watts = microjoules / (nanoseconds / 1e9) / 1e6 = microjoules * 1000 / nanoseconds 318 + watts=$(echo "scale=1; $energy_diff * 1000 / $time_diff" | bc) 319 + else 320 + watts="0" 321 + fi 322 + else 323 + watts="0" 324 + fi 325 + 326 + # Save current state 327 + echo "$current_energy $current_time" > "$state_file" 328 + 329 + jq -n --argjson watts "$watts" --argjson charging "$charging" '{watts: $watts, charging: $charging}' 330 + exit 0 331 + fi 332 + 333 + # Fallback: use battery power_now (only accurate when discharging) 334 + bat_path="" 335 + for p in /sys/class/power_supply/BAT* /sys/class/power_supply/BATT*; do 336 + if [ -f "$p/power_now" ]; then 337 + bat_path="$p" 338 + break 339 + fi 340 + done 341 + 342 + if [ -z "$bat_path" ]; then 343 + echo '{"watts": 0, "charging": false}' 344 + exit 0 345 + fi 346 + 347 + power_now=$(cat "$bat_path/power_now" 2>/dev/null || echo 0) 348 + watts=$(echo "scale=1; $power_now / 1000000" | bc) 349 + 350 + jq -n --argjson watts "$watts" --argjson charging "$charging" '{watts: $watts, charging: $charging}' 351 + ''; 352 + }; 353 + 249 354 batteryScript = pkgs.writeShellApplication { 250 355 name = "eww-battery"; 251 356 runtimeInputs = [ ··· 287 392 hours=$(echo "scale=2; $energy_now / $power_now" | bc) 288 393 fi 289 394 # Convert to hours:minutes 395 + # Note: bc outputs ".76" for values < 1, so cut returns empty string 290 396 h=$(echo "$hours" | cut -d. -f1) 397 + h=''${h:-0} # Default to 0 if empty (i.e., less than 1 hour) 291 398 m=$(echo "scale=0; ($hours - $h) * 60 / 1" | bc) 292 399 time_remaining="''${h}h ''${m}m" 293 400 else ··· 413 520 414 521 in 415 522 { 523 + # Make RAPL energy counters readable for power monitoring 524 + # Works on both Intel and AMD Zen CPUs (via intel_rapl_msr module) 525 + services.udev.extraRules = '' 526 + SUBSYSTEM=="powercap", ACTION=="add", RUN+="${pkgs.coreutils}/bin/chmod a+r /sys/class/powercap/%k/energy_uj" 527 + ''; 528 + 416 529 # eww daemon 417 530 systemd.user.services.eww = { 418 531 description = "ElKowars Wacky Widgets daemon";