Python libmm problems

Dan Williams dcbw at redhat.com
Wed Sep 13 16:57:32 UTC 2017


On Wed, 2017-09-13 at 17:23 +0100, colin.helliwell at ln-systems.com
wrote:
> I'm trying to write some python to get the operator id off the
> modem. 
> Due to limited knowledge of such things, I'm *not* using any
> notifcation
> callbacks etc, but simply trying to poll things.
> I've wrapped the functionality into a class (thinking to thus be able
> to
> easily contain the modem's objects etc in the instance).
> I poll an initial 'get modem' method:
> 
>         if self.connection is None:
>             self.connection = Gio.bus_get_sync (Gio.BusType.SYSTEM,
> None)
>         self.manager = ModemManager.Manager.new_sync
> (self.connection,
> Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START, None)
>         if self.manager is None:
>             # MM not found
>             self.connection = None
>             self.modem = None
>             self.obj = None
>             return None
>         # Search for the modem
>         for obj in self.manager.get_objects():
>             m = obj.get_modem()
>             # Look for my modem
>             if (m.get_primary_port() == "ttyS1"):
>                 self.obj = obj
>                 self.modem = m
>         return self.modem
> 
> Then, once the modem has been found by this, I go on to try to get
> the
> operator code by polling a further method:
> 
>         MccMnc  = None
>         if self.modem is not None:
>             # Return MCC/MNC if registered
>             if (self.modem.get_state() >=
> ModemManager.ModemState.REGISTERED):
>                     MccMnc =
> self.obj.get_modem_3gpp().get_operator_code()
>             else:
>                     print 'GetMccMnc', self.modem.get_state()
>         return MccMnc
> 
> What I'm seeing is that, even though mmcli shows the modem getting to
> 'connected', this function continues to just get a state of
> 'MM_MODEM_STATE_ENABLING'.
> If I (re)run the script after the modem has got connected, then it's
> working
> as expected.
> 
> I'm not sure if this in an error in my python oop, or incorrect use
> of
> libmm. Why aren't the repeated calls to get_state() seeing the change
> of
> state?

Internally all this stuff is still an event-based system listening on a
socket for data from ModemManager.  Which means you have to let that
code do some work to handle those events at some point, and the way
that happens is by letting the GLib mainloop run periodically.

What I'd suggest is to do your polling and work from a GLib timeout. 
That lets the mainloop run, and it lets your code essentially poll in a
simple way without doing callbacks and signals:

#!/usr/bin/env python
import gi
gi.require_version('ModemManager', '1.0')
from gi.repository import GLib, GObject, Gio, ModemManager
import sys, signal

main_loop = None
watcher = None

def signal_handler(data):
    main_loop.quit()

def get_modem_state(obj):
    modem = obj.get_modem()
    print "State: %s" % ModemManager.ModemState.get_string(modem.get_state())
    # Do whatever other work you need to do, as long as it doesn't take many seconds
    # True = continue running this timeout
    return True

main_loop = GLib.MainLoop()
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, signal_handler, None)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, signal_handler, None)

connection = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
manager = ModemManager.Manager.new_sync(connection,
                                        Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START,
                                        None)
modems = manager.get_objects()
if len(modems) == 0:
    print "no modems found"
    sys.exit(1)

GLib.timeout_add_seconds(5, get_modem_state, modems[0])
try:
    main_loop.run()
except KeyboardInterrupt:
    pass

Dan


More information about the ModemManager-devel mailing list