mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat(widget): Add Local Stats glance widget (#4642)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
692ad78c80
commit
9970d31520
23 changed files with 1256 additions and 24 deletions
|
|
@ -42,11 +42,13 @@ import org.meshtastic.core.database.entity.MyNodeEntity
|
|||
import org.meshtastic.core.database.entity.NodeEntity
|
||||
import org.meshtastic.core.database.model.Node
|
||||
import org.meshtastic.core.database.model.NodeSortOption
|
||||
import org.meshtastic.core.datastore.LocalStatsDataSource
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
import org.meshtastic.core.di.ProcessLifecycle
|
||||
import org.meshtastic.core.model.DataPacket
|
||||
import org.meshtastic.core.model.util.onlineTimeThreshold
|
||||
import org.meshtastic.proto.HardwareModel
|
||||
import org.meshtastic.proto.LocalStats
|
||||
import org.meshtastic.proto.User
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -57,10 +59,11 @@ import javax.inject.Singleton
|
|||
class NodeRepository
|
||||
@Inject
|
||||
constructor(
|
||||
@ProcessLifecycle processLifecycle: Lifecycle,
|
||||
@ProcessLifecycle private val processLifecycle: Lifecycle,
|
||||
private val nodeInfoReadDataSource: NodeInfoReadDataSource,
|
||||
private val nodeInfoWriteDataSource: NodeInfoWriteDataSource,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val localStatsDataSource: LocalStatsDataSource,
|
||||
) {
|
||||
/** Hardware info about our local device (can be null if not connected). */
|
||||
val myNodeInfo: StateFlow<MyNodeEntity?> =
|
||||
|
|
@ -81,6 +84,19 @@ constructor(
|
|||
val myId: StateFlow<String?>
|
||||
get() = _myId
|
||||
|
||||
/** The latest local stats telemetry received from the locally connected node. */
|
||||
val localStats: StateFlow<LocalStats> =
|
||||
localStatsDataSource.localStatsFlow.stateIn(
|
||||
processLifecycle.coroutineScope,
|
||||
SharingStarted.Eagerly,
|
||||
LocalStats(),
|
||||
)
|
||||
|
||||
/** Update the cached local stats telemetry. */
|
||||
fun updateLocalStats(stats: LocalStats) {
|
||||
processLifecycle.coroutineScope.launch { localStatsDataSource.setLocalStats(stats) }
|
||||
}
|
||||
|
||||
/** A reactive map from nodeNum to [Node] objects, representing the entire mesh. */
|
||||
val nodeDBbyNum: StateFlow<Map<Int, Node>> =
|
||||
nodeInfoReadDataSource
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.meshtastic.core.data.datasource.NodeInfoReadDataSource
|
|||
import org.meshtastic.core.data.datasource.NodeInfoWriteDataSource
|
||||
import org.meshtastic.core.database.entity.MeshLog
|
||||
import org.meshtastic.core.database.entity.MyNodeEntity
|
||||
import org.meshtastic.core.datastore.LocalStatsDataSource
|
||||
import org.meshtastic.core.di.CoroutineDispatchers
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
|
@ -49,6 +50,7 @@ class NodeRepositoryTest {
|
|||
private val writeDataSource: NodeInfoWriteDataSource = mockk(relaxed = true)
|
||||
private val lifecycle: Lifecycle = mockk(relaxed = true)
|
||||
private val lifecycleScope: LifecycleCoroutineScope = mockk()
|
||||
private val localStatsDataSource: LocalStatsDataSource = mockk(relaxed = true)
|
||||
|
||||
private val testDispatcher = StandardTestDispatcher()
|
||||
private val dispatchers = CoroutineDispatchers(main = testDispatcher, io = testDispatcher, default = testDispatcher)
|
||||
|
|
@ -88,7 +90,8 @@ class NodeRepositoryTest {
|
|||
val myNodeNum = 12345
|
||||
myNodeInfoFlow.value = createMyNodeEntity(myNodeNum)
|
||||
|
||||
val repository = NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers)
|
||||
val repository =
|
||||
NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers, localStatsDataSource)
|
||||
testScheduler.runCurrent()
|
||||
|
||||
val result = repository.effectiveLogNodeId(myNodeNum).filter { it == MeshLog.NODE_NUM_LOCAL }.first()
|
||||
|
|
@ -102,7 +105,8 @@ class NodeRepositoryTest {
|
|||
val remoteNodeNum = 67890
|
||||
myNodeInfoFlow.value = createMyNodeEntity(myNodeNum)
|
||||
|
||||
val repository = NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers)
|
||||
val repository =
|
||||
NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers, localStatsDataSource)
|
||||
testScheduler.runCurrent()
|
||||
|
||||
val result = repository.effectiveLogNodeId(remoteNodeNum).first()
|
||||
|
|
@ -117,7 +121,8 @@ class NodeRepositoryTest {
|
|||
val targetNodeNum = 111
|
||||
|
||||
myNodeInfoFlow.value = createMyNodeEntity(firstNodeNum)
|
||||
val repository = NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers)
|
||||
val repository =
|
||||
NodeRepository(lifecycle, readDataSource, writeDataSource, dispatchers, localStatsDataSource)
|
||||
testScheduler.runCurrent()
|
||||
|
||||
// Initially should be mapped to LOCAL because it matches
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue