Android Seri Bağlantı Noktası (Kotlin)

Table of Contents

Android Seri Bağlantı Noktası (Kotlin)

Kotlin’de yazılmış modern, iş parçacığı güvenli ve reaktif bir Android Seri Bağlantı Noktası kütüphanesi. Bu kütüphane, popüler xmaihh/Android-Serialport kütüphanesinin modernizasyonudur ve eşzamansız veri işleme için Kotlin Coroutines ve Flow’dan yararlanır.

  • Modern Yığın: %100 Kotlin, Coroutines ve Flow.
  • Reaktif API: Verileri sıcak Flow<ByteArray> olarak okuyun.
  • Paket İşleme: Çoklu ayrıştırma stratejileri (delimiter, fixedLength, startEndMarker, lengthPrefixed, customParser) ile “yapışkan paketler” için yerleşik destek.
  • Cihaz Keşfi: SerialPortFinder cihazdaki mevcut seri portları listeler.
  • Root Desteği: Seri bağlantı noktalarına erişmek için root izinleri talep eden yardımcı.
  • İş Parçacığı Güvenliği: G/Ç işlemleri Dispatchers.IO.
  • ‘ya yüklenir.

Kurulum

Seçenek 1: Maven Central (Önerilen)

Bağımlılığı modülünüzün build.gradle.kts dosyasına ekleyin:

dependencies {
    implementation("io.github.onatakduman:kserialport:1.1.3")
}

Seçenek 2: JitPack

JitPack deposunu settings.gradle.kts‘ye ekleyin:

dependencyResolutionManagement {
    depolar {
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
    }
}

Bağımlılığı ekleyin:

dependencies {
    implementation("com.github.onatakduman:kserialport:1.1.3")
}

Kullanım

1. Kullanılabilir Cihazları Listele

val finder = SerialPortFinder()
val devices = finder.getAllDevices() // Returns Array<String> örneğin, ["ttyS0 (serial)", ...]
val paths = finder.getAllDevicesPath() // Returns Array<String> örneğin, ["/dev/ttyS0", ...]

2. Seri Bağlantı Noktasını Açın

try {
    // 8N1 (Varsayılan)
    val serialPort = SerialPort("/dev/ttyS1", 9600)

    // Özel Yapılandırma: 8E1 (8 Veri biti, Çift Eşlik, 1 Durma biti)
    // val serialPort = SerialPort(
    // path = "/dev/ttyS1",
    // baudRate = 9600,
    // dataBits = SerialPort.DATA_BITS_8,
    // stopBits = SerialPort.STOP_BITS_1,
    // parity = SerialPort.PARITY_EVEN
    // )

    val bağlantı = serialPort.open()

    // Bağlantıyı kullan...
} catch (e: SecurityException) {
    // İzin hatasını ele al
} catch (e: IOException) {
    // Açma hatasını ele al
}

3. Veri Okuma (Reaktif)

Veri almak için readFlow‘u kullanın. Paket işleme operatörlerini doğrudan uygulayabilirsiniz.

// Basit okuma - ham baytları geldikleri gibi alın
lifecycleScope.launch {
    connection.readFlow.collect { bytes ->
        Log.d("Serial", "Received: ${bytes.toHexString()}")
    }
}

4. Paket Ayrıştırma (Yapışkan Paket İşleme)

Seri veriler genellikle parçalanmış veya birleştirilmiş olarak gelir. Paketlerin tamamını ayıklamak için bu operatörleri kullanın:

Sınırlayıcı Tabanlı

Paketleri bir sınırlayıcı dizisi (örn. satırsonu, CRLF) ile bölün:

connection.readFlow
    .delimiter(byteArrayOf(0x0A)) // \n ile böl
    .collect { packet ->
        Log.d("Serial", "Line: ${String(packet)}")
    }

Sabit Uzunluklu Paketler

Paketler her zaman aynı boyuta sahip olduğunda:

connection.readFlow
    .fixedLength(32) // 32 baytlık paketler
    .collect { packet ->
        // 32 baytlık paketi işleyin
    }

Başlangıç/Bitiş İşaretleyici Çerçeveleri

Verileri işaretleyicilerle çerçeveleyen protokoller için (örn. STX/ETX):

val STX = byteArrayOf(0x02)
val ETX = byteArrayOf(0x03)

connection.readFlow
    .startEndMarker(startMarker = STX, endMarker = ETX)
    .collect { packet ->
        // STX ve ETX arasında paket veri
    }

Uzunluk Önekli Paketler

Bir başlığın yük uzunluğunu içerdiği ikili protokollerde yaygındır:

// Protokol: [1 bayt uzunluk][yük]
connection.readFlow
    .lengthPrefixed(
        lengthFieldOffset = 0, // 0 baytındaki uzunluk
        lengthFieldSize = 1, // 1 bayt uzunluk alanı
        bigEndian = true
    )
    .collect { packet ->
        // Başlık dahil paketin tamamı
    }

// Daha karmaşık: [2 bayt başlık][2 bayt uzunluk BE][yük]
connection.readFlow
    .lengthPrefixed(
        lengthFieldOffset = 2, // Uzunluk alanı bayt 2'de başlar
        lengthFieldSize = 2, // 2 bayt uzunluk (big-endian)
        headerSize = 4, // Toplam başlık 4 bayttır
        bigEndian = true
    )
    .collect { packet -> }

Özel Ayrıştırıcı

Karmaşık protokoller için kendi mantığınızı uygulayın:

connection.readFlow
    .customParser { buffer ->
        // Henüz tamamlanmış paket yoksa null döndür
        if (buffer.size < 4) return@customParser null

        // Protokolünüzü ayrıştırın...
        val packetEnd = findPacketEnd(buffer)
        if (packetEnd == -1) return@customParser null

        // Paketi ve kalan baytları döndür
        PacketParser.ParseResult(
            packet = buffer.copyOfRange(0, packetEnd),
            kalan = buffer.copyOfRange(packetEnd, buffer.size)
        )
    }
    .collect { packet -> }

5. Veri Yaz

lifecycleScope.launch {
    val data = "Merhaba Dünya".toByteArray()
    connection.write(data)
}

6. Bağlantıyı Kapat

connection.close()

Lisans

Apache Lisansı 2.0

Post Tags :

Share :

Projenizi görüşelim!