Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Schampijer <simon@schampijer.de>2010-08-24 17:49:31 (GMT)
committer Simon Schampijer <simon@schampijer.de>2010-08-24 17:49:31 (GMT)
commitbcebef6fb02f20f1ac456cbc43c7ab3062f2d962 (patch)
tree5285f67cc0317f3443c7d0981f556ec6b76a7ae1
parenta75cc77e2276674b4ed623695cd6d7aa823c0d37 (diff)
GSM: show connection errors #1759 (Daniel Castelo)
-rw-r--r--extensions/deviceicon/network.py179
-rw-r--r--src/jarabe/model/network.py166
2 files changed, 281 insertions, 64 deletions
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index 6171f39..0789f9c 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -66,7 +66,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
class WirelessPalette(Palette):
@@ -214,34 +214,53 @@ class GsmPalette(Palette):
Palette.__init__(self, label=_('Wireless modem'))
self._current_state = None
+ self._failed_connection = 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.error_title_label = gtk.Label("")
+ self.error_title_label.set_alignment(0, 0.5)
+ self.error_title_label.set_line_wrap(True)
+ self.info_box.pack_start(self.error_title_label)
+ self.error_description_label = gtk.Label("")
+ self.error_description_label.set_alignment(0, 0.5)
+ self.error_description_label.set_line_wrap(True)
+ self.info_box.pack_start(self.error_description_label)
+
+ 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.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)
@@ -252,31 +271,41 @@ class GsmPalette(Palette):
alignment.add(child)
return alignment
- def set_state(self, state):
+ def update_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'))
+ if not self._failed_connection:
+ self._toggle_state_item.get_child().set_label(_('Connect'))
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._failed_connection = False
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:
+ message_error = self._get_error_by_nm_reason(reason)
+ self.add_alert(message_error[0], message_error[1])
else:
raise ValueError('Invalid GSM state while updating label and ' \
'text, %s' % str(self._current_state))
@@ -285,17 +314,60 @@ class GsmPalette(Palette):
if self._current_state == _GSM_STATE_NOT_READY:
pass
elif self._current_state == _GSM_STATE_DISCONNECTED:
+ self.error_title_label.hide()
+ self.error_description_label.hide()
self.emit('gsm-connect')
elif self._current_state == _GSM_STATE_CONNECTING:
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))
+ def add_alert(self, error, suggestion):
+ self._failed_connection = True
+ self._toggle_state_item.get_child().set_label(_('Try connection again'))
+
+ title = _('Error: %s') % error
+ self.error_title_label.set_markup('<b>%s</b>' % title)
+ self.error_title_label.show()
+
+ message = _('Suggestion: %s') % suggestion
+ self.error_description_label.set_text(message)
+ self.error_description_label.show()
+
+ def update_connection_time(self, connection_time=None):
+ if connection_time is not None:
+ self.props.secondary_text = _('Connected for %s') % \
+ connection_time.strftime('%H:%M:%S')
+ else:
+ self.props.secondary_text = _('Connected for %s') % '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 = _('Check your Pin/Puk configuration.')
+ elif reason in [network.NM_DEVICE_STATE_REASON_PPP_DISCONNECT,
+ network.NM_DEVICE_STATE_REASON_PPP_FAILED]:
+ message = _('Check your Access Point Name ' \
+ '(APN) configuration')
+ elif reason in [network.NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER,
+ network.NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT]:
+ message = _('Check the Number configuration.')
+ elif reason == network.NM_DEVICE_STATE_REASON_CONFIG_FAILED:
+ message = _('Check your configuration.')
+ else:
+ message = ''
+ message_tuple = (network.get_error_by_reason(reason), message)
+ return message_tuple
+
class WirelessDeviceView(ToolButton):
@@ -704,6 +776,10 @@ class GsmDeviceView(TrayIcon):
'/',
reply_handler=self.__connect_cb,
error_handler=self.__connect_error_cb)
+ else:
+ self._palette.add_alert(_('No GSM connection available.'), \
+ _('Create a connection in the ' \
+ 'control panel.'))
def __connect_cb(self, active_connection):
logging.debug('Connected successfully to gsm device, %s',
@@ -736,16 +812,17 @@ class GsmDeviceView(TrayIcon):
raise RuntimeError('Error when disconnecting gsm device, %s' % error)
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))
+ logging.debug('State: %s to %s, reason %s', old_state,
+ new_state, reason)
+ 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:
@@ -753,20 +830,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,
@@ -775,14 +854,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.update_state(gsm_state, reason)
def disconnect(self):
self._bus.remove_signal_receiver(self.__state_changed_cb,
@@ -791,24 +871,15 @@ 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):
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index cd0d46e..66d86d8 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -18,6 +18,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+from gettext import gettext as _
import logging
import os
import time
@@ -55,6 +56,49 @@ NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0
NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1
NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2
+
+NM_DEVICE_STATE_REASON_UNKNOWN = 0
+NM_DEVICE_STATE_REASON_NONE = 1
+NM_DEVICE_STATE_REASON_NOW_MANAGED = 2
+NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3
+NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4
+NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE = 5
+NM_DEVICE_STATE_REASON_CONFIG_EXPIRED = 6
+NM_DEVICE_STATE_REASON_NO_SECRETS = 7
+NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8
+NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9
+NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10
+NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11
+NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12
+NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13
+NM_DEVICE_STATE_REASON_PPP_FAILED = 14
+NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15
+NM_DEVICE_STATE_REASON_DHCP_ERROR = 16
+NM_DEVICE_STATE_REASON_DHCP_FAILED = 17
+NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18
+NM_DEVICE_STATE_REASON_SHARED_FAILED = 19
+NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20
+NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21
+NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22
+NM_DEVICE_STATE_REASON_MODEM_BUSY = 23
+NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24
+NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25
+NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26
+NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27
+NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28
+NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32
+NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33
+NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34
+NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35
+NM_DEVICE_STATE_REASON_REMOVED = 36
+NM_DEVICE_STATE_REASON_SLEEPING = 37
+NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38
+NM_DEVICE_STATE_REASON_USER_REQUESTED = 39
+NM_DEVICE_STATE_REASON_CARRIER = 40
+
NM_802_11_AP_FLAGS_NONE = 0x00000000
NM_802_11_AP_FLAGS_PRIVACY = 0x00000001
@@ -100,6 +144,103 @@ GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk'
_nm_settings = None
_conn_counter = 0
+_nm_device_state_reason_description = None
+
+def get_error_by_reason(reason):
+ global _nm_device_state_reason_description
+
+ if _nm_device_state_reason_description is None:
+ _nm_device_state_reason_description = {
+ NM_DEVICE_STATE_REASON_UNKNOWN: \
+ _("The reason for the device state change \ is unknown."),
+ NM_DEVICE_STATE_REASON_NONE: \
+ _("The state change is normal."),
+ NM_DEVICE_STATE_REASON_NOW_MANAGED: \
+ _("The device is now managed."),
+ NM_DEVICE_STATE_REASON_NOW_UNMANAGED: \
+ _("The device is no longer managed."),
+ NM_DEVICE_STATE_REASON_CONFIG_FAILED: \
+ _("The device could not be readied for configuration."),
+ NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE : \
+ _("IP configuration could not be reserved " \
+ "(no available address, timeout, etc)."),
+ NM_DEVICE_STATE_REASON_CONFIG_EXPIRED : \
+ _("The IP configuration is no longer valid."),
+ NM_DEVICE_STATE_REASON_NO_SECRETS : \
+ _("Secrets were required, but not provided."),
+ NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT : \
+ _("The 802.1X supplicant disconnected from "\
+ "the access point or authentication server."),
+ NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED : \
+ _("Configuration of the 802.1X supplicant failed."),
+ NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED : \
+ _("The 802.1X supplicant quit or failed unexpectedly."),
+ NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : \
+ _("The 802.1X supplicant took too long to authenticate."),
+ NM_DEVICE_STATE_REASON_PPP_START_FAILED : \
+ _("The PPP service failed to start within the allowed time."),
+ NM_DEVICE_STATE_REASON_PPP_DISCONNECT : \
+ _("The PPP service disconnected unexpectedly."),
+ NM_DEVICE_STATE_REASON_PPP_FAILED : \
+ _("The PPP service quit or failed unexpectedly."),
+ NM_DEVICE_STATE_REASON_DHCP_START_FAILED : \
+ _("The DHCP service failed to start within the allowed time."),
+ NM_DEVICE_STATE_REASON_DHCP_ERROR : \
+ _("The DHCP service reported an unexpected error."),
+ NM_DEVICE_STATE_REASON_DHCP_FAILED : \
+ _("The DHCP service quit or failed unexpectedly."),
+ NM_DEVICE_STATE_REASON_SHARED_START_FAILED : \
+ _("The shared connection service failed to start."),
+ NM_DEVICE_STATE_REASON_SHARED_FAILED : \
+ _("The shared connection service quit or " \
+ "failed unexpectedly."),
+ NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED : \
+ _("The AutoIP service failed to start."),
+ NM_DEVICE_STATE_REASON_AUTOIP_ERROR : \
+ _("The AutoIP service reported an unexpected error."),
+ NM_DEVICE_STATE_REASON_AUTOIP_FAILED : \
+ _("The AutoIP service quit or failed unexpectedly."),
+ NM_DEVICE_STATE_REASON_MODEM_BUSY : \
+ _("Dialing failed because the line was busy."),
+ NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE : \
+ _("Dialing failed because there was no dial tone."),
+ NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER : \
+ _("Dialing failed because there was no carrier."),
+ NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT : \
+ _("Dialing timed out."),
+ NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED : \
+ _("Dialing failed."),
+ NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED : \
+ _("Modem initialization failed."),
+ NM_DEVICE_STATE_REASON_GSM_APN_FAILED : \
+ _("Failed to select the specified GSM APN."),
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING : \
+ _("Not searching for networks."),
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED : \
+ _("Network registration was denied."),
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT : \
+ _("Network registration timed out."),
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED : \
+ _("Failed to register with the requested GSM network."),
+ NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED : \
+ _("PIN check failed."),
+ NM_DEVICE_STATE_REASON_FIRMWARE_MISSING : \
+ _("Necessary firmware for the device may be missing."),
+ NM_DEVICE_STATE_REASON_REMOVED : \
+ _("The device was removed."),
+ NM_DEVICE_STATE_REASON_SLEEPING : \
+ _("NetworkManager went to sleep."),
+ NM_DEVICE_STATE_REASON_CONNECTION_REMOVED : \
+ _("The device's active connection was removed " \
+ "or disappeared."),
+ NM_DEVICE_STATE_REASON_USER_REQUESTED : \
+ _("A user or client requested the disconnection."),
+ NM_DEVICE_STATE_REASON_CARRIER : \
+ _("The device's carrier/link changed.")}
+
+ return _nm_device_state_reason_description[reason]
+
+
def frequency_to_channel(frequency):
"""Returns the channel matching a given radio channel frequency. If a
@@ -480,17 +621,22 @@ class NMSettingsConnection(dbus.service.Object):
in_signature='sasb', out_signature='a{sa{sv}}')
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')
+ self.path, request_new)
+ if self._settings.connection.type is not NM_CONNECTION_TYPE_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:
- reply(self._secrets.get_dict())
-
+ 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__ = {