aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsidro Henoch <imhenoch@protonmail.com>2021-12-08 04:28:51 -0600
committerIsidro Henoch <imhenoch@protonmail.com>2021-12-08 04:28:51 -0600
commit04c2889895483f5925c90ed7a856d38391fcab45 (patch)
tree896334a1d8a0540b9d54c7390db2d78e61cadb1b
parentd2ee6a21355c390a4aaefc6ea847060c8e47c6ae (diff)
downloadetbsa-trackermap-mobile-04c2889895483f5925c90ed7a856d38391fcab45.tar.gz
etbsa-trackermap-mobile-04c2889895483f5925c90ed7a856d38391fcab45.tar.bz2
etbsa-trackermap-mobile-04c2889895483f5925c90ed7a856d38391fcab45.zip
WIP: Implements the basic structure for the units list/map
- Updates the Devices and Positions APIs to properly construct the Url's query when there are null values - Adds a units controller to the shared module - Adds a devices and map fragment that each print the fetched units on the console - Adds a units view model to connect previously mentioned fragments with the units controller
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt4
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt19
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt19
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt37
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/DevicesApi.kt8
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/PositionsApi.kt10
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Device.kt31
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Position.kt24
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt6
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt65
10 files changed, 192 insertions, 31 deletions
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
index b236577..e23c0de 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
@@ -6,6 +6,7 @@ import mx.trackermap.TrackerMap.android.units.UnitsViewModel
import mx.trackermap.TrackerMap.client.apis.DevicesApi
import mx.trackermap.TrackerMap.client.apis.PositionsApi
import mx.trackermap.TrackerMap.client.apis.SessionApi
+import mx.trackermap.TrackerMap.controllers.UnitsController
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.androidx.viewmodel.dsl.viewModel
@@ -23,9 +24,10 @@ class TrackerApp : Application() {
single { SessionApi(get()) }
single { DevicesApi(get()) }
single { PositionsApi(get()) }
+ single { UnitsController(get(), get()) }
viewModel { LoginViewModel(get(), get()) }
- viewModel { UnitsViewModel() }
+ single { UnitsViewModel(get()) }
}
startKoin {
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt
index 7e09b17..98c98cc 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt
@@ -1,16 +1,22 @@
package mx.trackermap.TrackerMap.android.devices
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
+import kotlinx.coroutines.DelicateCoroutinesApi
import mx.trackermap.TrackerMap.android.databinding.DevicesFragmentBinding
+import mx.trackermap.TrackerMap.android.units.UnitsViewModel
+import org.koin.androidx.viewmodel.ext.android.viewModel
class DevicesFragment: Fragment() {
private var _binding: DevicesFragmentBinding? = null
private val binding get() = _binding!!
+ private val unitsViewModel: UnitsViewModel by viewModel()
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -24,4 +30,17 @@ class DevicesFragment: Fragment() {
super.onDestroyView()
_binding = null
}
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ setupObservers()
+ }
+
+ @DelicateCoroutinesApi
+ private fun setupObservers() {
+ unitsViewModel.units.observe(this) { units ->
+ Log.d("DevicesFragment", "Success $units")
+ }
+ }
} \ No newline at end of file
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
index 0d4d91a..2ffaa2c 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
@@ -1,16 +1,22 @@
package mx.trackermap.TrackerMap.android.map
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
+import kotlinx.coroutines.DelicateCoroutinesApi
import mx.trackermap.TrackerMap.android.databinding.MapFragmentBinding
+import mx.trackermap.TrackerMap.android.units.UnitsViewModel
+import org.koin.androidx.viewmodel.ext.android.viewModel
class MapFragment: Fragment() {
private var _binding: MapFragmentBinding? = null
private val binding get() = _binding!!
+ private val unitsViewModel: UnitsViewModel by viewModel()
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -24,4 +30,17 @@ class MapFragment: Fragment() {
super.onDestroyView()
_binding = null
}
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ setupObservers()
+ }
+
+ @DelicateCoroutinesApi
+ private fun setupObservers() {
+ unitsViewModel.units.observe(this) { units ->
+ Log.d("MapFragment", "Success $units")
+ }
+ }
} \ No newline at end of file
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
index 11df89b..7ac6e28 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
@@ -2,15 +2,44 @@ package mx.trackermap.TrackerMap.android.units
import android.util.Log
import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.models.UnitInformation
+import mx.trackermap.TrackerMap.controllers.UnitsController
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
-class UnitsViewModel : ViewModel() {
+@DelicateCoroutinesApi
+class UnitsViewModel(
+ private val savedStateHandle: SavedStateHandle
+) : ViewModel(), KoinComponent {
enum class UnitsDisplayMode {
MAP, LIST
}
- var unitsDisplayMode = MutableLiveData<UnitsDisplayMode>(UnitsDisplayMode.MAP)
+ private val unitsController: UnitsController by inject()
+
+ var unitsDisplayMode = MutableLiveData(UnitsDisplayMode.MAP)
+ var units = MutableLiveData<List<UnitInformation>>()
+
+ init {
+ Log.d("UnitsViewModel", "Initializing Units View Model")
+ viewModelScope.launch {
+ setupObservers()
+ }
+ }
+
+ private suspend fun setupObservers() {
+ Log.d("UnitsViewModel", "Setup observers")
+ unitsController.displayedUnitsFlow.collect { units ->
+ this.units.value = units
+ }
+ }
fun toggleDisplayMode() {
Log.d("UnitsViewModel", "Toggling Display mode")
@@ -22,4 +51,8 @@ class UnitsViewModel : ViewModel() {
}
unitsDisplayMode.postValue(newDisplayMode)
}
+
+ fun search(query: String) {
+ unitsController.search(query)
+ }
} \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/DevicesApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/DevicesApi.kt
index bc87f78..331cc4e 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/DevicesApi.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/DevicesApi.kt
@@ -29,7 +29,13 @@ class DevicesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Api
*/
@Suppress("UNCHECKED_CAST")
suspend fun devicesGet(all: kotlin.Boolean? = null, userId: kotlin.Int? = null, id: kotlin.Int? = null, uniqueId: kotlin.String? = null): kotlin.Array<Device> {
- val localVariableQuery: MultiValueMap = mapOf("all" to listOf("$all"), "userId" to listOf("$userId"), "id" to listOf("$id"), "uniqueId" to listOf("$uniqueId"))
+ val query: MutableMap<String, List<String>> = mutableMapOf()
+ all?.let { query["all"] = listOf("$it") }
+ userId?.let { query["userId"] = listOf("$it") }
+ id?.let { query["id"] = listOf("$it") }
+ uniqueId?.let { query["uniqueId"] = listOf("$it") }
+ val localVariableQuery: MultiValueMap = query
+
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/devices", query = localVariableQuery
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/PositionsApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/PositionsApi.kt
index 8c1b73e..278611f 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/PositionsApi.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/PositionsApi.kt
@@ -27,8 +27,14 @@ class PositionsApi(basePath: kotlin.String = "https://demo.traccar.org/api") : A
* @return kotlin.Array<Position>
*/
@Suppress("UNCHECKED_CAST")
- suspend fun positionsGet(deviceId: kotlin.Int? = null, from: java.time.LocalDateTime? = null, to: java.time.LocalDateTime? = null, id: kotlin.Int? = null): kotlin.Array<Position> {
- val localVariableQuery: MultiValueMap = mapOf("deviceId" to listOf("$deviceId"), "from" to listOf("$from"), "to" to listOf("$to"), "id" to listOf("$id"))
+ suspend fun positionsGet(deviceId: kotlin.Int? = null, from: LocalDateTimeAdapter? = null, to: LocalDateTimeAdapter? = null, id: kotlin.Int? = null): kotlin.Array<Position> {
+ val query: MutableMap<String, List<String>> = mutableMapOf()
+ deviceId?.let { query["deviceId"] = listOf("$it") }
+ from?.let { query["from"] = listOf("$it") }
+ to?.let { query["to"] = listOf("$it") }
+ id?.let { query["id"] = listOf("$it") }
+ val localVariableQuery: MultiValueMap = query
+
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/positions", query = localVariableQuery
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Device.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Device.kt
index 3729345..f8a1642 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Device.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Device.kt
@@ -11,6 +11,9 @@
*/
package mx.trackermap.TrackerMap.client.models
+import kotlinx.datetime.LocalDateTime
+import kotlinx.serialization.Serializable
+
/**
*
@@ -29,22 +32,22 @@ package mx.trackermap.TrackerMap.client.models
* @param geofenceIds
* @param attributes
*/
+@Serializable
data class Device (
- val id: kotlin.Int? = null,
- val name: kotlin.String? = null,
- val uniqueId: kotlin.String? = null,
- val status: kotlin.String? = null,
- val disabled: kotlin.Boolean? = null,
+ val id: Int,
+ val name: String,
+ val uniqueId: String? = null,
+ val status: String? = null,
+ val disabled: Boolean? = null,
/* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */
- val lastUpdate: java.time.LocalDateTime? = null,
- val positionId: kotlin.Int? = null,
- val groupId: kotlin.Int? = null,
- val phone: kotlin.String? = null,
- val model: kotlin.String? = null,
- val contact: kotlin.String? = null,
- val category: kotlin.String? = null,
- val geofenceIds: kotlin.Array<kotlin.Int>? = null,
- val attributes: kotlin.Any? = null
+// val lastUpdate: LocalDateTime? = null,
+ val positionId: Int? = null,
+ val groupId: Int? = null,
+ val phone: String? = null,
+ val model: String? = null,
+ val contact: String? = null,
+ val category: String? = null,
+ val geofenceIds: Array<Int>? = null
) {
} \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Position.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Position.kt
index 0ce4ed2..d765825 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Position.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Position.kt
@@ -11,6 +11,9 @@
*/
package mx.trackermap.TrackerMap.client.models
+import kotlinx.datetime.LocalDateTime
+import kotlinx.serialization.Serializable
+
/**
*
@@ -32,28 +35,27 @@ package mx.trackermap.TrackerMap.client.models
* @param network
* @param attributes
*/
+@Serializable
data class Position (
val id: kotlin.Int? = null,
val deviceId: kotlin.Int? = null,
val protocol: kotlin.String? = null,
/* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */
- val deviceTime: java.time.LocalDateTime? = null,
+// val deviceTime: LocalDateTime? = null,
/* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */
- val fixTime: java.time.LocalDateTime? = null,
+// val fixTime: LocalDateTime? = null,
/* in IS0 8601 format. eg. `1963-11-22T18:30:00Z` */
- val serverTime: java.time.LocalDateTime? = null,
+// val serverTime: LocalDateTime? = null,
val outdated: kotlin.Boolean? = null,
val valid: kotlin.Boolean? = null,
- val latitude: java.math.BigDecimal? = null,
- val longitude: java.math.BigDecimal? = null,
- val altitude: java.math.BigDecimal? = null,
+ val latitude: Double? = null,
+ val longitude: Double? = null,
+ val altitude: Double? = null,
/* in knots */
- val speed: java.math.BigDecimal? = null,
- val course: java.math.BigDecimal? = null,
+ val speed: Double? = null,
+ val course: Double? = null,
val address: kotlin.String? = null,
- val accuracy: java.math.BigDecimal? = null,
- val network: kotlin.Any? = null,
- val attributes: kotlin.Any? = null
+ val accuracy: Double? = null
) {
} \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt
new file mode 100644
index 0000000..edebff0
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/UnitInformation.kt
@@ -0,0 +1,6 @@
+package mx.trackermap.TrackerMap.client.models
+
+data class UnitInformation(
+ val device: Device,
+ val position: Position?
+) \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt
new file mode 100644
index 0000000..9c11b79
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt
@@ -0,0 +1,65 @@
+package mx.trackermap.TrackerMap.controllers
+
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.apis.DevicesApi
+import mx.trackermap.TrackerMap.client.apis.PositionsApi
+import mx.trackermap.TrackerMap.client.models.Position
+import mx.trackermap.TrackerMap.client.models.UnitInformation
+
+@DelicateCoroutinesApi
+class UnitsController(
+ private val devicesApi: DevicesApi,
+ private val positionsApi: PositionsApi
+) {
+
+ val displayedUnitsFlow = MutableStateFlow<List<UnitInformation>>(emptyList())
+ private val unitsFlow = MutableStateFlow<List<UnitInformation>>(emptyList())
+ private val queryFlow = MutableStateFlow("")
+
+ init {
+ GlobalScope.launch {
+ fetchUnits()
+ }
+ GlobalScope.launch {
+ setupFlows()
+ }
+ }
+
+ suspend fun fetchUnits() {
+ val devices = devicesApi.devicesGet()
+ val positions = positionsApi.positionsGet()
+ val positionsMap: MutableMap<Int, Position> = mutableMapOf()
+
+ positions.forEach { position ->
+ position.deviceId?.let {
+ positionsMap[it] = position
+ }
+ }
+
+ val units = devices.map {
+ UnitInformation(it, positionsMap[it.id])
+ }
+ unitsFlow.value = units
+ }
+
+ fun search(query: String) {
+ queryFlow.value = query
+ }
+
+ suspend fun setupFlows() {
+ unitsFlow.combine(queryFlow) { units, query ->
+ units.filter { unit ->
+ unit.device.name.contains(query) ||
+ unit.device.contact?.contains(query) == true ||
+ unit.position?.address?.contains(query) == true
+ }
+ }.collect { units ->
+ this.displayedUnitsFlow.value = units
+ }
+ }
+} \ No newline at end of file