arbi 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/arbi ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'arbi'
4
+
5
+ client = Arbi::Client.new
6
+ client.start
7
+ client.close
data/bin/arbid ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'arbi'
4
+
5
+ server = Arbi::Server.new
6
+
7
+ ["KILL", "ABRT", "INT", "QUIT"].each do |sig|
8
+ trap(sig){
9
+ server.close
10
+ }
11
+ end
12
+
13
+ server.start
data/lib/arbi.rb ADDED
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/ruby
2
+
3
+ class Regexp
4
+ alias oldto_s to_s
5
+ def to_s
6
+ regex = oldto_s.gsub(/^\(\?|\)/, '')
7
+ "/#{regex.split(/:/, 2)[1]}/#{regex.split(':')[0].split('-')[0]}"
8
+ end
9
+ end
10
+
11
+ module Arbi
12
+
13
+ require 'getopt/long'
14
+ include Getopt
15
+
16
+ VERSION = "1.0.2"
17
+
18
+ @cmd = []
19
+
20
+ def self.add_plugin regex, instance
21
+ @cmd += [[regex, instance]]
22
+ end
23
+
24
+ def self.cmd
25
+ @cmd
26
+ end
27
+
28
+ def self.show_version
29
+ puts "Arbi (Client|Server) v#{VERSION}"
30
+ exit 0
31
+ end
32
+
33
+ class Server
34
+ require 'socket'
35
+
36
+ def initialize
37
+ @threads = Array.new
38
+ @sessions = Array.new
39
+ @address = 'localhost'
40
+ @port = 6969
41
+ parse_args
42
+ @server = TCPServer.new(@address, @port)
43
+ end
44
+
45
+ def show_help
46
+ puts "Arbi Server, USAGE:"
47
+ puts "\t#{$0} [switches]"
48
+ puts "\t\t--bind-address|-a\tAddress to bind, default to \"127.0.0.1\""
49
+ puts "\t\t --port|-p\tPort to use for server, default to 40"
50
+ puts "\t\t --version|-v\tPrint version and exit"
51
+ puts "\t\t --help|-h\tPrint this help and exit"
52
+ exit 0
53
+ end
54
+
55
+ def start
56
+ @servert = Thread.new do
57
+ while(session = @server.accept)
58
+ new_client session
59
+ end
60
+ end
61
+ @servert.join
62
+ end
63
+
64
+ def close
65
+ @sessions.each{ |session|
66
+ session.close
67
+ }
68
+
69
+ @threads.each{ |thread|
70
+ thread.kill
71
+ }
72
+ @server.close
73
+ @servert.kill
74
+ end
75
+
76
+ private
77
+
78
+ def parse_args
79
+ begin
80
+ opts = Arbi::Long.getopts(
81
+ ["--bind-address", "-a", Arbi::REQUIRED],
82
+ ["--port", "-p", Arbi::REQUIRED],
83
+ ["--help", "-h", Arbi::BOOLEAN],
84
+ ["--version", "-v", Arbi::BOOLEAN]
85
+ )
86
+ rescue Getopt::Long::Error => e
87
+ puts "Arguments error: #{e}"
88
+ exit 0
89
+ end
90
+
91
+ @address = opts['a'] if opts['a']
92
+ @port = opts['p'] if opts['p']
93
+ show_help if opts['h']
94
+ Arbi::show_version if opts['v']
95
+ end
96
+
97
+ def new_client session
98
+ @threads.push Thread.start(session){ |session|
99
+ while message = session.gets
100
+ toggle = true
101
+ message = message.strip
102
+ break if message =~ /^QUIT$/i
103
+
104
+ if message =~ /^HELP$/i
105
+ session.print "help:\r\n"
106
+ Arbi::cmd.each { |pair|
107
+ session.print "#{pair[0]}\r\n"
108
+ }
109
+ session.print "/^quit$/i\r\n"
110
+ session.print "/^version$/i\r\n"
111
+ session.print "/^help$/i\r\n"
112
+ session.print "END\r\n"
113
+ toggle = !toggle
114
+ end
115
+
116
+ if message =~ /^VERSION$/i
117
+ session.print "version:\r\nArbi (Client|Server) v#{VERSION}\r\nEND\r\n"
118
+ toggle = !toggle
119
+ end
120
+
121
+ Arbi::cmd.each { |pair|
122
+ if message =~ pair[0]
123
+ session.print (pair[1].class == Class ? pair[1].protocolize(pair[1].get_infos) : pair[1].class.protocolize(pair[1].get_infos))
124
+ toggle = !toggle
125
+ end
126
+ }
127
+ session.print "error:\r\nCommand doesn't exist\r\nEND\r\n" if toggle
128
+ end
129
+ @sessions -= [session]
130
+ session.close
131
+ }
132
+ @sessions.push session
133
+ end
134
+ end
135
+
136
+ class Client
137
+ def initialize
138
+ @address = 'localhost'
139
+ @port = 6969
140
+ @command = "help\r\nquit\r\n"
141
+ parse_args
142
+ @sock = TCPSocket.new(@address, @port)
143
+ end
144
+
145
+ def start
146
+ @sock.print @command
147
+ @command = @command.strip.split(/\r\n/).map(&:upcase)
148
+ @command.pop
149
+ toggle = false
150
+ while (line = @sock.gets)
151
+ puts (command = @command.shift) + ":"
152
+ buff = ""
153
+ while (l = @sock.gets).strip !~ /^END$/i do; buff << l; end
154
+ buff.gsub!(/END\s+$/m, '')
155
+ case line.strip
156
+ when /^error:$/i
157
+ puts "ERROR: #{buff}"
158
+ next
159
+ when /^help:$/i
160
+ puts buff
161
+ when /^version$:/i
162
+ puts buff
163
+ end
164
+ Arbi::cmd.each{|cmd|
165
+ puts (cmd[1].class == Class ? cmd[1].friendlize(buff) : cmd[1].class.friendlize(buff)) if command =~ cmd[0]
166
+ }
167
+ puts if @command != []
168
+ end
169
+ end
170
+
171
+ def close
172
+ @sock.close
173
+ end
174
+
175
+ def show_help
176
+ puts "Arbi client:"
177
+ puts "\tUSAGE: #{$0} [switches]"
178
+ puts "\t\t --help|-h\tshow this helps"
179
+ puts "\t\t--version|-v\tshow version of arbi"
180
+ puts "\t\t--address|-a\tset the address to connect, default to 'localhost'"
181
+ puts "\t\t --port|-p\tset the port to connect, default to 40"
182
+ puts "\t\t--command|-c\tset commands to execute, defaults is 'help'"
183
+ exit 0
184
+ end
185
+
186
+ private
187
+
188
+ def parse_args
189
+ begin
190
+ opts = Arbi::Long.getopts(
191
+ ["--help"],
192
+ ["--version"],
193
+ ["--address", "-a", Arbi::REQUIRED],
194
+ ["--port", "-p", Arbi::REQUIRED],
195
+ ["--commands", "-c", Arbi::REQUIRED]
196
+ )
197
+ rescue Arbi::Long::Error => e
198
+ p ARGV
199
+ $stderr.puts "Arguments error: #{e}"
200
+ exit 1
201
+ end
202
+
203
+ Arbi::show_version if opts["v"]
204
+ show_help if opts["h"]
205
+ @address = opts["a"] if opts["a"]
206
+ @port = opts["p"] if opts["p"]
207
+ @command = "#{opts["c"]},quit".gsub(/,+/, ',').gsub(/\s+/, '').split(/,/).
208
+ delete_if{|x|x=~/^quit$/i}.uniq.push('quit', '').join("\r\n") if opts["c"]
209
+ end
210
+ end
211
+ end
212
+
213
+ require 'arbi/plugins/batteries'
214
+ require 'arbi/plugins/cpu'
215
+ require 'arbi/plugins/diskspace'
216
+ require 'arbi/plugins/net'
217
+ require 'arbi/plugins/ram'
218
+ require 'arbi/plugins/thermal'
@@ -0,0 +1,3 @@
1
+ def file_get_content file
2
+ File.readlines(file).join
3
+ end
@@ -0,0 +1,85 @@
1
+ class Batteries
2
+ require 'arbi/common'
3
+
4
+ def initialize
5
+ @AC = {'sanity' => false, 'state' => false, 'percent' => false}
6
+ @batteries = Dir.glob "/proc/acpi/battery/*"
7
+ end
8
+
9
+ def get_infos
10
+ batteries = Hash.new
11
+ @batteries.each { |battery|
12
+ batteries.merge!(get_battery_infos(battery))
13
+ }
14
+ batteries.merge average batteries
15
+ end
16
+
17
+ def self.protocolize batteries
18
+ str = "batteries:\r\n"
19
+ batteries.each { |key, value|
20
+ str << "#{key}|#{value["percent"] || '-'}"
21
+ if key != "AVERAGE"
22
+ str << "|#{value["state"] || '-'}|#{value["sanity"] || '-'}"
23
+ end
24
+ str << "\r\n"
25
+ }
26
+ str << "END\r\n"
27
+ end
28
+
29
+ def self.friendlize raw
30
+ raw.strip!
31
+ max = raw.lines.map{|x| x.split(/\|/)[0].length}.max + 4
32
+ str = "NAME".ljust(max) + "PERC STATE SANITY\r\n"
33
+ raw.split(/\r?\n/).each { |line|
34
+ datas = line.split /\|/
35
+ str << datas[0].ljust(max) + datas[1].ljust(8)
36
+ if datas[0] != "AVERAGE"
37
+ str << datas[2].ljust(12) + datas[3]
38
+ end
39
+ str << "\r\n"
40
+ }
41
+ str
42
+ end
43
+
44
+ private
45
+
46
+ def average batteries
47
+ avg, n = 0, 0
48
+ batteries.each do |key, value|
49
+ if value["percent"]
50
+ avg += value["percent"].gsub(/%$/, '').to_i
51
+ n += 1
52
+ end
53
+ end
54
+ avg = (avg.to_f / n).to_s.gsub /\.0/, '' + '%'
55
+
56
+ ({'AVERAGE' => {
57
+ 'sanity' => '-',
58
+ 'state' => '-',
59
+ 'percent' => avg
60
+ }
61
+ })
62
+ end
63
+
64
+ def get_battery_infos dir
65
+ info = file_get_content dir + "/info"
66
+ state = file_get_content dir + "/state"
67
+ present = {'yes' => true, 'no' => false}[state.match(/^present:\s*?([^\s]+?)$/)[1]]
68
+ if !present then return {dir.gsub(/^\/proc\/acpi\/battery\//, '') => @AC} end
69
+ ({dir.gsub(/^\/proc\/acpi\/battery\//, '') => {
70
+ 'sanity' => sprintf('%.1f%%', 100.0 /
71
+ (info.match(/^design capacity:\s*?([^\s]+?) mAh$/)[1].to_i) *
72
+ (info.match(/^last full capacity:\s*?([^\s]+?) mAh$/)[1].to_i)).gsub(/\.0%$/, '%'),
73
+ 'state' => state.match(/^charging state:\s*?([^\s]+?)$/)[1],
74
+ 'percent' => sprintf('%.1f%%', 100.0 /
75
+ (info.match(/^last full capacity:\s*?([^\s]+?) mAh$/)[1].to_i) *
76
+ (state.match(/^remaining capacity:\s*?([^\s]+?) mAh$/)[1].to_i)).gsub(/\.0%$/, '%')
77
+ }})
78
+ end
79
+ end
80
+
81
+ if __FILE__ == $0
82
+ puts Batteries.friendlize Batteries.protocolize(Batteries.new.get_infos).gsub(/^batteries:\s+|^END\s+/m, '').strip
83
+ else
84
+ Arbi.add_plugin /^batteries$/i, Batteries.new
85
+ end
@@ -0,0 +1,89 @@
1
+ class Cpu
2
+ require 'arbi/common'
3
+ require 'thread'
4
+
5
+ def initialize
6
+ @prev = {:idle => Hash.new, :total => Hash.new}
7
+ @percents = Hash.new
8
+ @mutex = Mutex.new
9
+ @serv = Thread.new do
10
+ while true
11
+ @mutex.lock
12
+ update
13
+ @mutex.unlock
14
+ sleep 2
15
+ end
16
+ end
17
+ end
18
+
19
+ def get_infos
20
+ @mutex.lock
21
+ perc = @percents
22
+ @mutex.unlock
23
+ perc
24
+ end
25
+
26
+ def self.protocolize percents
27
+ str = "cpu:\r\n"
28
+ percents.each { |key, value|
29
+ str += "#{key}|#{value}\r\n"
30
+ }
31
+ str + "END\r\n"
32
+ end
33
+
34
+ def self.friendlize raw
35
+ raw = raw.to_s.strip
36
+ max = raw.lines.map{|x|x.split(/\|/)[0].length}.max + 4
37
+ str = "NAME".ljust(max) + "PERC\r\n"
38
+ raw.split(/\r?\n/).each { |line|
39
+ datas = line.split /\|/
40
+ str << datas[0].ljust(max) + datas[1] + "\r\n"
41
+ }
42
+ str
43
+ end
44
+
45
+ def close
46
+ @serv.kill
47
+ end
48
+
49
+ private
50
+
51
+ def update
52
+ file_get_content('/proc/stat').split("\n").each do |line|
53
+ if line =~ /^cpu/
54
+ datas = line.split /\s+/
55
+ name = datas.shift
56
+ name = (name == 'cpu' ? 'AVERAGE' : name)
57
+ total = eval datas.join('+')
58
+ idle = datas[3].to_i
59
+
60
+ if not @prev[:idle].include? name or not @prev[:total].include? name
61
+ @prev[:idle][name] = @prev[:total][name] = 0
62
+ end
63
+
64
+ @percents[name] = (100 * ((total - @prev[:total][name]) - (idle - @prev[:idle][name])) / (total - @prev[:total][name])).to_s + "%"
65
+ @prev[:idle][name] = idle
66
+ @prev[:total][name] = total
67
+ end
68
+ end
69
+
70
+ average = {"AVERAGE" => @percents["AVERAGE"]} and @percents.delete("AVERAGE") and @percents.merge!(average)
71
+ end
72
+ end
73
+
74
+ if __FILE__ == $0
75
+ x = Cpu.new
76
+ ["INT", "KILL", "ABRT", "ILL", "QUIT"].each do |sig|
77
+ trap(sig) do
78
+ x.close
79
+ exit 0
80
+ end
81
+ end
82
+ 10.times {
83
+ sleep 2
84
+ puts Cpu.friendlize Cpu.protocolize(x.get_infos).gsub(/^cpu:\s+|END\s+/m, '')
85
+ }
86
+ x.close
87
+ else
88
+ Arbi.add_plugin /^cpu$/i, Cpu.new
89
+ end
@@ -0,0 +1,68 @@
1
+ class Diskspace
2
+ require 'arbi/common'
3
+ require 'sys/filesystem'
4
+ include Sys
5
+
6
+ def get_infos
7
+ devices = Array.new
8
+ get_devices.each do |device|
9
+ begin
10
+ diskstat = Filesystem.stat device['point']
11
+ device.merge!({'usage' => (100 - (100.0 / diskstat.blocks * diskstat.blocks_available).round).to_s + "%",
12
+ 'space' => diskstat.blocks * diskstat.fragment_size})
13
+ devices += [device]
14
+ rescue
15
+ end
16
+ end
17
+ devices
18
+ end
19
+
20
+ def self.protocolize devices
21
+ str = "devices:\r\n"
22
+ devices.each do |device|
23
+ str += "#{device['device']}|#{device['point']}|#{device['usage']}|#{self.unitize device['space']}\r\n"
24
+ end
25
+ str + "END\r\n"
26
+ end
27
+
28
+ def self.friendlize raw
29
+ raw = raw.to_s.strip
30
+ dmax = [raw.lines.map{|line|line.split(/\|/)[0].length}.max + 4, 8].max
31
+ mmax = [raw.lines.map{|line|line.split(/\|/)[1].length}.max + 4, 7].max
32
+ str = "DEVICE".ljust(dmax) + "MOUNT".ljust(mmax) + "USE % SPACE\r\n"
33
+ raw.split(/\r?\n/).each { |line|
34
+ datas = line.split /\|/
35
+ str << datas[0].ljust(dmax) + datas[1].ljust(mmax) + datas[2].ljust(7) + datas[3] + "\r\n"
36
+ }
37
+ str
38
+ end
39
+
40
+ private
41
+
42
+ def get_devices
43
+ devices = Array.new
44
+ Filesystem.mounts do |fs|
45
+ devices += [{'device' => fs.name, 'point' => fs.mount_point}]
46
+ end
47
+ devices
48
+ end
49
+
50
+ def self.unitize misure
51
+ u = 'b'
52
+ %w(Kb Mb Gb Tb).each do |i|
53
+ if misure >= 1024
54
+ misure /= 1024.0
55
+ u = i
56
+ else
57
+ return misure.round.to_s + u
58
+ end
59
+ end
60
+ misure.round.to_s + u
61
+ end
62
+ end
63
+
64
+ if __FILE__ == $0
65
+ puts Diskspace.friendlize Diskspace.protocolize(Diskspace.new.get_infos).gsub(/^devices:\s+|END\s+$/m, '')
66
+ else
67
+ Arbi::add_plugin /^diskstats$/i, Diskspace.new
68
+ end
@@ -0,0 +1,120 @@
1
+ class Net
2
+ require 'arbi/common'
3
+ require 'thread'
4
+
5
+ def initialize
6
+ @stats = Hash.new
7
+ @prev = {:up => Hash.new, :down => Hash.new}
8
+ @mutex = Mutex.new
9
+ @serv = Thread.new do
10
+ while true
11
+ @mutex.lock
12
+ update
13
+ @mutex.unlock
14
+ sleep 2
15
+ end
16
+ end
17
+ end
18
+
19
+ def get_infos
20
+ @mutex.lock
21
+ s = @stats
22
+ @mutex.unlock
23
+ s
24
+ end
25
+
26
+ def self.protocolize stats
27
+ str = "net:\r\n"
28
+ stats.each { |key, value|
29
+ str += "#{key}|#{value[:up]}|#{value[:down]}|#{value[:state] ? 'on' : 'off'}"
30
+ if value[:quality]
31
+ str += "|#{value[:essid]}|#{value[:quality]}"
32
+ end
33
+ str += "\r\n"
34
+ }
35
+ str + "END\r\n"
36
+ end
37
+
38
+ def self.friendlize raw
39
+ raw = raw.to_s.strip
40
+ nmax = raw.lines.map{|x|x.split(/\|/)[0].length}.max + 4
41
+ umax = raw.lines.map{|x|x.split(/\|/)[1].gsub(/^(\d+\.\d).*$/, '\1').length}.max + 2
42
+ dmax = raw.lines.map{|x|x.split(/\|/)[2].gsub(/^(\d+\.\d).*$/, '\1').length}.max + 2
43
+ emax = [[raw.lines.map{|x|x.split(/\|/)[4].to_s.length}.max + 4, 7].max, 34].min
44
+ str = "NAME".ljust(nmax) + "UP DOWN STATE " + "ESSID".ljust(emax) + "QUALITY\r\n"
45
+ raw.split(/\r?\n/).each { |line|
46
+ datas = line.split(/\|/)
47
+ str << datas[0].ljust(nmax) + ('%.1f' % datas[1].to_f).ljust(8) + ('%.1f' % datas[2].to_f).ljust(8) + datas[3].ljust(7)
48
+ str << datas[4].ljust(emax) + datas[5] if datas[4]
49
+ str << "\r\n"
50
+ }
51
+ str
52
+ end
53
+
54
+ private
55
+
56
+ def update
57
+ file_get_content('/proc/net/dev').gsub(/^.*\|.*?\n/m, '').split("\n").each do |line|
58
+ datas = line.gsub(/^\s+|\s+$/, '').split(/:\s+|\s+/)
59
+ name = datas.shift
60
+ down = datas[0].to_i
61
+ up = datas[8].to_i
62
+
63
+ if not @prev[:up].include? name or not @prev[:down].include? name
64
+ @prev[:up][name] = @prev[:down][name] = 0
65
+ end
66
+
67
+ @stats[name] = {:up => (up - @prev[:up][name]) / 1024.0,
68
+ :down => (down - @prev[:down][name]) / 1024.0,
69
+ :state => get_state(name),
70
+ :quality => nil,
71
+ :essid => nil}
72
+ if @stats[name][:state]
73
+ @stats[name][:quality] = get_quality(name)
74
+ @stats[name][:essid] = get_essid(name) if @stats[name][:quality]
75
+ end
76
+ @prev[:up][name] = up
77
+ @prev[:down][name] = down
78
+ end
79
+ end
80
+
81
+ def get_state interface
82
+ if file_get_content('/proc/net/route') =~ /#{interface}/
83
+ true
84
+ else
85
+ false
86
+ end
87
+ end
88
+
89
+ def get_quality interface
90
+ begin
91
+ file_get_content('/proc/net/wireless').match(/^\s*?#{interface}:.*$/)[0].strip.split(/:\s+|\s+/)[2].gsub('.', '') + "%"
92
+ rescue
93
+ nil
94
+ end
95
+ end
96
+
97
+ def get_essid interface
98
+ require "socket"
99
+
100
+ iwreq = [interface, " " * 32, 32, 0].pack("a16pII")
101
+ sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
102
+ sock.ioctl(0x8B1B, iwreq)
103
+ return iwreq.unpack("a16pII")[1].strip
104
+ end
105
+
106
+ def close
107
+ @serv.kill
108
+ end
109
+ end
110
+
111
+ if __FILE__ == $0
112
+ x = Net.new
113
+ 10.times {
114
+ sleep 2
115
+ puts Net.friendlize Net.protocolize(x.get_infos).gsub(/^net:\s+|END\s+$/m, '')
116
+ }
117
+ x.close
118
+ else
119
+ Arbi::add_plugin /^net$/i, Net.new
120
+ end
@@ -0,0 +1,29 @@
1
+ class Ram
2
+ require 'arbi/common'
3
+
4
+ def get_infos
5
+ mem = file_get_content('/proc/meminfo')
6
+ total = mem.match(/^MemTotal:\s*?([0-9]+) kB/)[1].to_i
7
+ free = mem.match(/^MemFree:\s*?([0-9]+) kB/)[1].to_i +
8
+ mem.match(/^Buffers:\s*?([0-9]+) kB/)[1].to_i +
9
+ mem.match(/^Cached:\s*?([0-9]+) kB/)[1].to_i
10
+ perc = 100.0 / total * free
11
+ {'used' => sprintf('%.1f%%', 100.0 - perc),
12
+ 'free' => sprintf('%.1f%%', perc)}
13
+ end
14
+
15
+ def self.protocolize perc
16
+ "ram:\r\n#{perc['used']}|#{perc['free']}\r\nEND\r\n"
17
+ end
18
+
19
+ def self.friendlize raw
20
+ datas = raw.to_s.strip.split(/\r?\n/)[0].split(/\|/)
21
+ "USED FREE\r\n#{datas[0].ljust(8)}#{datas[1]}"
22
+ end
23
+ end
24
+
25
+ if __FILE__ == $0
26
+ puts Ram.friendlize Ram.protocolize(Ram.new.get_infos).gsub(/^ram:\s+|END\s+$/m, '')
27
+ else
28
+ Arbi::add_plugin /^ram$/i, Ram.new
29
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ class Thermal
4
+ require 'arbi/common'
5
+
6
+ def initialize
7
+ @temperatures = Hash.new
8
+ @tempdirs = Dir.glob "/proc/acpi/thermal_zone/*"
9
+ @tempdirs.each do |dir|
10
+ trip_points = file_get_content dir + "/trip_points"
11
+ name = dir.gsub(/^\/proc\/acpi\/thermal_zone\//, '')
12
+ @temperatures.merge!({name => {'temperature' => file_get_content(dir + '/temperature').match(
13
+ /^temperature:\s*?([0-9]{1,3}) C$/)[1],
14
+ 'trip_critical' => trip_points.match(/^critical \(S5\):\s*?([0-9]{1,3}) C$/)[1],}})
15
+ end
16
+ end
17
+
18
+ def get_infos
19
+ @tempdirs.each do |dir|
20
+ @temperatures[dir.gsub(/^\/proc\/acpi\/thermal_zone\//, '')]["temperature"] =
21
+ file_get_content(dir + '/temperature').match(/^temperature:\s*?([0-9]{1,3}) C$/)[1]
22
+ end
23
+ @temperatures.merge average
24
+ end
25
+
26
+ def self.protocolize temperatures
27
+ str = "thermal:\r\n"
28
+ temperatures.each do |key, value|
29
+ str += "#{key}|#{value["temperature"]}#{key == "AVERAGE" ? '' : '|' + (value["trip_critical"] || '-')}\r\n"
30
+ end
31
+ str += "END\r\n"
32
+ end
33
+
34
+ def self.friendlize raw
35
+ raw = raw.to_s.strip
36
+ nmax = raw.lines.map{|x|x.split(/\|/)[0].length}.max + 4
37
+ tmax = [raw.lines.map{|x|x.split(/\|/)[1].length}.max + 4, 6].max
38
+ str = "NAME".ljust(nmax) + "TEMP".ljust(tmax) + "CRITICAL\r\n"
39
+ raw.split(/\r?\n/).each { |line|
40
+ datas = line.split /\|/
41
+ str << datas[0].ljust(nmax) + "#{datas[1]}°C".ljust(tmax)
42
+ str << "#{datas[2]}°C" if datas[2]
43
+ str << "\r\n"
44
+ }
45
+ str
46
+ end
47
+
48
+ private
49
+
50
+ def average
51
+ avg, n = 0, 0
52
+ @temperatures.each do |value, key|
53
+ avg += key["temperature"].to_i
54
+ n += 1
55
+ end
56
+ avg = (sprintf '%.1f', (avg.to_f / n)).gsub /\.0$/, ''
57
+ return ({'AVERAGE' => {'temperature' => avg, 'trip_critical' => false}})
58
+ end
59
+ end
60
+
61
+ if __FILE__ == $0
62
+ puts Thermal.friendlize Thermal.protocolize(Thermal.new.get_infos).gsub(/^thermal:\s+|END\s+$/m, '')
63
+ else
64
+ Arbi::add_plugin /^thermal$/i, Thermal.new
65
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arbi
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 2
10
+ version: 1.0.2
11
+ platform: ruby
12
+ authors:
13
+ - shura
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-10 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: getopt
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sys-filesystem
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: ""
50
+ email: shura1991@gmail.com
51
+ executables:
52
+ - arbid
53
+ - arbi
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - lib/arbi.rb
60
+ - lib/arbi/common.rb
61
+ - lib/arbi/plugins/ram.rb
62
+ - lib/arbi/plugins/diskspace.rb
63
+ - lib/arbi/plugins/cpu.rb
64
+ - lib/arbi/plugins/batteries.rb
65
+ - lib/arbi/plugins/net.rb
66
+ - lib/arbi/plugins/thermal.rb
67
+ - bin/arbid
68
+ - bin/arbi
69
+ has_rdoc: true
70
+ homepage: http://github.com/shurizzle/arbi
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.3.7
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: ""
103
+ test_files: []
104
+