kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Refactor NsdManager and improve service display (#2292)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>pull/2309/head
rodzic
ec74bbfe19
commit
8b095aba09
|
|
@ -68,8 +68,9 @@ class BTScanModel @Inject constructor(
|
||||||
val devices = MutableLiveData<MutableMap<String, DeviceListEntry>>(mutableMapOf())
|
val devices = MutableLiveData<MutableMap<String, DeviceListEntry>>(mutableMapOf())
|
||||||
val errorText = MutableLiveData<String?>(null)
|
val errorText = MutableLiveData<String?>(null)
|
||||||
|
|
||||||
private val showMockInterface: StateFlow<Boolean> get() =
|
private val showMockInterface: StateFlow<Boolean>
|
||||||
MutableStateFlow(radioInterfaceService.isMockInterface()).asStateFlow()
|
get() =
|
||||||
|
MutableStateFlow(radioInterfaceService.isMockInterface()).asStateFlow()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
combine(
|
combine(
|
||||||
|
|
@ -84,7 +85,13 @@ class BTScanModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include a placeholder for "None"
|
// Include a placeholder for "None"
|
||||||
addDevice(DeviceListEntry(context.getString(R.string.none), NO_DEVICE_SELECTED, true))
|
addDevice(
|
||||||
|
DeviceListEntry(
|
||||||
|
context.getString(R.string.none),
|
||||||
|
NO_DEVICE_SELECTED,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if (showMockInterface) {
|
if (showMockInterface) {
|
||||||
addDevice(DeviceListEntry("Demo Mode", "m", true))
|
addDevice(DeviceListEntry("Demo Mode", "m", true))
|
||||||
|
|
@ -97,7 +104,19 @@ class BTScanModel @Inject constructor(
|
||||||
// Include Network Service Discovery
|
// Include Network Service Discovery
|
||||||
tcp.forEach { service ->
|
tcp.forEach { service ->
|
||||||
val address = service.toAddressString()
|
val address = service.toAddressString()
|
||||||
addDevice(DeviceListEntry(address, "t$address", true))
|
val txtRecords = service.attributes // Map<String, ByteArray?>
|
||||||
|
val shortNameBytes = txtRecords["shortname"]
|
||||||
|
val idBytes = txtRecords["id"]
|
||||||
|
|
||||||
|
val shortName = shortNameBytes?.let { String(it, Charsets.UTF_8) }
|
||||||
|
?: context.getString(R.string.meshtastic)
|
||||||
|
val deviceId =
|
||||||
|
idBytes?.let { String(it, Charsets.UTF_8) }?.replace("!", "")
|
||||||
|
var displayName = shortName
|
||||||
|
if (deviceId != null) {
|
||||||
|
displayName += "_$deviceId"
|
||||||
|
}
|
||||||
|
addDevice(DeviceListEntry(displayName, "t$address", true))
|
||||||
}
|
}
|
||||||
|
|
||||||
usb.forEach { (_, d) ->
|
usb.forEach { (_, d) ->
|
||||||
|
|
@ -160,10 +179,6 @@ class BTScanModel @Inject constructor(
|
||||||
|
|
||||||
private var scanJob: Job? = null
|
private var scanJob: Job? = null
|
||||||
|
|
||||||
val selectedAddress get() = radioInterfaceService.getDeviceAddress()
|
|
||||||
val selectedBluetooth: Boolean get() = selectedAddress?.getOrNull(0) == 'x'
|
|
||||||
|
|
||||||
// / Use the string for the NopInterface
|
|
||||||
val selectedAddressFlow: StateFlow<String?> = radioInterfaceService.currentDeviceAddressFlow
|
val selectedAddressFlow: StateFlow<String?> = radioInterfaceService.currentDeviceAddressFlow
|
||||||
|
|
||||||
val selectedNotNullFlow: StateFlow<String> = selectedAddressFlow
|
val selectedNotNullFlow: StateFlow<String> = selectedAddressFlow
|
||||||
|
|
|
||||||
|
|
@ -41,16 +41,13 @@ class NetworkRepository @Inject constructor(
|
||||||
.conflate()
|
.conflate()
|
||||||
|
|
||||||
val resolvedList: Flow<List<NsdServiceInfo>>
|
val resolvedList: Flow<List<NsdServiceInfo>>
|
||||||
get() = nsdManagerLazy.get().serviceList(SERVICE_TYPES, SERVICE_NAME)
|
get() = nsdManagerLazy.get().serviceList(SERVICE_TYPE)
|
||||||
.flowOn(dispatchers.io)
|
.flowOn(dispatchers.io)
|
||||||
.conflate()
|
.conflate()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// To find all available services use SERVICE_TYPE = "_services._dns-sd._udp"
|
|
||||||
internal const val SERVICE_NAME = "Meshtastic"
|
|
||||||
internal const val SERVICE_PORT = 4403
|
internal const val SERVICE_PORT = 4403
|
||||||
private const val SERVICE_TYPE = "_meshtastic._tcp"
|
private const val SERVICE_TYPE = "_meshtastic._tcp"
|
||||||
internal val SERVICE_TYPES = setOf("_http._tcp", SERVICE_TYPE)
|
|
||||||
|
|
||||||
fun NsdServiceInfo.toAddressString() = buildString {
|
fun NsdServiceInfo.toAddressString() = buildString {
|
||||||
append(@Suppress("DEPRECATION") host.toString().substring(1))
|
append(@Suppress("DEPRECATION") host.toString().substring(1))
|
||||||
|
|
|
||||||
|
|
@ -24,27 +24,16 @@ import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal fun NsdManager.serviceList(
|
|
||||||
serviceTypes: Set<String>,
|
|
||||||
serviceName: String,
|
|
||||||
): Flow<List<NsdServiceInfo>> {
|
|
||||||
val flows = serviceTypes.map { serviceType -> serviceList(serviceType, serviceName) }
|
|
||||||
return combine(flows) { lists -> lists.flatMap { it } }
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
internal fun NsdManager.serviceList(
|
internal fun NsdManager.serviceList(
|
||||||
serviceType: String,
|
serviceType: String,
|
||||||
serviceName: String,
|
|
||||||
): Flow<List<NsdServiceInfo>> = discoverServices(serviceType).mapLatest { serviceList ->
|
): Flow<List<NsdServiceInfo>> = discoverServices(serviceType).mapLatest { serviceList ->
|
||||||
serviceList
|
serviceList
|
||||||
.filter { it.serviceName.contains(serviceName) }
|
|
||||||
.mapNotNull { resolveService(it) }
|
.mapNotNull { resolveService(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,11 @@ fun DeviceListItem(
|
||||||
contentDescription
|
contentDescription
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
supportingContent = {
|
||||||
|
if (device.isTCP) {
|
||||||
|
Text(device.address)
|
||||||
|
}
|
||||||
|
},
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
Icon(
|
Icon(
|
||||||
|
|
|
||||||
|
|
@ -705,4 +705,5 @@
|
||||||
<string name="no_network_devices">No Network devices found.</string>
|
<string name="no_network_devices">No Network devices found.</string>
|
||||||
<string name="no_usb_devices">No USB Serial devices found.</string>
|
<string name="no_usb_devices">No USB Serial devices found.</string>
|
||||||
<string name="scroll_to_bottom">Scroll to bottom</string>
|
<string name="scroll_to_bottom">Scroll to bottom</string>
|
||||||
|
<string name="meshtastic">Meshtastic</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue