OK, I have solved the problem by digging in nmcli and mmcli docs with a use of python.
So basically, USB modem connections in nmcli are not by default binded to a specific device, as the port (i.e. /dev/ttyUSB29) can change anytime the machine is restarted or the device is plugged out and in again.
It is possible to create such binding by running:
nmcli con modify 'conn name' connection.interface-name 'device port'
In my case it may be:
nmcli con modify orange_primary connection.interface-name ttyUSB23
But it would work only if the desired modem is indeed available via /dev/ttyUSB23
However, there is a tool called mmcli (Modem Manager Client, not to confuse with nmcli), that allows to figure out which device is connected to which virtual port at any given moment. To list all connected modems one can simply call:
mmcli -L
Which will return list of all currently connected modems with their numbers.
To get all the details about the modem, it's current status, including the port it is available on, one may call:
mmcli -m modem_number
Where modem number is the number of the modem returned by the previous command.
By using grep, regular expressions, mmcli and nmcli it is possible to precisly determine the port the modem is connected to and bind it to the NetworkManager connection. Below you can find a simple python script (i suck at bash, sorry) that does the job.
import re
from os import popen as extern
modems_to_conns = {
'[QUALCOMM INCORPORATED] 0': 'orange_primary',
'[ZTE INCORPORATED] MF626' : 'play_backup'
}
output = extern('mmcli -L').read().split('\n')[2:-2]
output = [x.replace('\t/org/freedesktop/ModemManager1/Modem/','') for x in output]
modems = []
for line in output:
currentModem = {}
currentModem['no'] = line.split(' ')[0]
currentModem['name'] = line.replace(currentModem['no'] + ' ','')
port = extern('mmcli -m {0} | grep \'primary port\''.format(currentModem['no'])).read().replace('\n','')
port = re.findall('\'[^\']*\'',port)[0].replace('\'','')
currentModem['port'] = port
currentModem['connection'] = modems_to_conns[currentModem['name']]
modems.append(currentModem)
for modem in modems:
print "Assigning connection {0} to /dev/{1} ({2})".format(
modem['connection'],
modem['port'],
modem['name']
)
extern("nmcli con modify id '{0}' connection.interface-name {1}".format(
modem['connection'],
modem['port']
))
To adjust the script for your current situation just modify the modems_to_conns to map modem names as returned by mmcli to your nmcli connection names and run this script everytime you want to establish one of the connections.
That's beautiful work, and Python scripts are so much nicer than Bash. Have you tried the "sh" library? Even better. "from sh import mmcli, nmcli, grep, awk, ifconfig, sudo, bake". Find the Mobile Network Code (MNC), for instance: "mnc = awk(grep(mmcli('-m', '0', '--location-get'), 'Mobile network code'), '{ print $NF }').rstrip("\r\n")" – Sean McCarthy – 2019-12-08T21:23:15.947