diff --git a/kotlin-data-wedge-lib/proguard-rules.pro b/kotlin-data-wedge-lib/proguard-rules.pro index 1d79ef5..fca7775 100644 --- a/kotlin-data-wedge-lib/proguard-rules.pro +++ b/kotlin-data-wedge-lib/proguard-rules.pro @@ -64,3 +64,11 @@ -keep class dk.gls.kdw.configuration.scanner.ParityFlowScannerController { *; } + +-keep class dk.gls.kdw.configuration.scanner.DeviceId { + *; +} + +-keep class dk.gls.kdw.configuration.scanner.RemoteScannerNotification { + *; +} \ No newline at end of file diff --git a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/DataWedgeHardwareScanner.kt b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/DataWedgeHardwareScanner.kt index 58bc2df..e4cb935 100644 --- a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/DataWedgeHardwareScanner.kt +++ b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/DataWedgeHardwareScanner.kt @@ -14,16 +14,19 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch - class DataWedgeHardwareScanner( private val context: Context, - dispatcher: CoroutineDispatcher = Dispatchers.IO -) : HardwareScanner { + private val dispatcher: CoroutineDispatcher = Dispatchers.IO +) : IHardwareScanner { companion object { //Scanner Intent data locations @@ -67,7 +70,7 @@ class DataWedgeHardwareScanner( private const val BUNDLE_NOTIFICATION_CONFIG = "NOTIFICATION_CONFIG" private const val EXTRA_KEY_VALUE_DEVICE_IDENTIFIER = "DEVICE_IDENTIFIER" private const val EXTRA_KEY_VALUE_NOTIFICATION_SETTINGS = "NOTIFICATION_SETTINGS" - + private const val NOTIFICATIONS_DELAY: Long = 1000 } private val scope = CoroutineScope(dispatcher) @@ -96,11 +99,26 @@ class DataWedgeHardwareScanner( broadcastScannerAction(context, EXTRA_SCANNER_RESUME) } + //endregion + + //region scanner notifications + /** - * Send a notification on the remote scanner (RMS) + * Send a variable amount of notification lists specifying the notifications for the remote scanner (RMS) + * The notifications are send with a delay between parsed lists of 1000 ms + * Official documentation * @link https://techdocs.zebra.com/datawedge/8-2/guide/api/notify/ **/ - override fun remoteScannerNotification(deviceId: DeviceId, notifications: List) { + override fun remoteScannerNotifications(deviceId: DeviceId, vararg notifications: List) { + CoroutineScope(dispatcher).launch { + notifications.asFlow().map { + remoteScannerNotification(deviceId, it) + delay(NOTIFICATIONS_DELAY) + }.collect() + } + } + + private fun remoteScannerNotification(deviceId: DeviceId, notifications: List) { val bundleNotificationConfig = Bundle() bundleNotificationConfig.putString(EXTRA_KEY_VALUE_DEVICE_IDENTIFIER, deviceId.name) bundleNotificationConfig.putIntArray(EXTRA_KEY_VALUE_NOTIFICATION_SETTINGS, notifications.map { it.value }.toIntArray()) @@ -108,7 +126,6 @@ class DataWedgeHardwareScanner( val bundleNotify = Bundle() bundleNotify.putBundle(BUNDLE_NOTIFICATION_CONFIG, bundleNotificationConfig) - val dataWedgeIntent = Intent() dataWedgeIntent.action = ACTION_DATA_WEDGE dataWedgeIntent.putExtra(ACTION_NOTIFICATION_NOTIFY, bundleNotify) @@ -157,7 +174,7 @@ class DataWedgeHardwareScanner( } if (intent.hasExtra(RESULT_ENUMERATE_SCANNERS)) { val scannerList = intent.getSerializableExtra(RESULT_ENUMERATE_SCANNERS) as ArrayList - if(scannerList.size > 0) { + if (scannerList.size > 0) { scannerList.map { bunb -> val name = bunb.getString("SCANNER_NAME") val connectionState = bunb.getBoolean("SCANNER_CONNECTION_STATE") diff --git a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/HardwareScanner.kt b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/HardwareScanner.kt deleted file mode 100644 index 762af9d..0000000 --- a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/HardwareScanner.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dk.gls.kdw.configuration.scanner - -import dk.gls.kdw.model.scanner.ScannerOutput -import kotlinx.coroutines.flow.Flow - -interface HardwareScanner { - fun scannerOutputFlow(): Flow - fun suspendScanner() - fun resumeScanner() - fun remoteScannerNotification(deviceId: DeviceId, notifications: List) -} \ No newline at end of file diff --git a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/IHardwareScanner.kt b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/IHardwareScanner.kt new file mode 100644 index 0000000..3e84d05 --- /dev/null +++ b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/IHardwareScanner.kt @@ -0,0 +1,25 @@ +package dk.gls.kdw.configuration.scanner + +import dk.gls.kdw.model.scanner.ScannerOutput +import kotlinx.coroutines.flow.Flow + +interface IHardwareScanner { + /** + * Receive the [ScannerOutput] as a flow + */ + fun scannerOutputFlow(): Flow + + /** Suspend the scanner **/ + fun suspendScanner() + + /** Resume the scanner **/ + fun resumeScanner() + + /** + * Send a variable amount of notification lists specifying the notifications for the remote scanner (RMS) + * The notifications are send with a delay between parsed lists of 1000 ms + * Official documentation + * @link https://techdocs.zebra.com/datawedge/8-2/guide/api/notify/ + **/ + fun remoteScannerNotifications(deviceId: DeviceId, vararg notifications: List) +} \ No newline at end of file diff --git a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ParityFlowScannerController.kt b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ParityFlowScannerController.kt index 464e50e..7598b7d 100644 --- a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ParityFlowScannerController.kt +++ b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ParityFlowScannerController.kt @@ -9,14 +9,13 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.launch /** - * The parity flow scanner controller filters unnecessary calls to the underlying [DataWedgeHardwareScanner] by checking the last reported scanner status before sending new resume or suspend commands + * The parity flow scanner controller filters unnecessary calls to the underlying [IHardwareScanner] by checking the last reported scanner status before sending new resume or suspend commands * Therefore this scanner controllers [resumeScanner] and [suspendScanner] methods can safely be called multiple times without resulting in unnecessary broadcast intents being send to the Data wedge */ -class ParityFlowScannerController(dataWedgeHardwareScanner: DataWedgeHardwareScanner) : ScannerController(dataWedgeHardwareScanner) { +class ParityFlowScannerController(dataWedgeIHardwareScanner: IHardwareScanner) : ScannerController(dataWedgeIHardwareScanner) { //We have an actual scanner status flow and a desired scanner status flow for combining later private val actualScannerStatusEnumFlow = MutableSharedFlow(replay = 1) @@ -32,7 +31,7 @@ class ParityFlowScannerController(dataWedgeHardwareScanner: DataWedgeHardwareSca /** * Receive the [ScannerOutput] as a flow */ - override fun scannerOutputFlow(): Flow = dataWedgeHardwareScanner.scannerOutputFlow() + override fun scannerOutputFlow(): Flow = dataWedgeIHardwareScanner.scannerOutputFlow() //region Scanner status public interface @@ -52,8 +51,8 @@ class ParityFlowScannerController(dataWedgeHardwareScanner: DataWedgeHardwareSca desiredScannerStatusFlow.tryEmit(ScannerSimpleStatus.Enabled) } - override fun remoteScannerNotification(deviceId: DeviceId, notifications: List) { - dataWedgeHardwareScanner.remoteScannerNotification(deviceId, notifications) + override fun remoteScannerNotifications(deviceId: DeviceId, vararg notifications: List) { + dataWedgeIHardwareScanner.remoteScannerNotifications(deviceId, *notifications) } //endregion @@ -64,7 +63,7 @@ class ParityFlowScannerController(dataWedgeHardwareScanner: DataWedgeHardwareSca private fun CoroutineScope.subscribeToScannerFlow() = launch { scannerOutputFlow().collect { - if(it is ScannerOutput.Status) { + if (it is ScannerOutput.Status) { actualScannerStatusEnumFlow.emit(it.scannerStatus.toScannerSimpleStatus()) } } @@ -76,8 +75,8 @@ class ParityFlowScannerController(dataWedgeHardwareScanner: DataWedgeHardwareSca Log.d("ParityFlowScannerController", "scannerStatusParityFlow: $actual, $desired") if (actual != desired) { when (desired) { - ScannerSimpleStatus.Disabled -> dataWedgeHardwareScanner.suspendScanner() - ScannerSimpleStatus.Enabled -> dataWedgeHardwareScanner.resumeScanner() + ScannerSimpleStatus.Disabled -> dataWedgeIHardwareScanner.suspendScanner() + ScannerSimpleStatus.Enabled -> dataWedgeIHardwareScanner.resumeScanner() } } }.collect() diff --git a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ScannerController.kt b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ScannerController.kt index 2ea044a..7841470 100644 --- a/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ScannerController.kt +++ b/kotlin-data-wedge-lib/src/main/java/dk/gls/kdw/configuration/scanner/ScannerController.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow * The scanner controller makes it possible to suspend and resume the scanner and monitor [ScannerOutput] using a Flow */ abstract class ScannerController( - val dataWedgeHardwareScanner: DataWedgeHardwareScanner + val dataWedgeIHardwareScanner: IHardwareScanner ) { abstract fun scannerOutputFlow(): Flow @@ -16,6 +16,5 @@ abstract class ScannerController( abstract fun resumeScanner() - abstract fun remoteScannerNotification(deviceId: DeviceId, notifications: List) - + abstract fun remoteScannerNotifications(deviceId: DeviceId, vararg notifications: List) } \ No newline at end of file