arbi 1.0.7 → 1.0.8
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.
- 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
|