Linux, GSM, nmcli - working with two GSM Modems and connections

3

I have a following situation.

I have two USB modems (one Huwawei LTE modem, one ZTE 3G modem) with two different SIM cards from two different providers (orange and play to be specific).

Using Network Manager I want to create two connections and bind each connection to a specific device. However this connections seem to use only one modem (listed as /dev/cdc-wdm0) which is binded to ZTE device if both of them are connected at the same time. I also have two devices that probably are symlinks to some /dev/ttyUSB devices - /dev/gsmmodem and /dev/gsmmodem2.

What I would like to achieve is following situation:

  1. Connection A - modem Huwawei LTE, provider Orange, name orange_primary bringing it up by running nmcli con up orange_primary. If it fails, nmcli call fails.

  2. Connection B - modem ZTE 3G, provider Play, name play_backup, brining it up by running nmcli con up play_backup. If it fails, nmcli call fails.

What i have now:

Both connecitions use ZTE 3G modem, listed as /dev/cdc-wdm0, this modem has a Play Sim Card in, however when i call nmcli con up orange, it still conects via this modem / simcard / provider, as i believe the APN names and access numbers are the same for both.

I am using nmcli 0.9.10.0 on Debian 8 (Jessie).

Paweł Sopel

Posted 2017-07-10T13:58:15.527

Reputation: 61

Answers

3

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.

Paweł Sopel

Posted 2017-07-10T13:58:15.527

Reputation: 61

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

3

There are a shell script (based on the nmcli command) posted on this blogpost. it is very simple :

Connect the first modem then run:

nmcli -p con

Replace the UUID and the connection name on the shell script , let's say orange.sh , make it executable chmod +x orange.sh

To start the connection:

orange.sh start

to check the status:

orange.sh status

to stop the connection:

orange.sh stop

Follow the same steps to create a new script for the second Modem.

This is the shell script including the source:

# SCRIPT BEBINGS FROM HERE
#!/bin/bash

# Source: http://aithinking.wordpress.com/2012/06/13/startingstopping-mobile-broadband-services-in-linux/
# To get the connection name (id) and connection uuid, execute the following command
# nmcli -p con
# Replace defaultConnection and defaultConnectionsUUID with your own settings

defaultConnection=”Dialog GSM Postpaid”
defaultConnectionsUUID=daad515c-b1e7-4a5c-a139-669a1d28304a

interval=2

case “$1” in

start)

echo “Starting the mobile broadband connection: ” $defaultConnection ” (UUID – ” $defaultConnectionsUUID “)”
while true; do

LC_ALL=C nmcli -t -f TYPE,STATE dev | grep -q “^gsm:disconnected$”

if [ $? -eq 0 ]; then

echo “Device Found: ” $defaultConnection
break
else
echo “Device is not found. Retrying in ” $interval ” seconds.”
sleep $interval

fi

done
echo “Starting Wireless WAN”
nmcli -t nm wwan on
echo “Connecting ” $defaultConnection
nmcli -t con up uuid $defaultConnectionsUUID
echo “Successfully Connected”

;;

stop)

echo “Stopping the mobile broadband connection: ” $defaultConnection ” (UUID – ” $defaultConnectionsUUID “)”
nmcli -t con down uuid $defaultConnectionsUUID
echo “Stopping Wireless WAN”
nmcli -t nm wwan off
echo “Successfully Disconnected”

;;
status)

LC_ALL=C nmcli -t -f TYPE,STATE dev | grep -q “^gsm:disconnected$”
if [ $? -eq 0 ]; then
echo “Device not found or GSM disconnected”
else
echo “GSM Connected”
fi

;;
*)

echo “Mobile Broadband Startup Service”
echo $”Usage: $0 {start|stop|status}”
echo “”
echo “IMPORTANT!”
echo “Edit this script to replace the values for defaultConnection and defaultConnectionsUUID with your gsm connection details”
echo “We found the following Connections list (ONLY GSM TYPE) for your system”
echo ==================================
echo Connection list
echo ==================================
echo ID UUID TYPE
echo ———————————-
nmcli -p -f NAME,UUID,TYPE con | grep gsm
exit 1

esac
exit 0

# SCRIPT ENDS HERE

GAD3R

Posted 2017-07-10T13:58:15.527

Reputation: 2 677

Thank you a lot. I will check this for sure today and let you know if it works! – Paweł Sopel – 2017-07-11T08:08:54.477

Unfortuantely this script, altought very useful does not solve my primary problem of assigning connections to physical devices. I have figured out how to solve it and I will post a solution soon. – Paweł Sopel – 2017-07-11T13:49:45.207