battery 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .idea
2
+ log
3
+
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ # Use the gem instead of a dated version bundled with Ruby
7
+ gem 'minitest', '2.8.1'
8
+ gem 'mocha'
9
+ gem 'activesupport', '~>3.2.0'
10
+ gem 'simplecov', :require => false
11
+ end
12
+
13
+ group :development do
14
+ gem 'rake'
15
+ # enhance irb
16
+ gem 'awesome_print', :require => false
17
+ gem 'pry', :require => false
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ battery (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ activesupport (3.2.2)
10
+ i18n (~> 0.6)
11
+ multi_json (~> 1.0)
12
+ awesome_print (1.0.2)
13
+ coderay (1.0.5)
14
+ i18n (0.6.0)
15
+ metaclass (0.0.1)
16
+ method_source (0.7.1)
17
+ minitest (2.8.1)
18
+ mocha (0.10.5)
19
+ metaclass (~> 0.0.1)
20
+ multi_json (1.1.0)
21
+ pry (0.9.8.4)
22
+ coderay (~> 1.0.5)
23
+ method_source (~> 0.7.1)
24
+ slop (>= 2.4.4, < 3)
25
+ rake (0.9.2.2)
26
+ simplecov (0.6.1)
27
+ multi_json (~> 1.0)
28
+ simplecov-html (~> 0.5.3)
29
+ simplecov-html (0.5.3)
30
+ slop (2.4.4)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ activesupport (~> 3.2.0)
37
+ awesome_print
38
+ battery!
39
+ minitest (= 2.8.1)
40
+ mocha
41
+ pry
42
+ rake
43
+ simplecov
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2012 Piotr 'Qertoip' Włodarek
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # battery
2
+
3
+ API to your laptop's battery.
4
+
5
+ Based on the UPower tool available by default on Ubuntu and Debian distros.
6
+ Other data sources can be easilly added as plugins.
7
+
8
+ ## Example
9
+
10
+ battery = Battery.new
11
+ battery.energy_left # => 0.97 (almost fully charged)
12
+ battery.voltage # => 12.78 [V]
13
+ battery.charging? # => true
14
+ battery.vendor # => 'Panasonic'
15
+ battery.update.energy_left # => 0.96 (notice the updated value)
16
+
17
+ See the acceptance tests for the exhaustive list of examples. Don't fear to look at the code.
18
+
19
+ ## Installation
20
+
21
+ Add this to your Gemfile:
22
+
23
+ gem 'battery'
24
+
25
+ Then run:
26
+
27
+ bundle
28
+
29
+ ## Requirements
30
+
31
+ * Ruby 1.9.2
32
+
33
+ ## Running tests
34
+
35
+ Run all tests:
36
+
37
+ bundle exec rake test
38
+
39
+ Run only functional tests:
40
+
41
+ bundle exec rake test:functional
42
+
43
+ Run only acceptance tests:
44
+
45
+ bundle exec rake test:acceptance
46
+
47
+ ## License
48
+
49
+ Released under the MIT license. Copyright (C) 2012 Piotr 'Qertoip' Włodarek.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new( 'test:functional' ) do |t|
6
+ t.libs += ['test', 'lib']
7
+ t.pattern = FileList['test/functional/**/*_test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ Rake::TestTask.new( 'test:acceptance' ) do |t|
12
+ t.libs += ['test', 'lib']
13
+ t.pattern = FileList['test/acceptance/**/*_test.rb']
14
+ t.verbose = true
15
+ end
16
+
17
+ desc 'Run all tests'
18
+ task :test => ['test:functional', 'test:acceptance']
19
+
20
+ task :default => :test
data/battery.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'battery/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'battery'
7
+ s.version = Battery::VERSION
8
+ s.authors = ['Piotr \'Qertoip\' Włodarek']
9
+ s.email = ['qertoip@gmail.com']
10
+ s.homepage = 'https://github.com/qertoip/battery'
11
+ s.summary = %q{API to your laptop's battery.}
12
+ s.required_ruby_version = '>= 1.9.2'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ['lib']
18
+ end
data/d ADDED
@@ -0,0 +1 @@
1
+ bundle exec ruby test/test_console.rb
data/lib/battery.rb ADDED
@@ -0,0 +1,5 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'battery/battery'
4
+ require 'battery/version'
5
+ require 'battery/upower_data_source'
@@ -0,0 +1,37 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'forwardable'
4
+
5
+ class Battery
6
+
7
+ extend Forwardable
8
+
9
+ attr_accessor :data_source
10
+
11
+ def initialize( options = {} )
12
+ self.data_source = options[:data_source] || UPowerDataSource.new
13
+ end
14
+
15
+ def_delegators :data_source, :energy_left,
16
+ :energy_left_wh,
17
+ :max_energy_wh,
18
+ :design_max_energy_wh,
19
+ :voltage,
20
+ :charging?,
21
+ :discharging?,
22
+ :fully_charged?,
23
+ :present?,
24
+ :has_history?,
25
+ :has_stats?,
26
+ :vendor,
27
+ :model,
28
+ :serial,
29
+ :technology,
30
+ :last_update # => DateTime of the last refresh
31
+
32
+ def update
33
+ data_source.update
34
+ self
35
+ end
36
+
37
+ end
@@ -0,0 +1,115 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ class UPowerDataSource
4
+
5
+ attr_accessor :upower_command
6
+
7
+ def initialize( options = {} )
8
+ self.upower_command = options[:upower_command] || UPowerCommand.new
9
+ update
10
+ end
11
+
12
+ def vendor
13
+ fetch( 'vendor' )
14
+ end
15
+
16
+ def model
17
+ fetch( 'model' )
18
+ end
19
+
20
+ def serial
21
+ fetch( 'serial' )
22
+ end
23
+
24
+ def technology
25
+ fetch( 'technology' )
26
+ end
27
+
28
+ def last_update
29
+ fetch( 'updated', :as => DateTime )
30
+ end
31
+
32
+ def has_history?
33
+ fetch( 'has history', :as => Boolean )
34
+ end
35
+
36
+ def has_stats?
37
+ fetch( 'has statistics', :as => Boolean )
38
+ end
39
+
40
+ def present?
41
+ fetch( 'present', :as => Boolean )
42
+ end
43
+
44
+ def charging?
45
+ fetch( 'state' ) == 'charging'
46
+ end
47
+
48
+ def discharging?
49
+ fetch( 'state' ) == 'discharging'
50
+ end
51
+
52
+ def fully_charged?
53
+ fetch( 'state' ) == 'fully-charged'
54
+ end
55
+
56
+ def energy_left
57
+ fetch( 'percentage', :as => Float ) / 100.0
58
+ end
59
+
60
+ def energy_left_wh
61
+ fetch( 'energy', :as => Float )
62
+ end
63
+
64
+ def design_max_energy_wh
65
+ fetch( 'energy-full-design', :as => Float )
66
+ end
67
+
68
+ def max_energy_wh
69
+ fetch( 'energy-full', :as => Float )
70
+ end
71
+
72
+ def voltage
73
+ fetch( 'voltage', :as => Float )
74
+ end
75
+
76
+ def update
77
+ output = upower_command.exec
78
+ first_battery = output.scan( /Device:.*battery_.*\n((.|\n)+)\n(Daemon:|Device:)/ )
79
+ first_battery = first_battery.first.first rescue ''
80
+ first_battery_rows = first_battery.strip.split( /$/ ).map( &:strip ).reject{ |r| !r.include?( ':' ) }
81
+ first_battery_key_value_array = first_battery_rows.map{ |r| r.split( ':', 2 ) }.flatten.map( &:strip )
82
+ @values = Hash[*first_battery_key_value_array]
83
+ end
84
+
85
+ private
86
+
87
+ class UPowerCommand
88
+ def exec
89
+ `upower -d`
90
+ end
91
+ end
92
+
93
+ class Boolean
94
+ def self.parse( s )
95
+ return true if s == 'yes'
96
+ return false if s == 'no'
97
+ nil
98
+ end
99
+ end
100
+
101
+ def fetch( key, options = {} )
102
+ type = options[:as] || String
103
+ value = @values[key]
104
+ return nil if value.nil?
105
+ case type.name
106
+ when 'String' then value
107
+ when 'Float' then value.to_f
108
+ when 'DateTime' then DateTime.parse( value )
109
+ when 'UPowerDataSource::Boolean' then Boolean.parse( value )
110
+ when 'UPowerDataSource::Percents' then Percents.parse( value )
111
+ else raise "Unknown type #{type}"
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,5 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class Battery
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'test_helper'
4
+
5
+ class BatteryTest < ActiveSupport::TestCase
6
+
7
+ test '.works fine' do
8
+ battery = Battery.new
9
+
10
+ assert_kind_of( Float, battery.energy_left ) # => 0.97 [means 97%]
11
+ assert_kind_of( Float, battery.energy_left_wh ) # => 48.34 [Wh]
12
+
13
+ assert_kind_of( Float, battery.max_energy_wh ) # => 56.13 [Wh]
14
+ assert_kind_of( Float, battery.design_max_energy_wh ) # => 60.00 [Wh]
15
+
16
+ assert_kind_of( Float, battery.voltage ) # => 12.64 [V]
17
+
18
+ battery.charging?
19
+ battery.discharging?
20
+ battery.fully_charged?
21
+
22
+ battery.present?
23
+ battery.has_history?
24
+ battery.has_stats?
25
+
26
+ assert_kind_of( String, battery.vendor ) # => 'Panasonic'
27
+ assert_kind_of( String, battery.model ) # => '42T4793'
28
+ assert_kind_of( String, battery.serial ) # => '8651'
29
+ assert_kind_of( String, battery.technology ) # => 'lithium-ion'
30
+
31
+ assert_kind_of( DateTime, battery.last_update ) # => Sun Mar 25 18:51:10 2012
32
+
33
+ battery.update.energy_left
34
+ end
35
+
36
+ end
@@ -0,0 +1,41 @@
1
+ Device: /org/freedesktop/UPower/devices/line_power_AC
2
+ native-path: /sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:09/PNP0C09:00/ACPI0003:00/power_supply/AC
3
+ power supply: yes
4
+ updated: Sun Mar 25 15:46:05 2012 (11108 seconds ago)
5
+ has history: no
6
+ has statistics: no
7
+ line-power
8
+ online: yes
9
+
10
+ Device: /org/freedesktop/UPower/devices/battery_BAT0
11
+ native-path: /sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:09/PNP0C09:00/PNP0C0A:00/power_supply/BAT0
12
+ vendor: Panasonic
13
+ model: 42T4793
14
+ serial: 8651
15
+ power supply: yes
16
+ updated: Sun Mar 25 18:51:10 2012 (3 seconds ago)
17
+ has history: yes
18
+ has statistics: no
19
+ battery
20
+ present: yes
21
+ rechargeable: yes
22
+ state: fully-charged
23
+ energy: 49.87 Wh
24
+ energy-empty: 0 Wh
25
+ energy-full: 50.16 Wh
26
+ energy-full-design: 56.16 Wh
27
+ energy-rate: 0 W
28
+ voltage: 12.504 V
29
+ percentage: 99.4219%
30
+ capacity: 89.3162%
31
+ technology: lithium-ion
32
+
33
+ Daemon:
34
+ daemon-version: 0.9.13
35
+ can-suspend: yes
36
+ can-hibernate yes
37
+ on-battery: no
38
+ on-low-battery: no
39
+ lid-is-closed: no
40
+ lid-is-present: yes
41
+ is-docked: no
@@ -0,0 +1,105 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'test_helper'
4
+
5
+ class BatteryTest < ActiveSupport::TestCase
6
+
7
+ class UPowerCommandStub
8
+ def exec
9
+ File.read( File.dirname( __FILE__ ) + '/../fixtures/upower_output.txt' )
10
+ end
11
+ end
12
+
13
+ setup do
14
+ data_source = UPowerDataSource.new( :upower_command => UPowerCommandStub.new )
15
+ @battery = Battery.new( :data_source => data_source )
16
+ end
17
+
18
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
19
+
20
+ test '.energy_left' do
21
+ assert_equal( 0.994219, @battery.energy_left )
22
+ end
23
+
24
+ test '.energy_left_wh' do
25
+ assert_equal( 49.87, @battery.energy_left_wh )
26
+ end
27
+
28
+ test '.max_energy_wh' do
29
+ assert_equal( 50.16, @battery.max_energy_wh )
30
+ end
31
+
32
+ test '.design_max_energy_wh' do
33
+ assert_equal( 56.16, @battery.design_max_energy_wh )
34
+ end
35
+
36
+ test '.voltage' do
37
+ assert_equal( 12.504, @battery.voltage )
38
+ end
39
+
40
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
41
+
42
+ test '.discharging?' do
43
+ refute( @battery.discharging? )
44
+ end
45
+
46
+ test '.charging?' do
47
+ refute( @battery.charging? )
48
+ end
49
+
50
+ test 'fully_charged?' do
51
+ assert( @battery.fully_charged? )
52
+ end
53
+
54
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
55
+
56
+ test '.has_history?' do
57
+ assert( @battery.has_history? )
58
+ end
59
+
60
+ test '.has_stats?' do
61
+ refute( @battery.has_stats? )
62
+ end
63
+
64
+ test '.present?' do
65
+ assert( @battery.present? )
66
+ end
67
+
68
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69
+
70
+ test '.vendor' do
71
+ assert_equal( 'Panasonic', @battery.vendor )
72
+ end
73
+
74
+ test '.model' do
75
+ assert_equal( '42T4793', @battery.model )
76
+ end
77
+
78
+ test '.serial' do
79
+ assert_equal( '8651', @battery.serial )
80
+ end
81
+
82
+ test '.technology' do
83
+ assert_equal( 'lithium-ion', @battery.technology )
84
+ end
85
+
86
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
87
+
88
+ test '.last_update' do
89
+ assert_equal( DateTime.parse( 'Sun Mar 25 18:51:10 2012' ), @battery.last_update )
90
+ end
91
+
92
+ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
93
+
94
+ test '.update updates the state' do
95
+ data_source = UPowerDataSource.new( :upower_command => UPowerCommandStub.new )
96
+ battery = Battery.new( :data_source => data_source )
97
+ data_source.expects( :update )
98
+ battery.update
99
+ end
100
+
101
+ test '.update returns Battery' do
102
+ assert_kind_of( Battery, @battery.update )
103
+ end
104
+
105
+ end
@@ -0,0 +1,3 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'battery'
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ # Ensure that LOAD_PATH is the same as when running "rake test"; normally rake takes care of that
4
+ $LOAD_PATH << File.expand_path( ".", File.dirname( __FILE__ ) )
5
+ $LOAD_PATH << File.expand_path( "./lib", File.dirname( __FILE__ ) )
6
+ $LOAD_PATH << File.expand_path( "./test", File.dirname( __FILE__ ) )
7
+
8
+ # Boot the app
9
+ require_relative 'library_setup'
10
+
11
+ # Fire the console
12
+ require 'pry'
13
+ binding.pry
@@ -0,0 +1,16 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ # Load test coverage tool (must be loaded before any code)
4
+ #require 'simplecov'
5
+ #SimpleCov.start do
6
+ # add_filter '/test/'
7
+ # add_filter '/config/'
8
+ #end
9
+
10
+ # Load and initialize the application to be tested
11
+ require 'library_setup'
12
+
13
+ require 'active_support/test_case'
14
+
15
+ # Load test frameworks
16
+ require 'minitest/autorun'
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'test_helper'
4
+
5
+ # Load all tests
6
+ Dir.glob( './**/*_test.rb' ).each { |test_file| require test_file }
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: battery
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Piotr 'Qertoip' Włodarek
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-25 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email:
16
+ - qertoip@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - battery.gemspec
28
+ - d
29
+ - lib/battery.rb
30
+ - lib/battery/battery.rb
31
+ - lib/battery/upower_data_source.rb
32
+ - lib/battery/version.rb
33
+ - test/acceptance/battery_test.rb
34
+ - test/fixtures/upower_output.txt
35
+ - test/functional/battery_test.rb
36
+ - test/library_setup.rb
37
+ - test/test_console.rb
38
+ - test/test_helper.rb
39
+ - test/test_runner.rb
40
+ homepage: https://github.com/qertoip/battery
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: 1.9.2
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.11
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: API to your laptop's battery.
64
+ test_files: []