battery 1.0.0

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/.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: []