amdgpu_fan 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8bd1ed519a47f577ba017c94f03ac02101767434796821120aef3f9e12d9ba9
4
- data.tar.gz: 6d55c0d1c45d076d1409318332fade5d9038c8f4e64b86d8af2cb2d5eeb016df
3
+ metadata.gz: f831dbba03b1f54f0ed55055eea94371b658b4e797dae7899f3954b55e755a28
4
+ data.tar.gz: 9fa6dd181fbcae74b6441fe9a62200fb2be98be59c88d470a434c2b2730ea691
5
5
  SHA512:
6
- metadata.gz: dba9441882e19a730fe7863ac49ac196d6ac6b6ed4f55a1f086d2467c122cb58b7e57fb3dc27d0bfbddcaba9344a89992b59fce9c1f52edb44feb54e9a718b97
7
- data.tar.gz: 75b810c93258bbb39b2973f97e029cd602d70a61314da9e08af1a13fcaea5ec2ea7067e424aa0a3358d5a9b1863937cefa3a095897214f6ca8f0453757fd5250
6
+ metadata.gz: 92a2ab4778b838e1bbbe6607c8bb2ad4a5d9ec79f817f24fa03d5af460e73a857e2dd456b3fd0ca08ab58cc4a64924a981afd4a44c05be65dad449b65f56c1e9
7
+ data.tar.gz: 4b4d0cd42f4a0275e09230799c22c90eecf556a0adfa2918d579f43419878a2100f2230cb19491468b59dc1496badc71bfd9f6332c6fddb3d7cc7480f4c00b97
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # amdgpu-fan-rb
2
2
 
3
- [![Build Status](https://travis-ci.org/HarlemSquirrel/amdgpu-fan-rb.svg?branch=master)](https://travis-ci.org/HarlemSquirrel/amdgpu-fan-rb)
3
+ [![Build Status](https://travis-ci.org/HarlemSquirrel/amdgpu-fan-rb.svg?branch=master)](https://travis-ci.org/HarlemSquirrel/amdgpu-fan-rb) [![Maintainability](https://api.codeclimate.com/v1/badges/27233cee17ef6a2c14fd/maintainability)](https://codeclimate.com/github/HarlemSquirrel/amdgpu-fan-rb/maintainability)
4
4
 
5
5
  A Ruby CLI to read and set the fan speed for AMD Radeon graphics cards running on the AMDGPU Linux driver.
6
6
 
@@ -28,13 +28,18 @@ gem install amdgpu_fan
28
28
  ## Usage
29
29
 
30
30
  ```
31
- ➤ amdgpu_fan help
31
+ bin/amdgpu_fan
32
32
  Commands:
33
- amdgpu_fan auto # Set mode to automatic (requires sudo)
34
- amdgpu_fan help [COMMAND] # Describe available commands or one specific command
35
- amdgpu_fan set PERCENTAGE # Set fan speed to PERCENTAGE (requires sudo)
36
- amdgpu_fan status # View device info, current fan speed, and temperature
37
- amdgpu_fan watch [SECONDS] # Watch current fan speed, and temperature refreshed every n seconds
33
+ amdgpu_fan auto # Set fan mode to automatic (requires sudo)
34
+ amdgpu_fan connectors # View the status of the display connectors
35
+ amdgpu_fan help [COMMAND] # Describe available commands or one specific command
36
+ amdgpu_fan profile # View power profile details.
37
+ amdgpu_fan profile_auto # Set the power profile to automatic mode.
38
+ amdgpu_fan profile_force [PROFILE_NUM] # Manually set a power profile.
39
+ amdgpu_fan set PERCENTAGE # Set fan speed to PERCENTAGE (requires sudo)
40
+ amdgpu_fan status [--logo] # View device info, current fan speed, and temperature
41
+ amdgpu_fan watch [SECONDS] # Watch fan speed, load, power, and temperature refreshed every n seconds
42
+ amdgpu_fan watch_csv [SECONDS] # Watch stats in CSV format refreshed every n seconds defaulting to 1 second
38
43
 
39
44
  ➤ amdgpu_fan status
40
45
  📺 GPU: AMD Radeon (TM) R9 Fury Series
@@ -46,9 +51,16 @@ Commands:
46
51
  ➤ bin/amdgpu_fan watch 3
47
52
  Watching Advanced Micro Devices, Inc. [AMD/ATI] Radeon R9 FURY X / NANO every 3 second(s)...
48
53
  <Press Ctrl-C to exit>
49
- 2019-05-10 20:36:01 - Clock: 512Mhz Core, 500Mhz Memory, Fan: 1838 rpm [||| ]27%, Load: [||| ]28%, Power: 15.12 W, Temp: 28.0°C
50
- 2019-05-10 20:36:05 - Clock: 300Mhz Core, 500Mhz Memory, Fan: 1837 rpm [||||| ]49%, Load: [ ]0%, Power: 16.18 W, Temp: 29.0°C
51
- 2019-05-10 20:36:09 - Clock: 512Mhz Core, 500Mhz Memory, Fan: 1837 rpm [||||| ]49%, Load: [ ]0%, Power: 15.11 W, Temp: 28.0°C
54
+ 2019-05-28 20:57:41 | Core: 724Mhz | Memory: 500Mhz | Fan: 948 rpm [* ]14% | Load: [** ]24% | Power: 16.07 W [* ]6% | Temp: 34.0°C
55
+ 2019-05-28 20:57:45 | Core: 512Mhz | Memory: 500Mhz | Fan: 948 rpm [* ]14% | Load: [ ]0% | Power: 16.13 W [* ]7% | Temp: 34.0°C
56
+ 2019-05-28 20:57:49 | Core: 892Mhz | Memory: 500Mhz | Fan: 948 rpm [* ]14% | Load: [ ]0% | Power: 25.22 W [* ]5% | Temp: 33.0°C
57
+ 2019-05-28 20:57:53 | Core: 300Mhz | Memory: 500Mhz | Fan: 948 rpm [* ]14% | Load: [ ]0% | Power: 19.1 W [* ]6% | Temp: 33.0°C
58
+ 2019-05-28 20:57:57 | Core: 1050Mhz | Memory: 500Mhz | Fan: 948 rpm [* ]14% | Load: [********* ]94% | Power: 103.04 W [*** ]31% | Temp: 36.0°C
59
+ 2019-05-28 20:58:01 | Core: 1050Mhz | Memory: 500Mhz | Fan: 954 rpm [** ]15% | Load: [********* ]91% | Power: 158.07 W [***** ]53% | Temp: 38.0°C
60
+ 2019-05-28 20:58:05 | Core: 1050Mhz | Memory: 500Mhz | Fan: 977 rpm [** ]16% | Load: [**********]100% | Power: 218.01 W [******* ]73% | Temp: 40.0°C
61
+ 2019-05-28 20:58:09 | Core: 1050Mhz | Memory: 500Mhz | Fan: 1005 rpm [** ]16% | Load: [**********]100% | Power: 216.24 W [******* ]71% | Temp: 40.0°C
62
+ 2019-05-28 20:58:13 | Core: 1050Mhz | Memory: 500Mhz | Fan: 1033 rpm [** ]17% | Load: [**********]97% | Power: 109.25 W [**** ]39% | Temp: 38.0°C
63
+ 2019-05-28 20:58:17 | Core: 724Mhz | Memory: 500Mhz | Fan: 1058 rpm [** ]17% | Load: [ ]0% | Power: 17.17 W [* ]6% | Temp: 35.0°C
52
64
  ^C
53
65
  And now the watch is ended.
54
66
  ```
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
 
3
5
  require_relative '../lib/amdgpu_service'
@@ -4,22 +4,42 @@ require_relative '../config/environment'
4
4
 
5
5
  # The main class
6
6
  class AmdgpuFanCli < Thor
7
+ METER_CHAR = '*'
8
+ WATCH_FIELD_SEPARATOR = ' | '
9
+
7
10
  desc 'auto', 'Set fan mode to automatic (requires sudo)'
8
11
  def auto
9
- amdgpu_service.set_fan_mode! :auto
12
+ amdgpu_service.fan_mode = :auto
10
13
  puts fan_status
11
14
  end
12
15
 
13
16
  desc 'connectors', 'View the status of the display connectors'
14
17
  def connectors
15
- amdgpu_service.connectors_status.each do |connector,status|
18
+ amdgpu_service.connectors_status.each do |connector, status|
16
19
  puts "#{connector}: #{status}"
17
20
  end
18
21
  end
19
22
 
23
+ desc 'profile', 'View power profile details.'
24
+ def profile
25
+ puts amdgpu_service.profile_summary
26
+ end
27
+
28
+ desc 'profile_auto', 'Set the power profile to automatic mode.'
29
+ def profile_auto
30
+ amdgpu_service.profile_auto
31
+ puts amdgpu_service.profile_summary
32
+ end
33
+
34
+ desc 'profile_force [PROFILE_NUM]', 'Manually set a power profile.'
35
+ def profile_force(state)
36
+ amdgpu_service.profile_force = state
37
+ puts amdgpu_service.profile_summary
38
+ end
39
+
20
40
  desc 'set PERCENTAGE', 'Set fan speed to PERCENTAGE (requires sudo)'
21
41
  def set(percentage)
22
- return puts "Invalid percentage" unless (0..100).cover?(percentage.to_i)
42
+ return puts 'Invalid percentage' unless (0..100).cover?(percentage.to_i)
23
43
 
24
44
  amdgpu_service.set_fan_manual_speed! percent: percentage
25
45
  puts fan_status
@@ -28,57 +48,60 @@ class AmdgpuFanCli < Thor
28
48
  exit 1
29
49
  end
30
50
 
31
- desc 'status', 'View device info, current fan speed, and temperature'
32
- def status
33
- puts radeon_logo,
34
- "📺\tGPU: #{amdgpu_service.name}",
35
- "📄\tvBIOS: #{amdgpu_service.vbios_version}",
36
- clock_status,
37
- fan_status,
38
- "🌡\tTemp: #{amdgpu_service.temperature}°C",
39
- "⚡\tPower: #{amdgpu_service.power_dpm_state} mode using " \
40
- "#{amdgpu_service.power_draw} / #{amdgpu_service.power_max} Watts",
41
- "⚖\tLoad: #{percent_meter amdgpu_service.busy_percent, 20}"
51
+ desc 'status [--logo]', 'View device info, current fan speed, and temperature'
52
+ def status(option = nil)
53
+ puts radeon_logo if option == '--logo'
54
+ puts "📺 #{'GPU:'.ljust(7)} #{amdgpu_service.name}",
55
+ "📄 #{'vBIOS:'.ljust(7)} #{amdgpu_service.vbios_version}",
56
+ "⏰ #{'Clocks:'.ljust(7)} #{clock_status}",
57
+ "🌀 #{'Fan:'.ljust(7)} #{fan_status}",
58
+ "🌞 #{'Temp:'.ljust(7)} #{amdgpu_service.temperature}°C",
59
+ "⚡ #{'Power:'.ljust(7)} #{amdgpu_service.profile_mode} profile in " \
60
+ "#{amdgpu_service.power_dpm_state} mode using " \
61
+ "#{amdgpu_service.power_draw} / #{amdgpu_service.power_max} Watts "\
62
+ "(#{amdgpu_service.power_draw_percent}%)",
63
+ "⚖ #{'Load:'.ljust(7)} #{percent_meter amdgpu_service.busy_percent, 20}"
42
64
  end
43
65
 
44
66
  desc 'watch [SECONDS]', 'Watch fan speed, load, power, and temperature ' \
45
67
  'refreshed every n seconds'
46
- def watch(seconds=1)
47
- return puts "Seconds must be from 1 to 600" unless (1..600).cover?(seconds.to_i)
68
+ def watch(seconds = 1)
69
+ return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
48
70
 
49
71
  puts "Watching #{amdgpu_service.name} every #{seconds} second(s)...",
50
72
  ' <Press Ctrl-C to exit>'
51
73
 
52
- trap "SIGINT" do
74
+ trap 'SIGINT' do
53
75
  puts "\nAnd now the watch is ended."
54
76
  exit 0
55
77
  end
56
78
 
57
79
  loop do
58
- puts "#{Time.now.strftime("%F %T")} - " \
59
- "Clock: #{amdgpu_service.core_clock} Core, #{amdgpu_service.memory_clock} Memory,\t" \
60
- "Fan: #{amdgpu_service.fan_speed_rpm} rpm #{percent_meter amdgpu_service.fan_speed_percent},\t" \
61
- "Load: #{percent_meter amdgpu_service.busy_percent},\t" \
62
- "Power: #{amdgpu_service.power_draw} W,\t" \
63
- "Temp: #{amdgpu_service.temperature}°C "
64
- sleep seconds.to_i
80
+ time = Time.now
81
+ puts [time.strftime('%F %T'), summary_clock, summary_fan, summary_load, summary_power,
82
+ summary_temp].join(WATCH_FIELD_SEPARATOR)
83
+
84
+ # It can take a second or two to run the above so we remove them from the wait
85
+ # here to get a more consistant watch interval.
86
+ sec_left_to_wait = time.to_i + seconds.to_i - Time.now.to_i
87
+ sleep sec_left_to_wait if sec_left_to_wait.positive?
65
88
  end
66
89
  end
67
90
 
68
91
  desc 'watch_csv [SECONDS]', 'Watch stats in CSV format ' \
69
92
  'refreshed every n seconds defaulting to 1 second'
70
- def watch_csv(seconds=1)
71
- return puts "Seconds must be from 1 to 600" unless (1..600).cover?(seconds.to_i)
93
+ def watch_csv(seconds = 1)
94
+ return puts 'Seconds must be from 1 to 600' unless (1..600).cover?(seconds.to_i)
72
95
 
73
96
  puts 'Timestamp, Core Clock (Mhz),Memory Clock (Mhz),Fan speed (rpm), '\
74
97
  'Load (%),Power (Watts),Temp (°C)'
75
98
 
76
- trap "SIGINT" do
99
+ trap 'SIGINT' do
77
100
  exit 0
78
101
  end
79
102
 
80
103
  loop do
81
- puts [Time.now.strftime("%F %T"),
104
+ puts [Time.now.strftime('%F %T'),
82
105
  amdgpu_service.core_clock,
83
106
  amdgpu_service.memory_clock,
84
107
  amdgpu_service.fan_speed_rpm,
@@ -96,25 +119,49 @@ class AmdgpuFanCli < Thor
96
119
  end
97
120
 
98
121
  def clock_status
99
- "⏰\tClocks: #{amdgpu_service.core_clock} Core, " \
100
- "#{amdgpu_service.memory_clock} Memory"
122
+ "#{amdgpu_service.core_clock} Core, #{amdgpu_service.memory_clock} Memory"
101
123
  end
102
124
 
103
125
  def current_time
104
- Time.now.strftime("%F %T")
126
+ Time.now.strftime('%F %T')
105
127
  end
106
128
 
107
129
  def fan_status
108
- "🌀\tFan: #{amdgpu_service.fan_mode} mode running at " \
109
- "#{amdgpu_service.fan_speed_percent}% ~ #{amdgpu_service.fan_speed_rpm} rpm"
130
+ "#{amdgpu_service.fan_mode} mode running at " \
131
+ "#{amdgpu_service.fan_speed_rpm} rpm (#{amdgpu_service.fan_speed_percent}%)"
110
132
  end
111
133
 
112
134
  def percent_meter(percent, length = 10)
113
135
  progress_bar_count = (length * percent.to_f / 100).round
114
- "[#{'|' * progress_bar_count}#{' ' * (length - progress_bar_count)}]#{percent}%"
136
+ percent_string = "#{percent}%".ljust(4)
137
+ "[#{METER_CHAR * progress_bar_count}#{' ' * (length - progress_bar_count)}]#{percent_string}"
115
138
  end
116
139
 
117
140
  def radeon_logo
118
141
  File.read(File.join(__dir__, '../lib/radeon_r_black_red_100x100.ascii'))
119
142
  end
143
+
144
+ def summary_clock
145
+ "Core: #{amdgpu_service.core_clock.ljust(7)} #{WATCH_FIELD_SEPARATOR}"\
146
+ "Memory: #{amdgpu_service.memory_clock.ljust(7)}"
147
+ end
148
+
149
+ def summary_fan
150
+ fan_speed_string = "#{amdgpu_service.fan_speed_rpm} rpm".ljust(8)
151
+ "Fan: #{fan_speed_string} #{percent_meter(amdgpu_service.fan_speed_percent)}"
152
+ end
153
+
154
+ def summary_load
155
+ "Load: #{percent_meter amdgpu_service.busy_percent}"
156
+ end
157
+
158
+ def summary_power
159
+ power_string = "#{amdgpu_service.power_draw} W".ljust(amdgpu_service.power_max.to_s.length + 3)
160
+ "Power: #{power_string} #{percent_meter amdgpu_service.power_draw_percent}"
161
+ end
162
+
163
+ def summary_temp
164
+ temp_string = "#{amdgpu_service.temperature}°C".ljust(7)
165
+ "Temp: #{temp_string}"
166
+ end
120
167
  end
@@ -27,14 +27,14 @@ class AmdgpuService
27
27
  end
28
28
 
29
29
  def core_clock
30
- clock_from_pp_file "/sys/class/drm/card#{card_num}/device/pp_dpm_sclk"
30
+ clock_from_pp_file "#{base_card_folder}/pp_dpm_sclk"
31
31
  end
32
32
 
33
33
  def fan_mode
34
34
  FAN_MODES[File.read(fan_mode_file).strip] || 'unknown'
35
35
  end
36
36
 
37
- def set_fan_mode!(mode)
37
+ def fan_mode=(mode)
38
38
  `echo "#{FAN_MODES.key(mode.to_s)}" | sudo tee #{fan_mode_file}`
39
39
  end
40
40
 
@@ -51,7 +51,7 @@ class AmdgpuService
51
51
  end
52
52
 
53
53
  def memory_clock
54
- clock_from_pp_file "/sys/class/drm/card#{card_num}/device/pp_dpm_mclk"
54
+ clock_from_pp_file "#{base_card_folder}/pp_dpm_mclk"
55
55
  end
56
56
 
57
57
  def name
@@ -66,10 +66,31 @@ class AmdgpuService
66
66
  power_raw_to_watts File.read(power_avg_file)
67
67
  end
68
68
 
69
+ def power_draw_percent
70
+ (power_draw.to_f / power_max.to_i * 100).round
71
+ end
72
+
69
73
  def power_max
70
74
  @power_max ||= power_raw_to_watts File.read(power_max_file)
71
75
  end
72
76
 
77
+ def profile_auto
78
+ `echo "auto" | sudo tee "#{base_card_folder}/power_dpm_force_performance_level"`
79
+ end
80
+
81
+ def profile_force=(state)
82
+ `echo "manual" | sudo tee "#{base_card_folder}/power_dpm_force_performance_level"`
83
+ `echo "#{state}" | sudo tee "#{base_card_folder}/pp_power_profile_mode"`
84
+ end
85
+
86
+ def profile_mode
87
+ File.read("#{base_card_folder}/pp_power_profile_mode").slice(/\w+ \*/).delete('*').strip
88
+ end
89
+
90
+ def profile_summary
91
+ File.read("#{base_card_folder}/pp_power_profile_mode")
92
+ end
93
+
73
94
  def set_fan_manual_speed!(percent: nil, raw: nil)
74
95
  if valid_fan_percent_speed?(percent)
75
96
  new_raw = (percent.to_f / 100 * fan_speed_raw_max.to_i).round
@@ -79,7 +100,7 @@ class AmdgpuService
79
100
 
80
101
  raise(self.class::Error, 'Invalid fan speed provided') if new_raw.to_s.empty?
81
102
 
82
- set_fan_mode!(:manual) unless fan_mode == 'manual'
103
+ fan_mode = :manual unless fan_mode == 'manual'
83
104
 
84
105
  `echo "#{new_raw}" | sudo tee #{fan_power_file}`
85
106
  end
@@ -99,7 +120,7 @@ class AmdgpuService
99
120
  end
100
121
 
101
122
  def clock_from_pp_file(file)
102
- File.read(file).slice /\w+(?= \*)/
123
+ File.read(file).slice(/\w+(?= \*)/)
103
124
  end
104
125
 
105
126
  def connectors_files
@@ -147,10 +168,10 @@ class AmdgpuService
147
168
  end
148
169
 
149
170
  def valid_fan_raw_speed?(raw)
150
- (1..fan_speed_raw_max.to_i).include?(raw.to_i)
171
+ (1..fan_speed_raw_max.to_i).cover?(raw.to_i)
151
172
  end
152
173
 
153
174
  def valid_fan_percent_speed?(percent)
154
- (1..100.to_i).include?(percent.to_i)
175
+ (1..100.to_i).cover?(percent.to_i)
155
176
  end
156
177
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amdgpu_fan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McCormack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-14 00:00:00.000000000 Z
11
+ date: 2019-11-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A CLI for amdgpu fans
13
+ description: A CLI for interacting with the amdgpu Linux driver
14
14
  email: harlemsquirrel@gmail.com
15
15
  executables:
16
16
  - amdgpu_fan
@@ -42,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
44
  requirements: []
45
- rubygems_version: 3.0.3
45
+ rubygems_version: 3.0.6
46
46
  signing_key:
47
47
  specification_version: 4
48
48
  summary: A CLI to view and set fan speeds for AMD graphics cards running on the open