Skip to content

About

πŸš€ Kotlin Multiplatform ESC/POS thermal printing library β€” Android, iOS, Desktop, Web, Wasm. Bluetooth, BLE, USB, Network TCP. Receipt builder with QR/barcode, images, and status monitoring.

Topics

Resources

Code of conduct

Contributing

Stars

7 stars

Watchers

2 watching

Forks

Latest commit

Β 

History

138 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ–¨οΈ KmpPrinter

Kotlin Multiplatform ESC/POS Thermal Printing Library

GitHub Release License GitHub Stars Kotlin CI

A single unified API for thermal printer discovery, connection, ESC/POS receipt building, and status monitoring β€” across Android, iOS, JVM/Desktop, and JS.


✨ Features

  • βœ… Multiplatform β€” Android, iOS, JVM/Desktop, JS
  • βœ… Multiple Transports β€” Bluetooth Classic, BLE, USB, Network TCP, Serial, Virtual
  • βœ… ESC/POS Receipt DSL β€” text styling, alignment, tables, dividers, images, barcodes, QR codes
  • βœ… Flow-based Discovery β€” reactive printer scanning via Kotlin coroutines
  • βœ… Status Monitoring β€” real-time paper out, cover open, error detection
  • βœ… Chunked Sending β€” prevents printer buffer overflow
  • βœ… Concurrency Protection β€” built-in mutex for safe multi-thread printing
  • βœ… Preview Rendering β€” render receipts virtually for UI preview
  • βœ… MIT Licensed β€” free for commercial and personal use

πŸ“± Platform Support

Platform Bluetooth Classic BLE USB Network TCP Status Query
Android βœ… βœ… βœ… βœ… βœ…
iOS ❌ βœ… ❌ βœ… βœ…
JVM/Desktop βœ… OS serial/queue βœ… BlueZ helper βœ… raw USB/serial βœ… ⚠️ Transport dependent
Web (JS) ❌ Not supported βœ… (Chrome WebBLE) βœ… (WebUSB) ❌ Not supported ⚠️ Browser dependent

Support depends on printer firmware, OS APIs, browser capabilities, and hardware transport. See Transport Support for details.


πŸš€ Quick Start

1. Add Repository

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://raw.githubusercontent.com/ringga-dev/kmp-printer/maven-repo")
        }
    }
}

2. Add Dependency

// build.gradle.kts
kotlin {
    sourceSets {
        commonMain.dependencies {
            // Core Engine
            implementation("io.github.ringga-dev:kmp_printer:2.3.6")
            
            // Optional: Compose Multiplatform UI Components (Adaptive & Zero-Bloat)
            implementation("io.github.ringga-dev:kmp_printer-ui:2.3.6")
        }
    }
}

Maven users:

<!-- Core Engine -->
<dependency>
    <groupId>io.github.ringga-dev</groupId>
    <artifactId>kmp_printer</artifactId>
    <version>2.3.6</version>
</dependency>

<!-- UI Components -->
<dependency>
    <groupId>io.github.ringga-dev</groupId>
    <artifactId>kmp_printer-ui</artifactId>
    <version>2.3.6</version>
</dependency>

Available on Maven Central β€” no extra repository needed.

3. Print Your First Receipt

import ngga.ring.printer.KmpPrinter
import ngga.ring.printer.model.PrinterConfig

val printer = KmpPrinter()
val config = PrinterConfig(
    name = "Receipt Printer",
    connectionType = "NETWORK",
    address = "192.168.1.50",
    port = 9100,
    characterPerLine = 32,
    paperWidth = 58
)

printer.print(config) {
    alignCenter()
    bold(true)
    line("β˜• COFFEE SHOP")
    bold(false)
    divider()
    tableRow(listOf("Americano", "2", "6.00"), listOf(2, 1, 1))
    tableRow(listOf("Latte", "1", "4.50"), listOf(2, 1, 1))
    divider()
    line("Total: $10.50", align = "RIGHT")
    feed(1)
    qrCodeNative("https://example.com", center = true)
    feed(3)
    cut()
}.collect { status -> println(status) }

🧩 Usage Examples

πŸ“‹ Receipt Builder DSL

printer.print(config) {
    setCharset(PrinterCharset.USA_EUROPE)
    alignCenter()
    image(myBitmap, center = true)
    feed(2)
    bold(true)
    fontSize(2)
    line("HEADER")
    fontSize(1)
    bold(false)
    divider('=')
    table(listOf("Item", "Qty", "Price"), listOf(2, 1, 1))
    tableRow(listOf("Product 1", "3", "9.99"), listOf(2, 1, 1))
    barcode("123456789012", type = BarcodeType.EAN13)
    feed(2)
    cut()
}

πŸ“± Typed Devices & Discovery (PrinterDevice)

Mendukung model PrinterDevice yang strongly-typed per tipe koneksi (Bluetooth, Ble, Usb, Network, Serial, Virtual):

import ngga.ring.printer.model.PrinterConnection
import ngga.ring.printer.model.PrinterDevices
import ngga.ring.printer.model.PrinterProfile

// 1. Scan / Discovery Otomatis
printer.discoverDevices(PrinterConnection.BLUETOOTH).collect { devices ->
    devices.forEach { device ->
        println("Device: ${device.name} - ${device.address}")
    }
}

// 2. Inisialisasi Manual via Factory
val cashierUsb = PrinterDevices.usb("Epson TM-T82", "USB_RAW:04B8:0202")
val kitchenNet = PrinterDevices.network("Kitchen", host = "192.168.1.200", port = 9100)
val portableBt = PrinterDevices.bluetooth("RPP02N", "00:11:22:33:44:55")

// 3. Cetak langsung dengan Device & Profile
printer.print(kitchenNet, profile = PrinterProfile.MM80) {
    line("ORDER #102")
    cut()
}

⚑ Multi-Printer Parallel Sessions (PrinterSession)

Untuk aplikasi POS yang mencetak ke banyak printer secara bersamaan tanpa saling memutus koneksi:

val cashierSession = printer.openSession(PrinterDevices.usb("Kasir", "USB_RAW:04B8:0202"))
val kitchenSession = printer.openSession(PrinterDevices.network("Dapur", "192.168.1.200"))

// Cetak paralel ke kasir dan dapur
cashierSession.print { line("Struk Pembayaran") }
kitchenSession.print { line("Pesanan Dapur") }

🏷️ TSPL Label Printing (Stiker & Barcode)

Dukungan pembuatan stiker label thermal (TSC/TSPL protocol):

printer.printLabel(cashierUsb, widthMm = 40.0, heightMm = 30.0) {
    direction(0)
    text(x = 10, y = 10, content = "PRODUK UTAMA", font = "3")
    barcode(x = 10, y = 45, data = "89912345678", type = "128", height = 40)
    qrcode(x = 200, y = 45, data = "https://example.com")
    print(sets = 1, copies = 1)
}

🌍 Arabic & RTL Text Shaping

Penataan teks bahasa Arab dan RTL otomatis untuk printer thermal:

printer.print(portableBt) {
    lineArabic("Ψ΄ΩƒΨ±Ψ§ Ω„Ψ²ΩŠΨ§Ψ±ΨͺΩƒΩ… - Ω…Ψ±Ψ­Ψ¨Ψ§Ω‹ Ψ¨ΩƒΩ…")
    cut()
}

πŸ” Printer Discovery (Network)

printer.discovery("NETWORK") { log ->
    println("Scanning: $log")
}.collect { devices ->
    devices.forEach { device ->
        println("Found: ${device.name} at ${device.address}:${device.port}")
    }
}

πŸ“Š Status Monitoring

printer.monitorStatus(config, intervalMs = 2000).collect { status ->
    when {
        status.isPaperOut -> sendAlert("πŸ“’ Printer kehabisan kertas!")
        status.isCoverOpen -> sendAlert("πŸ”“ Cover printer terbuka!")
        !status.isOnline -> sendAlert("⚠️ Printer offline!")
    }
}

πŸŽ› Typed Transport Configs

val networkConfig = PrinterConfig(
    name = "Kitchen Printer",
    connection = PrinterConnection.NETWORK,
    profile = PrinterProfile.MM58,
    address = "192.168.1.50"
)

🎨 Print Quality

printer.print(config) {
    printQuality(PrintQuality.Dark)
    line("High density thermal output")
    cut()
}

πŸ“ Layout: Margin, Centering & Line Spacing

PrinterConfig / PrinterProfile mendukung pengaturan margin, centering, dan jarak antar baris:

val config = PrinterConfig(
    name = "Receipt Printer",
    connectionType = "NETWORK",
    address = "192.168.1.50",
    characterPerLine = 32,
    paperWidth = 58,
    paperWidthDots = 384,   // direkomendasikan eksplisit β€” fallback heuristic bisa meleset
    leftMargin = 20,        // margin kiri dalam dots
    rightMargin = 0,        // margin kanan dalam dots (baru sejak 2.3.6)
    autoCenter = false,     // true = margin kiri dicerminkan ke kanan (simetris)
    lineSpacing = 40        // jarak antar baris dalam dots; 0 = default printer
)
  • Area printable = paperWidthDots - leftMargin - rightMargin, jadi isi tidak lagi meluap/terpotong di sisi kanan.
  • centerText(text) dan centerWrapped(text, maxLine) memakai perataan hardware (ESC a 1) β€” semua baris hasil word-wrap tetap center, termasuk yang lebih dari 2 baris. Untuk perilaku lama (software padding) gunakan centerTextSingleLine(text).
  • lineSpacing > 0 diterapkan otomatis saat initialize() via command ESC 3 n.

πŸ“š Documentation

Document Description
Transport Support Platform-by-platform transport compatibility
Printer OS Setup OS-level driver & permission setup (Linux udev, Windows, macOS)
API & Migration Typed configs, profiles, migration from v1
Releasing How to publish to GitHub Maven & Maven Central
GitHub Pages Online documentation site

πŸ›  Development

# Build all platforms
./gradlew build

# Run JVM tests
./gradlew :printer:jvmTest

# Compile specific targets
./gradlew :printer:compileKotlinMetadata
./gradlew :printer:compileKotlinJs
./gradlew :printer:compileDebugKotlinAndroid

# Update version in docs after changing LIB_VERSION in gradle.properties
./gradlew syncDocumentationVersion

πŸ— Architecture

printer/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ commonMain/        # Shared platform-independent logic
β”‚   β”‚   β”œβ”€β”€ model/         # Printer models, configs, enums
β”‚   β”‚   β”œβ”€β”€ manager/       # Connection management, discovery
β”‚   β”‚   β”œβ”€β”€ usecase/       # Print, discover, diagnose
β”‚   β”‚   └── util/          # ESC/POS commands, rendering, preview
β”‚   β”œβ”€β”€ androidMain/       # Android BLE, USB, Network, Bluetooth
β”‚   β”œβ”€β”€ iosMain/           # iOS BLE, Network
β”‚   β”œβ”€β”€ jvmMain/           # Desktop USB, Serial, Network, BlueZ
β”‚   β”œβ”€β”€ jsMain/            # Web Bluetooth, USB
β”œβ”€β”€ androidApp/            # Android sample app
β”œβ”€β”€ desktopApp/            # JVM Desktop sample app
└── iosApp/                # iOS sample app

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines on:

  • Code style and PR process
  • Platform-specific testing
  • How to add new transport support

β˜• Donasi

Jika library ini membantu proyek Anda, dukung pengembangan dengan mentraktir kopi:

Trakteer Saya

πŸ‘‰ https://trakteer.id/ringga_dev/gift


πŸ“„ License

MIT License β€” see LICENSE.

Copyright (c) 2026 Ringga. Free to use, modify, and distribute in commercial and non-commercial applications.


Built with ❀️ and Kotlin Multiplatform β€” ⭐ Star on GitHub

About

πŸš€ Kotlin Multiplatform ESC/POS thermal printing library β€” Android, iOS, Desktop, Web, Wasm. Bluetooth, BLE, USB, Network TCP. Receipt builder with QR/barcode, images, and status monitoring.

Topics

Resources

Code of conduct

Contributing

Stars

7 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages