Skip to content

Instantly share code, notes, and snippets.

@znz znz/battwalker.rb
Created Oct 8, 2009

Embed
What would you like to do?
battwalker改変(中途半端でバグあり)
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
=begin
Name: battmonwalker.rb
Version: 0.41
Date: 2009-09-27
Author: moyashi <hitoriblog_NO_NO_SPAM@gmail.com>
Description: Alternate battery status indicator for SHARP NetWalker
Modified by: znz
=end
#list = [980, 962, 944, 930, 915, 903, 895, 888, 882, 868, 770]
#list = [980, 961, 942, 928, 913, 900, 892, 886, 881, 867, 770]
require 'fileutils'
require 'gtk2'
# バッテリー残量を取得するスペシャルファイル
BATTERY_SF = "/proc/battery"
# ACアダプタの接続状況を取得するスペシャルファイル
POWER_SUPPLY_SF = "/sys/class/power_supply/mc13892_charger/uevent"
# ログファイル名
BATTERY_LOG_FILE_NAME = "#{ENV['HOME']}/battwalker_log/batterylog-#{Time.now.strftime('%Y%m%d%H%M%S')}.txt"
# 更新間隔
BATTERY_REFRESH_INTERVAL = 60
# バッテリーのシャットダウン残量
BATTERY_MIN_REMAIN = 770
# バッテリーの満容量
BATTERY_MAX_REMAIN = 980
# アイコン文字色
BATTERY_ICON_STR_COLOR = "#ffffff"
# アイコン文字縁取り色
BATTERY_ICON_STR_EDGE_COLOR = "#333333"
# アイコン縁取り色
BATTERY_ICON_EDGE_COLOR = "#777777"
# アイコンの背景色
BATTERY_ICON_BG_COLOR = {
90 => 0x76ea40ff,
80 => 0x95ea40ff,
70 => 0xb4ea40ff,
60 => 0xd3ea40ff,
50 => 0xeae140ff,
40 => 0xeac140ff,
30 => 0xeaa240ff,
20 => 0xea8240ff,
10 => 0xea6340ff,
00 => 0xea4440ff,
}
# 残量情報を格納するオブジェクト
Remain = Struct.new(:icon_color_code, :raw, :milli_volt, :percent, :ac)
# バッテリー情報を取得するオブジェクト
class Battery
def initialize(min_remain=770, max_remain=980)
# NetWalkerのバッテリー放電曲線のモデル
# 数字が小さい=平坦 数字が大きい=急峻
gradient = [9, 9, 7, 7, 6, 4, 3, 2, 7, 46]
# モデルを実際のスケールに展開
expanded_gradient = gradient.map {|x|
x * ((max_remain - min_remain) / 100.0)
}
#モデルを実際の閾値に展開
@thresholds = [max_remain]
max = max_remain
expanded_gradient.each do |i|
max = max - i
@thresholds.push(max.round())
end
end
# ACアダプタに接続中か
def ac?()
if (File.readable?(POWER_SUPPLY_SF))
File.foreach(POWER_SUPPLY_SF) do |line|
if /\APOWER_SUPPLY_ONLINE=/ =~ line
return $'.to_i == 1
end
end
else
return false
end
end
# バッテリー残量情報を格納するRemainオブジェクトを返す
def remain()
if (File.readable?(BATTERY_SF))
# バラツキが大きいので、20回計測して平均を取る
raw = 0
milli_voit = 0
20.times do
File.open(BATTERY_SF, "r") do |f|
mv, rest = f.gets.split(/\D+/, 2)
milli_voit += mv.to_i
raw += rest.to_i
end
end
r = Remain.new
r.milli_volt = milli_voit / 20
r.raw = raw / 20
r.ac = ac?
ic = 0
pc = 0
(1...@thresholds.size).each do |n|
if @thresholds[n]+1 < r.raw
ic = (10-n)*10
pc = _assort(n-1, r.raw)
break
end
end
r.percent = pc
r.icon_color_code = ic
return r
end
end
# 残量のパーセンテージ変換
def _assort(s1, s2)
unit = (@thresholds[s1-1] - (@thresholds[s1] + 1)) / 10.0
return 90 - (s1 * 10) + ((s2 - (@thresholds[s1] + 1)) / unit).round
end
end
# バッテリー残量を書き出すロガー
class Logger
def initialize(logfile=BATTERY_LOG_FILE_NAME)
FileUtils.mkpath(File.dirname(logfile))
@logfile = File.open(logfile, 'a')
@logfile.sync = true
end
def write(r)
data = [
Time.now.strftime("%Y-%m-%d %H:%M:%S"),
r.raw,
r.milli_volt,
r.percent,
r.ac,
"\n"
]
@logfile.write(data.join("\t"))
end
end
# ステータスアイコン
class BattWalker < Gtk::StatusIcon
def initialize
super
@logger = Logger.new
@battery = Battery.new(BATTERY_MIN_REMAIN, BATTERY_MAX_REMAIN)
# 経過時間タイマー
@lapsed_time = 0
# アイコンクリック時に実行するメソッド
self.signal_connect('activate') do
update(false)
end
end
def timer_start
Gtk::timeout_add(1000 * 60) do
if (@battery.ac?)
@lapsed_time = 0
else
@lapsed_time += 1
end
true
end
update(true)
Gtk::timeout_add(BATTERY_REFRESH_INTERVAL * 1000) do
update(true)
true
end
end
def formatted_lapsed_time
hours = @lapsed_time / 60
minutes = @lapsed_time % 60
return "#{hours}時間#{minutes}分"
end
# アイコン更新処理
def update(logging)
# バッテリー残量取得
r = @battery.remain
icon_size = 24
# アイコン描画用のPixbufを生成
@pixbuf ||= Gdk::Pixbuf.new(Gdk::Pixbuf::ColorSpace::RGB, true, 8, icon_size, icon_size)
@pixbuf.fill!(BATTERY_ICON_BG_COLOR[r.icon_color_code])
@drawable ||= @pixbuf.render_pixmap_and_mask(alpha_threshold=127)[0]
@gc ||= Gdk::GC.new(@drawable)
@colormap ||= Gdk::Colormap.system
# アイコン枠描画
unless defined?(@icon_edge_color)
@icon_edge_color = Gdk::Color.parse(BATTERY_ICON_EDGE_COLOR)
@colormap.alloc_color(@icon_edge_color, false, true)
end
@gc.set_foreground(@icon_edge_color)
@drawable.draw_rectangle(@gc, false, 0, 0, icon_size, icon_size)
# アイコン内残量テキスト描画準備
unless defined?(@layout)
@layout = Gtk::Invisible.new.create_pango_layout()
fontdesc = Pango::FontDescription.new
fontdesc.set_family("URW Gothic L")
fontdesc.set_weight(Pango::WEIGHT_BOLD)
fontdesc.set_size(100 * 100)
@layout.alignment = Pango::ALIGN_RIGHT
@layout.font_description = fontdesc
end
@layout.text = r.ac ? "AC" : "#{r.percent}"
w, h = @layout.pixel_size()
# アイコン内テキスト黒フチ描画(座標ずらして4回描画)
unless defined?(@text_color)
@str_edge_color = Gdk::Color.parse(BATTERY_ICON_STR_EDGE_COLOR)
@colormap.alloc_color(@str_edge_color, false, true)
end
[[1, 1], [-1, 1], [1, -1], [-1, -1]].each do |a|
@drawable.draw_layout(@gc,
(icon_size-w)/2.0 + a[0],
(icon_size-h)/2.0 + a[1],
@layout, @str_edge_color)
end
# アイコン内テキスト描画
unless defined?(@str_color)
@str_color = Gdk::Color.parse(BATTERY_ICON_STR_COLOR)
@colormap.alloc_color(@str_color, false, true)
end
@drawable.draw_layout(@gc,
(icon_size - w) / 2.0,
(icon_size - h) / 2.0,
@layout, @str_color)
self.pixbuf = Gdk::Pixbuf.from_drawable(@colormap,
@drawable, 0, 0, -1, -1, nil)
# tooltip設定
per = r.ac ? "[AC接続中]" : "#{r.percent}%"
lapsed = r.ac ? "" : "\n#{formatted_lapsed_time}経過"
self.tooltip = "#{per}\n#{r.milli_volt}mV (#{r.raw})#{lapsed}"
# ログ書き込み
@logger.write(r) if logging
return true
end
end
if __FILE__ == $0
bw = BattWalker.new
bw.timer_start
Gtk.main
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.