iStats 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9bff6f43ceaf154fc22a175a84ab82d3f1230346
4
- data.tar.gz: bcd0dbe5bdbf052142511505b98d8f600d0c1703
3
+ metadata.gz: e4b51e404e967587290c2dffb093f7703ab1440f
4
+ data.tar.gz: d4c35add73857760cbcd18a1f3bd6c23f53f3373
5
5
  SHA512:
6
- metadata.gz: a640c65868a3f78e2f7fb2f9221ccb1de7f7f013e8c81ba5f83fb19d208468c5b1377648a1430323e1d36528ed31100d10bc12841b01e698277665b4d1947ab0
7
- data.tar.gz: 6d640b55b90680bdf895d685eff2b1ce2b17d3b3fc9e1d438f2dd980e10eade76cfcf87fe0eaf9fd4cb8b2ddcab7e8eae464c665ab2675daf2c8c52a5b7622cb
6
+ metadata.gz: 7d2a747930f420134915c961db00568d8bb17bc3b64bdad0ba7a371e7f4fc27460572c69a0a602202eb063d21caeb043375cdb48f89ebba3d0fd2f9feb1a9c4c
7
+ data.tar.gz: bcb29f420afbd849737bc859772a332df2e6d796c8f89184716ccb3be3a793035d19cd0011e577d4e902f62caf3d28ab48703de7d6ccf1b612fa726559b4cba6
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- iStats (0.0.3)
4
+ iStats (0.0.4)
5
5
  sparkr
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,33 +1,42 @@
1
- iStats
1
+ iStats [![Gem Version](https://badge.fury.io/rb/iStats.svg)](http://badge.fury.io/rb/iStats)
2
2
  ======
3
3
 
4
- Quick attempt at writing a Ruby wrapper for a small C library that interacts with the IOKit library (apple) to get the CPU temperature. Will expand to more hardware data and stats in the future.
4
+ Quick attempt at writing a Ruby wrapper for a small C library that interacts with the IOKit library (apple) to get the CPU temperature and fan speed. Will expand to more hardware data and stats in the future.
5
+
6
+ #### Warning
7
+ A [bug in Ruby](https://bugs.ruby-lang.org/issues/9624) and Apple XCode 5.1 onwards (new CLANG version) might make it impossible to install this gem if you are using Ruby from the Xcode command-line tools package. If you are using RVM or homebrew to manage your Ruby installation you should be fine.
5
8
 
6
9
  #### Tested on
7
10
  MacBook Pro 2012<br>
8
11
  OS X 10.9.2<br>
9
12
  Ruby: 1.9.3, 2.0.0, 2.1.1<br>
10
13
 
11
- ## Screenshot
12
- ![](http://i.imgur.com/ht2NZCL.gif)
13
-
14
14
  ## Installation
15
15
 
16
16
  $ gem install iStats
17
17
 
18
+ ## Screenshot
19
+ #### All Stats
20
+ ![](http://i.imgur.com/pNZwCmg.png)
21
+
22
+ #### Sparkline levels
23
+ ![](http://i.imgur.com/ht2NZCL.gif)
24
+
18
25
  ## Usage
19
26
 
20
27
  ```
21
- - iStats: help ---------------------------------------------------
28
+ - iStats: help ---------------------------------------------------
22
29
 
23
- istats --help This help text
24
- istats --version Print current version
30
+ istats --help This help text
31
+ istats --version Print current version
25
32
 
26
- istats all Print all stats
27
- istats cpu Print all CPU stats
28
- istats cpu [temp | temperature] Print CPU temperature
33
+ istats all Print all stats
34
+ istats cpu Print all CPU stats
35
+ istats cpu [temp | temperature] Print CPU temperature
36
+ istats fan Print all fan stats
37
+ istats fan [speed] Print fan speed
29
38
 
30
- for more help see: https://github.com/Chris911/iStats
39
+ for more help see: https://github.com/Chris911/iStats
31
40
  ```
32
41
 
33
42
  ## Contributing
@@ -2,7 +2,7 @@ require 'mkmf'
2
2
 
3
3
  extension_name = 'osx_stats'
4
4
 
5
- CONFIG['LDSHARED'] << ' -framework IOKit '
5
+ CONFIG['LDSHARED'] << ' -framework IOKit -framework CoreFoundation '
6
6
 
7
7
  # The destination
8
8
  dir_config(extension_name)
@@ -205,53 +205,152 @@ int SMCGetFanNumber(char *key)
205
205
  return _strtoul((char *)val.bytes, val.dataSize, 10);
206
206
  }
207
207
 
208
- // int main(int argc, char *argv[])
209
- // {
210
- // SMCOpen();
211
- // //printf("%0.1f°C\n", SMCGetTemperature(SMC_KEY_CPU_TEMP));
212
- // //printf("%0.1f\n", SMCGetFanSpeed(0));
213
- // //printf("%0.1f\n", SMCGetFanSpeed(3));
214
- // //printf("%i\n", SMCGetFanNumber(SMC_KEY_FAN_NUM));
215
- // SMCClose();
216
- //
217
- // return 0;
218
- // }
208
+ /* Battery info
209
+ * Ref: http://www.newosxbook.com/src.jl?tree=listings&file=bat.c
210
+ * https://developer.apple.com/library/mac/documentation/IOKit/Reference/IOPowerSources_header_reference/Reference/reference.html
211
+ */
212
+ void dumpDict (CFDictionaryRef Dict)
213
+ {
214
+ // Helper function to just dump a CFDictioary as XML
215
+ CFDataRef xml = CFPropertyListCreateXMLData(kCFAllocatorDefault, (CFPropertyListRef)Dict);
216
+ if (xml) { write(1, CFDataGetBytePtr(xml), CFDataGetLength(xml)); CFRelease(xml); }
217
+ }
219
218
 
220
- //
221
- // RUBY MODULE
222
- //
219
+ CFDictionaryRef powerSourceInfo(int Debug)
220
+ {
221
+ CFTypeRef powerInfo;
222
+ CFArrayRef powerSourcesList;
223
+ CFDictionaryRef powerSourceInformation;
224
+
225
+ powerInfo = IOPSCopyPowerSourcesInfo();
226
+
227
+ if(! powerInfo) return NULL;
228
+
229
+ powerSourcesList = IOPSCopyPowerSourcesList(powerInfo);
230
+ if(!powerSourcesList) {
231
+ CFRelease(powerInfo);
232
+ return NULL;
233
+ }
234
+
235
+ // Should only get one source. But in practice, check for > 0 sources
236
+ if (CFArrayGetCount(powerSourcesList))
237
+ {
238
+ powerSourceInformation = IOPSGetPowerSourceDescription(powerInfo, CFArrayGetValueAtIndex(powerSourcesList, 0));
239
+
240
+ if (Debug) dumpDict (powerSourceInformation);
241
+
242
+ //CFRelease(powerInfo);
243
+ //CFRelease(powerSourcesList);
244
+ return powerSourceInformation;
245
+ }
246
+
247
+ CFRelease(powerInfo);
248
+ CFRelease(powerSourcesList);
249
+ return NULL;
250
+ }
251
+
252
+ int getDesignCycleCount() {
253
+ CFDictionaryRef powerSourceInformation = powerSourceInfo(0);
254
+
255
+ if(powerSourceInformation == NULL)
256
+ return 0;
257
+
258
+ CFNumberRef designCycleCountRef = (CFNumberRef) CFDictionaryGetValue(powerSourceInformation, CFSTR("DesignCycleCount"));
259
+ uint32_t designCycleCount;
260
+ if ( ! CFNumberGetValue(designCycleCountRef, // CFNumberRef number,
261
+ kCFNumberSInt32Type, // CFNumberType theType,
262
+ &designCycleCount)) // void *valuePtr);
263
+ return 0;
264
+ else
265
+ return designCycleCount;
266
+ }
267
+
268
+ const char* getBatteryHealth() {
269
+ CFDictionaryRef powerSourceInformation = powerSourceInfo(0);
270
+
271
+ if(powerSourceInformation == NULL)
272
+ return "Unknown";
273
+
274
+ CFStringRef batteryHealthRef = (CFStringRef) CFDictionaryGetValue(powerSourceInformation, CFSTR("BatteryHealth"));
275
+
276
+ const char *batteryHealth = CFStringGetCStringPtr(batteryHealthRef, // CFStringRef theString,
277
+ kCFStringEncodingMacRoman); //CFStringEncoding encoding);
278
+ return batteryHealth;
279
+ }
280
+
281
+ /*
282
+ RUBY MODULES
283
+ */
223
284
  VALUE CPU_STATS = Qnil;
224
285
  VALUE FAN_STATS = Qnil;
286
+ VALUE BATTERY_STATS = Qnil;
287
+ /*
288
+ * Define Ruby modules and associated methods
289
+ * We never call this, Ruby does.
290
+ */
225
291
  void Init_osx_stats() {
226
- CPU_STATS = rb_define_module("CPU_STATS");
227
- rb_define_method(CPU_STATS, "get_cpu_temp", method_get_cpu_temp, 0);
292
+ CPU_STATS = rb_define_module("CPU_STATS");
293
+ rb_define_method(CPU_STATS, "get_cpu_temp", method_get_cpu_temp, 0);
294
+
295
+ FAN_STATS = rb_define_module("FAN_STATS");
296
+ rb_define_method(FAN_STATS, "get_fan_number", method_get_fan_number, 0);
297
+ rb_define_method(FAN_STATS, "get_fan_speed", method_get_fan_speed, 1);
228
298
 
229
- FAN_STATS = rb_define_module("FAN_STATS");
230
- rb_define_method(FAN_STATS, "get_fan_number", method_get_fan_number, 0);
231
- rb_define_method(FAN_STATS, "get_fan_speed", method_get_fan_speed, 1);
299
+ BATTERY_STATS = rb_define_module("BATTERY_STATS");
300
+ rb_define_method(BATTERY_STATS, "get_battery_health", method_get_battery_health, 0);
301
+ rb_define_method(BATTERY_STATS, "get_battery_design_cycle_count", method_get_battery_design_cycle_count, 0);
232
302
  }
233
303
 
234
304
  VALUE method_get_cpu_temp(VALUE self) {
235
- SMCOpen();
236
- double temp = SMCGetTemperature(SMC_KEY_CPU_TEMP);
237
- SMCClose();
305
+ SMCOpen();
306
+ double temp = SMCGetTemperature(SMC_KEY_CPU_TEMP);
307
+ SMCClose();
238
308
 
239
- return rb_float_new(temp);
309
+ return rb_float_new(temp);
240
310
  }
241
311
 
242
312
  VALUE method_get_fan_number(VALUE self) {
243
- SMCOpen();
244
- int num = SMCGetFanNumber(SMC_KEY_FAN_NUM);
245
- SMCClose();
313
+ SMCOpen();
314
+ int num = SMCGetFanNumber(SMC_KEY_FAN_NUM);
315
+ SMCClose();
246
316
 
247
- return INT2NUM(num);
317
+ return INT2NUM(num);
248
318
  }
249
319
 
250
320
  VALUE method_get_fan_speed(VALUE self, VALUE num) {
251
- uint fanNum = NUM2UINT(num);
252
- SMCOpen();
253
- float speed = SMCGetFanSpeed(fanNum);
254
- SMCClose();
321
+ uint fanNum = NUM2UINT(num);
322
+ SMCOpen();
323
+ float speed = SMCGetFanSpeed(fanNum);
324
+ SMCClose();
255
325
 
256
- return rb_float_new(speed);
326
+ return rb_float_new(speed);
257
327
  }
328
+
329
+ VALUE method_get_battery_health(VALUE self) {
330
+ const char* health = getBatteryHealth();
331
+ return rb_str_new2(health);
332
+ }
333
+
334
+ VALUE method_get_battery_design_cycle_count(VALUE self) {
335
+ int cc = getDesignCycleCount();
336
+ return INT2NUM(cc);
337
+ }
338
+
339
+ /* Main method used for test */
340
+ // int main(int argc, char *argv[])
341
+ // {
342
+ // //SMCOpen();
343
+ // //printf("%0.1f°C\n", SMCGetTemperature(SMC_KEY_CPU_TEMP));
344
+ // //printf("%0.1f\n", SMCGetFanSpeed(0));
345
+ // //printf("%0.1f\n", SMCGetFanSpeed(3));
346
+ // //printf("%i\n", SMCGetFanNumber(SMC_KEY_FAN_NUM));
347
+ // //SMCClose();
348
+ //
349
+ // int designCycleCount = getDesignCycleCount();
350
+ // const char* batteryHealth = getBatteryHealth();
351
+ //
352
+ // if (designCycleCount) printf ("%i\n", designCycleCount);
353
+ // if (batteryHealth) printf ("%s\n", batteryHealth);
354
+ //
355
+ // return 0;
356
+ // }
@@ -20,6 +20,7 @@
20
20
  #ifndef __SMC_H__
21
21
  #define __SMC_H__
22
22
  #include "ruby.h"
23
+ #include <CoreFoundation/CoreFoundation.h>
23
24
  #endif
24
25
 
25
26
  #define VERSION "0.01"
@@ -90,14 +91,20 @@ typedef struct {
90
91
  SMCBytes_t bytes;
91
92
  } SMCVal_t;
92
93
 
93
-
94
94
  // prototypes
95
95
  float SMCGetFanSpeed(int fanNum);
96
96
  int SMCGetFanNumber(char *key);
97
97
  double SMCGetTemperature(char *key);
98
+ const char* getBatteryHealth();
99
+ int getDesignCycleCount();
100
+ CFTypeRef IOPSCopyPowerSourcesInfo(void);
101
+ CFArrayRef IOPSCopyPowerSourcesList(CFTypeRef blob);
102
+ CFDictionaryRef IOPSGetPowerSourceDescription(CFTypeRef blob, CFTypeRef ps);
98
103
 
99
104
  // Ruby modules
100
105
  void Init_osx_stats();
101
106
  VALUE method_get_cpu_temp(VALUE self);
102
107
  VALUE method_get_fan_speed(VALUE self, VALUE num);
103
108
  VALUE method_get_fan_number(VALUE self);
109
+ VALUE method_get_battery_health(VALUE self);
110
+ VALUE method_get_battery_design_cycle_count(VALUE self);
@@ -12,6 +12,7 @@ require 'iStats/symbols'
12
12
  require 'iStats/command'
13
13
  require 'iStats/cpu'
14
14
  require 'iStats/fan'
15
+ require 'iStats/battery'
15
16
 
16
17
  module IStats
17
18
  def self.options
@@ -0,0 +1,79 @@
1
+ # Fan Stats
2
+ # Extend BATTERY_STATS C module (ext/osx_stats/smc.c)
3
+ #
4
+ module IStats
5
+ class Battery
6
+ extend BATTERY_STATS
7
+ class << self
8
+ include IStats::Color
9
+
10
+ # Delegate CLI command to function
11
+ #
12
+ def delegate(stat)
13
+ case stat
14
+ when 'all'
15
+ all
16
+ when 'health'
17
+ battery_health
18
+ when 'cycle_count', 'cc'
19
+ cycle_count
20
+ else
21
+ Command.help "Unknown stat for Battery: #{stat}"
22
+ end
23
+ end
24
+
25
+ # Call all functions (stats)
26
+ #
27
+ def all
28
+ battery_health
29
+ cycle_count
30
+ end
31
+
32
+ # Prints the battery cycle count info
33
+ #
34
+ def cycle_count
35
+ data = %x( ioreg -l | grep Capacity )
36
+ cycle_count = data[/"Cycle Count"=([0-9]*)/, 1]
37
+ if cycle_count == nil
38
+ puts "Cycle count: unknown"
39
+ else
40
+ max_cycle_count = design_cycle_count
41
+ percentage = (cycle_count.to_f/max_cycle_count.to_f)*100
42
+
43
+ list = [0, 30, 55, 80, 100, 130]
44
+ sparkline = Sparkr.sparkline(list) do |tick, count, index|
45
+ if index.between?(0, 5) and percentage > 95
46
+ flash_red(tick)
47
+ elsif index.between?(0, 1)
48
+ green(tick)
49
+ elsif index.between?(2, 3) and percentage > 45
50
+ light_yellow(tick)
51
+ elsif index == 4 and percentage > 65
52
+ yellow(tick)
53
+ elsif index == 5 and percentage > 85
54
+ red(tick)
55
+ else
56
+ tick
57
+ end
58
+ end
59
+ puts "Cycle count: #{cycle_count} " + sparkline
60
+ puts "Max cycle count: #{max_cycle_count}"
61
+ end
62
+ end
63
+
64
+ # Get the battery health
65
+ # Calls a C method from BATTERY_STATS module
66
+ #
67
+ def battery_health
68
+ puts "Battery health: #{get_battery_health}"
69
+ end
70
+
71
+ # Get the battery design cycle count
72
+ # Calls a C method from BATTERY_STATS module
73
+ #
74
+ def design_cycle_count
75
+ get_battery_design_cycle_count
76
+ end
77
+ end
78
+ end
79
+ end
@@ -4,6 +4,10 @@ module IStats
4
4
  class << self
5
5
  include IStats::Color
6
6
 
7
+ # Executes a command
8
+ #
9
+ # args - Command line arguments
10
+ #
7
11
  def execute(*args)
8
12
  # Default command is 'all'
9
13
  category = args.empty? ? 'all' : args.shift
@@ -13,6 +17,11 @@ module IStats
13
17
  delegate(category, stat)
14
18
  end
15
19
 
20
+ # Delegate command to proper class
21
+ #
22
+ # category - Hardware we are targeting (CPU, fan, etc.)
23
+ # stat - The stat we want
24
+ #
16
25
  def delegate(category, stat)
17
26
  case category
18
27
  when 'all'
@@ -21,17 +30,22 @@ module IStats
21
30
  Cpu.delegate stat
22
31
  when 'fan'
23
32
  Fan.delegate stat
33
+ when 'battery'
34
+ Battery.delegate stat
24
35
  else
25
36
  help("Unknown category: #{category}")
26
37
  end
27
38
  end
28
39
 
40
+ # Execute all the stats methodes for all modules
41
+ #
29
42
  def all
30
- # Exec all
31
43
  puts "--- CPU Stats ---\n"
32
44
  Cpu.all
33
45
  puts "\n--- Fan Stats ---\n"
34
46
  Fan.all
47
+ puts "\n--- Battery Stats ---\n"
48
+ Battery.all
35
49
  end
36
50
 
37
51
  # Public: Parse extra options
@@ -75,6 +89,8 @@ module IStats
75
89
  istats cpu [temp | temperature] Print CPU temperature
76
90
  istats fan Print all fan stats
77
91
  istats fan [speed] Print fan speed
92
+ istats battery [health] Print battery health
93
+ istats battery [cycleCount | cc] Print battery cycle count info
78
94
 
79
95
  for more help see: https://github.com/Chris911/iStats
80
96
  ".gsub(/^ {8}/, '') # strip the first eight spaces of every line
@@ -1,11 +1,14 @@
1
+ # CPU Stats
2
+ # Extend CPU_STATS C module (ext/osx_stats/smc.c)
3
+ #
1
4
  module IStats
2
- # CPU Stats
3
- # Extend CPU_STATS C module (ext/osx_stats/smc.c)
4
5
  class Cpu
5
6
  extend CPU_STATS
6
7
  class << self
7
8
  include IStats::Color
8
9
 
10
+ # Delegate CLI command to function
11
+ #
9
12
  def delegate(stat)
10
13
  case stat
11
14
  when 'all'
@@ -17,10 +20,15 @@ module IStats
17
20
  end
18
21
  end
19
22
 
23
+ # Call all functions (stats)
24
+ #
20
25
  def all
21
26
  cpu_temperature
22
27
  end
23
28
 
29
+ # Print CPU temperature with sparkline
30
+ # TODO: Move sparkline function to printer class
31
+ #
24
32
  def cpu_temperature
25
33
  t = get_cpu_temp
26
34
  message = "CPU temp: #{t}#{Symbols.degree}C "
@@ -1,11 +1,14 @@
1
+ # Fan Stats
2
+ # Extend FAN_STATS C module (ext/osx_stats/smc.c)
3
+ #
1
4
  module IStats
2
- # Fan Stats
3
- # Extend FAN_STATS C module (ext/osx_stats/smc.c)
4
5
  class Fan
5
6
  extend FAN_STATS
6
7
  class << self
7
8
  include IStats::Color
8
9
 
10
+ # Delegate CLI command to function
11
+ #
9
12
  def delegate(stat)
10
13
  case stat
11
14
  when 'all'
@@ -19,20 +22,28 @@ module IStats
19
22
  end
20
23
  end
21
24
 
25
+ # Call all functions (stats)
26
+ #
22
27
  def all
23
28
  print_fan_number
24
29
  fans_speed
25
30
  end
26
31
 
32
+ # Get the number of fans on system
33
+ # Calls a C method from FAN_STATS module
34
+ #
27
35
  def fan_number
28
- # C method
29
36
  get_fan_number
30
37
  end
31
38
 
39
+ # Print number of fan(s)
40
+ #
32
41
  def print_fan_number
33
- puts "Total fans on system: #{fan_number}"
42
+ puts "Total fans in system: #{fan_number}"
34
43
  end
35
44
 
45
+ # Get and print the speed of each fan
46
+ #
36
47
  def fans_speed
37
48
  fanNum = fan_number
38
49
  (0..(fanNum-1)).each do |n|
@@ -41,6 +52,12 @@ module IStats
41
52
  end
42
53
  end
43
54
 
55
+ # Actually print fan speed with Sparkline
56
+ # TODO: Move sparkline function to printer class
57
+ #
58
+ # fanNum - The fan number
59
+ # speed - Fan speed in RPM
60
+ #
44
61
  def print_fan_speed(fanNum, speed)
45
62
  message = "Fan #{fanNum} speed: #{speed} RPM "
46
63
  list = [0, 30, 55, 80, 100, 130]
@@ -1,3 +1,3 @@
1
1
  module IStats
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iStats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris911
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-14 00:00:00.000000000 Z
11
+ date: 2014-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sparkr
@@ -87,6 +87,7 @@ files:
87
87
  - ext/osx_stats/smc.h
88
88
  - iStats.gemspec
89
89
  - lib/iStats.rb
90
+ - lib/iStats/battery.rb
90
91
  - lib/iStats/color.rb
91
92
  - lib/iStats/command.rb
92
93
  - lib/iStats/cpu.rb