KmpPrinter

Kotlin Multiplatform ESC/POS thermal printing library

🖨️ KmpPrinter

Kotlin Multiplatform ESC/POS Thermal Printing Library

GitHub Release
License
GitHub Stars
Kotlin
Platforms
CI

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


✨ Features


📱 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) ⚠️ Browser dependent
Wasm ⚠️ 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 {
            implementation("io.github.ringga-dev:kmp_printer:2.3.3")
        }
    }
}

Maven users:
xml <!-- pom.xml --> <dependency> <groupId>io.github.ringga-dev</groupId> <artifactId>kmp_printer</artifactId> <version>2.3.3</version> <!-- sync-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()
}

🔍 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 (New API)

// Recommended for new code — avoids hardcoded strings
val networkConfig = PrinterConfig(
    name = "Kitchen Printer",
    connection = PrinterConnection.NETWORK,
    profile = PrinterProfile.MM58,
    address = "192.168.1.50"
)

val bleConfig = PrinterConfig(
    name = "Portable Printer",
    connection = PrinterConnection.BLE,
    address = "00:11:22:33:44:55",
    profile = PrinterProfile.MM80
)
printer.print(config) {
    printQuality(PrintQuality.Dark)
    line("High density thermal output")
    cut()
}

📚 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:compileKotlinWasmJs
./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, Serial, Network
│   └── wasmJsMain/        # Wasm hardware bridge
├── androidApp/            # Android sample app
├── desktopApp/            # JVM Desktop sample app
└── iosApp/                # iOS sample app

🤝 Contributing

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


📄 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