diff --git a/solar.py b/solar.py new file mode 100644 index 00000000..e935428d --- /dev/null +++ b/solar.py @@ -0,0 +1,125 @@ +import time +import threading +import subprocess +from collections import namedtuple + +import gobject +import pygtk +pygtk.require('2.0') +import gtk + +from logitech import unifying_receiver as ur + + +KEYBOARD_NAME = 'Wireless Solar Keyboard K750' +TITLE = 'Solar [K750]' + +NOTIFY_DESKTOP = True +BLINK_ICON = 3 + +OK = 0 +NO_RECEIVER = 1 +NO_K750 = 2 +NO_STATUS = 3 + +SLEEP = (10, 30, 25, 15) +TEXT = ('K750 keyboard connected', + 'Logitech Unifying Receiver not detected', + 'K750 keyboard not detected', + 'K750 keyboard not responding') +# ICON_NAMES = ( +# 'status_good', 'status_attention', +# 'status_attention', 'status_warning' +# ) +CHARGE_LUX_TEXT = 'Charge: %d%% Lux: %d' + + +K750_Status = namedtuple('K750_Status', + ['receiver', 'device', 'status', 'charge', 'lux']) + + +def notify_desktop(status_code, text): + global NOTIFY_DESKTOP + if NOTIFY_DESKTOP: + try: + program = ('/usr/bin/notify-send', '-u', 'low', TITLE, text) + subprocess.Popen(program, close_fds=True) + except OSError: + NOTIFY_DESKTOP = False + + +def update_status_icon(status_icon, status_changed, k750): + text = TEXT[k750.status] + if k750.status == OK: + text += '\n' + (CHARGE_LUX_TEXT % (k750.charge, k750.lux)) + # print text + status_icon.set_tooltip_text(text) + + if status_changed: + notify_desktop(k750.status, text) + if BLINK_ICON: + status_icon.set_blinking(True) + time.sleep(BLINK_ICON) + status_icon.set_blinking(False) + + +def read_charge(receiver, device): + status, charge, lux = NO_RECEIVER, -1, -1 + + if receiver is None: + receiver = ur.open() + device = None + + if receiver and not device: + try: + device = ur.find_device(receiver, "keyboard", KEYBOARD_NAME) + except ur.NoReceiver: + ur.close(receiver) + receiver = None + + if receiver: + if device: + try: + charge_lux = ur.get_solar_charge(receiver, device) + if charge_lux is None: + device = None + status = NO_STATUS + else: + charge, lux = charge_lux + status = OK + except ur.NoReceiver: + ur.close(receiver) + receiver = None + else: + status = NO_K750 + + return K750_Status(receiver, device, status, charge, lux) + + +class StatusThread(threading.Thread): + def __init__(self, status_icon): + super(StatusThread, self).__init__() + self.daemon = True + self.status_icon = status_icon + + def run(self): + last_status = NO_RECEIVER + k750 = K750_Status(None, None, NO_RECEIVER, 0, 0) + + while True: + k750 = read_charge(k750.receiver, k750.device) + status_changed = k750.status != last_status + gobject.idle_add(update_status_icon, self.status_icon, status_changed, k750) + last_status = k750.status + time.sleep(SLEEP[k750.status]) + + +if __name__ == "__main__": + status_icon = gtk.status_icon_new_from_file('images/icon.png') + status_icon.set_title('Solar') + status_icon.set_tooltip_text('Initializing...') + status_icon.connect("popup_menu", gtk.main_quit) + + gobject.threads_init() + StatusThread(status_icon).start() + gtk.main()