From 7c8a65b8d1ae8a049bf67260acb6fafbd95adac9 Mon Sep 17 00:00:00 2001 From: Isidro Henoch Date: Tue, 21 Dec 2021 14:21:16 -0600 Subject: Implements the commands list - Shows command details - Sends a selected command to a device --- .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 7 ++- .../details/commands/UnitCommandsFragment.kt | 34 ++++++++++++++- .../details/commands/UnitCommandsViewModel.kt | 50 ++++++++++++++++++++++ .../information/UnitInformationViewModel.kt | 8 ++-- .../src/main/res/layout/unit_details_commands.xml | 29 +++++++++---- androidApp/src/main/res/values/dimen.xml | 1 + androidApp/src/main/res/values/strings.xml | 1 + .../TrackerMap/client/apis/CommandsApi.kt | 9 +++- .../trackermap/TrackerMap/client/models/Command.kt | 8 ++-- .../TrackerMap/controllers/CommandsController.kt | 29 ------------- 10 files changed, 127 insertions(+), 49 deletions(-) create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt delete mode 100644 shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt 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 7929832..f46a5c9 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -1,9 +1,11 @@ package mx.trackermap.TrackerMap.android import android.app.Application +import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsViewModel import mx.trackermap.TrackerMap.android.details.information.UnitInformationViewModel import mx.trackermap.TrackerMap.android.session.LoginViewModel import mx.trackermap.TrackerMap.android.units.UnitsViewModel +import mx.trackermap.TrackerMap.client.apis.CommandsApi import mx.trackermap.TrackerMap.client.apis.DevicesApi import mx.trackermap.TrackerMap.client.apis.PositionsApi import mx.trackermap.TrackerMap.client.apis.SessionApi @@ -25,10 +27,13 @@ class TrackerApp : Application() { single { SessionApi(get()) } single { DevicesApi(get()) } single { PositionsApi(get()) } + single { CommandsApi(get()) } + single { UnitsController(get(), get()) } viewModel { LoginViewModel(get(), get()) } - viewModel { UnitInformationViewModel() } + viewModel { UnitInformationViewModel(get()) } + viewModel { UnitCommandsViewModel(get()) } single { UnitsViewModel(get()) } } diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt index 0391c16..bb0da4f 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt @@ -1,17 +1,23 @@ package mx.trackermap.TrackerMap.android.details.commands import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter import androidx.fragment.app.Fragment import mx.trackermap.TrackerMap.android.databinding.UnitDetailsCommandsBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter +import org.koin.androidx.viewmodel.ext.android.viewModel class UnitCommandsFragment: Fragment() { private var _binding: UnitDetailsCommandsBinding? = null private val binding get() = _binding!! + private val unitCommandsViewModel: UnitCommandsViewModel by viewModel() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -23,12 +29,36 @@ class UnitCommandsFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) - binding.unitCommandsText.text = "COMMANDS for ID - $id" + + setupObservers() + setupEvents() } override fun onDestroyView() { super.onDestroyView() _binding = null } + + private fun setupObservers() { + unitCommandsViewModel.commands.observe(this) { commands -> + Log.d("UnitCommandsFragment", "Device commands - $commands") + val context = activity!!.applicationContext + val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1) + adapter.addAll(commands.map { it.description }) + binding.commandsList.adapter = adapter + } + + val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) + unitCommandsViewModel.fetchCommands(id) + } + + private fun setupEvents() { + binding.commandsList.setOnItemClickListener { _, _, index, _ -> + Log.d("UnitCommandsFragment", "Selected item at index - $index") + unitCommandsViewModel.selectCommand(index) + } + binding.sendCommandButton.setOnClickListener { + unitCommandsViewModel.sendCommand() + } + } } \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt new file mode 100644 index 0000000..06c0439 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsViewModel.kt @@ -0,0 +1,50 @@ +package mx.trackermap.TrackerMap.android.details.commands + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.launch +import mx.trackermap.TrackerMap.client.apis.CommandsApi +import mx.trackermap.TrackerMap.client.models.Command +import org.koin.core.component.KoinComponent + +@DelicateCoroutinesApi +class UnitCommandsViewModel( + private val commandsApi: CommandsApi +) : ViewModel(), KoinComponent { + + var commands = MutableLiveData>() + private var selectedCommand: Command? = null + private var deviceId: Int? = null + + fun fetchCommands(deviceId: Int?) { + this.deviceId = deviceId + viewModelScope.launch { + val commands = commandsApi.commandsGet(deviceId = deviceId) + this@UnitCommandsViewModel.commands.value = commands.toList() + } + } + + fun selectCommand(index: Int) { + val command = commands.value?.get(index) + Log.d("UnitCommandsVM", "Selected Command - $command") + command?.deviceId = this.deviceId + + this.selectedCommand = command + } + + fun sendCommand() { + if (selectedCommand == null) { + Log.d("UnitCommandsVM", "No Command Selection") + return + } + + Log.d("UnitCommandsVM", "Sending command - $selectedCommand") + viewModelScope.launch { + val command = commandsApi.commandsSendPost(selectedCommand!!) + Log.d("UnitCommandsVM", "Command sent - $command") + } + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt index e7100e1..11daaaf 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt @@ -11,9 +11,11 @@ import mx.trackermap.TrackerMap.controllers.UnitsController import org.koin.core.component.KoinComponent import org.koin.core.component.inject -class UnitInformationViewModel: ViewModel(), KoinComponent { - @DelicateCoroutinesApi - private val unitsController: UnitsController by inject() +@DelicateCoroutinesApi +class UnitInformationViewModel constructor( + private val unitsController: UnitsController +) : ViewModel(), KoinComponent { + var unit = MutableLiveData() init { diff --git a/androidApp/src/main/res/layout/unit_details_commands.xml b/androidApp/src/main/res/layout/unit_details_commands.xml index dfd6516..e98b113 100644 --- a/androidApp/src/main/res/layout/unit_details_commands.xml +++ b/androidApp/src/main/res/layout/unit_details_commands.xml @@ -1,19 +1,30 @@ + android:layout_width="match_parent" + android:layout_height="match_parent"> + + - + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/commandsList" /> \ No newline at end of file diff --git a/androidApp/src/main/res/values/dimen.xml b/androidApp/src/main/res/values/dimen.xml index 6ce7887..18fd0eb 100644 --- a/androidApp/src/main/res/values/dimen.xml +++ b/androidApp/src/main/res/values/dimen.xml @@ -1,6 +1,7 @@ 8dp + 16dp 20dp diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index 5692688..7478ddb 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -25,4 +25,5 @@ Type to search Key Value + Send Command \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt index 8f60153..e840888 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/CommandsApi.kt @@ -30,7 +30,14 @@ class CommandsApi(basePath: kotlin.String = "https://demo.traccar.org/api") : Ap */ @Suppress("UNCHECKED_CAST") suspend fun commandsGet(all: kotlin.Boolean? = null, userId: kotlin.Int? = null, deviceId: kotlin.Int? = null, groupId: kotlin.Int? = null, refresh: kotlin.Boolean? = null): kotlin.Array { - val localVariableQuery: MultiValueMap = mapOf("all" to listOf("$all"), "userId" to listOf("$userId"), "deviceId" to listOf("$deviceId"), "groupId" to listOf("$groupId"), "refresh" to listOf("$refresh")) + val query: MutableMap> = mutableMapOf() + all?.let { query["all"] = listOf("$it") } + userId?.let { query["userId"] = listOf("$it") } + deviceId?.let { query["deviceId"] = listOf("$it") } + groupId?.let { query["groupId"] = listOf("$it") } + refresh?.let { query["refresh"] = listOf("$it") } + val localVariableQuery: MultiValueMap = query + val localVariableConfig = RequestConfig( RequestMethod.GET, "/commands", query = localVariableQuery diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt index c1c6a5d..37b22d4 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Command.kt @@ -11,6 +11,7 @@ */ package mx.trackermap.TrackerMap.client.models +import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonPrimitive @@ -22,12 +23,11 @@ import kotlinx.serialization.json.JsonPrimitive * @param type * @param attributes */ +@Serializable data class Command ( - val id: Int? = null, - val deviceId: Int? = null, + var deviceId: Int? = null, val description: String? = null, val type: String? = null, val attributes: Map = mapOf() -) { -} \ No newline at end of file +) \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt deleted file mode 100644 index b710763..0000000 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/CommandsController.kt +++ /dev/null @@ -1,29 +0,0 @@ -package mx.trackermap.TrackerMap.controllers - -import mx.trackermap.TrackerMap.client.apis.CommandsApi -import mx.trackermap.TrackerMap.client.models.Command -import mx.trackermap.TrackerMap.client.models.Device - -class CommandsController( - val commandsApi: CommandsApi, - val sessionController: SessionController) -{ - var commands = emptyArray() - val deviceCommands = mutableMapOf>() - - suspend fun getAllCommands () { - sessionController.user?.id?.let { - commands = commandsApi.commandsGet(userId = it) - } - } - - suspend fun getDeviceCommands (device: Device) { - device.id?.let { - deviceCommands[it] = commandsApi.commandsSendGet (deviceId = device.id) - } - } - - suspend fun sendCommand (command: Command) { - commandsApi.commandsSendPost(command) - } -} \ No newline at end of file -- cgit v1.2.3