arbi 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/arbi +3 -5
- data/bin/arbid +3 -11
- data/lib/arbi.rb +31 -256
- data/lib/arbi/cli/client.rb +89 -0
- data/lib/arbi/cli/server.rb +75 -0
- data/lib/arbi/client.rb +52 -0
- data/lib/arbi/config.rb +70 -0
- data/lib/arbi/modules.rb +183 -0
- data/lib/arbi/modules/acpi/adapter.rb +62 -0
- data/lib/arbi/modules/acpi/battery.rb +99 -0
- data/lib/arbi/modules/acpi/utils.rb +50 -0
- data/lib/arbi/modules/adapter.rb +22 -0
- data/lib/arbi/modules/battery.rb +22 -0
- data/lib/arbi/modules/cpu.rb +88 -0
- data/lib/arbi/modules/diskstat.rb +81 -0
- data/lib/arbi/modules/help.rb +40 -0
- data/lib/arbi/modules/net.rb +120 -0
- data/lib/arbi/modules/ram.rb +52 -0
- data/lib/arbi/modules/sys/adapter.rb +60 -0
- data/lib/arbi/modules/sys/battery.rb +101 -0
- data/lib/arbi/modules/sys/thermal.rb +71 -0
- data/lib/arbi/modules/version.rb +42 -0
- data/lib/arbi/server.rb +67 -0
- data/lib/arbi/timeline.rb +70 -0
- data/lib/arbi/utils/numeric.rb +81 -0
- data/lib/arbi/utils/table.rb +48 -0
- data/lib/arbi/version.rb +23 -0
- metadata +53 -10
- data/lib/arbi/common.rb +0 -3
- data/lib/arbi/plugins/batteries.rb +0 -85
- data/lib/arbi/plugins/cpu.rb +0 -89
- data/lib/arbi/plugins/diskspace.rb +0 -68
- data/lib/arbi/plugins/net.rb +0 -120
- data/lib/arbi/plugins/ram.rb +0 -29
- data/lib/arbi/plugins/thermal.rb +0 -71
@@ -0,0 +1,60 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Arbi
|
21
|
+
|
22
|
+
module Modules
|
23
|
+
|
24
|
+
module Sys
|
25
|
+
|
26
|
+
class Adapter < Arbi::Modules::Module
|
27
|
+
def initialize(data = [])
|
28
|
+
super(data)
|
29
|
+
@adapters = Dir.glob('/sys/class/power_supply/*').select {|ad|
|
30
|
+
File.read("#{ad}/type").strip == 'Mains'
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
!@adapters.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def refresh
|
39
|
+
@data = []
|
40
|
+
|
41
|
+
@adapters.each {|adapter|
|
42
|
+
@data << {
|
43
|
+
name: File.basename(adapter),
|
44
|
+
state: (File.read("#{adapter}/online").to_i.zero? ? false : true)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def format
|
50
|
+
tablize([['NAME', 'STATE']] + @data.map {|adapter|
|
51
|
+
[adapter[:name] || adapter['name'], (adapter[:state] || adapter['state']) ? 'on' : 'off']
|
52
|
+
})
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Arbi
|
21
|
+
|
22
|
+
module Modules
|
23
|
+
|
24
|
+
module Sys
|
25
|
+
|
26
|
+
class Battery < Arbi::Modules::Module
|
27
|
+
def initialize(data = [])
|
28
|
+
super(data)
|
29
|
+
@batteries = Dir.glob('/sys/class/power_supply/*').select {|dir| File.read("#{dir}/type").strip == 'Battery' }
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
!@batteries.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
def refresh
|
37
|
+
@data = []
|
38
|
+
|
39
|
+
@batteries.each {|battery|
|
40
|
+
@data << self.battery_info(battery)
|
41
|
+
}
|
42
|
+
@data << self.average(@data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def format
|
46
|
+
tablize([['NAME', 'PERCENT', 'STATE', 'SANITY']] + @data.map {|x|
|
47
|
+
[x[:name] || x['name'], x[:percent] || x['percent'], x[:state] || x['state'], x[:sanity] || x['sanity']]
|
48
|
+
})
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
def battery_info(dir)
|
53
|
+
raw = {
|
54
|
+
design_capacity: File.read("#{dir}/energy_full_design").strip.to_i,
|
55
|
+
last_full_capacity: File.read("#{dir}/energy_full").strip.to_i,
|
56
|
+
remaining_capacity: File.read("#{dir}/energy_now").strip.to_i,
|
57
|
+
present: (File.read("#{dir}/present").strip.to_i.zero? ? false : true),
|
58
|
+
charging_state: File.read("#{dir}/status").strip.downcase.gsub(/^full$/, 'charged')
|
59
|
+
}
|
60
|
+
|
61
|
+
return not_present(File.basename(dir)) unless raw[:present]
|
62
|
+
|
63
|
+
{
|
64
|
+
name: File.basename(dir),
|
65
|
+
sanity: ("%.1f%%" % [100.0 / raw[:design_capacity] * raw[:last_full_capacity]]),
|
66
|
+
state: raw[:charging_state],
|
67
|
+
percent: ("%.1f%%" % [100.0 / raw[:last_full_capacity] * raw[:remaining_capacity]])
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def average(batteries)
|
72
|
+
avg, n = 0, 0
|
73
|
+
|
74
|
+
batteries.each {|battery|
|
75
|
+
avg += battery[:percent].gsub(/%$/, '').to_f and n += 1 if battery[:percent]
|
76
|
+
}
|
77
|
+
avg = "%.1f%%" % [avg / n] rescue false
|
78
|
+
|
79
|
+
{
|
80
|
+
name: 'AVERAGE',
|
81
|
+
sanity: false,
|
82
|
+
state: false,
|
83
|
+
percent: avg
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def not_present(name)
|
88
|
+
{
|
89
|
+
name: name,
|
90
|
+
sanity: false,
|
91
|
+
state: false,
|
92
|
+
percent: false
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Arbi
|
21
|
+
|
22
|
+
module Modules
|
23
|
+
|
24
|
+
module Sys
|
25
|
+
|
26
|
+
class Thermal < Arbi::Modules::Module
|
27
|
+
def initialize(data = [])
|
28
|
+
super(data)
|
29
|
+
@trips = {}
|
30
|
+
@tempdirs = Dir.glob('/sys/class/thermal/thermal_zone*')
|
31
|
+
|
32
|
+
@tempdirs.each {|dir|
|
33
|
+
name = File.basename(dir)
|
34
|
+
|
35
|
+
Dir.glob("#{dir}/trip_point_*").select {|x| x =~ /_temp$/ }.each {|trip|
|
36
|
+
if File.read(trip.gsub(/emp$/, 'ype')).strip == 'critical'
|
37
|
+
@trips[name] = "#{File.read(trip).to_i / 1000} C"
|
38
|
+
end
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def valid?
|
44
|
+
!@tempdirs.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
def refresh
|
48
|
+
@data = []
|
49
|
+
|
50
|
+
@tempdirs.each {|dir|
|
51
|
+
name = File.basename(dir)
|
52
|
+
@data << {
|
53
|
+
name: name,
|
54
|
+
temperature: "#{File.read("#{dir}/temp").to_i / 1000} C",
|
55
|
+
trip_point: @trips[name]
|
56
|
+
}
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def format
|
61
|
+
tablize([['NAME', 'TEMPERATURE', 'TRIP POINT']] + @data.map {|therm|
|
62
|
+
[therm[:name] || therm['name'], therm[:temperature] || therm['temperature'], therm[:trip_point] || therm['trip_point']]
|
63
|
+
})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'arbi/version'
|
21
|
+
|
22
|
+
module Arbi
|
23
|
+
|
24
|
+
module Modules
|
25
|
+
|
26
|
+
class Version < Module
|
27
|
+
def valid?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def refresh
|
32
|
+
@data = Arbi::VERSION
|
33
|
+
end
|
34
|
+
|
35
|
+
def format
|
36
|
+
@data
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/arbi/server.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'eventmachine'
|
21
|
+
require 'arbi/modules'
|
22
|
+
|
23
|
+
module Arbi
|
24
|
+
|
25
|
+
class Server
|
26
|
+
module Server
|
27
|
+
def post_init
|
28
|
+
send_data("OH HAI! ^_^\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def receive_data(data)
|
32
|
+
if data.strip.downcase =~ /^(quit|exit)$/
|
33
|
+
close_connection
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
obj = Arbi.modules[data.strip.downcase]
|
38
|
+
|
39
|
+
if obj
|
40
|
+
send_data(obj.to_json)
|
41
|
+
else
|
42
|
+
send_data(Arbi::Modules::Error.new('Command doesn\'t exist').to_json)
|
43
|
+
end
|
44
|
+
rescue Exception => e
|
45
|
+
Arbi.debug(e.to_s)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(address = '127.0.0.1', port = 6969)
|
50
|
+
@address = address || '127.0.0.1'
|
51
|
+
@port = port || 6969
|
52
|
+
end
|
53
|
+
|
54
|
+
def start
|
55
|
+
EventMachine.run {
|
56
|
+
TimeLine.run
|
57
|
+
EventMachine.start_server(@address, @port, Arbi::Server::Server)
|
58
|
+
Arbi.debug("Starting server on #{@address}:#{@port}")
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.start(address = '127.0.0.1', port = 6969)
|
63
|
+
self.new(address, port).start
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'eventmachine'
|
21
|
+
require 'timeout'
|
22
|
+
|
23
|
+
module TimeLine
|
24
|
+
class Job
|
25
|
+
attr_reader :every, :timeout, :proc
|
26
|
+
|
27
|
+
def initialize(ev = 2, to = 5, &blk)
|
28
|
+
self.every = ev
|
29
|
+
self.timeout = to
|
30
|
+
self.proc = blk
|
31
|
+
|
32
|
+
TimeLine.register(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def every=(ev)
|
36
|
+
raise ArgumentError, "every must be an Integer > 0" unless ev.is_a?(Integer) and ev > 0
|
37
|
+
@every = ev
|
38
|
+
end
|
39
|
+
|
40
|
+
def timeout=(to)
|
41
|
+
raise ArgumentError, "timeout must be an Integer > 0" unless to.is_a?(Integer) and to > 0
|
42
|
+
@timeout = to
|
43
|
+
end
|
44
|
+
|
45
|
+
def proc=(blk)
|
46
|
+
raise ArgumentError, "proc must be a Proc" unless blk.is_a?(Proc)
|
47
|
+
@proc = blk
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
def register(job)
|
53
|
+
raise ArgumentError, "job must be a TimeLine::Job" unless job.is_a?(TimeLine::Job)
|
54
|
+
@@jobs ||= []
|
55
|
+
@@jobs << job
|
56
|
+
end
|
57
|
+
|
58
|
+
def run
|
59
|
+
@@jobs ||= []
|
60
|
+
@@jobs.each {|job|
|
61
|
+
EventMachine::PeriodicTimer.new(job.every) do
|
62
|
+
timeout(job.timeout) {
|
63
|
+
job.proc.call
|
64
|
+
}
|
65
|
+
end
|
66
|
+
}
|
67
|
+
self
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#--
|
2
|
+
# Copyleft shura. [ shura1991@gmail.com ]
|
3
|
+
#
|
4
|
+
# This file is part of arbi.
|
5
|
+
#
|
6
|
+
# arbi is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# arbi is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with arbi. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
class Numeric
|
21
|
+
|
22
|
+
module Scalar
|
23
|
+
attr_accessor :unit
|
24
|
+
|
25
|
+
MULTIPLIERS = {
|
26
|
+
?Y => 10 ** 24, ?Z => 10 ** 21, ?E => 10 ** 18,
|
27
|
+
?P => 10 ** 15, ?T => 10 ** 12, ?G => 10 ** 9,
|
28
|
+
?M => 10 ** 6, ?k => 10 ** 3, ?h => 10 ** 2, 'da' => 10,
|
29
|
+
|
30
|
+
?y => 10 ** -24, ?z => 10 ** -21, ?a => 10 ** -18,
|
31
|
+
?f => 10 ** -15, ?p => 10 ** -12, ?n => 10 ** -9,
|
32
|
+
?u => 10 ** -9, ?m => 10 ** -3, ?c => 10 ** -2, ?d => 10 ** -1
|
33
|
+
}
|
34
|
+
|
35
|
+
alias __method_missing__ method_missing
|
36
|
+
def method_missing(sym, *args, &blk)
|
37
|
+
if MULTIPLIERS.include?(sym.to_s)
|
38
|
+
self / MULTIPLIERS[sym.to_s]
|
39
|
+
else
|
40
|
+
self.__method_missing__(sym, *args, &blk) if sym != :to_str
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.parse(str)
|
46
|
+
if str.strip.match(/^([^\s]+)\s+(#{Numeric::Scalar::MULTIPLIERS.keys.map {|x|
|
47
|
+
Regexp.escape(x)
|
48
|
+
}.join(?|)})?(.*?)$/)
|
49
|
+
num, mul, unit = $1, $2, $3
|
50
|
+
v = begin
|
51
|
+
Integer(num)
|
52
|
+
rescue ArgumentError
|
53
|
+
Float(num) rescue nil
|
54
|
+
end
|
55
|
+
|
56
|
+
return nil unless v
|
57
|
+
|
58
|
+
if Numeric::Scalar::MULTIPLIERS[mul]
|
59
|
+
v = (v * Numeric::Scalar::MULTIPLIERS[mul]).to_f
|
60
|
+
end
|
61
|
+
|
62
|
+
if !unit.empty?
|
63
|
+
v.unit = unit.dup
|
64
|
+
end
|
65
|
+
|
66
|
+
return v
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Integer
|
72
|
+
include Numeric::Scalar
|
73
|
+
end
|
74
|
+
|
75
|
+
class Float
|
76
|
+
include Numeric::Scalar
|
77
|
+
end
|
78
|
+
|
79
|
+
class Rational
|
80
|
+
include Numeric::Scalar
|
81
|
+
end
|