Hücresel Bağlantı
TEKNİK REHBER HÜCRESEL BAĞLANTI QMI / MBIM 2026

QMI & MBIM
düşük seviye modem.

Qualcomm QMI protokolü, libqmi/qmicli araçları, Microsoft MBIM standardı ve libmbim — data session yönetimi ve Python ile modem kontrolü.

00 QMI protokol mimarisi — Qualcomm Modem Interface

QMI (Qualcomm MSM Interface), Qualcomm MDM yongasetlerinde kullanılan tescilli bir protokoldür. AT komutlarına göre çok daha hızlı ve zengin API sunar.

  QMI Protokol Yığını
  ──────────────────────────────────────────────────
  Uygulama (qmicli, libqmi, Python)
        ↓  libqmi userspace kütüphanesi
  QMI servisler:
        ├── WDS  (Wireless Data Service)  → data oturumları
        ├── NAS  (Network Access Service) → ağ durumu, sinyal
        ├── DMS  (Device Management Svc) → cihaz bilgisi
        ├── UIM  (User Identity Module)   → SIM yönetimi
        ├── WMS  (Wireless Messaging)     → SMS
        ├── LOC  (Location Service)       → GPS/GNSS
        └── PDC  (Platform Device Config) → firmware
        ↓  /dev/cdc-wdm0  (cdc_wdm kernel driver)
  USB cihaz   →  Qualcomm MDM modem
        ↓  USB vendor-specific interface
  Modem RF yığını   (EC25, RM500Q, Sierra EM7455...)
    

QMI vs AT karşılaştırması

Özellik AT Komutları QMI
Protokol türü ASCII metin Binary TLV (Type-Length-Value)
Hız Düşük (serialize) Yüksek (asenkron)
Çoklu istemci Hayır (tek port) Evet (çok istemci)
Hata yönetimi OK/ERROR Detaylı hata kodları
Standartlaşma ITU V.250 (standart) Qualcomm tescilli
Kernel driver option, cdc-acm qmi_wwan
bash — QMI cihaz tespiti
# USB cihazı gör
lsusb
# Bus 001 Device 003: ID 2c7c:0125 Quectel EC25

# qmi_wwan driver yüklü mü?
lsmod | grep qmi
# qmi_wwan              28672  0
# cdc_wdm               20480  1 qmi_wwan

# Driver yükle (gerekirse)
modprobe qmi_wwan
modprobe cdc_wdm

# QMI kontrol cihazı
ls /dev/cdc-wdm*
# /dev/cdc-wdm0

# wwan0 ağ arayüzü
ip link show wwan0
# 4: wwan0: <BROADCAST,MULTICAST,NOARP> mtu 1500 ...

# USB interface numarası ile eşleşme
ls -la /sys/class/net/wwan0/device/
cat /sys/class/net/wwan0/device/uevent
# DRIVER=qmi_wwan
# PRODUCT=2c7c/125/0

01 libqmi kurulum ve qmicli temel kullanımı

libqmi, QMI protokolünü implement eden açık kaynak kütüphanedir. qmicli, libqmi'yi kullanan komut satırı aracıdır.

bash — libqmi kurulum
# Debian / Ubuntu
apt-get install libqmi-utils

# Versiyon kontrol
qmicli --version
# qmicli 1.34.0

# Cihaz bilgisi al (DMS)
qmicli -d /dev/cdc-wdm0 --dms-get-ids
# [/dev/cdc-wdm0] Device IDs retrieved:
#         ESN: '0'
#        IMEI: '867729040000001'
#        MEID: '0'

# Üretici bilgisi
qmicli -d /dev/cdc-wdm0 --dms-get-manufacturer
# [/dev/cdc-wdm0] Device manufacturer retrieved:
#       Manufacturer: 'Quectel'

# Model ve revision
qmicli -d /dev/cdc-wdm0 --dms-get-model
qmicli -d /dev/cdc-wdm0 --dms-get-revision

# QMI modem state
qmicli -d /dev/cdc-wdm0 --dms-get-operating-mode
# [/dev/cdc-wdm0] Operating mode retrieved:
#     Mode: 'online'

# Raw IP modu ayarla (wwan0 için gerekli)
qmicli -d /dev/cdc-wdm0 --wda-set-data-format=raw-ip
ip link set wwan0 arp off
ip link set wwan0 up

02 WDS servisi — data session yönetimi

WDS (Wireless Data Service), QMI'nin veri oturumlarını yöneten servisidir. Bağlantı kurma, kesme ve durum sorgulama burada gerçekleşir.

bash — WDS ile data bağlantısı
# WDS paket servisi durumu sorgula
qmicli -d /dev/cdc-wdm0 --wds-get-packet-service-status
# [/dev/cdc-wdm0] Packet service status retrieved:
#     Connection status: 'disconnected'

# Data bağlantısı kur (APN ile)
qmicli -d /dev/cdc-wdm0 \
  --wds-start-network="apn=internet,ip-type=4" \
  --client-no-release-cid
# [/dev/cdc-wdm0] Network started
#     Packet data handle: '2249109920'
# [/dev/cdc-wdm0] Client ID not released:
#     Service: 'wds'
#     CID: '19'

# ÖNEMLİ: handle ve CID değerlerini kaydet
HANDLE=2249109920
CID=19

# Bağlantı durumunu sorgula
qmicli -d /dev/cdc-wdm0 --wds-get-packet-service-status
# Connection status: 'connected'

# IP ayarlarını al
qmicli -d /dev/cdc-wdm0 --wds-get-current-settings
# [/dev/cdc-wdm0] Current settings retrieved:
#         IP Family: IPv4
#         IP Address: 100.65.45.123
#            Prefix: 30
#           Gateway: 100.65.45.124
#       Primary DNS: 8.8.8.8
#     Secondary DNS: 8.8.4.4

# IP adresini wwan0'a ata
ip addr add 100.65.45.123/30 dev wwan0
ip route add default via 100.65.45.124 dev wwan0
echo "nameserver 8.8.8.8" > /etc/resolv.conf

# Bağlantıyı kes
qmicli -d /dev/cdc-wdm0 \
  --wds-stop-network=$HANDLE \
  --client-cid=$CID

# Veri istatistikleri
qmicli -d /dev/cdc-wdm0 --wds-get-data-bearer-technology
qmicli -d /dev/cdc-wdm0 --wds-get-packet-statistics

Tam bağlantı script'i

bash — qmi-connect.sh
#!/bin/bash
# QMI ile tam LTE bağlantı scripti
DEVICE=/dev/cdc-wdm0
IFACE=wwan0
APN="${1:-internet}"

log() { logger -t qmi-connect "$*"; echo "$*"; }

# Raw IP modu
log "Raw IP modu ayarlanıyor..."
qmicli -d $DEVICE --wda-set-data-format=raw-ip
ip link set $IFACE arp off
ip link set $IFACE up

# Data session başlat
log "Data session başlatılıyor (APN=$APN)..."
OUTPUT=$(qmicli -d $DEVICE \
  --wds-start-network="apn=$APN,ip-type=4" \
  --client-no-release-cid 2>&1)

HANDLE=$(echo "$OUTPUT" | grep -oP 'handle: '\''\K[0-9]+')
CID=$(echo "$OUTPUT" | grep -oP 'CID: '\''\K[0-9]+')

if [ -z "$HANDLE" ]; then
    log "HATA: Bağlantı kurulamadı"
    echo "$OUTPUT"
    exit 1
fi

log "Bağlantı kuruldu. Handle=$HANDLE, CID=$CID"

# IP ayarlarını al ve uygula
SETTINGS=$(qmicli -d $DEVICE --wds-get-current-settings 2>&1)
IP=$(echo "$SETTINGS"   | grep -oP 'IP Address: \K[\d.]+')
GW=$(echo "$SETTINGS"   | grep -oP 'Gateway: \K[\d.]+')
DNS=$(echo "$SETTINGS"  | grep -oP 'Primary DNS: \K[\d.]+')

log "IP=$IP GW=$GW DNS=$DNS"

ip addr flush dev $IFACE
ip addr add "$IP/30" dev $IFACE
ip route add default via "$GW" dev $IFACE metric 100
echo "nameserver $DNS" > /etc/resolv.conf

# Handle ve CID'yi kaydet (disconnect için)
echo "$HANDLE $CID" > /run/qmi-session

log "LTE bağlantısı hazır: $IP"

03 NAS servisi — network durumu ve sinyal

NAS (Network Access Service), ağ kayıt durumu, operatör seçimi ve sinyal ölçümlerini sağlar. AT+CREG ve AT+CSQ'nun QMI karşılığıdır.

bash — NAS sorgular
# Sinyal gücü ölç
qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength
# [/dev/cdc-wdm0] Successfully got signal strength
#     Current:
#         Network 'lte': '-71 dBm'
#     RSSI:
#         Network 'lte': '-71 dBm'
#     ECIO:
#         Network 'lte': '0.0 dBm'
#     SNR:
#         Network 'lte': '22.8 dB'
#     IO: '-106 dBm'

# Sinyal detayları (RSRP, RSRQ)
qmicli -d /dev/cdc-wdm0 --nas-get-signal-info
# [/dev/cdc-wdm0] Successfully got signal info
#     LTE:
#         RSSI: '-71 dBm'
#         RSRQ: '-11 dB'
#         RSRP: '-93 dBm'
#          SNR: '22.8 dB'

# Network kayıt durumu
qmicli -d /dev/cdc-wdm0 --nas-get-serving-system
# [/dev/cdc-wdm0] Got serving system:
#     Registration state: 'registered'
#      CS: 'attached'  PS: 'attached'
#      MCC: '286'  MNC: '01'  (Turkcell)
#      Roaming: no

# LTE cell bilgisi
qmicli -d /dev/cdc-wdm0 --nas-get-cell-location-info
# [/dev/cdc-wdm0] Got cell location info
#     Intrafrequency LTE Info:
#         UE In Idle: 'no'
#         PLMN: '28601'
#         Tracking Area Code: '0x0B13'
#         Global Cell ID: '0x021A4D01'
#         EUTRA Absolute RF Channel Number: 1750
#         Serving Cell ID: 123
#         Cell Reselection Priority: 4
#         Non-intrafrequency threshold: -10
#         Threshold serving low: -10

# Desteklenen bandlar
qmicli -d /dev/cdc-wdm0 --nas-get-rf-band-info
# [/dev/cdc-wdm0] Got RF band info
#         Radio Interface: 'lte'
#                   Band: 'eutran-3'
#     Active Bandwidth: '20'

# Operatör tarama
qmicli -d /dev/cdc-wdm0 --nas-network-scan
# (bu işlem uzun sürebilir, ~30s)

04 DMS servisi — cihaz bilgisi ve firmware

DMS (Device Management Service), modem kimliği, donanım bilgisi, pil durumu ve firmware güncelleme işlemlerini kapsar.

bash — DMS sorgular
# Tüm cihaz bilgisi
qmicli -d /dev/cdc-wdm0 --dms-get-ids
qmicli -d /dev/cdc-wdm0 --dms-get-manufacturer
qmicli -d /dev/cdc-wdm0 --dms-get-model
qmicli -d /dev/cdc-wdm0 --dms-get-revision

# Donanım versiyonu
qmicli -d /dev/cdc-wdm0 --dms-get-hardware-revision
# [/dev/cdc-wdm0] Hardware revision retrieved:
#     Revision: '10000'

# Çalışma modu
qmicli -d /dev/cdc-wdm0 --dms-get-operating-mode
# Mode: 'online'
# HW restricted: 'no'

# Çevrimdışı moda geç (RF kapat)
qmicli -d /dev/cdc-wdm0 --dms-set-operating-mode=offline

# Online moda dön
qmicli -d /dev/cdc-wdm0 --dms-set-operating-mode=online

# Modem sıfırla
qmicli -d /dev/cdc-wdm0 --dms-set-operating-mode=reset

# Desteklenen bandlar
qmicli -d /dev/cdc-wdm0 --dms-get-band-capabilities

# UIM (SIM) slot bilgisi
qmicli -d /dev/cdc-wdm0 --uim-get-card-status
# [/dev/cdc-wdm0] Successfully got card status
#     Slot [1]:
#         Card state: 'present'
#          UPIN state: 'unblocked'
#          UPIN retries: '3'
#          UPUK retries: '10'
#         Application [1]:
#             Type: 'usim'
#             State: 'ready'
#             Personalization state: 'ready'
#             UPIN replaces PIN1: 'no'
#             PIN1 state: 'disabled'

05 MBIM protokolü — Microsoft USB modem standardı

MBIM (Mobile Broadband Interface Model), USB IF tarafından standartlaştırılmış modem protokolüdür. Qualcomm, Sierra, Telit ve diğer üreticiler destekler.

  MBIM Protokol Yığını
  ──────────────────────────────────────────────────
  Uygulama (mbimcli, libmbim, NetworkManager)
        ↓  libmbim userspace kütüphanesi
  MBIM komutlar:
        ├── MBIM_CID_DEVICE_CAPS     → cihaz bilgisi
        ├── MBIM_CID_SUBSCRIBER_READY → SIM durumu
        ├── MBIM_CID_REGISTER_STATE  → ağ kaydı
        ├── MBIM_CID_SIGNAL_STATE    → sinyal gücü
        ├── MBIM_CID_CONNECT         → data bağlantısı
        ├── MBIM_CID_IP_CONFIGURATION → IP ayarları
        └── MBIM_CID_SMS_*           → SMS
        ↓  /dev/cdc-wdm0 (cdc_mbim kernel driver)
  USB CDC NCM/MBIM arayüzüModem   (Sierra EM7455, Telit FN980, Quectel EM120R)
    
bash — MBIM driver tespiti
# cdc_mbim driver yüklü mü?
lsmod | grep mbim
# cdc_mbim               28672  0
# cdc_wdm                20480  1 cdc_mbim

# MBIM kontrol cihazı
ls /dev/cdc-wdm*
# /dev/cdc-wdm0

# wwan0 ağ arayüzü (MBIM için de aynı)
ip link show wwan0

# QMI mi MBIM mi? USB descriptor'a bak
lsusb -v -d 2c7c:0125 | grep -A3 "bInterfaceSubClass"
# bInterfaceSubClass  14 = MBIM
# bInterfaceSubClass  255 = QMI (vendor specific)

06 libmbim ve mbimcli kullanımı

libmbim ve mbimcli, MBIM modemlerini yönetmek için kullanılır. qmicli'ye benzer sözdizimi sunar.

bash — mbimcli temel kullanım
# Kurulum
apt-get install libmbim-utils

# Versiyon
mbimcli --version
# mbimcli 1.28.0

# Cihaz bilgisi
mbimcli -d /dev/cdc-wdm0 --query-device-caps
# [/dev/cdc-wdm0] Device capabilities retrieved:
#               Device type: 'embedded'
#             Cellular class: 'gsm'
#             Voice class: 'no-voice'
#               SIM class: 'removable'
#           Data class: 'lte'
#                 SMS caps: 'pdu-send, pdu-receive'
#                 Control caps: 'reg-manual'
#             Max sessions: '4'
#           Custom data class: ''
#                   Dev ID: '867729040000001'
#              Firmware info: 'EC25EFAR06A12M4G'
#              Hardware info: ''

# SIM durumu
mbimcli -d /dev/cdc-wdm0 --query-subscriber-ready-status
# Ready state: 'initialized'
#     IMSI: '286011234567890'
#     ICCID: '89901012345678901234'
#     Subscriber ID: '286011234567890'

# Ağ kayıt durumu
mbimcli -d /dev/cdc-wdm0 --query-register-state
# Register state: 'home'
#       Network error: 'unknown'
#      Available data class: 'lte'
#       Current cellular class: 'gsm'
#       Provider ID: '28601'
#       Provider name: 'Turkcell'
#       Roaming text: ''

# Sinyal gücü
mbimcli -d /dev/cdc-wdm0 --query-signal-state
# Signal: '71' (0-100 arası, 100 en iyi)

# Data bağlantısı kur
mbimcli -d /dev/cdc-wdm0 \
  --connect="apn='internet',ip-type=ipv4" \
  --no-open --no-close
# [/dev/cdc-wdm0] Successfully connected
#       Session ID: '0'
#      Activation state: 'activated'
#         IP type: 'ipv4'

# IP konfigürasyonu al
mbimcli -d /dev/cdc-wdm0 --query-ip-configuration=0
# IPv4 configuration:
#       Method: 'static'
#      Address: '100.65.45.123'
#       Prefix: '30'
#      Gateway: '100.65.45.124'
#          DNS: '8.8.8.8'

# Bağlantıyı kes
mbimcli -d /dev/cdc-wdm0 --disconnect=0

07 Raw data session — wwan0 üzerinden trafik

QMI veya MBIM ile data session kurduktan sonra wwan0 arayüzünü ağa hazır hale getirme — raw IP modu ve routing.

bash — wwan0 hazırlık ve routing
# 1. Raw IP modu (QMI için zorunlu)
qmicli -d /dev/cdc-wdm0 --wda-set-data-format=raw-ip
ip link set wwan0 arp off
ip link set wwan0 mtu 1500
ip link set wwan0 up

# 2. Data session başlat ve IP al
qmicli -d /dev/cdc-wdm0 \
  --wds-start-network="apn=internet,ip-type=4" \
  --client-no-release-cid
# Packet data handle: '2249109920'

# 3. IP ayarlarını uygula
IP="100.65.45.123"
GW="100.65.45.124"
ip addr add ${IP}/30 dev wwan0
ip route add default via $GW dev wwan0 metric 100

# 4. DNS ayarla
echo "nameserver 8.8.8.8" > /etc/resolv.conf

# 5. Bağlantı testi
ping -c 3 -I wwan0 8.8.8.8
# PING 8.8.8.8 (8.8.8.8): 56 data bytes
# 64 bytes from 8.8.8.8: icmp_seq=0 ttl=56 time=28.4 ms

# 6. İstatistikler
ip -s link show wwan0
cat /sys/class/net/wwan0/statistics/rx_bytes
cat /sys/class/net/wwan0/statistics/tx_bytes

# 7. DHCP ile otomatik IP (udhcpc)
# Bazı modemler DHCP'yi de destekler
udhcpc -i wwan0 -n -q -t 10

# 8. Bağlantıyı kes
qmicli -d /dev/cdc-wdm0 \
  --wds-stop-network=2249109920 \
  --client-cid=19
ip addr flush dev wwan0
ip link set wwan0 down
RAW IP

QMI data session'ı raw IP kullanır — Ethernet frame yok, ARP yok. ip link set wwan0 arp off zorunludur. MBIM bazı durumlarda NCM (Ethernet frame) kullanabilir, bu durumda ARP gerekir.

08 Practical — Python libqmi binding ile modem yönetimi

qmicli'yi subprocess ile çağırarak Python'da modem yönetimi — JSON benzeri ayrıştırma ve tam data session yönetimi.

python — qmi_manager.py
#!/usr/bin/env python3
"""
QMI modem yöneticisi — qmicli subprocess wrapper.
Gereksinimler: libqmi-utils, Python 3.8+
"""
import subprocess
import re
import time
import logging
import ipaddress

log = logging.getLogger('QMIManager')
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s [%(levelname)s] %(message)s')


class QMIManager:
    def __init__(self, device='/dev/cdc-wdm0', iface='wwan0'):
        self.device = device
        self.iface = iface
        self._session_handle = None
        self._client_cid = None

    def _run(self, *args, timeout=30):
        cmd = ['qmicli', '-d', self.device] + list(args)
        try:
            r = subprocess.run(cmd, capture_output=True, text=True,
                               timeout=timeout)
            return r.stdout + r.stderr
        except subprocess.TimeoutExpired:
            log.error(f"Zaman aşımı: {' '.join(args)}")
            return ''

    def _parse_field(self, text, pattern):
        m = re.search(pattern, text)
        return m.group(1).strip() if m else None

    # ── Cihaz bilgisi ─────────────────────────────────────
    def get_device_info(self):
        out = self._run('--dms-get-ids')
        out += self._run('--dms-get-manufacturer')
        out += self._run('--dms-get-model')
        out += self._run('--dms-get-revision')
        return {
            'imei':         self._parse_field(out, r"IMEI: '([^']+)'"),
            'manufacturer': self._parse_field(out, r"Manufacturer: '([^']+)'"),
            'model':        self._parse_field(out, r"Model: '([^']+)'"),
            'revision':     self._parse_field(out, r"Revision: '([^']+)'"),
        }

    # ── Sinyal ────────────────────────────────────────────
    def get_signal(self):
        out = self._run('--nas-get-signal-info')
        return {
            'rssi': self._parse_field(out, r"RSSI: '(-?\d+ dBm)'"),
            'rsrq': self._parse_field(out, r"RSRQ: '(-?\d+ dB)'"),
            'rsrp': self._parse_field(out, r"RSRP: '(-?\d+ dBm)'"),
            'sinr': self._parse_field(out, r"SNR: '(-?[\d.]+ dB)'"),
        }

    # ── Ağ kayıt ──────────────────────────────────────────
    def get_registration(self):
        out = self._run('--nas-get-serving-system')
        state = self._parse_field(out, r"Registration state: '([^']+)'")
        plmn  = self._parse_field(out, r"MNC: '(\d+)'")
        return {
            'state':      state,
            'registered': state == 'registered',
            'roaming':    'roaming' in (out.lower()),
            'plmn':       plmn,
        }

    def wait_registered(self, timeout=120):
        log.info("LTE ağına kayıt bekleniyor...")
        start = time.time()
        while time.time() - start < timeout:
            reg = self.get_registration()
            if reg['registered']:
                log.info(f"Kayıt OK {'(roaming)' if reg['roaming'] else '(ev ağı)'}")
                return True
            time.sleep(4)
        return False

    # ── Data session ──────────────────────────────────────
    def setup_raw_ip(self):
        log.info("Raw IP modu ayarlanıyor...")
        self._run('--wda-set-data-format=raw-ip')
        subprocess.run(['ip', 'link', 'set', self.iface, 'arp', 'off'])
        subprocess.run(['ip', 'link', 'set', self.iface, 'mtu', '1500'])
        subprocess.run(['ip', 'link', 'set', self.iface, 'up'])

    def start_data_session(self, apn='internet'):
        log.info(f"Data session başlatılıyor (APN={apn})...")
        out = self._run(
            f'--wds-start-network=apn={apn},ip-type=4',
            '--client-no-release-cid',
            timeout=60
        )
        self._session_handle = self._parse_field(
            out, r"Packet data handle: '(\d+)'"
        )
        self._client_cid = self._parse_field(
            out, r"CID: '(\d+)'"
        )
        if self._session_handle:
            log.info(f"Session: handle={self._session_handle}, CID={self._client_cid}")
            return True
        log.error(f"Session başlatılamadı: {out}")
        return False

    def get_ip_settings(self):
        out = self._run('--wds-get-current-settings')
        return {
            'ip':  self._parse_field(out, r"IP Address: ([\d.]+)"),
            'gw':  self._parse_field(out, r"Gateway: ([\d.]+)"),
            'dns': self._parse_field(out, r"Primary DNS: ([\d.]+)"),
            'prefix': self._parse_field(out, r"Prefix: (\d+)"),
        }

    def apply_ip_settings(self, settings):
        ip, gw, dns = settings['ip'], settings['gw'], settings['dns']
        prefix = settings.get('prefix', '30')
        log.info(f"IP uygulanıyor: {ip}/{prefix} gw={gw}")
        subprocess.run(['ip', 'addr', 'flush', 'dev', self.iface])
        subprocess.run(['ip', 'addr', 'add', f'{ip}/{prefix}', 'dev', self.iface])
        subprocess.run(['ip', 'route', 'add', 'default', 'via', gw,
                        'dev', self.iface, 'metric', '100'])
        with open('/etc/resolv.conf', 'w') as f:
            f.write(f'nameserver {dns}\n')

    def stop_data_session(self):
        if not self._session_handle:
            return
        log.info("Data session durduruluyor...")
        self._run(
            f'--wds-stop-network={self._session_handle}',
            f'--client-cid={self._client_cid}'
        )
        subprocess.run(['ip', 'addr', 'flush', 'dev', self.iface])
        subprocess.run(['ip', 'link', 'set', self.iface, 'down'])
        self._session_handle = None
        self._client_cid = None

    # ── Tam bağlantı ──────────────────────────────────────
    def connect(self, apn='internet'):
        info = self.get_device_info()
        log.info(f"Modem: {info.get('manufacturer')} {info.get('model')}")
        log.info(f"IMEI : {info.get('imei')}")

        self.setup_raw_ip()

        if not self.wait_registered():
            log.error("Ağ kaydı başarısız")
            return False

        if not self.start_data_session(apn):
            return False

        time.sleep(2)
        settings = self.get_ip_settings()
        if settings['ip']:
            self.apply_ip_settings(settings)
            log.info(f"Bağlantı hazır: {settings['ip']}")
            return True
        return False


def main():
    qmi = QMIManager(device='/dev/cdc-wdm0', iface='wwan0')

    if qmi.connect(apn='internet'):
        sig = qmi.get_signal()
        log.info(f"Sinyal: {sig}")

        # 60 saniye bekle, sonra kes
        log.info("60s aktif, sonra bağlantı kesilecek...")
        time.sleep(60)
        qmi.stop_data_session()
    else:
        log.error("Bağlantı kurulamadı")


if __name__ == '__main__':
    main()
GI-QMI (Python binding)

Doğrudan libqmi Python binding için python3-qmi paketi bazı dağıtımlarda mevcuttur. GObject Introspection üzerinden çalışır. subprocess wrapper yaklaşımı ise hiçbir ek bağımlılık gerektirmez ve production'da daha güvenilirdir.