Created
October 8, 2009 00:06
-
-
Save znz/204569 to your computer and use it in GitHub Desktop.
battwalker改変(中途半端でバグあり)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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