Hardware Info working properly 100%

This commit is contained in:
VetheonGames 2023-09-24 17:31:26 -06:00
parent 96638a1e7d
commit 1e39a0cd5f
9 changed files with 300 additions and 90 deletions

2
.gitignore vendored
View File

@ -56,3 +56,5 @@ build-iPhoneSimulator/
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
# .rubocop-https?--*
bin/runtime_log.log
.gitignore

10
Gemfile
View File

@ -1,9 +1,13 @@
# frozen_string_literal: true
source "https://rubygems.org"
source 'https://rubygems.org'
# gem "rails"
gem "tty-prompt", "~> 0.23.1"
gem 'speedtest_net', '~> 0.9.2'
gem "speedtest_net", "~> 0.9.2"
gem 'reline', '~> 0.3.8'
gem 'curses', '~> 1.4', require: false
gem "tty-prompt", "~> 0.23.1"

View File

@ -1,14 +1,16 @@
GEM
remote: https://rubygems.org/
specs:
byebug (11.1.3)
curb (1.0.5)
curses (1.4.4)
ethon (0.16.0)
ffi (>= 1.15.0)
ffi (1.15.5)
io-console (0.6.0)
pastel (0.8.0)
tty-color (~> 0.5)
rdebug (0.1)
reline (0.3.8)
io-console (~> 0.5)
rexml (3.2.6)
speedtest_net (0.9.2)
curb (>= 0.9, < 2.0)
@ -32,8 +34,8 @@ PLATFORMS
x86_64-linux
DEPENDENCIES
byebug (~> 11.1)
rdebug (~> 0.1)
curses (~> 1.4)
reline (~> 0.3.8)
speedtest_net (~> 0.9.2)
tty-prompt (~> 0.23.1)

View File

@ -2,6 +2,9 @@ Starting system info gathering... \n
Gathering CPU info \n
Gathering RAM info \n
Gathering Disk info \n
{:model=>"SAMSUNG MZ7PD256", :type=>"SSD", :transport=>"ata"}
{:model=>"ST2000DM006-2DM1", :type=>"HDD", :transport=>"ata"}
{:model=>"Timetec 30TT253X", :type=>"SSD", :transport=>"ata"}
Gathering GPU info \n
Gathering Kernel info \n
Gathering Network info \n

View File

@ -1,36 +0,0 @@
{
"cpu": {
"model": "Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz",
"speed": "3.36 GHz",
"cores": 4,
"threads": 4
},
"ram": {
"total_ram": 23,
"used_ram": 4,
"ram_type": "None",
"ram_speed": "2133 MT/s"
},
"disks": [
{
"model": "SAMSUNG MZ7PD256",
"type": "SSD",
"transport": "ata"
},
{
"model": "ST2000DM006-2DM1",
"type": "HDD",
"transport": "ata"
},
{
"model": "Timetec 30TT253X",
"type": "SSD",
"transport": "ata"
}
],
"gpu": {
"model": "NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] (rev a1)",
"opengl_driver_version": "4.6.0 NVIDIA 535.104.05",
"vulkan_driver_version": "1.3.264"
}
}

View File

@ -5,6 +5,7 @@ class CpuInfo
cpu_info = {}
cores = 0
threads = 0
manufacturer = nil
File.open('/proc/cpuinfo', 'r') do |f|
f.each_line do |line|
@ -18,19 +19,42 @@ class CpuInfo
cores += 1 if key == 'core id'
threads += 1 if key == 'processor'
# Filter out the specific information
# Determine the manufacturer
if key == 'vendor_id'
manufacturer = if value.include?('Intel')
'Intel'
elsif value.include?('AMD')
'AMD'
else
'Unknown'
end
end
# Filter out the specific information based on manufacturer
case key
when 'model name'
cpu_info[:model] = value
case manufacturer
when 'Intel'
cleaned_model = value.match(/Intel\(R\) Core\(TM\) (\w+-?\d+)/)
cpu_info[:model] = "Intel Core #{cleaned_model[1]}" if cleaned_model
when 'AMD'
cleaned_model = value.match(/AMD Ryzen (\d+ \w+)/)
cpu_info[:model] = "AMD Ryzen #{cleaned_model[1]}" if cleaned_model
end
when 'cpu MHz'
speed_ghz = (value.to_f * 1e-3).round(2)
cpu_info[:speed] = "#{speed_ghz} GHz"
when 'cache size'
cpu_info[:l3_cache] = value if value.include?('L3')
end
end
end
# Fetch L3 Cache size using lscpu
lscpu_output = `lscpu | grep "L3 cache"`.strip
if lscpu_output && !lscpu_output.empty?
l3_cache_match = lscpu_output.match(/L3 cache:\s+(.+)/)
cpu_info[:l3_cache] = l3_cache_match[1] if l3_cache_match
end
cpu_info[:cores] = cores
cpu_info[:threads] = threads
cpu_info

View File

@ -31,6 +31,7 @@ class DiskInfo
transport: transport || 'Unknown'
}
disk_info << disk
File.open('runtime_log.log', 'a') { |f| f.puts("#{disk}") }
end
disk_info

View File

@ -1,64 +1,247 @@
# frozen_string_literal: true
require 'tty-prompt'
require 'json'
require 'curses'
require 'readline'
class DisplayHandler
def self.display(system_info)
# Log the entire system_info to a log file
File.open('system_info.log', 'w') do |f|
f.puts(JSON.pretty_generate(system_info))
end
setup_readline
Curses.init_screen
Curses.start_color
Curses.init_pair(1, Curses::COLOR_BLUE, Curses::COLOR_BLACK)
Curses.init_pair(2, Curses::COLOR_GREEN, Curses::COLOR_BLACK)
Curses.init_pair(3, Curses::COLOR_YELLOW, Curses::COLOR_BLACK)
prompt = TTY::Prompt.new
@main_win = Curses::Window.new(0, 0, 0, 0)
@menu_win = @main_win.subwin(Curses.lines - 4, 20, 1, 1)
@info_win = @main_win.subwin(Curses.lines - 4, Curses.cols - 22, 1, 22)
@menu_win.keypad(true)
choices = [
{ name: 'OS Info', value: :os },
{ name: 'Hardware Info', value: :hardware },
{ name: 'Network Info', value: :network },
{ name: 'Exit', value: :exit }
]
exit_menu = false # Flag to indicate if the menu should exit
loop do
user_choice = prompt.select('Choose an option:', choices)
draw_main_box
draw_menu_box
draw_info_box
case user_choice
when :os
display_os_info(system_info.slice(:kernel, :os, :uptime))
when :hardware
display_hardware_info(system_info.slice(:cpu, :ram, :disk, :gpu))
when :network
display_network_info(system_info.slice(:network, :nic))
when :exit
break
choices = ['OS Info', 'Hardware Info', 'Network Info', 'Exit']
selected_index = 0
loop do
row = 2 # Starting row
col = 3 # Starting column
choices.each_with_index do |choice, index|
@menu_win.setpos(row + index, col) # Explicitly set position for each choice
if index == selected_index
@menu_win.attron(Curses.color_pair(3)) { @menu_win.addstr(choice) }
else
@menu_win.addstr(choice)
end
@menu_win.setpos(row + index + 1, col) # Move to the next line
end
@menu_win.refresh
input = @menu_win.getch
case input
when Curses::KEY_UP
selected_index = [selected_index - 1, 0].max
when Curses::KEY_DOWN
selected_index = [selected_index + 1, choices.length - 1].min
when 10, 13 # Enter key
case choices[selected_index]
when 'Exit'
exit_menu = true # Set flag to true
break # Break inner loop
when 'OS Info'
display_os_info(system_info.slice(:kernel, :os, :uptime))
when 'Hardware Info'
display_hardware_info(system_info.slice(:cpu, :ram, :disks, :gpu))
when 'Network Info'
display_network_info(system_info.slice(:network, :nic))
end
end
break if exit_menu # Break outer loop if flag is true
end
break if exit_menu # Break outer loop if flag is true
end
Curses.close_screen
end
def self.draw_main_box
@main_win.box('|', '-')
@main_win.setpos(0, (Curses.cols - 11) / 2)
@main_win.addstr('System Info')
@main_win.setpos(Curses.lines - 1, Curses.cols - 4)
@main_win.addstr('V1.0')
@main_win.refresh
end
def self.draw_menu_box
@menu_win.box('|', '-')
@menu_win.setpos(0, 5)
@menu_win.addstr('Menu')
@menu_win.refresh
end
def self.draw_info_box
@info_win.box('|', '-')
@info_win.setpos(0, @info_win.maxx - 13)
@info_win.addstr('Information')
@info_win.refresh
end
def self.prepare_info_window(title)
@info_win.clear
draw_info_box
@info_win.setpos(2, 2)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr(title) }
@info_win.setpos(3, 2)
@info_win.addstr('-' * (title.length + 2))
end
def self.display_os_info(os_info)
# Display OS information
puts "\nOS Information:"
puts '---------------'
os_info.each do |key, value|
puts "#{key.capitalize}: #{value}"
end
@info_win.clear
draw_info_box
@info_win.setpos(2, 2)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('OS Information') }
@info_win.setpos(3, 2)
@info_win.addstr('--------------')
display_info(os_info, @info_win)
@info_win.refresh
end
def self.display_hardware_info(hardware_info)
# Display Hardware information (CPU, RAM, etc.)
puts "\nHardware Information:"
puts '---------------------'
hardware_info.each do |key, value|
puts "#{key.capitalize}: #{value}"
end
@info_win.clear
draw_info_box
# CPU and RAM on the left side
left_row = 4
left_row = display_cpu_info(hardware_info[:cpu], left_row)
display_ram_info(hardware_info[:ram], left_row)
# Disks and GPU on the right side
right_row = 4
right_col = 40 # Adjust this value to place it at the desired column
right_row = display_disk_info(hardware_info[:disks], right_row, right_col)
display_gpu_info(hardware_info[:gpu], right_row, right_col)
@info_win.refresh
end
def self.display_cpu_info(cpu_info, start_row)
@info_win.setpos(start_row, 2)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('CPU Information') }
start_row += 1
@info_win.setpos(start_row, 2)
@info_win.addstr('--------------')
start_row += 1
@info_win.setpos(start_row, 2)
display_info(cpu_info, @info_win, start_row, 4)
start_row += cpu_info.keys.length + 1
start_row
end
def self.display_ram_info(ram_info, start_row, col = 2)
@info_win.setpos(start_row, col)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('RAM Information') }
start_row += 1
@info_win.setpos(start_row, col)
@info_win.addstr('--------------')
start_row += 1
display_info(ram_info, @info_win, start_row, 4, col)
start_row += ram_info.keys.length + 1
start_row
end
def self.display_disk_info(disk_info, start_row, col = 2)
@info_win.setpos(start_row, col)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('Disk Information')}
start_row += 1
@info_win.setpos(start_row, col)
@info_win.addstr('---------------')
start_row += 1
display_info({ disks: disk_info }, @info_win, start_row, 0, col)
start_row += (disk_info.length * 3) + 1
start_row
end
def self.display_gpu_info(gpu_info, start_row, col = 2)
@info_win.setpos(start_row, col)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('GPU Information')}
start_row += 1
@info_win.setpos(start_row, col)
@info_win.addstr('--------------')
start_row += 1
display_info(gpu_info, @info_win, start_row, 4, col)
start_row += gpu_info.keys.length + 1
start_row
end
def self.display_network_info(network_info)
# Display Network information
puts "\nNetwork Information:"
puts '--------------------'
network_info.each do |key, value|
puts "#{key.capitalize}: #{value}"
@info_win.clear
draw_info_box
@info_win.setpos(2, 2)
@info_win.attron(Curses.color_pair(1)) { @info_win.addstr('Network Information') }
@info_win.setpos(3, 2)
@info_win.addstr('-------------------')
display_info(network_info, @info_win)
@info_win.refresh
end
def self.display_info(info_hash, win, row = 4, indent = 0, col = 2)
info_hash.each do |key, value|
row = handle_value_type(value, win, row, indent, col, key)
end
row
end
def self.handle_value_type(value, win, row, indent, col, key)
formatted_key = key.to_s.gsub('_', ' ').split.map(&:capitalize).join(' ')
if value.is_a?(Hash)
display_hash_value(value, win, row, indent, col, formatted_key)
elsif value.is_a?(Array)
display_array_value(value, win, row, indent, col)
else
display_scalar_value(value, win, row, indent, col, formatted_key)
end
end
def self.display_hash_value(value, win, row, indent, col, key)
win.setpos(row, col + indent)
win.addstr("#{key}: ")
display_info(value, win, row, indent + 4, col)
end
def self.display_array_value(value, win, row, indent, col)
value.each do |item|
if item.is_a?(Hash)
row = display_info(item, win, row, indent + 4, col)
else
win.setpos(row, col + indent + 4)
win.addstr(item.to_s)
row += 1
end
end
row
end
def self.display_scalar_value(value, win, row, indent, col, key)
win.setpos(row, col + indent)
win.addstr("#{key}: #{value}")
row + 1
end
def self.setup_readline
# Set up Readline for proper terminal settings
Readline.emacs_editing_mode
# the above line sets Readline to emacs_editing_mode so that terminals behave like they're supposed to
Readline.completion_append_character = ' '
# we remove Readlines thing where it adds a space to the end of tab completes because it breaks the Curses cursor
Readline.completion_proc = proc { |_s| [] }
# here we basically are disabling tab completion all together. That's because for some reason it breaks the cursor
end
private_class_method :display_info, :setup_readline
end

View File

@ -7,10 +7,37 @@ class GpuInfo
# Use `lspci` to get basic GPU information
lspci_output = `lspci | grep VGA`.strip
if lspci_output && !lspci_output.empty?
# Extract the model and other details
model_match = lspci_output.match(/VGA compatible controller: (.+)$/)
gpu_info[:model] = model_match[1] if model_match
# Determine the manufacturer
manufacturer = case lspci_output
when /NVIDIA/
'NVIDIA'
when /Advanced Micro Devices, Inc./
'AMD'
when /Intel Corporation/
'Intel'
else
'Unknown'
end
# Extract the model and other details based on manufacturer
case manufacturer
when 'NVIDIA'
model_match = lspci_output.match(/NVIDIA Corporation (\w+) \[.*GTX (\d+ \d+GB)\]/) ||
lspci_output.match(/NVIDIA Corporation (\w+) \[.*RTX (\d+ \d+GB)\]/)
gpu_info[:model] = "NVIDIA GTX #{model_match[2]}" if model_match
when 'AMD'
model_match = lspci_output.match(/Advanced Micro Devices, Inc. \[.*Radeon (\w+ \d+)\]/) ||
lspci_output.match(/Advanced Micro Devices, Inc. \[.*RX (\d+)\]/)
gpu_info[:model] = "AMD Radeon #{model_match[1]}" if model_match
when 'Intel'
model_match = lspci_output.match(/Intel Corporation.*HD Graphics (\d+)/) ||
lspci_output.match(/Intel Corporation.*Iris Xe Graphics/)
gpu_info[:model] = "Intel #{model_match[1]}" if model_match
else
gpu_info[:model] = lspci_output # Fallback to the original string if no match
end
end
# Fetch Video RAM amount