hardwaremon 1.2.2__tar.gz → 1.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/PKG-INFO +1 -1
  2. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/hardwaremon.py +123 -152
  3. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/PKG-INFO +1 -1
  4. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/.github/workflows/publish.yml +0 -0
  5. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/.github/workflows/python-app.yml +0 -0
  6. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/.gitignore +0 -0
  7. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/HardwareMon.sh +0 -0
  8. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/LICENSE +0 -0
  9. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/README.md +0 -0
  10. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/Windows/HardwareMon.exe +0 -0
  11. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/Windows/hardwaremon_win.py +0 -0
  12. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/assets/demo.gif +0 -0
  13. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/__init__.py +0 -0
  14. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/hardwaremon_gui.py +0 -0
  15. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/board.png +0 -0
  16. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/cpu.png +0 -0
  17. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/disk.png +0 -0
  18. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/gpu.png +0 -0
  19. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/os.png +0 -0
  20. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon/icons/ram.png +0 -0
  21. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/SOURCES.txt +0 -0
  22. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/dependency_links.txt +0 -0
  23. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/entry_points.txt +0 -0
  24. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/requires.txt +0 -0
  25. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/hardwaremon.egg-info/top_level.txt +0 -0
  26. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/pyproject.toml +0 -0
  27. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/requirements.txt +0 -0
  28. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/setup.cfg +0 -0
  29. {hardwaremon-1.2.2 → hardwaremon-1.2.3}/test_hardwaremon.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hardwaremon
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Hardware monitoring tool for Linux
5
5
  Author: Louis
6
6
  Requires-Python: >=3.8
@@ -117,65 +117,32 @@ def check_alerts():
117
117
  return alerts
118
118
 
119
119
 
120
- def gpu_info() -> list[str]:
121
- lines = ["=== GPU Information ==="]
122
-
120
+ def gpu_info():
121
+ lines = ["=== GPU INFORMATION ===", ""]
123
122
  try:
124
- if platform.system() != "Linux":
125
- return ["GPU info not implemented for this OS."]
126
-
127
- # 1. Find dedicated AMD / NVIDIA GPUs
128
- cmd = (
129
- "lspci | grep -Ei '(NVIDIA Corporation|Advanced Micro Devices, Inc.)' | "
130
- "grep -E '(VGA|3D)' | grep -vi 'APU'"
131
- )
132
- gpus = [l for l in run(cmd).splitlines() if l]
133
-
134
- if not gpus:
135
- return ["No dedicated AMD or NVIDIA GPU found."]
136
-
137
- for gpu in gpus:
138
- lines.append(gpu)
139
-
140
- # Extract PCI bus ID (e.g. 01:00.0)
141
- bus_id = gpu.split()[0]
142
-
143
- # 2. PCIe lane width (current + max)
144
- pcie_info = run(f"lspci -s {bus_id} -vv")
145
- lane_match = re.search(
146
- r"LnkSta:\s+Speed\s+[^,]+,\s+Width\s+x(\d+).*?LnkCap:\s+Speed\s+[^,]+,\s+Width\s+x(\d+)",
147
- pcie_info,
148
- re.S,
149
- )
150
- if lane_match:
151
- current, maximum = lane_match.groups()
152
- lines.append(f" PCIe: x{current} (max x{maximum})")
153
- else:
154
- lines.append(" PCIe: Unknown")
155
-
156
- # 3. VRAM detection
157
- if "NVIDIA" in gpu:
158
- vram = run(
159
- "nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits"
160
- )
161
- lines.append(f" VRAM: {vram} MB" if vram else " VRAM: Unknown")
162
-
163
- elif "Advanced Micro Devices" in gpu:
164
- # Try sysfs first (works without Xorg / on Wayland)
165
- vram_bytes = run(
166
- f"cat /sys/bus/pci/devices/0000:{bus_id}/mem_info_vram_total 2>/dev/null"
167
- )
168
- if vram_bytes and vram_bytes.isdigit():
169
- vram_mb = int(vram_bytes) // (1024 ** 2)
170
- lines.append(f" VRAM: {vram_mb} MB")
171
- else:
172
- # Fallback: rocm-smi
173
- vram = run("rocm-smi --showmeminfo vram 2>/dev/null | grep 'Total Memory'")
174
- lines.append(f" VRAM: {vram}" if vram else " VRAM: Unknown")
123
+ # Try NVIDIA first
124
+ nvidia = subprocess.getoutput("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader")
125
+ if nvidia and "error" not in nvidia.lower() and "not found" not in nvidia.lower():
126
+ for line in nvidia.strip().split("\n"):
127
+ lines.append(line.strip())
128
+ return lines
129
+
130
+ # Try AMD via rocm-smi
131
+ amd = subprocess.getoutput("rocm-smi --showproductname 2>/dev/null")
132
+ if amd and "not found" not in amd.lower() and "error" not in amd.lower():
133
+ for line in amd.strip().split("\n"):
134
+ lines.append(line.strip())
135
+ return lines
136
+
137
+ # Fall back to lspci
138
+ out = subprocess.getoutput("lspci | grep -Ei 'vga|3d|display'")
139
+ if out:
140
+ lines.extend(out.strip().split("\n"))
141
+ else:
142
+ lines.append("GPU info not available")
175
143
 
176
144
  except Exception as e:
177
- lines.append(f"Error retrieving GPU info: {e}")
178
-
145
+ lines.append(f"GPU info error: {e}")
179
146
  return lines
180
147
 
181
148
  # GPU temp (if available)
@@ -399,74 +366,6 @@ def memory_temperature():
399
366
  return lines if len(lines) > 1 else ["===No Memory temperature data found==="]
400
367
 
401
368
 
402
- def gpu_info():
403
- lines = ["=== GPU Information ==="]
404
-
405
- try:
406
- if platform.system() != "Linux":
407
- return ["GPU info not implemented for this OS."]
408
-
409
- # 1. Find ONLY dedicated AMD / NVIDIA GPUs
410
- cmd = (
411
- "lspci | grep -Ei "
412
- "'(NVIDIA Corporation|Advanced Micro Devices, Inc.)' | "
413
- "'(VGA|3D)' | "
414
- "'(APU)' -vi"
415
- "grep -E '(VGA|3D)' | "
416
- "grep -vi 'APU'"
417
- )
418
- gpus = [l for l in os.popen(cmd).read().splitlines() if l]
419
-
420
- if not gpus:
421
- return ["No dedicated AMD or NVIDIA GPU found."]
422
-
423
- for gpu in gpus:
424
- lines.append(gpu)
425
-
426
- # Extract PCI bus ID (e.g. 01:00.0)
427
- bus_id = gpu.split()[0]
428
-
429
- # 2. PCIe lane width (current + max)
430
- pcie_info = os.popen(f"lspci -s {bus_id} -vv").read()
431
- lane_match = re.search(
432
- r"LnkSta:\s+Speed\s+[^,]+,\s+Width\s+x(\d+).*?\n.*?LnkCap:\s+Speed\s+[^,]+,\s+Width\s+x(\d+)",
433
- pcie_info,
434
- re.S
435
- )
436
-
437
- if lane_match:
438
- current, maximum = lane_match.groups()
439
- lines.append(f" PCIe: x{current} (max x{maximum})")
440
- else:
441
- lines.append(" PCIe: Unknown")
442
-
443
- # 3. VRAM detection
444
- if "NVIDIA" in gpu:
445
- vram = os.popen(
446
- "nvidia-smi --query-gpu=memory.total "
447
- "--format=csv,noheader,nounits"
448
- ).read().strip()
449
- if vram:
450
- lines.append(f" VRAM: {vram} MB")
451
- else:
452
- lines.append(" VRAM: Unknown")
453
-
454
- elif "Advanced Micro Devices" in gpu:
455
- vram = os.popen(
456
- "grep -i 'VRAM' /var/log/Xorg.0.log 2>/dev/null | head -n1"
457
- ).read().strip()
458
- if vram:
459
- lines.append(f" VRAM: {vram}")
460
- else:
461
- lines.append(" VRAM: Unknown (AMD userspace tools vary)")
462
-
463
- return lines
464
-
465
- except Exception as e:
466
- return [f"GPU info error: {e}"]
467
-
468
-
469
-
470
369
 
471
370
 
472
371
  def intel_gpu_info():
@@ -588,36 +487,110 @@ def drive_info():
588
487
 
589
488
  def gpu_temperature():
590
489
  lines = ["=== GPU Temperature ==="]
591
- temps = psutil.sensors_temperatures()
592
- if not temps:
593
- return ["GPU temperature sensors not available"]
594
-
595
- for name, entries in temps.items():
596
- for entry in entries:
597
- if "gpu" in entry.label.lower() or "nvidia" in name.lower() or "amdgpu" in name.lower():
598
- if entry.label:
599
- lines.append(f"{entry.label}: {entry.current} °C")
600
- else:
601
- lines.append(f"{name}: {entry.current} °C")
602
-
603
- return lines if len(lines) > 1 else ["===No GPU temperature data found==="]
604
-
490
+ found = False
491
+
492
+ # NVIDIA
493
+ nvidia = subprocess.getoutput("nvidia-smi --query-gpu=name,temperature.gpu --format=csv,noheader 2>/dev/null")
494
+ if nvidia and "not found" not in nvidia.lower() and "error" not in nvidia.lower() and "failed" not in nvidia.lower():
495
+ for line in nvidia.strip().split("\n"):
496
+ parts = line.split(",")
497
+ if len(parts) == 2:
498
+ name, temp = parts[0].strip(), parts[1].strip()
499
+ lines.append(f"{name}: {temp} °C")
500
+ found = True
501
+
502
+ # AMD via rocm-smi
503
+ amd = subprocess.getoutput("rocm-smi --showtemp 2>/dev/null")
504
+ if amd and "not found" not in amd.lower() and "error" not in amd.lower():
505
+ for line in amd.strip().split("\n"):
506
+ if "temperature" in line.lower() or "°c" in line.lower() or "temp" in line.lower():
507
+ lines.append(line.strip())
508
+ found = True
509
+
510
+ # AMD fallback via hwmon (works without rocm-smi)
511
+ if not found:
512
+ hwmon_base = "/sys/class/hwmon"
513
+ if os.path.exists(hwmon_base):
514
+ for hw in os.listdir(hwmon_base):
515
+ hw_path = os.path.join(hwmon_base, hw)
516
+ name = read_sys(os.path.join(hw_path, "name")) or ""
517
+ if "amdgpu" in name.lower():
518
+ for f in os.listdir(hw_path):
519
+ if f.startswith("temp") and f.endswith("_input"):
520
+ raw = read_sys(os.path.join(hw_path, f))
521
+ label_file = f.replace("_input", "_label")
522
+ label = read_sys(os.path.join(hw_path, label_file)) or f
523
+ if raw and raw.isdigit():
524
+ lines.append(f"AMD ({label}): {int(raw) // 1000} °C")
525
+ found = True
526
+
527
+ return lines if found else ["=== No GPU temperature data found ==="]
528
+
529
+
530
+ def get_package_manager():
531
+ for pm, cmd in [("apt", "sudo apt install i2c-tools"),
532
+ ("dnf", "sudo dnf install i2c-tools"),
533
+ ("pacman", "sudo pacman -S i2c-tools"),
534
+ ("zypper", "sudo zypper install i2c-tools")]:
535
+ if subprocess.getoutput(f"which {pm} 2>/dev/null").strip():
536
+ return cmd
537
+ return "install i2c-tools via your package manager"
605
538
 
606
539
  def memory_temperature():
607
540
  lines = ["=== Memory Temperature ==="]
608
- temps = psutil.sensors_temperatures()
609
- if not temps:
610
- return ["Memory temperature sensors not available"]
611
-
612
- for name, entries in temps.items():
613
- for entry in entries:
614
- if "memory" in entry.label.lower() or "ram" in name.lower():
615
- if entry.label:
616
- lines.append(f"{entry.label}: {entry.current} °C")
617
- else:
618
- lines.append(f"{name}: {entry.current} °C")
541
+ found = False
542
+
543
+ i2c_available = subprocess.getoutput("which decode-dimms 2>/dev/null").strip()
544
+ eeprom_loaded = "eeprom" in subprocess.getoutput("lsmod 2>/dev/null")
545
+
546
+ if not i2c_available or not eeprom_loaded:
547
+ lines.append("DIMM Memory temperature unavailable.")
548
+ lines.append("")
549
+ if not i2c_available:
550
+ lines.append(" → Install i2c-tools:")
551
+ lines.append(f" {get_package_manager()}")
552
+ if not eeprom_loaded:
553
+ lines.append(" → Load the eeprom kernel module:")
554
+ lines.append(" sudo modprobe eeprom")
555
+ lines.append(" (Add 'eeprom' to /etc/modules to persist across reboots)")
556
+ return lines
619
557
 
620
- return lines if len(lines) > 1 else ["===No Memory temperature data found==="]
558
+ # Try decode-dimms
559
+ decode = subprocess.getoutput("decode-dimms 2>/dev/null")
560
+ if decode and "not found" not in decode.lower() and "command not found" not in decode.lower():
561
+ for line in decode.split("\n"):
562
+ if "temperature" in line.lower():
563
+ lines.append(line.strip())
564
+ found = True
565
+
566
+ # Try hwmon
567
+ if not found:
568
+ hwmon_base = "/sys/class/hwmon"
569
+ if os.path.exists(hwmon_base):
570
+ for hw in os.listdir(hwmon_base):
571
+ hw_path = os.path.join(hwmon_base, hw)
572
+ name = read_sys(os.path.join(hw_path, "name")) or ""
573
+ if any(k in name.lower() for k in ("dimm", "ddr", "ram", "memory", "spd")):
574
+ for f in os.listdir(hw_path):
575
+ if f.startswith("temp") and f.endswith("_input"):
576
+ raw = read_sys(os.path.join(hw_path, f))
577
+ label_file = f.replace("_input", "_label")
578
+ label = read_sys(os.path.join(hw_path, label_file)) or f
579
+ if raw and raw.isdigit():
580
+ lines.append(f"{name} ({label}): {int(raw) // 1000} °C")
581
+ found = True
582
+
583
+ # psutil fallback
584
+ if not found:
585
+ temps = psutil.sensors_temperatures()
586
+ if temps:
587
+ for name, entries in temps.items():
588
+ for entry in entries:
589
+ if "memory" in entry.label.lower() or "ram" in name.lower() or "dimm" in name.lower():
590
+ lines.append(f"{entry.label or name}: {entry.current} °C")
591
+ found = True
592
+
593
+ return lines if found else ["=== No memory temperature data found ==="]
621
594
 
622
595
 
623
596
  def cpu_temperature():
@@ -854,8 +827,6 @@ def system_summary():
854
827
 
855
828
  return lines
856
829
 
857
- # ---------- Full Sections Placeholder ----------
858
- # Replace this with your actual SECTIONS list from your app
859
830
  SECTIONS = [
860
831
  system_info,
861
832
  swap_memory,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hardwaremon
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Hardware monitoring tool for Linux
5
5
  Author: Louis
6
6
  Requires-Python: >=3.8
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes