Battery Widget for Linux (Pure Lua)

From awesome
Jump to: navigation, search

by Fredrik Ax <mailto:frax@axnet.nu>

This widget is written entirely in LUA for awesome 3.2.

It depends on Linux ACPI_BATTERY, ACPI_SYSFS_POWER and SYSFS ("/sys/class/power_supply/BAT[0-N]/*").

It provides a textbox widget that shows your current battery status (or "No Bat" if not available) in percent and an estimation of how long until fully (dis)charged

When clicked, it simply updates it self.

The widget must be defined before it is added to the wibox where it is going to be used. So using the mywibox as defined in the default rc.lua the code should be inserted before the loop (for s = 1, screen.count() do) containing the statement starting with:

mywibox[s].widgets = {

This is the code to be inserted:

-- Create fraxbat widget
fraxbat = widget({ type = "textbox", name = "fraxbat", align = "right" })
fraxbat.text = 'fraxbat';

-- Globals used by fraxbat
fraxbat_st= nil
fraxbat_ts= nil
fraxbat_ch= nil
fraxbat_now = nil
fraxbat_est= nil

-- Function for updating fraxbat
function hook_fraxbat (tbw, bat)
   -- Battery Present?
   local fh= io.open("/sys/class/power_supply/"..bat.."/present", "r")
   if fh == nil then
      tbw.text="No Bat"
      return(nil)
   end
   local stat= fh:read()
   fh:close()
   if tonumber(stat) < 1 then
      tbw.text="Bat Not Present"
      return(nil)
   end

   -- Status (Charging, Full or Discharging)
   fh= io.open("/sys/class/power_supply/"..bat.."/status", "r")
   if fh == nil then
      tbw.text="N/S"
      return(nil)
   end
   stat= fh:read()
   fh:close()
   if stat == 'Full' then
      tbw.text="100%"
      return(nil)
   end
   stat= string.upper(string.sub(stat, 1, 1))
   if stat == 'D' then tag= 'i' else tag= 'b' end

   -- Remaining + Estimated (Dis)Charging Time
   local charge= 
   fh= io.open("/sys/class/power_supply/"..bat.."/charge_full_design", "r")
   if fh ~= nil then
      local full= fh:read()
      fh:close()
      full= tonumber(full)
      if full ~= nil then
        fh= io.open("/sys/class/power_supply/"..bat.."/charge_now", "r")
        if fh ~= nil then
           local now= fh:read()
           local est= 
           fh:close()
           if fraxbat_st == stat then
              delta= os.difftime(os.time(),fraxbat_ts)
              est= math.abs(fraxbat_ch - now)
              if delta > 30 and est > 0 then
                 est= delta/est
                 if now == fraxbat_now then
                    est= fraxbat_est
                 else
                    fraxbat_est= est
                    fraxbat_now= now
                 end
                 if stat == 'D' then
                    est= now*est
                 else
                    est= (full-now)*est
                 end
                 local h= math.floor(est/3600)
                 est= est - h*3600
                 est= string.format(',%02d:%02d',h,math.floor(est/60))
              else
                 est= 
              end
           else
              fraxbat_st= stat
              fraxbat_ts= os.time()
              fraxbat_ch= now
              fraxbat_now= nil
              fraxbat_est= nil
           end
           charge=':<'..tag..'>'..tostring(math.ceil((100*now)/full))..'%</'..tag..'>'..est
        end
      end
   end
   tbw.text= stat..charge
end

Optional mouse button bindings for fraxbat (replace 'BAT0' with whatever you use)

fraxbat.buttons(fraxbat,{ button({ }, 1, function () hook_fraxbat(fraxbat,'BAT0') end),
                         button({ }, 2, function () hook_fraxbat(fraxbat,'BAT0') end),
                         button({ }, 3, function () hook_fraxbat(fraxbat,'BAT0') end) })

Don't forget to make the widget visible, e.g. by adding it to the mywibox as defined by the default rc.lua, look for the line starting with

mywibox[s].widgets = {

and insert "fraxbat," into the list of widgets.

Finally you need to register a timer that keeps the widget updated.

To update it every 10:th second add the following at the end of your rc.lua (replace 'BAT0' with whatever tou use):

awful.hooks.timer.register(10, function () hook_fraxbat(fraxbat,'BAT0') end)
Personal tools