Skip to content

Commit

Permalink
Merge pull request #21 from tillhub/develop
Browse files Browse the repository at this point in the history
v1.6.0 improvements and simplification of interface
  • Loading branch information
djordjeh authored Jan 23, 2024
2 parents b9c12d7 + 2430422 commit 665b48c
Show file tree
Hide file tree
Showing 26 changed files with 171 additions and 241 deletions.
3 changes: 1 addition & 2 deletions buildSrc/src/main/java/ConfigData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ object ConfigData {
const val applicationId = "de.tillhub.printengine"
const val minSdkVersion = 21
const val targetSdkVersion = 34
const val versionCode = 17
const val versionName = "1.5.0"
const val versionName = "1.6.0"

val JAVA_VERSION = JavaVersion.VERSION_17
val JVM_TARGET = JAVA_VERSION.toString()
Expand Down
17 changes: 2 additions & 15 deletions src/main/java/de/tillhub/printengine/PrintService.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
package de.tillhub.printengine

import de.tillhub.printengine.data.PrinterConnectionState
import de.tillhub.printengine.data.PrinterResult
import de.tillhub.printengine.data.PrinterState
import kotlinx.coroutines.flow.StateFlow
import timber.log.Timber

abstract class PrintService {
abstract var printController: PrinterController?
abstract val printerConnectionState: StateFlow<PrinterConnectionState>

@Suppress("TooGenericExceptionCaught")
inline fun <T> withPrinterOrDefault(default: T, body: (PrinterController) -> T): T {
return printController?.let {
try {
body(it)
} catch (e: Exception) {
Timber.e(e)
default
}
} ?: default
}
abstract val printerState: StateFlow<PrinterState>

@Suppress("TooGenericExceptionCaught")
inline fun <T> withPrinterCatching(body: (PrinterController) -> T): PrinterResult<T> {
Expand Down
20 changes: 2 additions & 18 deletions src/main/java/de/tillhub/printengine/Printer.kt
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
package de.tillhub.printengine

import de.tillhub.printengine.data.PrintJob
import de.tillhub.printengine.data.PrinterConnectionState
import de.tillhub.printengine.data.PrinterState
import de.tillhub.printengine.data.PrintingIntensity
import de.tillhub.printengine.data.PrinterResult
import de.tillhub.printengine.data.PrinterInfo
import de.tillhub.printengine.data.PrinterSettings
import de.tillhub.printengine.data.PrintingPaperSpec
import kotlinx.coroutines.flow.StateFlow

/**
* Represents one printer and allows to manage the printers connection issue print commands.
*/
interface Printer {
fun setEnabled(enabled: Boolean)
fun observeConnection(): StateFlow<PrinterConnectionState>
val settings: PrinterSettings
fun observePrinterState(): StateFlow<PrinterState>
fun setPrintingIntensity(intensity: PrintingIntensity)
suspend fun getPrinterInfo(): PrinterResult<PrinterInfo>

suspend fun startPrintJob(job: PrintJob): PrinterResult<Unit>

/**
* Due to the distance between the paper hatch and the print head,
* the paper needs to be fed out automatically
* But if the Api does not support it, it will be replaced by printing three lines
*/
suspend fun feedPaper(): PrinterResult<Unit>

/**
* Printer cuts paper and throws exception on machines without a cutter
*/
suspend fun cutPaper(): PrinterResult<Unit>

companion object {
val DEFAULT_PRINTER_WIDTH = PrintingPaperSpec.PAX_PAPER_56MM.characterCount
}
Expand Down
120 changes: 48 additions & 72 deletions src/main/java/de/tillhub/printengine/PrinterImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ package de.tillhub.printengine
import de.tillhub.printengine.analytics.PrintAnalytics
import de.tillhub.printengine.data.PrintCommand
import de.tillhub.printengine.data.PrintJob
import de.tillhub.printengine.data.PrinterConnectionState
import de.tillhub.printengine.data.PrinterInfo
import de.tillhub.printengine.data.PrinterResult
import de.tillhub.printengine.data.PrinterSettings
import de.tillhub.printengine.data.PrinterState
import de.tillhub.printengine.data.PrintingIntensity
import de.tillhub.printengine.data.doOnError
import de.tillhub.printengine.dispatcher.DispatcherProvider
import de.tillhub.printengine.dispatcher.DispatcherProviderImp
import de.tillhub.printengine.pax.PaxPrintService
import de.tillhub.printengine.sunmi.SunmiPrintService
import de.tillhub.printengine.verifone.VerifonePrintService
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import timber.log.Timber

class PrinterImpl(
private val printService: PrintService,
private val analytics: PrintAnalytics?
private val analytics: PrintAnalytics?,
private val dispatcherProvider: DispatcherProvider = DispatcherProviderImp()
) : Printer {

init {
Expand All @@ -29,88 +31,62 @@ class PrinterImpl(
}
}

private var enabled: Boolean = true
private var printingIntensity: PrintingIntensity = PrintingIntensity.DEFAULT

override fun setEnabled(enabled: Boolean) {
this.enabled = enabled
override val settings: PrinterSettings by lazy {
PrinterSettings()
}

override fun observeConnection(): StateFlow<PrinterConnectionState> = printService.printerConnectionState

override fun observePrinterState(): StateFlow<PrinterState> =
printService.withPrinterOrDefault(default = MutableStateFlow(PrinterState.Error.Unknown)) {
it.observePrinterState()
}

override fun setPrintingIntensity(intensity: PrintingIntensity) {
printingIntensity = intensity
}
override fun observePrinterState(): StateFlow<PrinterState> = printService.printerState

override suspend fun getPrinterInfo(): PrinterResult<PrinterInfo> =
printService.withPrinterCatching {
it.getPrinterInfo().let { info ->
PrinterInfo(
info.serialNumber,
info.deviceModel,
info.printerVersion,
info.printerPaperSpec,
info.printingFontType,
info.printerHead,
info.printedDistance,
info.serviceVersion
)
withContext(dispatcherProvider.iO()) {
printService.withPrinterCatching {
it.getPrinterInfo().let { info ->
PrinterInfo(
info.serialNumber,
info.deviceModel,
info.printerVersion,
info.printerPaperSpec,
info.printingFontType,
info.printerHead,
info.printedDistance,
info.serviceVersion
)
}
}.doOnError {
logWarning("getting printer info")
}
}.doOnError {
logWarning("getting printer info")
}

override suspend fun startPrintJob(job: PrintJob): PrinterResult<Unit> =
printService.withPrinterCatching { controller ->
logInfo(
"""receipt: START #################
withContext(dispatcherProvider.iO()) {
printService.withPrinterCatching { controller ->
logInfo(
"""receipt: START #################
|${job.description}
|receipt END #################
|""".trimMargin()
)
if (enabled && job.isNotEmpty) {
controller.setIntensity(printingIntensity)
controller.setFontSize(controller.getPrinterInfo().printingFontType)
job.commands.forEach { command ->
when (command) {
is PrintCommand.Barcode -> controller.printBarcode(command.barcode)
is PrintCommand.Image -> controller.printImage(command.image)
is PrintCommand.QrCode -> controller.printQr(command.code)
is PrintCommand.RawData -> controller.sendRawData(command.data)
is PrintCommand.Text -> controller.printText(command.text)
PrintCommand.CutPaper -> controller.cutPaper()
PrintCommand.FeedPaper -> controller.feedPaper()
)
if (settings.enabled && job.isNotEmpty) {
controller.setIntensity(settings.printingIntensity)
controller.setFontSize(controller.getPrinterInfo().printingFontType)
job.commands.forEach { command ->
when (command) {
is PrintCommand.Barcode -> controller.printBarcode(command.barcode)
is PrintCommand.Image -> controller.printImage(command.image)
is PrintCommand.QrCode -> controller.printQr(command.code)
is PrintCommand.RawData -> controller.sendRawData(command.data)
is PrintCommand.Text -> controller.printText(command.text)
PrintCommand.CutPaper -> controller.cutPaper()
PrintCommand.FeedPaper -> controller.feedPaper()
}
}
controller.start()
analytics?.logPrintReceipt(job.description)
}
controller.start()
analytics?.logPrintReceipt(job.description)
}
}.doOnError {
logWarning("printing job '${job.description}'")
analytics?.logErrorPrintReceipt("printing text '${job.description}'")
}

override suspend fun feedPaper(): PrinterResult<Unit> =
printService.withPrinterCatching {
if (enabled) {
it.feedPaper()
}
}.doOnError {
logWarning("feeding paper")
}

override suspend fun cutPaper(): PrinterResult<Unit> =
printService.withPrinterCatching {
if (enabled) {
it.cutPaper()
}.doOnError {
logWarning("printing job '${job.description}'")
analytics?.logErrorPrintReceipt("printing text '${job.description}'")
}
}.doOnError {
logWarning("cutting paper")
}

private fun logInfo(message: String) {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/de/tillhub/printengine/data/PrintCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ sealed class PrintCommand {
data class Barcode(val barcode: String) : PrintCommand()
data class QrCode(val code: String) : PrintCommand()
data class RawData(val data: RawPrinterData) : PrintCommand()
/**
* Due to the distance between the paper hatch and the print head,
* the paper needs to be fed out automatically
* But if the Api does not support it, it will be replaced by printing three lines
*/
object FeedPaper : PrintCommand()
/**
* Printer cuts paper and throws exception on machines without a cutter
*/
object CutPaper : PrintCommand()
}

This file was deleted.

6 changes: 6 additions & 0 deletions src/main/java/de/tillhub/printengine/data/PrinterSettings.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package de.tillhub.printengine.data

data class PrinterSettings(
var enabled: Boolean = true,
var printingIntensity: PrintingIntensity = PrintingIntensity.DEFAULT
)
34 changes: 22 additions & 12 deletions src/main/java/de/tillhub/printengine/data/PrinterState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@ package de.tillhub.printengine.data
* State of the [Printer] in case a connection is established.
*/
sealed class PrinterState {
/** Trying to find supported printer */
object CheckingForPrinter : PrinterState()

/** The printer works normally / printer is running */
object Connected : PrinterState()

/** Preparing printer / printer found but still initializing */
object Preparing : PrinterState()

/** Printer was not detected / does not exist */
object PrinterNotDetected : PrinterState()

/** Printer found but operating */
object Busy : PrinterState()

/** Printer error */
sealed class Error : PrinterState() {
/** Connection to printer has lost */
object ConnectionLost : Error()

/** Printer was not detected / does not exist */
object NotAvailable : PrinterState()

/** Abnormal communication / printer hardware interface is abnormal */
object AbnormalCommunication : Error()

Expand Down Expand Up @@ -48,23 +54,27 @@ sealed class PrinterState {
/** Unknown error state */
object Unknown : Error()

/**
* Pax A920 specific
*/

object FormatPrintDataPacketError : Error()
/** Print job cannot continue, but could be resumed later. */
object PrintingUnfinished : Error()

object Malfunctions : Error()

object PrintingUnfinished : Error()
/**
* Pax A920 specific
*/
sealed class Pax : Error() {
object FormatPrintDataPacketError : Pax()

object NotInstalledFontLibrary : Error()
object NotInstalledFontLibrary : Pax()

object DataPackageTooLong : Error()
object DataPackageTooLong : Pax()
}

/**
* Verifone specific
*/
object InternalError : Error()
sealed class Verifone : Error() {
object InternalError : Verifone()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.tillhub.printengine.dispatcher

import kotlinx.coroutines.CoroutineDispatcher

interface DispatcherProvider {
fun iO(): CoroutineDispatcher
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.tillhub.printengine.dispatcher

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

class DispatcherProviderImp : DispatcherProvider {
override fun iO(): CoroutineDispatcher = Dispatchers.IO
}
Loading

0 comments on commit 665b48c

Please sign in to comment.