[Sugar-devel] 3G Support: show connection errors- Patch 1759

Daniel Castelo dcastelo at plan.ceibal.edu.uy
Tue May 18 15:26:44 EDT 2010


I have this ticket pending, could you give your feedback? Thanks!!!

http://bugs.sugarlabs.org/ticket/1759

This patch improves the feature 3G Support (added in 0.88).
Includes:
Show the connection errors
Apply Eben's Mockup:
http://wiki.sugarlabs.org/go/File:3G_device.png<http://wiki.sugarlabs.org/go/File:3G_device.png>


---
 extensions/deviceicon/network.py |  183
++++++++++++++++++++++++++------------
 src/jarabe/model/network.py      |   34 +++++---
 2 files changed, 148 insertions(+), 69 deletions(-)

diff --git a/extensions/deviceicon/network.py
b/extensions/deviceicon/network.py
index 94a4293..995446c 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -39,6 +39,8 @@ from sugar.graphics.tray import TrayIcon
 from sugar.graphics import xocolor
 from sugar.util import unique_id
 from sugar import profile
+from sugar.graphics.icon import Icon
+from sugar.graphics.menuitem import MenuItem

 from jarabe.model import network
 from jarabe.model.network import Settings
@@ -63,7 +65,7 @@ _GSM_STATE_NOT_READY = 0
 _GSM_STATE_DISCONNECTED = 1
 _GSM_STATE_CONNECTING = 2
 _GSM_STATE_CONNECTED = 3
-_GSM_STATE_NEED_AUTH = 4
+_GSM_STATE_FAILED = 4

 def frequency_to_channel(frequency):
     ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
@@ -214,6 +216,7 @@ class WiredPalette(Palette):
             ip_address_text = ""
         self._ip_address_label.set_text(ip_address_text)

+
 class GsmPalette(Palette):
     __gtype_name__ = 'SugarGsmPalette'

@@ -227,36 +230,48 @@ class GsmPalette(Palette):
     def __init__(self):

         Palette.__init__(self, label=_('Wireless modem'))
-
         self._current_state = None
+        self._alert = False

-        self._toggle_state_item = gtk.MenuItem('')
+        self._toggle_state_item = MenuItem('')
         self._toggle_state_item.connect('activate', self.__toggle_state_cb)
         self.menu.append(self._toggle_state_item)
         self._toggle_state_item.show()

-        self.set_state(_GSM_STATE_NOT_READY)
-
         self.info_box = gtk.VBox()
-
-        self.data_label = gtk.Label()
-        self.data_label.props.xalign = 0.0
-        label_alignment = self._add_widget_with_padding(self.data_label)
-        self.info_box.pack_start(label_alignment)
-        self.data_label.show()
+        self.connection_info_box = gtk.HBox()
+
+        icon = Icon(icon_name='data-upload', icon_size=gtk.ICON_SIZE_MENU)
+        self.connection_info_box.pack_start(icon)
+        icon.show()
+        self._data_label_up = gtk.Label()
+        self._data_label_up.props.xalign = 0.0
+        label_alignment =
self._add_widget_with_padding(self._data_label_up)
+        self.connection_info_box.pack_start(label_alignment)
+        self._data_label_up.show()
         label_alignment.show()

-        self.connection_time_label = gtk.Label()
-        self.connection_time_label.props.xalign = 0.0
-        label_alignment = self._add_widget_with_padding( \
-                self.connection_time_label)
-        self.info_box.pack_start(label_alignment)
-        self.connection_time_label.show()
+        icon = Icon(icon_name='data-download',
icon_size=gtk.ICON_SIZE_MENU)
+        self.connection_info_box.pack_start(icon)
+        icon.show()
+        self._data_label_down = gtk.Label()
+        self._data_label_down.props.xalign = 0.0
+        label_alignment =
self._add_widget_with_padding(self._data_label_down)
+        self.connection_info_box.pack_start(label_alignment)
+        self._data_label_down.show()
         label_alignment.show()
+
+        self.info_box.pack_start(self.connection_info_box)

+        self._error_accept_item = MenuItem('')
+        self._error_accept_item.connect('activate', self.__error_accept_cb)
+        self.menu.append(self._error_accept_item)
+
         self.info_box.show()
         self.set_content(self.info_box)

+        self.set_state(_GSM_STATE_NOT_READY)
+
     def _add_widget_with_padding(self, child, xalign=0, yalign=0.5):
         alignment = gtk.Alignment(xalign=xalign, yalign=yalign,
                                   xscale=1, yscale=0.33)
@@ -267,35 +282,89 @@ class GsmPalette(Palette):
         alignment.add(child)
         return alignment

-    def set_state(self, state):
+    def set_state(self, state, reason=0):
         self._current_state = state
-        self._update_label_and_text()
+        self._update_label_and_text(reason)

-    def _update_label_and_text(self):
+    def _update_label_and_text(self, reason=0):
+
         if self._current_state == _GSM_STATE_NOT_READY:
             self._toggle_state_item.get_child().set_label('...')
             self.props.secondary_text = _('Please wait...')
-
+
         elif self._current_state == _GSM_STATE_DISCONNECTED:
             self._toggle_state_item.get_child().set_label(_('Connect'))
-            self.props.secondary_text = _('Disconnected')
-
+            if not self._alert:
+                self.props.secondary_text = _('Disconnected')
+            icon = Icon(icon_name='dialog-ok', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)
+
         elif self._current_state == _GSM_STATE_CONNECTING:
             self._toggle_state_item.get_child().set_label(_('Cancel'))
             self.props.secondary_text = _('Connecting...')
+            icon = Icon(icon_name='dialog-cancel', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)

         elif self._current_state == _GSM_STATE_CONNECTED:
             self._toggle_state_item.get_child().set_label(_('Disconnect'))
-            self.props.secondary_text = _('Connected')
-
-        elif self._current_state == _GSM_STATE_NEED_AUTH:
-            self._toggle_state_item.get_child().set_label(_('Sim requires
Pin/Puk'))
-            self.props.secondary_text = _('Authentication Error')
+            self.update_connection_time()
+            icon = Icon(icon_name='media-eject', \
+                        icon_size=gtk.ICON_SIZE_MENU)
+            self._toggle_state_item.set_image(icon)
+
+        elif self._current_state == _GSM_STATE_FAILED:
+            self.add_alert(_('Connection Error'), \
+                            self._get_error_by_nm_reason(reason))

         else:
             raise ValueError('Invalid GSM state while updating label and '
\
                              'text, %s' % str(self._current_state))
-
+
+    def add_alert(self, title, message):
+        self._alert = True
+        self.props.secondary_text = title
+        self._error_accept_item.get_child().set_label(message)
+        self._error_accept_item.show()
+        self._toggle_state_item.set_sensitive(False)
+
+
+    def __error_accept_cb(self, alert):
+        self._alert = False
+        self._update_label_and_text()
+        self._error_accept_item.get_child().set_label('')
+        self._error_accept_item.hide()
+        self._toggle_state_item.set_sensitive(True)
+        self._full_request = [0, 0]
+
+    def update_connection_time(self, connection_time=None):
+        if (connection_time is not None):
+            self.props.secondary_text = _('Connected for ' + \
+                                      connection_time.strftime('%H:%M:%S'))
+        else:
+            self.props.secondary_text = _('Connected for ' \
+                                          + '00:00:00')
+
+    def update_stats(self, in_bytes, out_bytes):
+        in_KBytes = in_bytes / 1024
+        out_KBytes = out_bytes / 1024
+        self._data_label_up.set_text(_("%d KB") % (out_KBytes))
+        self._data_label_down.set_text(_("%d KB") % (in_KBytes))
+
+    def _get_error_by_nm_reason(self, reason):
+        if reason in [network.NM_DEVICE_STATE_REASON_NO_SECRETS,
network.NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED]:
+            message = _('The Pin/Puk configuration is not valid.')
+        elif reason in [network.NM_DEVICE_STATE_REASON_PPP_DISCONNECT,
network.NM_DEVICE_STATE_REASON_PPP_FAILED]:
+            message = _('Check the APN configuration.')
+        elif reason in [network.NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER]:
+            message = _('Check the tel number configuration.')
+        elif reason in [network.NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT]:
+            message = _('Time out. Check the tel configuration')
+        else:
+            message = _('Unexpected error.')
+        return message
+
     def __toggle_state_cb(self, menuitem):
         if self._current_state == _GSM_STATE_NOT_READY:
             pass
@@ -305,12 +374,10 @@ class GsmPalette(Palette):
             self.emit('gsm-disconnect')
         elif self._current_state == _GSM_STATE_CONNECTED:
             self.emit('gsm-disconnect')
-        elif self._current_state == _GSM_STATE_NEED_AUTH:
-            self.emit('gsm-disconnect')
         else:
             raise ValueError('Invalid GSM state while emitting signal, %s'
% \
                              str(self._current_state))
-
+

 class WirelessDeviceView(ToolButton):

@@ -747,6 +814,7 @@ class GsmDeviceView(TrayIcon):
                                       signal_name='PppStats',
                                       path=self._device.object_path,
                                       dbus_interface=_NM_SERIAL_IFACE)
+
     def create_palette(self):
         palette = GsmPalette()

@@ -774,6 +842,9 @@ class GsmDeviceView(TrayIcon):
                                         '/',
                                         reply_handler=self.__connect_cb,

error_handler=self.__connect_error_cb)
+        else:
+            self._palette.add_alert(_('Connection Error'), \
+                                    _('There is no gsm connection
available'))

     def __connect_cb(self, active_connection):
         logging.debug('Connected successfully to gsm device, %s',
@@ -807,15 +878,15 @@ class GsmDeviceView(TrayIcon):

     def __state_changed_cb(self, new_state, old_state, reason):
         logging.debug('State: %s to %s, reason %s', old_state, new_state,
reason)
-        self._update_state(int(new_state))
+        self._update_state(int(new_state), int(old_state), int(reason))

     def __current_state_check_cb(self, properties):
-        self._update_state(int(properties['State']))
+        self._update_state(int(properties['State']), 0, 0)

     def __current_state_check_error_cb(self, error):
         raise RuntimeError('Error when checking gsm device state, %s' %
error)

-    def _update_state(self, state):
+    def _update_state(self, state, old_state, reason):
         gsm_state = None

         if state is network.DEVICE_STATE_ACTIVATED:
@@ -823,20 +894,22 @@ class GsmDeviceView(TrayIcon):
             connection = network.find_gsm_connection()
             if connection is not None:
                 connection.set_connected()
-                self._connection_timestamp =  time.time() - \
+                self._connection_timestamp = time.time() - \
                         connection.get_settings().connection.timestamp
                 self._connection_time_handler =
gobject.timeout_add_seconds( \
                         1, self.__connection_timecount_cb)
-                self._update_stats(0, 0)
-                self._update_connection_time()
-                self._palette.info_box.show()
+                self._palette.update_connection_time()
+                self._palette.update_stats(0, 0)
+                if self._palette is not None:
+                    self._palette.connection_info_box.show()

         elif state is network.DEVICE_STATE_DISCONNECTED:
             gsm_state = _GSM_STATE_DISCONNECTED
             self._connection_timestamp = 0
             if self._connection_time_handler is not None:
                 gobject.source_remove(self._connection_time_handler)
-            self._palette.info_box.hide()
+            if self._palette is not None:
+                self._palette.connection_info_box.hide()

         elif state in [network.DEVICE_STATE_UNMANAGED,
                        network.DEVICE_STATE_UNAVAILABLE,
@@ -845,14 +918,15 @@ class GsmDeviceView(TrayIcon):

         elif state in [network.DEVICE_STATE_PREPARE,
                        network.DEVICE_STATE_CONFIG,
-                       network.DEVICE_STATE_IP_CONFIG]:
+                       network.DEVICE_STATE_IP_CONFIG,
+                       network.DEVICE_STATE_NEED_AUTH]:
             gsm_state = _GSM_STATE_CONNECTING
-
-        elif state in [network.DEVICE_STATE_NEED_AUTH]:
-            gsm_state = _GSM_STATE_NEED_AUTH
+
+        elif state == network.DEVICE_STATE_FAILED:
+            gsm_state = _GSM_STATE_FAILED

         if self._palette is not None:
-            self._palette.set_state(gsm_state)
+            self._palette.set_state(gsm_state, reason)

     def disconnect(self):
         self._bus.remove_signal_receiver(self.__state_changed_cb,
@@ -861,25 +935,17 @@ class GsmDeviceView(TrayIcon):
                                          dbus_interface=_NM_DEVICE_IFACE)

     def __ppp_stats_changed_cb(self, in_bytes, out_bytes):
-        self._update_stats(in_bytes, out_bytes)
-
-    def _update_stats(self, in_bytes, out_bytes):
-        in_KBytes = in_bytes / 1024
-        out_KBytes = out_bytes / 1024
-        text = _("Data sent %d KB / received %d KB") % (out_KBytes,
in_KBytes)
-        self._palette.data_label.set_text(text)
+        self._palette.update_stats(in_bytes, out_bytes)

     def __connection_timecount_cb(self):
         self._connection_timestamp = self._connection_timestamp + 1
-        self._update_connection_time()
+        connection_time = \
+            datetime.datetime.fromtimestamp(self._connection_timestamp)
+        self._palette.update_connection_time(connection_time)
         return True

-    def _update_connection_time(self):
-        connection_time = datetime.datetime.fromtimestamp( \
-                self._connection_timestamp)
-        text = _("Connection time ") + connection_time.strftime('%H : %M :
%S')
-        self._palette.connection_time_label.set_text(text)

+
 class WirelessDeviceObserver(object):
     def __init__(self, device, tray, device_type):
         self._device = device
@@ -950,6 +1016,7 @@ class WiredDeviceObserver(object):
                 del self._device_view
                 self._device_view = None

+
 class GsmDeviceObserver(object):
     def __init__(self, device, tray):
         self._device = device
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index 3a949da..579ed8d 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -54,6 +54,13 @@ NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0
 NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1
 NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2

+NM_DEVICE_STATE_REASON_NO_SECRETS = 7
+NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13
+NM_DEVICE_STATE_REASON_PPP_FAILED = 14
+NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25
+NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26
+NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34
+
 NM_802_11_AP_FLAGS_NONE = 0x00000000
 NM_802_11_AP_FLAGS_PRIVACY = 0x00000001

@@ -444,17 +451,22 @@ class NMSettingsConnection(dbus.service.Object):
     def GetSecrets(self, setting_name, hints, request_new, reply, error):
         logging.debug('Secrets requested for connection %s request_new=%s',
             self.path, request_new)
-        if request_new or self._secrets is None:
-            # request_new is for example the case when the pw on the AP
changes
-            response = SecretsResponse(self, reply, error)
-            try:
-                self.secrets_request.send(self, response=response)
-            except Exception:
-                logging.exception('Error requesting the secrets via
dialog')
-        else:
-            reply(self._secrets.get_dict())
-
-
+        if self._settings.connection.type is not 'gsm':
+                if request_new or self._secrets is None:
+                    # request_new is for example the case when the pw on
the AP changes
+                    response = SecretsResponse(self, reply, error)
+                    try:
+                        self.secrets_request.send(self, response=response)
+                    except Exception:
+                        logging.exception('Error requesting the secrets via
dialog')
+                else:
+                    reply(self._secrets.get_dict())
+        else:
+                if not request_new:
+                    reply(self._secrets.get_dict())
+                else:
+                    raise Exception('The stored GSM secret has already been
supplied ')
+
 class AccessPoint(gobject.GObject):
     __gsignals__ = {
         'props-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
-- 
1.6.2.5


-- 
Ing. Daniel Castelo
Plan Ceibal - Área Técnica
Avda. Italia 6201
Montevideo - Uruguay.
Tel.: 601.57.73 Interno 2228
E-mail : dcastelo at plan.ceibal.edu.uy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.sugarlabs.org/archive/sugar-devel/attachments/20100518/34dd442c/attachment-0001.htm 


More information about the Sugar-devel mailing list