mirror of
https://github.com/oliexdev/openScale.git
synced 2025-10-28 22:27:38 +01:00
Saved Bluetooth device information by storing and retrieving the manufacturerData. This provides more complete device data for reconnection and debugging purposes.
This commit is contained in:
@@ -161,7 +161,7 @@ class MiScaleHandler : ScaleDeviceHandler() {
|
|||||||
} else {
|
} else {
|
||||||
// ---- v2: keep robust modern order (same as legacy v2 effectively) ----
|
// ---- v2: keep robust modern order (same as legacy v2 effectively) ----
|
||||||
setNotifyOn(svcPrimary, CHAR_MI_HISTORY)
|
setNotifyOn(svcPrimary, CHAR_MI_HISTORY)
|
||||||
runCatching { setNotifyOn(svcPrimary, CHAR_WEIGHT_MEAS) } // optional
|
// runCatching { setNotifyOn(svcPrimary, CHAR_WEIGHT_MEAS) } // optional
|
||||||
writeTo(svcPrimary, CHAR_MI_HISTORY, ENABLE_HISTORY_MAGIC, withResponse = true)
|
writeTo(svcPrimary, CHAR_MI_HISTORY, ENABLE_HISTORY_MAGIC, withResponse = true)
|
||||||
|
|
||||||
val uniq = unique16()
|
val uniq = unique16()
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
package com.health.openscale.core.facade
|
package com.health.openscale.core.facade
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.SparseArray
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||||
@@ -47,12 +49,14 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import androidx.core.util.size
|
||||||
|
import org.json.JSONObject
|
||||||
|
import androidx.core.util.isNotEmpty
|
||||||
|
|
||||||
// DataStore instance for user settings
|
// DataStore instance for user settings
|
||||||
val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
|
val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
|
||||||
@@ -78,6 +82,8 @@ object SettingsPreferenceKeys {
|
|||||||
val SAVED_BLUETOOTH_DEVICE_RSSI = intPreferencesKey("saved_bluetooth_device_rssi")
|
val SAVED_BLUETOOTH_DEVICE_RSSI = intPreferencesKey("saved_bluetooth_device_rssi")
|
||||||
val SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS = stringSetPreferencesKey("saved_bluetooth_device_service_uuids")
|
val SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS = stringSetPreferencesKey("saved_bluetooth_device_service_uuids")
|
||||||
val SAVED_BLUETOOTH_DEVICE_HANDLER_HINT = stringPreferencesKey("saved_bluetooth_device_handler_hint")
|
val SAVED_BLUETOOTH_DEVICE_HANDLER_HINT = stringPreferencesKey("saved_bluetooth_device_handler_hint")
|
||||||
|
val SAVED_BLUETOOTH_DEVICE_MANUFACTURER_DATA = stringPreferencesKey("saved_bluetooth_device_manufacturer_data")
|
||||||
|
|
||||||
val SAVED_BLUETOOTH_TUNE_PROFILE = stringPreferencesKey("saved_bluetooth_tune_profile")
|
val SAVED_BLUETOOTH_TUNE_PROFILE = stringPreferencesKey("saved_bluetooth_tune_profile")
|
||||||
|
|
||||||
// Settings for chart
|
// Settings for chart
|
||||||
@@ -390,8 +396,16 @@ class SettingsFacadeImpl @Inject constructor(
|
|||||||
val rssiF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_RSSI.name, 0)
|
val rssiF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_RSSI.name, 0)
|
||||||
val uuidsF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS.name, emptySet<String>())
|
val uuidsF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS.name, emptySet<String>())
|
||||||
val hintF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT.name, null as String?)
|
val hintF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT.name, null as String?)
|
||||||
|
val manDataF = observeSetting(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_MANUFACTURER_DATA.name, null as String?)
|
||||||
|
|
||||||
|
return combine(addrF, nameF, rssiF, uuidsF, hintF, manDataF) { array ->
|
||||||
|
val addr = array[0] as String?
|
||||||
|
val name = array[1] as String?
|
||||||
|
val rssi = array[2] as Int
|
||||||
|
val uuidStrSet = (array[3] as? Set<*>)?.filterIsInstance<String>() ?: emptySet()
|
||||||
|
val hint = array[4] as String?
|
||||||
|
val manDataJson = array[5] as String?
|
||||||
|
|
||||||
return combine(addrF, nameF, rssiF, uuidsF, hintF) { addr, name, rssi, uuidStrSet, hint ->
|
|
||||||
if (addr.isNullOrBlank() || name.isNullOrBlank()) {
|
if (addr.isNullOrBlank() || name.isNullOrBlank()) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@@ -400,12 +414,24 @@ class SettingsFacadeImpl @Inject constructor(
|
|||||||
.mapNotNull { runCatching { UUID.fromString(it) }.getOrNull() }
|
.mapNotNull { runCatching { UUID.fromString(it) }.getOrNull() }
|
||||||
.sortedBy { it.toString() }
|
.sortedBy { it.toString() }
|
||||||
|
|
||||||
|
// ManufacturerData
|
||||||
|
val manData = SparseArray<ByteArray>()
|
||||||
|
manDataJson?.let { jsonStr ->
|
||||||
|
runCatching {
|
||||||
|
val jsonObj = JSONObject(jsonStr)
|
||||||
|
jsonObj.keys().forEach { key ->
|
||||||
|
val value = Base64.decode(jsonObj.getString(key), Base64.NO_WRAP)
|
||||||
|
manData.put(key.toInt(), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScannedDeviceInfo(
|
ScannedDeviceInfo(
|
||||||
name = name,
|
name = name,
|
||||||
address = addr,
|
address = addr,
|
||||||
rssi = rssi,
|
rssi = rssi,
|
||||||
serviceUuids = uuids,
|
serviceUuids = uuids,
|
||||||
manufacturerData = null,
|
manufacturerData = if (manData.isNotEmpty()) manData else null,
|
||||||
isSupported = false,
|
isSupported = false,
|
||||||
determinedHandlerDisplayName = hint
|
determinedHandlerDisplayName = hint
|
||||||
)
|
)
|
||||||
@@ -418,7 +444,7 @@ class SettingsFacadeImpl @Inject constructor(
|
|||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun saveSavedDevice(device: com.health.openscale.core.service.ScannedDeviceInfo) {
|
override suspend fun saveSavedDevice(device: ScannedDeviceInfo) {
|
||||||
LogManager.i(TAG, "Saving device snapshot: addr=${device.address}, name=${device.name}, uuids=${device.serviceUuids.size}, hint=${device.determinedHandlerDisplayName}")
|
LogManager.i(TAG, "Saving device snapshot: addr=${device.address}, name=${device.name}, uuids=${device.serviceUuids.size}, hint=${device.determinedHandlerDisplayName}")
|
||||||
dataStore.edit { prefs ->
|
dataStore.edit { prefs ->
|
||||||
prefs[SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_ADDRESS] = device.address
|
prefs[SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_ADDRESS] = device.address
|
||||||
@@ -428,6 +454,16 @@ class SettingsFacadeImpl @Inject constructor(
|
|||||||
device.determinedHandlerDisplayName?.let {
|
device.determinedHandlerDisplayName?.let {
|
||||||
prefs[SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT] = it
|
prefs[SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT] = it
|
||||||
} ?: prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT)
|
} ?: prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT)
|
||||||
|
|
||||||
|
val manData = JSONObject()
|
||||||
|
device.manufacturerData?.let { sparse ->
|
||||||
|
for (i in 0 until sparse.size) {
|
||||||
|
val key = sparse.keyAt(i).toString()
|
||||||
|
val value = Base64.encodeToString(sparse.valueAt(i), Base64.NO_WRAP)
|
||||||
|
manData.put(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prefs[SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_MANUFACTURER_DATA] = manData.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +475,7 @@ class SettingsFacadeImpl @Inject constructor(
|
|||||||
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_RSSI)
|
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_RSSI)
|
||||||
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS)
|
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_SERVICE_UUIDS)
|
||||||
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT)
|
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_HANDLER_HINT)
|
||||||
|
prefs.remove(SettingsPreferenceKeys.SAVED_BLUETOOTH_DEVICE_MANUFACTURER_DATA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user