Hardware Info working properly 100%
This commit is contained in:
parent
96638a1e7d
commit
1e39a0cd5f
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
10
Gemfile
|
@ -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"
|
||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user