Skip to content

Commit 1daa1b7

Browse files
committed
add stoppable iperf test
1 parent 96ad964 commit 1daa1b7

16 files changed

+301
-262
lines changed

app/src/main/java/com/lcl/lclmeasurementtool/MainActivity2.kt

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -46,46 +46,11 @@ class MainActivity2 : ComponentActivity() {
4646
lateinit var simStateMonitor: SimStateMonitor
4747

4848
val viewModel: MainActivityViewModel by viewModels()
49-
val signalVM: SignalStrengthViewModel by viewModels()
50-
val connectivityVM: ConnectivityViewModel by viewModels()
51-
52-
val signals = listOf(
53-
SignalStrengthReportModel("deviceID1", 123.121, 456.451, "timestamp1", "cellID1", -81, 1),
54-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp2", "cellID2", -82, 2),
55-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp3", "cellID2", -82, 2),
56-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp4", "cellID2", -82, 2),
57-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp5", "cellID2", -82, 2),
58-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp6", "cellID2", -82, 2),
59-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp7", "cellID2", -82, 2),
60-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp8", "cellID2", -82, 2),
61-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp9", "cellID2", -82, 2),
62-
SignalStrengthReportModel("deviceID2", 123.122, 456.452, "timestamp10", "cellID2", -82, 2),
63-
)
64-
65-
val connectivities = listOf(
66-
ConnectivityReportModel(123.123, 345.345, "timestamp1", "hi1", "deviceID1", 123.31, 345.51, 23.21, 0.0),
67-
ConnectivityReportModel(123.123, 345.345, "timestamp2", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
68-
ConnectivityReportModel(123.123, 345.345, "timestamp3", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
69-
ConnectivityReportModel(123.123, 345.345, "timestamp4", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
70-
ConnectivityReportModel(123.123, 345.345, "timestamp5", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
71-
ConnectivityReportModel(123.123, 345.345, "timestamp6", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
72-
ConnectivityReportModel(123.123, 345.345, "timestamp7", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
73-
ConnectivityReportModel(123.123, 345.345, "timestamp8", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
74-
ConnectivityReportModel(123.123, 345.345, "timestamp9", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
75-
ConnectivityReportModel(123.123, 345.345, "timestamp10", "hi2", "deviceID2", 123.32, 345.52, 23.22, 10.3),
76-
)
7749

7850
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
7951
override fun onCreate(savedInstanceState: Bundle?) {
8052

8153
super.onCreate(savedInstanceState)
82-
signals.forEach {
83-
signalVM.insert(it)
84-
}
85-
86-
connectivities.forEach {
87-
connectivityVM.insert(it)
88-
}
8954

9055
if (!hasPermission()) {
9156
XXPermissions.with(this)
@@ -119,9 +84,6 @@ class MainActivity2 : ComponentActivity() {
11984
}
12085
}
12186

122-
123-
124-
12587
var uiState: MainActivityUiState by mutableStateOf(MainActivityUiState.Login)
12688

12789
lifecycleScope.launch {
@@ -141,6 +103,7 @@ class MainActivity2 : ComponentActivity() {
141103
WindowCompat.setDecorFitsSystemWindows(window, false)
142104
setContent {
143105
// if (uiState == MainActivityUiState.Login) {
106+
// viewModel.setDeviceId(UUID.randomUUID().toString())
144107
// Login(viewModel = viewModel)
145108
// return@setContent
146109
// }

app/src/main/java/com/lcl/lclmeasurementtool/MainActivityViewModel.kt

Lines changed: 139 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.lcl.lclmeasurementtool
22

33
import android.content.Context
4+
import android.location.Location
45
import android.os.Build
56
import android.telephony.CellSignalStrength
67
import android.util.Log
@@ -14,7 +15,6 @@ import com.kongzue.dialogx.dialogs.TipDialog
1415
import com.lcl.lclmeasurementtool.Utils.ECDSA
1516
import com.lcl.lclmeasurementtool.Utils.Hex
1617
import com.lcl.lclmeasurementtool.Utils.SecurityUtils
17-
import com.lcl.lclmeasurementtool.Utils.SignalStrengthLevel
1818
import com.lcl.lclmeasurementtool.constants.NetworkConstants
1919
import com.lcl.lclmeasurementtool.features.iperf.IperfRunner
2020
import com.lcl.lclmeasurementtool.features.iperf.IperfStatus
@@ -23,13 +23,15 @@ import com.lcl.lclmeasurementtool.features.ping.PingError
2323
import com.lcl.lclmeasurementtool.features.ping.PingErrorCase
2424
import com.lcl.lclmeasurementtool.features.ping.PingResult
2525
import com.lcl.lclmeasurementtool.location.LocationService
26-
import com.lcl.lclmeasurementtool.model.datamodel.QRCodeKeysModel
27-
import com.lcl.lclmeasurementtool.model.datamodel.RegistrationModel
28-
import com.lcl.lclmeasurementtool.model.datamodel.UserData
26+
import com.lcl.lclmeasurementtool.model.datamodel.*
27+
import com.lcl.lclmeasurementtool.model.repository.ConnectivityRepository
2928
import com.lcl.lclmeasurementtool.model.repository.NetworkApiRepository
29+
import com.lcl.lclmeasurementtool.model.repository.SignalStrengthRepository
3030
import com.lcl.lclmeasurementtool.model.repository.UserDataRepository
3131
import com.lcl.lclmeasurementtool.telephony.SignalStrengthLevelEnum
3232
import com.lcl.lclmeasurementtool.telephony.SignalStrengthMonitor
33+
import com.lcl.lclmeasurementtool.ui.LCLLoadingWheel
34+
import com.lcl.lclmeasurementtool.util.TimeUtil
3335
import dagger.hilt.android.lifecycle.HiltViewModel
3436
import kotlinx.coroutines.*
3537
import kotlinx.coroutines.flow.*
@@ -44,7 +46,9 @@ class MainActivityViewModel @Inject constructor(
4446
private val userDataRepository: UserDataRepository,
4547
private val networkApi: NetworkApiRepository,
4648
private val locationService: LocationService,
47-
private val signalStrengthMonitor: SignalStrengthMonitor
49+
private val signalStrengthMonitor: SignalStrengthMonitor,
50+
private val connectivityRepository: ConnectivityRepository,
51+
private val signalStrengthRepository: SignalStrengthRepository
4852
) : ViewModel() {
4953

5054
companion object {
@@ -60,12 +64,6 @@ class MainActivityViewModel @Inject constructor(
6064
started = SharingStarted.WhileSubscribed(5_000)
6165
)
6266

63-
fun getLocation() = viewModelScope.launch {
64-
locationService.lastLocation().collect {
65-
Log.d(TAG, it.toString())
66-
}
67-
}
68-
6967
// Authentication
7068
fun login(hPKR: ByteString, skT: ByteString) = viewModelScope.launch {
7169
userDataRepository.setKeys(hPKR, skT)
@@ -79,6 +77,14 @@ class MainActivityViewModel @Inject constructor(
7977
userDataRepository.setR(R)
8078
}
8179

80+
fun setDeviceId(id: String) = viewModelScope.launch {
81+
userDataRepository.setDeviceID(id)
82+
}
83+
84+
private val getDeviceID = userDataRepository.userData.map { it.deviceID }
85+
86+
87+
8288
private suspend fun register(registration: RegistrationModel) = networkApi.register(registration)
8389

8490
suspend fun saveAndSend(result: String): LoginStatus {
@@ -202,13 +208,13 @@ class MainActivityViewModel @Inject constructor(
202208

203209

204210
// Network Testing
205-
private val _jobs = mutableListOf<Job>()
206211
private var _pingResult = MutableStateFlow(PingResultState())
207212
private var _downloadResult = MutableStateFlow(ConnectivityTestResult())
208213
private var _uploadResult = MutableStateFlow(ConnectivityTestResult())
209214
private val _isTestActive = MutableStateFlow(false)
210215

211216

217+
val isTestActive = _isTestActive.asStateFlow()
212218
val pingResult: StateFlow<PingResultState> = _pingResult.asStateFlow()
213219
var downloadResult: StateFlow<ConnectivityTestResult> = _downloadResult.asStateFlow()
214220
var uploadResult: StateFlow<ConnectivityTestResult> = _uploadResult.asStateFlow()
@@ -232,9 +238,7 @@ class MainActivityViewModel @Inject constructor(
232238
started = SharingStarted.WhileSubscribed(5_000)
233239
)
234240

235-
val isTestActive = _isTestActive.asStateFlow()
236-
237-
fun doPing() = viewModelScope.launch {
241+
private suspend fun runPing() {
238242
try {
239243
Ping.cancellableStart(address = NetworkConstants.PING_TEST_ADDRESS, timeout = 1000)
240244
.onStart {
@@ -243,9 +247,7 @@ class MainActivityViewModel @Inject constructor(
243247
}
244248
.onCompletion {
245249
if (it != null) {
246-
// save to DB and send over the network
247250
Log.d(TAG, "Error is ${it.message}")
248-
} else {
249251
_isTestActive.value = false
250252
}
251253
}
@@ -261,39 +263,143 @@ class MainActivityViewModel @Inject constructor(
261263
}
262264
}
263265

264-
fun getUploadResult(context: Context) = viewModelScope.launch {
266+
private suspend fun getUploadResult(context: Context) {
265267
IperfRunner().getTestResult(IperfRunner.iperfUploadConfig, context.cacheDir)
266-
.collect { result ->
267-
_uploadResult.value = when(result.status) {
268+
.onStart {
269+
_isTestActive.value = true
270+
}
271+
.onCompletion {
272+
if (it != null) {
273+
// save to DB and send over the network
274+
Log.d(TAG, "Error is ${it.message}")
275+
_isTestActive.value = false
276+
}
277+
}
278+
.collectLatest { result ->
279+
_uploadResult.value = when(result.status) {
268280
IperfStatus.RUNNING -> ConnectivityTestResult.Result(result.bandWidth, Color.LightGray)
269281
IperfStatus.FINISHED -> ConnectivityTestResult.Result(result.bandWidth, Color.Black)
270-
IperfStatus.ERROR -> ConnectivityTestResult.Error(result.errorMSg!!)
282+
IperfStatus.ERROR -> {
283+
_isTestActive.value = false
284+
ConnectivityTestResult.Error(result.errorMSg!!)
285+
}
271286
}
272287
}
273288
}
274289

275290

276-
fun getDownloadResult(context: Context) = viewModelScope.launch {
291+
private suspend fun getDownloadResult(context: Context) {
277292
IperfRunner().getTestResult(IperfRunner.iperfDownloadConfig, context.cacheDir)
293+
.onStart {
294+
_isTestActive.value = true
295+
}
278296
.onCompletion {
279-
_isTestActive.value = false
280-
// TODO: write data to the database
297+
if (it != null) {
298+
// save to DB and send over the network
299+
Log.d(TAG, "Error is ${it.message}")
300+
_isTestActive.value = false
301+
}
281302
}
282-
.collect { result ->
283-
_downloadResult.value = when(result.status) {
303+
.collectLatest { result ->
304+
_downloadResult.value = when(result.status) {
284305
IperfStatus.RUNNING -> ConnectivityTestResult.Result(result.bandWidth, Color.LightGray)
285306
IperfStatus.FINISHED -> ConnectivityTestResult.Result(result.bandWidth, Color.Black)
286-
IperfStatus.ERROR -> ConnectivityTestResult.Error(result.errorMSg!!)
307+
IperfStatus.ERROR -> {
308+
_isTestActive.value = false
309+
ConnectivityTestResult.Error(result.errorMSg!!)
310+
}
311+
}
312+
}
313+
}
314+
315+
private var testJob: Job? = null
316+
317+
fun runTest(context: Context) {
318+
if (testJob?.isActive == true) {
319+
testJob?.cancel()
320+
}
321+
322+
testJob = viewModelScope.launch {
323+
resetTestResult()
324+
325+
try {
326+
runPing()
327+
328+
if (_pingResult.value is PingResultState.Error) {
329+
this.cancel("Ping Test Failed")
330+
}
331+
ensureActive()
332+
333+
getUploadResult(context = context)
334+
335+
if (_uploadResult.value is ConnectivityTestResult.Error) {
336+
this.cancel("Upload Test Failed")
337+
}
338+
339+
ensureActive()
340+
341+
getDownloadResult(context = context)
342+
343+
if (_downloadResult.value is ConnectivityTestResult.Error) {
344+
this.cancel("Download Test Failed")
345+
}
346+
347+
ensureActive()
348+
349+
_isTestActive.value = false
350+
Log.d(TAG, "ping, upload, download are finished")
351+
val curTime = TimeUtil.getCurrentTime()
352+
val cellID = signalStrengthMonitor.getCellID()
353+
354+
locationService.lastLocation().combine(getDeviceID) { locaion, deviceID ->
355+
Pair(locaion, deviceID)
356+
}.collect {
357+
Log.d(TAG, it.first.toString())
358+
Log.d(TAG, it.second)
359+
val connectivityResult = ConnectivityReportModel(
360+
it.first.latitude,
361+
it.first.longitude,
362+
curTime,
363+
cellID,
364+
it.second,
365+
(_uploadResult.value as ConnectivityTestResult.Result).result.dropLast(5)
366+
.toDouble(),
367+
(_downloadResult.value as ConnectivityTestResult.Result).result.dropLast(5)
368+
.toDouble(),
369+
(_pingResult.value as PingResultState.Success).result.avg!!.toDouble(),
370+
(_pingResult.value as PingResultState.Success).result.numLoss!!.toDouble(),
371+
)
372+
373+
connectivityRepository.insert(connectivityResult)
374+
375+
val signalStrengthResult = SignalStrengthReportModel(
376+
it.first.latitude,
377+
it.first.longitude,
378+
curTime,
379+
cellID,
380+
it.second,
381+
signalStrengthResult.value.dbm,
382+
signalStrengthResult.value.level.level
383+
)
384+
signalStrengthRepository.insert(signalStrengthResult)
385+
}
386+
} catch (e: Exception) {
387+
Log.d(TAG, "catch $e")
287388
}
288389
}
289390
}
290391

291-
fun doIperf(context: Context) = viewModelScope.launch {
292-
val uploadJob = getUploadResult(context = context)
293-
_jobs.add(uploadJob)
294-
uploadJob.join()
295-
val downloadJob = getDownloadResult(context = context)
296-
_jobs.add(downloadJob)
392+
fun cancelTest() {
393+
Log.d(TAG, "cancellation: the test job is $testJob")
394+
testJob?.cancel(CancellationException("Shit, cancel this test!!!"))
395+
Log.d(TAG, "Tests cancelled")
396+
resetTestResult()
397+
}
398+
399+
private fun resetTestResult() {
400+
_pingResult.value = PingResultState.Error(PingError(PingErrorCase.OK, null))
401+
_uploadResult.value = ConnectivityTestResult.Result("0.0 Mbit", Color.LightGray)
402+
_downloadResult.value = ConnectivityTestResult.Result("0.0 Mbit", Color.LightGray)
297403
}
298404
}
299405

app/src/main/java/com/lcl/lclmeasurementtool/database/dao/ConnectivityDao.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface ConnectivityDao {
1212

1313
// READ
1414
@Transaction
15-
@Query("SELECT * FROM connectivity_table ORDER BY time_stamp ASC")
15+
@Query("SELECT * FROM connectivity_table ORDER BY time_stamp DESC")
1616
fun getAll(): Flow<List<ConnectivityReportModel>>
1717

1818
// DELETE

app/src/main/java/com/lcl/lclmeasurementtool/database/dao/SignalStrengthDao.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface SignalStrengthDao {
1212

1313
// READ
1414
@Transaction
15-
@Query("SELECT * FROM signal_strength_table ORDER BY time_stamp ASC")
15+
@Query("SELECT * FROM signal_strength_table ORDER BY time_stamp DESC")
1616
fun getAll(): Flow<List<SignalStrengthReportModel>>
1717

1818
// DELETE

0 commit comments

Comments
 (0)