#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GUI for battery on Neo Freerunner
# written by HdR <hdr@meetr.de>
# contributions by <haduong@centre-cired.fr>
# battery status icons made by Kore Nordmann <mail@kore-nordmann.de>
# start icon from tango icons <http://tango.freedesktop.org/Tango_Desktop_Project>
#
# ! this script comes with explicit no warranty !
# ! Trying to draw more current than the USB charger is rated for leads to overheating
# ! This is dangerous and can lead to fire
# ! Use at your own risk
#
# License: GPL version ???

import gobject,gtk
import os

class BatteryGUI:
   charger_type = "/sys/class/i2c-adapter/i2c-0/0-0073/charger_type"
   capacity =   "/sys/devices/platform/bq27000-battery.0/power_supply/bat/capacity"
   chargefull = "/sys/devices/platform/bq27000-battery.0/power_supply/bat/charge_full"
   voltage =    "/sys/devices/platform/bq27000-battery.0/power_supply/bat/voltage_now"
   current =    "/sys/devices/platform/bq27000-battery.0/power_supply/bat/current_now"
   status =     "/sys/devices/platform/bq27000-battery.0/power_supply/bat/status"
   temp =       "/sys/devices/platform/bq27000-battery.0/power_supply/bat/temp"
   timetofull = "/sys/devices/platform/bq27000-battery.0/power_supply/bat/time_to_full_now"
   timetoempty= "/sys/devices/platform/bq27000-battery.0/power_supply/bat/time_to_empty_now"
   image_dir = "/usr/share/battery/"
   usb_limit = "/sys/class/i2c-adapter/i2c-0/0-0073/force_usb_limit_dangerous"
   #charger_type = "charger_type"
   #capacity = "capacity"
   #voltage = "voltage"
   #status = "status"
   #image_dir = "./"

   def delete_event(self, widget, event=None, data=None):
      gtk.main_quit()
      return False

   # Check the amperage
   def check_type(self):
      self.f = open(self.charger_type, 'r')
      self.type = self.f.readline().rstrip('\n')
      self.f.close()

      try:
         self.charger = self.type.split(" ")[3]
      except:
         return False

      if (self.charger == '1A'):
         self.amperage = 1000;
      elif (self.charger == '500mA'):
         self.amperage = 500;
      elif (self.charger == '100mA'):
         self.amperage = 100;
      else:
         self.amperage = False;

      return (self.amperage)

   # Check battery capacity percentage now
   def check_capacity(self):
      self.f = open(self.capacity, 'r')
      self.q = self.f.readline().rstrip('\n')
      self.f.close()
      return (int(self.q))

   # Check battery full charge capacity
   def check_chargefull(self):
      self.f = open(self.chargefull, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q / 1000000;
      return (self.v)

   # Check battery voltage
   def check_voltage(self):
      self.f = open(self.voltage, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q/1000000;
      return (self.v)

   # Check battery current
   def check_current(self):
      self.f = open(self.current, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q/1000;
      return (self.v)

   # Check battery temperature
   def check_temp(self):
      self.f = open(self.temp, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q/10;
      return (self.v)

   # Check status (Charging/Discharging)
   def check_status(self):
      self.f = open(self.status, 'r')
      self.q = self.f.readline().rstrip('\n')
      self.f.close()
      return(self.q)

   # Check the time to full
   def check_timetofull(self):
      self.f = open(self.timetofull, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q/60;
      return (self.v)

   # Check the time to empty
   def check_timetoempty(self):
      self.f = open(self.timetoempty, 'r')
      self.q = float(self.f.readline().rstrip('\n'))
      self.f.close()
      self.v = self.q/60;
      return (self.v)


   # Set the load amperage manually
   def set_charge_limit(self, button, limit):
      if (self.check_type()):
         os.system("echo %d > %s" % (limit,self.usb_limit))
      return True
   
   # Update the energy left label
   def update_capacity(self, label, image):
      cap = self.check_capacity()
      capAh = self.check_chargefull() * cap / 100
      label.set_text ("Energy left: %d%%   %.2f Ah" % (cap, capAh))

      if (cap <= 5):
         image.set_from_file(self.image_dir+"battery_stat_00.png")
      elif (cap <= 20):
         image.set_from_file(self.image_dir+"battery_stat_11.png")
      elif (cap <= 38):
         image.set_from_file(self.image_dir+"battery_stat_23.png")
      elif (cap <= 56):
         image.set_from_file(self.image_dir+"battery_stat_42.png")
      elif (cap <= 85):
         image.set_from_file(self.image_dir+"battery_stat_64.png")
      else:
         image.set_from_file(self.image_dir+"battery_stat_99.png")
      return True

   ## Update the capacity label
   #def update_chargefull(self, label):
      #fullcap = self.check_chargefull()
      #label.set_text ("Full charge: %.2f Ah" % fullcap)
      #return True

   # Update the charge label
   def update_charge(self, label):
      rate = self.check_type()
      if (rate):
         label.set_text ("Battery charging: %d mA" % rate)
      else:
         label.set_text ("Battery charging: %s" % self.check_status())
      return True

   def update_temp(self, label):
      temp = self.check_temp()
      label.set_text ("Temperature: %.1f °C" % temp)
      return True

   def update_power(self, label):
      voltage = self.check_voltage()
      current = self.check_current()
      power = voltage * current
      label.set_text ("%.2f V   %.1f mA   %.0f mW" % (voltage, current, power))
      return True

   def update_timeto(self, label):
      timetofull = self.check_timetofull()
      timetoempty = self.check_timetoempty()
      if ((timetofull > 0) and (timetofull < 65535)):
         label.set_text ("Time to full: %d mn / %.1f h" % (timetofull, timetofull/60))
      elif ((timetoempty > 0) and (timetoempty < 65535)):
         label.set_text ("Autonomy: %d mn / %.1f h" % (timetoempty, timetoempty/60))
      else:
         label.set_text ("-")
      return True

   # Gtk GUI
   def __init__(self):
      # init main window
      self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
      self.win.connect("delete_event", self.delete_event)

      # add a VBox
      self.vbox = gtk.VBox(homogeneous=False, spacing=5)
      self.win.add(self.vbox)
      self.vbox.show()

      # add a HBox
      self.hbox0 = gtk.HBox()
      self.vbox.pack_start(self.hbox0)
      self.hbox0.show()

      # Add a Image
      self.stat_image = gtk.Image()
      self.stat_image.set_from_file(self.image_dir+"battery_stat_01.png")
      self.hbox0.pack_start(self.stat_image)
      self.stat_image.show()

      # Add a Vbox for info labels
      self.vbox1 = gtk.VBox()
      self.hbox0.pack_start(self.vbox1)
      self.vbox1.show()

      # Add Capacity label
      self.capacity_label = gtk.Label("Energy left: checking")
      self.vbox1.pack_start(self.capacity_label)
      self.capacity_label.show()
      gobject.timeout_add (2000, self.update_capacity, self.capacity_label, self.stat_image)

      # Add temperature label
      self.temp_label = gtk.Label("Temperature: checking")
      self.vbox1.pack_start(self.temp_label)
      self.temp_label.show()
      gobject.timeout_add (4000, self.update_temp, self.temp_label)

      # Add chargelevel label
      self.charge_label = gtk.Label("Battery charging: checking")
      self.vbox1.pack_start(self.charge_label)
      self.charge_label.show()
      gobject.timeout_add (2000, self.update_charge, self.charge_label)

      # Add timeto label
      self.timeto_label = gtk.Label("Time to: checking")
      self.vbox1.pack_start(self.timeto_label)
      self.timeto_label.show()
      gobject.timeout_add (2000, self.update_timeto, self.timeto_label)

      # Add power label
      self.power_label = gtk.Label("Power: checking")
      self.vbox1.pack_start(self.power_label)
      self.power_label.show()
      gobject.timeout_add (2000, self.update_power, self.power_label)

      ## Add Full charge label
      #self.chargefull_label = gtk.Label("Full charge: checking")
      #self.vbox1.pack_start(self.chargefull_label)
      #self.chargefull_label.show()
      #gobject.timeout_add (10000, self.update_chargefull, self.chargefull_label)

      # Add HBox for buttons
      self.hbox1 = gtk.HBox(homogeneous=False, spacing=5)
      self.vbox.pack_start(self.hbox1)
      self.hbox1.show()

      # Add button for 100mA
      self.button_100 = gtk.Button("Charge at\n100mA")
      self.hbox1.pack_start(self.button_100)
      self.button_100.connect("clicked", self.set_charge_limit, 100)
      self.button_100.show()

      # Add button for 500mA
      self.button_500 = gtk.Button("Charge at\n500mA")
      self.hbox1.pack_start(self.button_500)
      self.button_500.connect("clicked", self.set_charge_limit, 500)
      self.button_500.show()

      # add button for 1000mA
      self.button_1000 = gtk.Button("Charge at\n1000mA")
      self.hbox1.pack_start(self.button_1000)
      self.button_1000.connect("clicked", self.set_charge_limit, 1000)
      self.button_1000.show()

      # add exit button
      self.button_exit = gtk.Button("Close")
      self.vbox.pack_start(self.button_exit)
      self.button_exit.connect("clicked", self.delete_event)
      self.button_exit.show()

      # show main window
      self.win.show()
   
   def main(self):
      gtk.main()

if __name__ == '__main__':
   gui = BatteryGUI()
   gui.main()
