From e5e670835a23872d0caf32784ed2b5feb9f12d4d Mon Sep 17 00:00:00 2001 From: oliexdev Date: Wed, 13 Aug 2025 09:08:12 +0200 Subject: [PATCH] Refactor ScaleFactory and BluetoothScannerManager to use ScannedDeviceInfo --- .../openscale/core/bluetooth/ScaleFactory.kt | 62 +++++++++---------- .../bluetooth/BluetoothScannerManager.kt | 16 +++-- .../ui/screen/bluetooth/BluetoothViewModel.kt | 14 ++--- 3 files changed, 41 insertions(+), 51 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/ScaleFactory.kt b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/ScaleFactory.kt index 019e5171..a79c8f2f 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/ScaleFactory.kt +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/ScaleFactory.kt @@ -17,6 +17,8 @@ */ package com.health.openscale.core.bluetooth +import android.R.attr.identifier +import android.R.attr.name import android.content.Context import android.util.SparseArray import com.health.openscale.core.bluetooth.scales.DummyScaleHandler @@ -77,9 +79,7 @@ class ScaleFactory( // List of modern Kotlin-based device handlers. // These are checked first for device compatibility. private val modernKotlinHandlers: List = listOf( - DummyScaleHandler("Mi Scale"), // Recognizes devices with "Mi Scale" in their name - DummyScaleHandler("Beurer"), // Recognizes devices with "Beurer" in their name - DummyScaleHandler("BF700") // Recognizes devices with "BF700" in their name + DummyScaleHandler("Test") // Recognizes devices with "Test" in their name ) /** @@ -87,11 +87,20 @@ class ScaleFactory( * This method contains the logic to map device names to specific Java driver classes. * * @param context The application context. - * @param deviceName The name of the Bluetooth device. + * @param deviceInfo Information about the scanned Bluetooth device. * @return A [BluetoothCommunication] instance if a matching driver is found, otherwise null. */ - private fun createLegacyJavaDriver(context: Context?, deviceName: String): BluetoothCommunication? { - val name = deviceName.lowercase() + private fun createLegacyJavaDriver(context: Context?, deviceInfo: ScannedDeviceInfo): BluetoothCommunication? { + val deviceName : String + val name : String + + if (deviceInfo.name != null) { + deviceName = deviceInfo.name + name = deviceInfo.name.lowercase() + } else { + deviceName = deviceInfo.determinedHandlerDisplayName ?: "UnknownDevice" + name = deviceInfo.determinedHandlerDisplayName?.lowercase() ?: "UnknownDevice" + } if (name.startsWith("BEURER BF700".lowercase()) || name.startsWith("BEURER BF800".lowercase()) @@ -256,11 +265,11 @@ class ScaleFactory( * Creates a [ScaleCommunicator] using the legacy Java driver approach. * It wraps a [BluetoothCommunication] instance (Java driver) in a [LegacyScaleAdapter]. * - * @param identifier The device name or other identifier used to find a legacy Java driver. + * @param deviceInfo The device information used to find a legacy Java driver. * @return A [LegacyScaleAdapter] instance if a suitable Java driver is found, otherwise null. */ - private fun createLegacyCommunicator(identifier: String): ScaleCommunicator? { - val javaDriverInstance = createLegacyJavaDriver(applicationContext, identifier) + private fun createLegacyCommunicator(deviceInfo: ScannedDeviceInfo): ScaleCommunicator? { + val javaDriverInstance = createLegacyJavaDriver(applicationContext, deviceInfo) return if (javaDriverInstance != null) { LogManager.i(TAG, "Creating LegacyScaleAdapter with Java driver '${javaDriverInstance.javaClass.simpleName}'.") LegacyScaleAdapter( @@ -269,7 +278,7 @@ class ScaleFactory( databaseRepository = databaseRepository ) } else { - LogManager.w(TAG, "Could not create LegacyScaleAdapter: No Java driver found for '$identifier'.") + LogManager.w(TAG, "Could not create LegacyScaleAdapter: No Java driver found for '${deviceInfo.name}'.") null } } @@ -332,12 +341,10 @@ class ScaleFactory( LogManager.d(TAG, "No modern Kotlin handler actively claimed '${primaryIdentifier}' or could create a communicator.") // 2. Fallback to legacy adapter if no modern handler matched or created a communicator. - // The device name (or a specific legacy handler name, if known from `determinedHandlerDisplayName`) is used. - val identifierForLegacy = deviceInfo.determinedHandlerDisplayName ?: primaryIdentifier - LogManager.i(TAG, "Attempting fallback to legacy adapter for identifier '${identifierForLegacy}'.") - val legacyCommunicator = createLegacyCommunicator(identifierForLegacy) + LogManager.i(TAG, "Attempting fallback to legacy adapter for identifier '${deviceInfo.name}'.") + val legacyCommunicator = createLegacyCommunicator(deviceInfo) if (legacyCommunicator != null) { - LogManager.i(TAG, "Legacy communicator '${legacyCommunicator.javaClass.simpleName}' created for device (identifier: '${identifierForLegacy}').") + LogManager.i(TAG, "Legacy communicator '${legacyCommunicator.javaClass.simpleName}' created for device ('${deviceInfo.name}').") return legacyCommunicator } @@ -349,39 +356,26 @@ class ScaleFactory( * Checks if any known handler (modern Kotlin or legacy Java-based) can theoretically support the given device. * This can be used by the UI to indicate if a device is potentially recognizable. * - * @param deviceName The name of the Bluetooth device. - * @param deviceAddress The MAC address of the device. - * @param serviceUuids A list of advertised service UUIDs. - * @param manufacturerData Manufacturer-specific data from the advertisement. + * @param deviceInfo Information about the scanned Bluetooth device. * @return A Pair where `first` is true if a handler is found, and `second` is the name of the handler/driver, or null. */ - fun getSupportingHandlerInfo( - deviceName: String?, - deviceAddress: String, - serviceUuids: List, - manufacturerData: SparseArray? - ): Pair { - val primaryIdentifier = deviceName ?: "UnknownDevice" - // LogManager.d(TAG, "getSupportingHandlerInfo for: '$primaryIdentifier', Addr: $deviceAddress, UUIDs: ${serviceUuids.size}, ManuData: ${manufacturerData != null}") - + fun getSupportingHandlerInfo(deviceInfo : ScannedDeviceInfo): Pair { // Check modern handlers first for (handler in modernKotlinHandlers) { - if (handler.canHandleDevice(deviceName, deviceAddress, serviceUuids, manufacturerData)) { - // LogManager.d(TAG, "getSupportingHandlerInfo: Modern handler '${handler.getDriverName()}' matches '$primaryIdentifier'.") + if (handler.canHandleDevice(deviceInfo.name, deviceInfo.address, deviceInfo.serviceUuids, deviceInfo.manufacturerData)) { return true to handler.getDriverName() // The "driver name" of the modern handler } } // Then check if a legacy driver would exist based on the name - if (deviceName != null) { - val legacyJavaDriver = createLegacyJavaDriver(applicationContext, deviceName) + if (deviceInfo.name != null) { + val legacyJavaDriver = createLegacyJavaDriver(applicationContext, deviceInfo) if (legacyJavaDriver != null) { - // LogManager.d(TAG, "getSupportingHandlerInfo: Legacy driver '${legacyJavaDriver.javaClass.simpleName}' matches '$deviceName'.") // Return the driver name from the BluetoothCommunication interface if available and meaningful. return true to legacyJavaDriver.driverName() // Assumes BluetoothCommunication has a driverName() method. } } - LogManager.d(TAG, "getSupportingHandlerInfo: No supporting handler found for '$primaryIdentifier'.") + LogManager.d(TAG, "getSupportingHandlerInfo: No supporting handler found for ${deviceInfo.name}.") return false to null } } diff --git a/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothScannerManager.kt b/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothScannerManager.kt index 40b9188e..45043c04 100644 --- a/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothScannerManager.kt +++ b/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothScannerManager.kt @@ -250,23 +250,21 @@ class BluetoothScannerManager( val serviceUuids: List = scanResult.scanRecord?.serviceUuids?.mapNotNull { it?.uuid } ?: emptyList() val manufacturerData: SparseArray? = scanResult.scanRecord?.manufacturerSpecificData - val (isSupported, handlerName) = scaleFactory.getSupportingHandlerInfo( - deviceName = deviceName, - deviceAddress = deviceAddress, - serviceUuids = serviceUuids, - manufacturerData = manufacturerData - ) - val newDevice = ScannedDeviceInfo( name = deviceName, address = deviceAddress, rssi = rssi, serviceUuids = serviceUuids, manufacturerData = manufacturerData, - isSupported = isSupported, - determinedHandlerDisplayName = handlerName + isSupported = false, // will be determined in the next getSupportingHandlerInfo + determinedHandlerDisplayName = null // // will be determined in the next getSupportingHandlerInfo ) + val (isSupported, handlerName) = scaleFactory.getSupportingHandlerInfo(newDevice) + + newDevice.isSupported = isSupported + newDevice.determinedHandlerDisplayName = handlerName + val existingDevice = deviceMap[newDevice.address] var listShouldBeUpdated = false diff --git a/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothViewModel.kt b/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothViewModel.kt index ead04e88..1b66c88e 100644 --- a/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothViewModel.kt +++ b/android_app/app/src/main/java/com/health/openscale/ui/screen/bluetooth/BluetoothViewModel.kt @@ -344,12 +344,6 @@ class BluetoothViewModel( // For a saved device, we need to re-evaluate its support status using ScaleFactory, // as supported handlers might change with app updates. LogManager.d(TAG, "Re-evaluating support for saved device '$name' ($address) using ScaleFactory.") - val (isPotentiallySupported, handlerNameFromFactory) = scaleFactory.getSupportingHandlerInfo( - deviceName = name, - deviceAddress = address, - serviceUuids = emptyList(), // Service UUIDs are unknown without a fresh scan. - manufacturerData = null // Manufacturer data is unknown without a fresh scan. - ) val deviceInfoForConnect = ScannedDeviceInfo( name = name, @@ -357,10 +351,14 @@ class BluetoothViewModel( rssi = 0, // RSSI is not relevant for a direct connection attempt to a saved device. serviceUuids = emptyList(), manufacturerData = null, - isSupported = isPotentiallySupported, // Use current support assessment. - determinedHandlerDisplayName = handlerNameFromFactory + isSupported = false, // will be determined by getSupportingHandlerInfo + determinedHandlerDisplayName = null // will be determined by getSupportingHandlerInfo ) + val (isPotentiallySupported, handlerNameFromFactory) = scaleFactory.getSupportingHandlerInfo(deviceInfoForConnect) + deviceInfoForConnect.isSupported = isPotentiallySupported + deviceInfoForConnect.determinedHandlerDisplayName = handlerNameFromFactory + if (!deviceInfoForConnect.isSupported) { LogManager.w(TAG, "Saved device '$name' ($address) is currently not supported by ScaleFactory. Connection aborted.") // This error is specific to connecting to a *saved* device that's no longer supported.