1
1
package com.lcl.lclmeasurementtool
2
2
3
3
import android.content.Context
4
+ import android.location.Location
4
5
import android.os.Build
5
6
import android.telephony.CellSignalStrength
6
7
import android.util.Log
@@ -14,7 +15,6 @@ import com.kongzue.dialogx.dialogs.TipDialog
14
15
import com.lcl.lclmeasurementtool.Utils.ECDSA
15
16
import com.lcl.lclmeasurementtool.Utils.Hex
16
17
import com.lcl.lclmeasurementtool.Utils.SecurityUtils
17
- import com.lcl.lclmeasurementtool.Utils.SignalStrengthLevel
18
18
import com.lcl.lclmeasurementtool.constants.NetworkConstants
19
19
import com.lcl.lclmeasurementtool.features.iperf.IperfRunner
20
20
import com.lcl.lclmeasurementtool.features.iperf.IperfStatus
@@ -23,13 +23,15 @@ import com.lcl.lclmeasurementtool.features.ping.PingError
23
23
import com.lcl.lclmeasurementtool.features.ping.PingErrorCase
24
24
import com.lcl.lclmeasurementtool.features.ping.PingResult
25
25
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
29
28
import com.lcl.lclmeasurementtool.model.repository.NetworkApiRepository
29
+ import com.lcl.lclmeasurementtool.model.repository.SignalStrengthRepository
30
30
import com.lcl.lclmeasurementtool.model.repository.UserDataRepository
31
31
import com.lcl.lclmeasurementtool.telephony.SignalStrengthLevelEnum
32
32
import com.lcl.lclmeasurementtool.telephony.SignalStrengthMonitor
33
+ import com.lcl.lclmeasurementtool.ui.LCLLoadingWheel
34
+ import com.lcl.lclmeasurementtool.util.TimeUtil
33
35
import dagger.hilt.android.lifecycle.HiltViewModel
34
36
import kotlinx.coroutines.*
35
37
import kotlinx.coroutines.flow.*
@@ -44,7 +46,9 @@ class MainActivityViewModel @Inject constructor(
44
46
private val userDataRepository : UserDataRepository ,
45
47
private val networkApi : NetworkApiRepository ,
46
48
private val locationService : LocationService ,
47
- private val signalStrengthMonitor : SignalStrengthMonitor
49
+ private val signalStrengthMonitor : SignalStrengthMonitor ,
50
+ private val connectivityRepository : ConnectivityRepository ,
51
+ private val signalStrengthRepository : SignalStrengthRepository
48
52
) : ViewModel() {
49
53
50
54
companion object {
@@ -60,12 +64,6 @@ class MainActivityViewModel @Inject constructor(
60
64
started = SharingStarted .WhileSubscribed (5_000 )
61
65
)
62
66
63
- fun getLocation () = viewModelScope.launch {
64
- locationService.lastLocation().collect {
65
- Log .d(TAG , it.toString())
66
- }
67
- }
68
-
69
67
// Authentication
70
68
fun login (hPKR : ByteString , skT : ByteString ) = viewModelScope.launch {
71
69
userDataRepository.setKeys(hPKR, skT)
@@ -79,6 +77,14 @@ class MainActivityViewModel @Inject constructor(
79
77
userDataRepository.setR(R )
80
78
}
81
79
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
+
82
88
private suspend fun register (registration : RegistrationModel ) = networkApi.register(registration)
83
89
84
90
suspend fun saveAndSend (result : String ): LoginStatus {
@@ -202,13 +208,13 @@ class MainActivityViewModel @Inject constructor(
202
208
203
209
204
210
// Network Testing
205
- private val _jobs = mutableListOf<Job >()
206
211
private var _pingResult = MutableStateFlow (PingResultState ())
207
212
private var _downloadResult = MutableStateFlow (ConnectivityTestResult ())
208
213
private var _uploadResult = MutableStateFlow (ConnectivityTestResult ())
209
214
private val _isTestActive = MutableStateFlow (false )
210
215
211
216
217
+ val isTestActive = _isTestActive .asStateFlow()
212
218
val pingResult: StateFlow <PingResultState > = _pingResult .asStateFlow()
213
219
var downloadResult: StateFlow <ConnectivityTestResult > = _downloadResult .asStateFlow()
214
220
var uploadResult: StateFlow <ConnectivityTestResult > = _uploadResult .asStateFlow()
@@ -232,9 +238,7 @@ class MainActivityViewModel @Inject constructor(
232
238
started = SharingStarted .WhileSubscribed (5_000 )
233
239
)
234
240
235
- val isTestActive = _isTestActive .asStateFlow()
236
-
237
- fun doPing () = viewModelScope.launch {
241
+ private suspend fun runPing () {
238
242
try {
239
243
Ping .cancellableStart(address = NetworkConstants .PING_TEST_ADDRESS , timeout = 1000 )
240
244
.onStart {
@@ -243,9 +247,7 @@ class MainActivityViewModel @Inject constructor(
243
247
}
244
248
.onCompletion {
245
249
if (it != null ) {
246
- // save to DB and send over the network
247
250
Log .d(TAG , " Error is ${it.message} " )
248
- } else {
249
251
_isTestActive .value = false
250
252
}
251
253
}
@@ -261,39 +263,143 @@ class MainActivityViewModel @Inject constructor(
261
263
}
262
264
}
263
265
264
- fun getUploadResult (context : Context ) = viewModelScope.launch {
266
+ private suspend fun getUploadResult (context : Context ) {
265
267
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) {
268
280
IperfStatus .RUNNING -> ConnectivityTestResult .Result (result.bandWidth, Color .LightGray )
269
281
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
+ }
271
286
}
272
287
}
273
288
}
274
289
275
290
276
- fun getDownloadResult (context : Context ) = viewModelScope.launch {
291
+ private suspend fun getDownloadResult (context : Context ) {
277
292
IperfRunner ().getTestResult(IperfRunner .iperfDownloadConfig, context.cacheDir)
293
+ .onStart {
294
+ _isTestActive .value = true
295
+ }
278
296
.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
+ }
281
302
}
282
- .collect { result ->
283
- _downloadResult .value = when (result.status) {
303
+ .collectLatest { result ->
304
+ _downloadResult .value = when (result.status) {
284
305
IperfStatus .RUNNING -> ConnectivityTestResult .Result (result.bandWidth, Color .LightGray )
285
306
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 " )
287
388
}
288
389
}
289
390
}
290
391
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 )
297
403
}
298
404
}
299
405
0 commit comments