#!/usr/bin/python

import re

import gobject
import gtk
import serial
import egg.trayicon

class Monitor(gobject.GObject):
    __metaclass__ = gobject.GObjectMeta

    __gproperties__ = {
        'signal_strength': (
            gobject.TYPE_FLOAT, 'signal strength', 'Signal Strength', 0, 1, 0,
            gobject.PARAM_READWRITE),
        'operator': (
            gobject.TYPE_STRING, 'operator', 'Operator', '',
            gobject.PARAM_READWRITE),
        }

    def __init__(self, port='/dev/ttyUSB2', speed=460800):
        gobject.GObject.__init__(self)
        self.ser = serial.Serial(port, speed, timeout=1)
        gobject.io_add_watch(self.ser.fileno(),
            gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP, self._readable)

    def command(self, command):
        self.ser.write(command + '\r\n')

    def request_strength(self):
        self.command('AT+CSQ')

    def request_registration(self):
        pass

    def request_operator(self):
        self.command('AT+COPS?')

    def _readline(self):
        line = self.ser.readline().strip()

        if line == 'OK':
            return

        if line.startswith('AT+'):
            return

        match = re.match('\+CSQ: (\d+)', line)

        if match:
            strength = int(match.group(1))
            self.set_property('signal_strength', strength / 31.0)
            return

        if line == '+COPS: 0':
            self.set_property('operator', None)
            return

        match = re.match('\+COPS: \d,\d,"([^"]+)",\d', line)

        if match:
            operator = match.group(1)
            self.set_property('operator', operator)
            return

        if line:
            print `line`

    def _readable(self, source, condition):
        self._readline()
        return True

    def do_get_property(self, property):
        if property.name == 'signal-strength':
            return self.signal_strength
        elif property.name == 'operator':
            return self.operator
        else:
            raise AttributeError(property.name)

    def do_set_property(self, property, value):
        if property.name == 'signal-strength':
            self.signal_strength = value
        elif property.name == 'operator':
            self.operator = value
        else:
            raise AttributeError(property.name)

def cb_signal_strength(obj, property, label):
    strength = obj.get_property('signal-strength')
    label.set_text('%d%%' % int(strength * 100))

def cb_operator(obj, property, tooltips, eb):
    operator = obj.get_property('operator')
    tooltips.set_tip(eb, operator)

def cb_timeout(monitor):
    monitor.request_strength()
    return True

if __name__ == '__main__':
    t = egg.trayicon.TrayIcon("Signal strength")

    eb = gtk.EventBox()
    label = gtk.Label('')

    eb.add(label)
    t.add(eb)
    t.show_all()

    if t.get_property('orientation') == gtk.ORIENTATION_VERTICAL:
        label.set_angle(90)

    tooltips = gtk.Tooltips()
    tooltips.enable()

    monitor = Monitor()
    monitor.connect('notify::signal-strength', cb_signal_strength, label)
    monitor.connect('notify::operator', cb_operator, tooltips, eb)
    monitor.request_strength()
    monitor.request_operator()
    gobject.timeout_add(3000, cb_timeout, monitor)

    try:
        gtk.main()
    except KeyboardInterrupt:
        pass

