Hücresel Bağlantı
TEKNİK REHBER HÜCRESEL BAĞLANTI AT KOMUTLARI 2026

Modem Temelleri
AT komutları.

ITU V.250 standardından SIM yönetimine, APN konfigürasyonundan SMS'e — GSM/LTE modemleri Python ile kontrol etmenin tam rehberi.

00 AT komutları standardı — ITU V.250

AT komutları (Hayes komut seti), 1981'de Hayes Communications tarafından geliştirilmiş ve ITU-T V.250 ile standardize edilmiştir. Bugün tüm GSM/LTE/5G modemlerin temel kontrol arayüzüdür.

  AT Komut Mimarisi
  ────────────────────────────────────────────────
  Uygulama (Python, C, bash)
        ↓  UART / USB ACM / USB Serial
  /dev/ttyUSB0  veya  /dev/ttyACM0
        ↓  AT komutları (ASCII metin)
  Modem AT işlemcisi   (EC25, SIM7600, RM500Q)
        ↓
  Cellular RF yığını   (LTE, NB-IoT, 5G NR)
    

AT komut formatı

FORMAT

Her AT komutu AT ile başlar ve \r\n (CR+LF) ile biter. Komutlar büyük/küçük harf duyarsızdır. Yanıt her zaman OK veya ERROR ile biter.

Komut türü
Sözdizimi
Açıklama
Test
AT+CMD=?
Desteklenen parametre aralığını sorgula
Okuma
AT+CMD?
Mevcut değeri oku
Yazma
AT+CMD=<val>
Değer ata
Eylem
AT+CMD
Komutu çalıştır
bash — AT komut test (minicom)
# Modem cihazını bul
ls /dev/ttyUSB* /dev/ttyACM*
# /dev/ttyUSB1  /dev/ttyUSB2  /dev/ttyUSB3

# minicom ile bağlan (Ctrl+A Q ile çık)
minicom -D /dev/ttyUSB2 -b 115200

# Ya da screen
screen /dev/ttyUSB2 115200

# Python ile hızlı test
python3 -c "
import serial, time
s = serial.Serial('/dev/ttyUSB2', 115200, timeout=2)
s.write(b'AT\r\n')
time.sleep(0.2)
print(s.read(s.in_waiting).decode())
s.close()
"
# OK

01 Temel AT komutları — ATI, AT+CIMI, AT+CSQ, AT+COPS

Her LTE/5G modemin desteklediği temel AT komutları — cihaz bilgisi, SIM IMSI, sinyal gücü ve operatör seçimi.

AT — cihaz ve ağ bilgisi
# ATI — üretici ve model bilgisi
ATI
# Quectel
# EC25EFAR06A12M4G
# Revision: EC25EFAR06A12M4G
# OK

# AT+CGMI — üretici adı
AT+CGMI
# Quectel
# OK

# AT+CGMM — model adı
AT+CGMM
# EC25
# OK

# AT+CGSN — IMEI numarası
AT+CGSN
# 867729040000001
# OK

# AT+CIMI — SIM IMSI numarası
AT+CIMI
# 286011234567890
# OK

# AT+CCID — SIM ICCID (kart seri no)
AT+CCID
# +CCID: 89901012345678901234
# OK

# AT+CSQ — sinyal kalitesi (RSSI)
AT+CSQ
# +CSQ: 23,0
# 23 → -83 dBm (0–31 arası, 99=bilinmiyor)
# 0 → BER (0-7 arası, 99=bilinmiyor)
# OK

# AT+COPS — operatör bilgisi (mevcut)
AT+COPS?
# +COPS: 0,0,"Turkcell",7
# 0=otomatik, 0=uzun alfanümerik, "Turkcell", 7=LTE
# OK

# AT+COPS=? — mevcut operatörleri tara
AT+COPS=?
# +COPS: (2,"Turkcell","TKCL","28601",7),
#        (3,"Vodafone TR","VODTR","28602",7),
#        (3,"Turk Telekom","TRKCEL","28603",7)
# OK

# AT+COPS=1,2,"28601",7 — manuel operatör seç
AT+COPS=1,2,"28601",7
# OK

Sinyal kalitesi dönüşüm tablosu

AT+CSQ değeri
dBm (RSSI)
Kalite
0
≤ −113 dBm
Yok / çok zayıf
1
−111 dBm
Yok
2–9
−109 → −95 dBm
Zayıf
10–14
−93 → −83 dBm
Orta
15–19
−81 → −73 dBm
İyi
20–30
−71 → −53 dBm
Mükemmel
31
≥ −51 dBm
Maksimum
99
Bilinmiyor
Sinyal yok

02 PPP vs QMI vs MBIM — veri bağlantısı karşılaştırması

LTE modem ile Linux arasında veri bağlantısı kurmanın üç farklı yöntemi vardır. Her birinin avantaj ve dezavantajları vardır.

Özellik PPP QMI MBIM
Protokol türü Seri hat protokolü Qualcomm özel Microsoft standart
Hız Düşük (CPU yükü) Yüksek (native) Yüksek (native)
Kernel arayüzü ppp0 wwan0 / rmnet wwan0
Linux driver ppp, pppd qmi_wwan cdc_mbim
Userspace lib pppd libqmi libmbim
ModemManager Desteklenir Tam destek Tam destek
Embedded uygunluğu Yeterli Mükemmel İyi
Yonga seti Tüm modemler Qualcomm MDM Qualcomm + diğerleri

PPP bağlantı kurma

bash — pppd ile LTE bağlantısı
# /etc/ppp/peers/lte dosyası
cat /etc/ppp/peers/lte
# /dev/ttyUSB2
# 115200
# connect '/usr/sbin/chat -v -f /etc/chatscripts/gprs'
# noauth
# defaultroute
# usepeerdns
# persist
# noipdefault

# /etc/chatscripts/gprs
cat /etc/chatscripts/gprs
# ABORT BUSY ABORT ERROR ABORT 'NO CARRIER'
# '' ATZ
# OK 'AT+CGDCONT=1,"IP","internet"'
# OK ATD*99#
# CONNECT ''

# PPP bağlantısını başlat
pppd call lte
# ppp0 arayüzü oluşturulur, IP atanır
ifconfig ppp0
# ppp0: flags=4305  mtu 1500
#        inet 100.65.12.45  P-t-P:10.64.64.64
#        TX bytes:1234 RX bytes:5678

03 SIM yönetimi — AT+CPIN, AT+CLCK, PIN/PUK

SIM kart durumu sorgulama, PIN/PUK girişi ve SIM kilidi yönetimi — embedded sistemlerde SIM otomasyonu için kritik komutlar.

AT — SIM durum ve PIN yönetimi
# AT+CPIN — SIM PIN durumu sorgula
AT+CPIN?
# +CPIN: READY          → SIM hazır, PIN gerekmez
# +CPIN: SIM PIN        → PIN bekleniyor
# +CPIN: SIM PUK        → PUK bekleniyor (3 yanlış PIN)
# +CPIN: SIM PIN2       → PIN2 gerekli
# OK

# PIN gir (SIM PIN durumundayken)
AT+CPIN="1234"
# OK

# PUK ve yeni PIN gir (SIM PUK durumundayken)
AT+CPIN="12345678","1234"
# OK

# AT+CLCK — SIM kilidi sorgula/değiştir
# AT+CLCK="SC",2 → PIN kilidi durumunu sorgula
AT+CLCK="SC",2
# +CLCK: 1   → PIN kilidi aktif
# OK

# PIN kilidini kapat
AT+CLCK="SC",0,"1234"
# OK

# PIN kilidini aç
AT+CLCK="SC",1,"1234"
# OK

# AT+CPWD — PIN değiştir
AT+CPWD="SC","1234","5678"
# OK (eski PIN: 1234, yeni PIN: 5678)

# AT+CIMI — SIM'in IMSI numarasını oku
AT+CIMI
# 286011234567890
# OK

# AT+QSIMSTAT — SIM fiziksel durum (Quectel)
AT+QSIMSTAT?
# +QSIMSTAT: 0,1   → 0=otomatik rapor kapalı, 1=SIM takılı
# OK
DİKKAT

Yanlış PIN girişinin 3 denemesi sonucu SIM PUK durumuna girer. PUK'un da 10 yanlış girişi SIM kartı kalıcı olarak kilitler. Embedded sistemlerde PIN denemelerini sayın.

Python ile PIN yönetimi

python — sim_manager.py
import serial
import time

class ModemAT:
    def __init__(self, port='/dev/ttyUSB2', baudrate=115200):
        self.ser = serial.Serial(port, baudrate, timeout=3)
        time.sleep(0.5)

    def send(self, cmd, wait=1.0):
        self.ser.write((cmd + '\r\n').encode())
        time.sleep(wait)
        resp = self.ser.read(self.ser.in_waiting).decode(errors='replace')
        return resp.strip()

    def check_sim(self):
        resp = self.send('AT+CPIN?')
        if 'READY' in resp:
            return 'ready'
        elif 'SIM PIN' in resp:
            return 'pin_required'
        elif 'SIM PUK' in resp:
            return 'puk_required'
        return 'unknown'

    def enter_pin(self, pin):
        resp = self.send(f'AT+CPIN="{pin}"', wait=2.0)
        return 'OK' in resp

    def enter_puk(self, puk, new_pin):
        resp = self.send(f'AT+CPIN="{puk}","{new_pin}"', wait=2.0)
        return 'OK' in resp

    def close(self):
        self.ser.close()


def main():
    modem = ModemAT('/dev/ttyUSB2')
    status = modem.check_sim()
    print(f"SIM durumu: {status}")

    if status == 'pin_required':
        if modem.enter_pin('1234'):
            print("PIN kabul edildi")
        else:
            print("PIN reddedildi!")

    elif status == 'puk_required':
        print("PUK gerekiyor, dikkatli olun!")
        if modem.enter_puk('12345678', '1234'):
            print("PUK kabul edildi, yeni PIN ayarlandı")

    elif status == 'ready':
        resp = modem.send('AT+CIMI')
        imsi = [l for l in resp.split('\n') if l.strip().isdigit()]
        print(f"IMSI: {imsi[0].strip() if imsi else 'okunamadı'}")

    modem.close()

if __name__ == '__main__':
    main()

04 APN konfigürasyonu — AT+CGDCONT, bağlantı kurma

APN (Access Point Name), modem ile operatörün veri ağı arasındaki bağlantı noktasıdır. Doğru APN olmadan data bağlantısı kurulamaz.

AT — APN konfigürasyonu
# AT+CGDCONT — PDP context tanımla
# Sözdizimi: AT+CGDCONT=<cid>,<pdp_type>,<apn>

# Mevcut PDP context'leri listele
AT+CGDCONT?
# +CGDCONT: 1,"IP","super","",0,0
# OK

# APN ayarla (Turkcell için)
AT+CGDCONT=1,"IP","internet"
# OK

# IPv4/IPv6 dual-stack APN
AT+CGDCONT=1,"IPV4V6","internet"
# OK

# AT+CGACT — PDP context'i aktive et
AT+CGACT=1,1
# OK

# PDP context durumunu sorgula
AT+CGACT?
# +CGACT: 1,1    → context 1 aktif
# OK

# AT+CGPADDR — atanan IP adresini sorgula
AT+CGPADDR=1
# +CGPADDR: 1,"100.65.45.123"
# OK

# Quectel — AT+QICSGP ile APN yönetimi
AT+QICSGP=1,1,"internet","","",1
# 1=context id, 1=IPv4, "internet"=APN
# ""=kullanıcı, ""=şifre, 1=PAP/CHAP
# OK

# SIM7600 — AT+CGSOCKCONT ile APN
AT+CGSOCKCONT=1,"IP","internet"
# OK
Operatör
APN
Notlar
Turkcell
internet
Standart data
Vodafone TR
internet
Standart data
Türk Telekom
mgb
Standart data
Twilio
super
IoT SIM
1NCE
iot.1nce.net
NB-IoT/LTE-M
AWS IoT
Operatöre göre değişir
Private APN

05 Network registration — AT+CREG, AT+CEREG

GSM/GPRS kayıt durumu için AT+CREG, LTE/4G kayıt durumu için AT+CEREG kullanılır. NB-IoT için AT+CEREG özellikle önemlidir.

AT — network kayıt sorgulaması
# AT+CREG — GSM/GPRS kayıt durumu
AT+CREG?
# +CREG: 0,1
# 0=bildirim kapalı, 1=kayıtlı (ev ağı)
# Durum değerleri:
# 0 = Kayıtsız, aramıyor
# 1 = Kayıtlı, ev ağı
# 2 = Kayıtsız, arıyor
# 3 = Kayıt reddedildi
# 4 = Bilinmiyor
# 5 = Kayıtlı, roaming
# OK

# AT+CEREG — LTE/EPS kayıt durumu
AT+CEREG?
# +CEREG: 0,1
# OK

# Detaylı kayıt bilgisi (TAC, CI)
AT+CEREG=2
AT+CEREG?
# +CEREG: 2,1,"0B13","021A4D01",7
# 2=detaylı mod, 1=kayıtlı, "0B13"=TAC, "021A4D01"=CI, 7=LTE
# OK

# AT+QNWINFO — ağ bilgisi (Quectel)
AT+QNWINFO
# +QNWINFO: "FDD LTE","28601","LTE BAND 3",1750
# OK

# AT+QENG — serving cell bilgisi (Quectel)
AT+QENG="servingcell"
# +QENG: "servingcell","NOCONN","LTE","FDD",286,01,021A4D01,
#   123,1750,3,4,4,-83,-12,-54,16,41
# OK

# AT+CEREG için unsolicited kayıt bildirimleri aç
AT+CEREG=1
# Şimdi ağ değiştiğinde otomatik bildirim gelir:
# +CEREG: 1  → kayıt oldu
# +CEREG: 0  → bağlantı kesildi

Kayıt izleme döngüsü (Python)

python — network_watch.py
import serial, time, re

def wait_registered(port='/dev/ttyUSB2', timeout=60):
    ser = serial.Serial(port, 115200, timeout=2)
    start = time.time()
    print("LTE ağına kayıt bekleniyor...")
    while time.time() - start < timeout:
        ser.write(b'AT+CEREG?\r\n')
        time.sleep(1)
        resp = ser.read(ser.in_waiting).decode(errors='replace')
        m = re.search(r'\+CEREG:\s*\d,(\d)', resp)
        if m:
            stat = int(m.group(1))
            if stat in (1, 5):   # 1=ev, 5=roaming
                ser.close()
                return True, 'roaming' if stat == 5 else 'home'
            print(f"  Durum: {stat}, bekleniyor...")
    ser.close()
    return False, 'timeout'

ok, mode = wait_registered()
if ok:
    print(f"Kayıt başarılı — mod: {mode}")
else:
    print("Kayıt zaman aşımı!")

06 SMS gönderme ve alma — AT+CMGS, AT+CMGR

AT komutlarıyla SMS gönderme (PDU ve metin modu) ve alma. Embedded sistemlerde OTP, alarm bildirimi ve uzaktan komut için kullanılır.

AT — SMS metin modu
# SMS metin moduna geç
AT+CMGF=1
# OK

# SMS gönder
AT+CMGS="+905001234567"
# > (modem prompt bekler)
Sistem alarmı: Sicaklik 85C asild!
# Ctrl+Z ile gönder (0x1A)
# +CMGS: 42
# OK  (42 = mesaj referans no)

# SMS klasörlerini listele
AT+CMGL="ALL"
# +CMGL: 1,"REC READ","+905009876543","","26/01/15,10:30:00+12"
# Merhaba, test mesaji
# OK

# Belirli bir SMS'i oku (index 1)
AT+CMGR=1
# +CMGR: "REC READ","+905009876543","","26/01/15,10:30:00+12"
# Merhaba, test mesaji
# OK

# SMS sil (index 1)
AT+CMGD=1
# OK

# Tüm okunmuş SMS'leri sil
AT+CMGD=1,1
# OK

# Yeni SMS bildirimi aktif et
AT+CNMI=2,1,0,0,0
# Yeni SMS geldiğinde:
# +CMTI: "SM",2   → SM klasörü, index 2
# OK

Python ile SMS gönderme

python — sms_sender.py
import serial
import time

def send_sms(port, number, message):
    ser = serial.Serial(port, 115200, timeout=5)
    time.sleep(0.3)

    def cmd(c, wait=0.5):
        ser.write((c + '\r\n').encode())
        time.sleep(wait)
        return ser.read(ser.in_waiting).decode(errors='replace')

    # Metin moduna geç
    r = cmd('AT+CMGF=1')
    if 'OK' not in r:
        raise RuntimeError("CMGF hatası")

    # Alıcı numarasını gir
    ser.write(f'AT+CMGS="{number}"\r\n'.encode())
    time.sleep(0.5)
    r = ser.read(ser.in_waiting).decode(errors='replace')
    if '>' not in r:
        raise RuntimeError("SMS prompt alınamadı")

    # Mesajı gönder (Ctrl+Z = 0x1A ile bitir)
    ser.write(message.encode() + b'\x1a')
    time.sleep(5)  # SMS gönderimi için bekle
    r = ser.read(ser.in_waiting).decode(errors='replace')

    ser.close()

    if '+CMGS:' in r:
        ref = r.split('+CMGS:')[1].split('\n')[0].strip()
        print(f"SMS gönderildi, ref={ref}")
        return True
    else:
        print(f"Hata: {r}")
        return False


send_sms('/dev/ttyUSB2', '+905001234567', 'Sicaklik alarmi: 85C')

07 Baud rate, flow control ve modem reset

Seri port parametreleri, donanım akış kontrolü ve modem sıfırlama prosedürleri — güvenilir embedded modem iletişimi için zorunlu bilgiler.

AT — baud rate ve flow control
# AT+IPR — baud rate sorgula
AT+IPR?
# +IPR: 115200
# OK

# Baud rate değiştir (dikkatli kullan!)
AT+IPR=921600
# OK (terminal artık 921600 ile bağlanmalı)

# AT&K — akış kontrolü
AT&K0
# OK (akış kontrolü kapalı)
AT&K3
# OK (RTS/CTS donanım akış kontrolü)
AT&K4
# OK (XON/XOFF yazılım akış kontrolü)

# AT&V — mevcut ayarları görüntüle
AT&V

# ATZ — modem ayarlarını fabrika varsayılanına sıfırla
ATZ
# OK

# AT&F — fabrika ayarlarına dön
AT&F
# OK

# AT+CFUN — modem fonksiyon modu
AT+CFUN?
# +CFUN: 1   → tam fonksiyon
# OK

# Soft reset (RF kapalı, sonra tam açık)
AT+CFUN=0    # RF kapat (minimum fonksiyon)
AT+CFUN=1    # Tam fonksiyon (reset ile)

# Quectel — modem yeniden başlat
AT+QPOWD=1
# POWERED DOWN

# SIM7600 — modem yeniden başlat
AT+CRESET
# OK
# +CPIN: READY  (yaklaşık 10s sonra)

Python pyserial ile doğru baud ayarı

python — serial_config.py
import serial

# Doğru seri port ayarları
ser = serial.Serial(
    port='/dev/ttyUSB2',
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    rtscts=False,    # RTS/CTS donanım akış kontrolü
    xonxoff=False,   # XON/XOFF yazılım akış kontrolü
    timeout=3,
    write_timeout=3
)

# DTR/RTS pinlerini ayarla (bazı modemlerde önemli)
ser.dtr = True
ser.rts = True

print(f"Port açık: {ser.is_open}")
print(f"Baud: {ser.baudrate}")

ser.write(b'AT\r\n')
import time; time.sleep(0.2)
print(ser.read(ser.in_waiting).decode())
ser.close()

08 Practical — EC25/SIM7600 Python AT kontrolü

Quectel EC25 veya SIMCom SIM7600 modemi Python ile kontrol eden tam bir sınıf — bağlantı yönetimi, sinyal izleme ve data oturumu.

python — lte_modem.py
#!/usr/bin/env python3
"""
LTE Modem AT Kontrolcüsü
Quectel EC25 / SIMCom SIM7600 ile test edilmiştir.
Gereksinimler: pip install pyserial
"""
import serial
import time
import re
import threading
import logging

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


class LTEModem:
    def __init__(self, port='/dev/ttyUSB2', baudrate=115200):
        self.port = port
        self.baudrate = baudrate
        self.ser = None
        self._lock = threading.Lock()
        self._urcs = []   # unsolicited result codes

    def open(self):
        self.ser = serial.Serial(
            self.port, self.baudrate,
            rtscts=False, xonxoff=False, timeout=3
        )
        time.sleep(0.5)
        log.info(f"Port açıldı: {self.port}")

    def close(self):
        if self.ser and self.ser.is_open:
            self.ser.close()

    def send_cmd(self, cmd, timeout=5.0, expect='OK'):
        """AT komutu gönder, yanıt bekle."""
        with self._lock:
            self.ser.reset_input_buffer()
            self.ser.write((cmd + '\r\n').encode())
            deadline = time.time() + timeout
            resp = ''
            while time.time() < deadline:
                if self.ser.in_waiting:
                    chunk = self.ser.read(self.ser.in_waiting).decode(errors='replace')
                    resp += chunk
                    if expect in resp or 'ERROR' in resp:
                        break
                time.sleep(0.05)
        return resp.strip()

    # ── Cihaz bilgisi ─────────────────────────────────────
    def get_info(self):
        info = {}
        for key, cmd in [('model', 'AT+CGMM'), ('imei', 'AT+CGSN'),
                         ('imsi', 'AT+CIMI'), ('fw', 'AT+CGMR')]:
            resp = self.send_cmd(cmd)
            lines = [l.strip() for l in resp.split('\n')
                     if l.strip() and l.strip() not in ('OK', cmd.split('+')[1])]
            info[key] = lines[0] if lines else ''
        return info

    # ── Sinyal kalitesi ───────────────────────────────────
    def get_signal(self):
        resp = self.send_cmd('AT+CSQ')
        m = re.search(r'\+CSQ:\s*(\d+),(\d+)', resp)
        if m:
            rssi_raw = int(m.group(1))
            rssi_dbm = -113 + rssi_raw * 2 if rssi_raw < 99 else None
            return {'raw': rssi_raw, 'dbm': rssi_dbm}
        return None

    def get_lte_signal(self):
        """Quectel: LTE RSRP/RSRQ/SINR"""
        resp = self.send_cmd('AT+QCSQ')
        m = re.search(r'\+QCSQ:\s*"([^"]+)",(-?\d+),(-?\d+),(-?\d+),(-?\d+)', resp)
        if m:
            return {
                'rat': m.group(1),
                'rssi': int(m.group(2)),
                'rsrp': int(m.group(3)),
                'sinr': int(m.group(4)),
                'rsrq': int(m.group(5)),
            }
        return None

    # ── Ağ kaydı ──────────────────────────────────────────
    def get_registration(self):
        resp = self.send_cmd('AT+CEREG?')
        m = re.search(r'\+CEREG:\s*\d,(\d)', resp)
        if m:
            stat = int(m.group(1))
            return {
                'registered': stat in (1, 5),
                'roaming':    stat == 5,
                'status':     stat
            }
        return None

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

    # ── APN ve data bağlantısı ────────────────────────────
    def setup_apn(self, apn='internet', pdp_type='IP', cid=1):
        resp = self.send_cmd(f'AT+CGDCONT={cid},"{pdp_type}","{apn}"')
        return 'OK' in resp

    def activate_pdp(self, cid=1):
        resp = self.send_cmd(f'AT+CGACT=1,{cid}', timeout=30)
        return 'OK' in resp

    def get_ip(self, cid=1):
        resp = self.send_cmd(f'AT+CGPADDR={cid}')
        m = re.search(r'\+CGPADDR:\s*\d+,"([^"]+)"', resp)
        return m.group(1) if m else None

    # ── Tam bağlantı sekansı ──────────────────────────────
    def connect(self, apn='internet'):
        log.info("Modem başlatılıyor...")

        # SIM kontrolü
        r = self.send_cmd('AT+CPIN?')
        if 'READY' not in r:
            log.error(f"SIM hazır değil: {r}")
            return False

        # APN ayarla
        self.setup_apn(apn)

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

        # PDP aktive et
        if not self.activate_pdp():
            log.error("PDP aktivasyon başarısız")
            return False

        ip = self.get_ip()
        log.info(f"Bağlantı kuruldu. IP: {ip}")
        return True


# ── Ana program ───────────────────────────────────────────
def main():
    modem = LTEModem(port='/dev/ttyUSB2')
    modem.open()

    info = modem.get_info()
    log.info(f"Model : {info.get('model','?')}")
    log.info(f"IMEI  : {info.get('imei','?')}")
    log.info(f"IMSI  : {info.get('imsi','?')}")

    sig = modem.get_signal()
    if sig:
        log.info(f"Sinyal: {sig['raw']} ({sig['dbm']} dBm)")

    lte_sig = modem.get_lte_signal()
    if lte_sig:
        log.info(f"LTE   : {lte_sig}")

    ok = modem.connect(apn='internet')
    if ok:
        log.info("Data bağlantısı hazır!")
        # wwan0 / usb0 arayüzüne DHCP çek
        import subprocess
        subprocess.run(['udhcpc', '-i', 'wwan0', '-n'], timeout=15)

    modem.close()


if __name__ == '__main__':
    main()
NOT

EC25 modemi genellikle /dev/ttyUSB0 (diag), /dev/ttyUSB1 (GPS NMEA), /dev/ttyUSB2 (AT komutları), /dev/ttyUSB3 (modem data) portları açar. AT komutları için ttyUSB2 kullanın. Data için QMI/MBIM tercih edin.