aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2022-01-08 02:31:33 -0600
committerIván Ávalos <avalos@disroot.org>2022-01-08 02:31:33 -0600
commite93ad9e3251013c07c71f20dc4523e4d09aa26bd (patch)
tree6c8aab9c3433bc69f5b1ff27260ff1c3b53f12ca
parente4d2741d3820e843e168c79ba99a0d830b9b1889 (diff)
downloadetbsa-trackermap-mobile-e93ad9e3251013c07c71f20dc4523e4d09aa26bd.tar.gz
etbsa-trackermap-mobile-e93ad9e3251013c07c71f20dc4523e4d09aa26bd.tar.bz2
etbsa-trackermap-mobile-e93ad9e3251013c07c71f20dc4523e4d09aa26bd.zip
Finished events report, implemented GeofenceController, fixed geofencesGet() and many fixes
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt11
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt102
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt129
-rw-r--r--androidApp/src/main/res/layout/unit_details_reports.xml55
-rw-r--r--androidApp/src/main/res/values-es-rMX/strings.xml22
-rw-r--r--androidApp/src/main/res/values/strings.xml22
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/GeofencesApi.kt45
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt6
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Geofence.kt2
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofenceController.kt14
-rw-r--r--shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofencesController.kt30
11 files changed, 319 insertions, 119 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 16cad74..1563534 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt
@@ -1,16 +1,14 @@
package mx.trackermap.TrackerMap.android
import android.app.Application
+import kotlinx.coroutines.DelicateCoroutinesApi
import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsViewModel
import mx.trackermap.TrackerMap.android.details.information.UnitInformationViewModel
import mx.trackermap.TrackerMap.android.details.reports.UnitReportsViewModel
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.ReportsApi
-import mx.trackermap.TrackerMap.client.apis.SessionApi
+import mx.trackermap.TrackerMap.client.apis.*
+import mx.trackermap.TrackerMap.controllers.GeofencesController
import mx.trackermap.TrackerMap.controllers.UnitsController
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
@@ -19,6 +17,7 @@ import org.koin.core.context.startKoin
import org.koin.core.logger.Level
import org.koin.dsl.module
+@DelicateCoroutinesApi
class TrackerApp : Application() {
override fun onCreate() {
@@ -31,8 +30,10 @@ class TrackerApp : Application() {
single { PositionsApi(get()) }
single { CommandsApi(get()) }
single { ReportsApi(get()) }
+ single { GeofencesApi(get()) }
single { UnitsController(get(), get()) }
+ single { GeofencesController(get()) }
viewModel { LoginViewModel(get(), get()) }
viewModel { UnitInformationViewModel(get()) }
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
index bbd1fd7..33b0dfc 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
@@ -8,18 +8,24 @@ import android.view.ViewGroup
import android.widget.PopupMenu
import android.widget.TableRow
import android.widget.TextView
+import androidx.core.view.setMargins
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
+import kotlinx.coroutines.DelicateCoroutinesApi
import mx.trackermap.TrackerMap.android.R
import mx.trackermap.TrackerMap.android.databinding.UnitDetailsReportsBinding
import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter
import mx.trackermap.TrackerMap.android.map.MapFragment
import mx.trackermap.TrackerMap.android.map.MarkerTransformations
import mx.trackermap.TrackerMap.client.models.Event
+import mx.trackermap.TrackerMap.client.models.EventInformation
import mx.trackermap.TrackerMap.client.models.Position
import mx.trackermap.TrackerMap.client.models.Stop
+import mx.trackermap.TrackerMap.utils.Formatter
import org.koin.androidx.viewmodel.ext.android.viewModel
+import kotlin.math.max
+@DelicateCoroutinesApi
class UnitReportsFragment : Fragment() {
private var _binding: UnitDetailsReportsBinding? = null
@@ -42,8 +48,8 @@ class UnitReportsFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- unitReportsViewModel.deviceId.value =
- arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0
+ unitReportsViewModel.setDeviceId(
+ arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) ?: 0)
initializeMap()
setupEvents()
setupObservers()
@@ -62,21 +68,23 @@ class UnitReportsFragment : Fragment() {
private fun setupEvents() {
binding.reportType.setOnPositionChangedListener { position ->
- unitReportsViewModel.reportType.value = when (position) {
- 0 -> UnitReportsViewModel.ReportType.POSITIONS
- 1 -> UnitReportsViewModel.ReportType.EVENTS
- else -> UnitReportsViewModel.ReportType.STOPS
- }
+ unitReportsViewModel.setReportType(
+ when (position) {
+ 0 -> UnitReportsViewModel.ReportType.POSITIONS
+ 1 -> UnitReportsViewModel.ReportType.EVENTS
+ else -> UnitReportsViewModel.ReportType.STOPS
+ }
+ )
}
binding.periodButton.setOnClickListener {
showPeriodPopUp(it)
}
- unitReportsViewModel.reportPeriod.value = UnitReportsViewModel.ReportPeriod.DAY
- unitReportsViewModel.reportType.value = UnitReportsViewModel.ReportType.POSITIONS
+ unitReportsViewModel.setReportPeriod(UnitReportsViewModel.ReportPeriod.DAY)
+ unitReportsViewModel.setReportType(UnitReportsViewModel.ReportType.POSITIONS)
}
private fun setupObservers() {
- unitReportsViewModel.report.observe(this) { report ->
+ unitReportsViewModel.report.observe(viewLifecycleOwner) { report ->
Log.d("UnitReportsFragment", "Report available: $report")
when (report) {
@@ -96,7 +104,7 @@ class UnitReportsFragment : Fragment() {
}
}
- unitReportsViewModel.reportPeriod.observe(this) { period ->
+ unitReportsViewModel.reportPeriod.observe(viewLifecycleOwner) { period ->
Log.d("UnitReportsFragment", "Period changed: $period")
if (period == null) {
return@observe
@@ -110,17 +118,23 @@ class UnitReportsFragment : Fragment() {
}
)
}
+
+ unitReportsViewModel.geofences.observe(this) { geofences ->
+ Log.d("UnitReportsFragment", "Success $geofences")
+ }
}
private fun showPeriodPopUp(view: View) {
val popOver = PopupMenu(context, view)
popOver.menuInflater.inflate(R.menu.report_period_options, popOver.menu)
popOver.setOnMenuItemClickListener { item ->
- unitReportsViewModel.reportPeriod.value = when (item.itemId) {
- R.id.dayOption -> UnitReportsViewModel.ReportPeriod.DAY
- R.id.weekOption -> UnitReportsViewModel.ReportPeriod.WEEK
- else -> UnitReportsViewModel.ReportPeriod.MONTH
- }
+ unitReportsViewModel.setReportPeriod(
+ when (item.itemId) {
+ R.id.dayOption -> UnitReportsViewModel.ReportPeriod.DAY
+ R.id.weekOption -> UnitReportsViewModel.ReportPeriod.WEEK
+ else -> UnitReportsViewModel.ReportPeriod.MONTH
+ }
+ )
true
}
popOver.show()
@@ -137,25 +151,69 @@ class UnitReportsFragment : Fragment() {
)
}
- private fun display(events: Array<Event>) {
+ private fun display(events: Array<EventInformation>) {
Log.d("UnitReportsFragment", "Displaying events: $events")
binding.eventsScroll.visibility = View.VISIBLE
binding.reportsMapContainer.visibility = View.GONE
- binding.eventsTable.removeViews(1, Math.max(0, binding.eventsTable.childCount - 1))
+ binding.eventsTable.removeViews(1, max(0, binding.eventsTable.childCount - 1))
val context = context!!
events.forEach { event ->
+ val layoutParams = TableRow.LayoutParams()
+ layoutParams.setMargins(
+ resources.getDimensionPixelSize(R.dimen.padding)
+ )
val row = TableRow(context)
- val eventText = TextView(context)
val datetimeText = TextView(context)
+ val eventText = TextView(context)
+ val geofenceText = TextView(context)
+ val addressText = TextView(context)
+
+ datetimeText.layoutParams = layoutParams
+ eventText.layoutParams = layoutParams
+ geofenceText.layoutParams = layoutParams
+ addressText.layoutParams = layoutParams
- row.addView(eventText)
row.addView(datetimeText)
+ row.addView(eventText)
+ row.addView(geofenceText)
+ row.addView(addressText)
binding.eventsTable.addView(row)
- eventText.text = event.type
- datetimeText.text = event.eventTime
+ event.event.eventTime?.let { it ->
+ datetimeText.text = Formatter.formatDate(it)
+ }
+ event.event.type?.let {
+ eventText.text = getString(when (it) {
+ "deviceOnline" -> R.string.event_device_online
+ "deviceUnknown" -> R.string.event_device_unknown
+ "deviceOffline" -> R.string.event_device_offline
+ "deviceInactive" -> R.string.event_device_inactive
+ "deviceMoving" -> R.string.event_device_moving
+ "deviceStopped" -> R.string.event_device_stopped
+ "deviceOverspeed" -> R.string.event_device_overspeed
+ "deviceFuelDrop" -> R.string.event_device_fuel_drop
+ "commandResult" -> R.string.event_command_result
+ "geofenceEnter" -> R.string.event_geofence_enter
+ "geofenceExit" -> R.string.event_geofence_exit
+ "alarm" -> R.string.event_alarm
+ "ignitionOn" -> R.string.event_ignition_on
+ "ignitionOff" -> R.string.event_ignition_off
+ "maintenance" -> R.string.event_maintenance
+ "textMessage" -> R.string.event_text_message
+ "driverChanged" -> R.string.event_driver_changed
+ else -> R.string.event_unknown
+ })
+ }
+ event.event.geofenceId?.let {
+ val geofence = unitReportsViewModel.getGeofence(it)
+ Log.d("UnitReportsFragment", "Getting geofence $geofence")
+ geofenceText.text = geofence?.name
+ }
+ event.position?.let {
+ addressText.text = it.address
+ }
}
}
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
index 98b8a34..48486e1 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsViewModel.kt
@@ -1,22 +1,20 @@
package mx.trackermap.TrackerMap.android.details.reports
import android.util.Log
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.SavedStateHandle
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.asFlow
-import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.*
+import kotlinx.coroutines.DelicateCoroutinesApi
import java.text.SimpleDateFormat
-import java.util.Calendar
-import java.util.Date
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import mx.trackermap.TrackerMap.client.apis.ReportsApi
-import mx.trackermap.TrackerMap.client.models.Event
-import mx.trackermap.TrackerMap.client.models.Position
-import mx.trackermap.TrackerMap.client.models.Stop
+import mx.trackermap.TrackerMap.client.models.*
+import mx.trackermap.TrackerMap.controllers.GeofencesController
import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+import java.util.*
+import java.util.Calendar
+@DelicateCoroutinesApi
class UnitReportsViewModel(
private val reportsApi: ReportsApi,
savedStateHandle: SavedStateHandle
@@ -24,7 +22,7 @@ class UnitReportsViewModel(
sealed class Report {
class PositionsReport(val positions: Array<Position>) : Report()
- class EventsReport(val events: Array<Event>) : Report()
+ class EventsReport(val events: Array<EventInformation>) : Report()
class StopsReport(val stops: Array<Stop>) : Report()
object LoadingReport: Report()
}
@@ -37,13 +35,22 @@ class UnitReportsViewModel(
DAY, WEEK, MONTH
}
- var deviceId = savedStateHandle.getLiveData("deviceId", 0)
- val reportType: MutableLiveData<ReportType> = savedStateHandle.getLiveData("reportType", null)
- val reportPeriod: MutableLiveData<ReportPeriod> =
+ private val geofenceController: GeofencesController by inject()
+
+ private var _deviceId = savedStateHandle.getLiveData("deviceId", 0)
+ private val _reportType: MutableLiveData<ReportType> = savedStateHandle.getLiveData("reportType", null)
+ private val _reportPeriod: MutableLiveData<ReportPeriod> =
savedStateHandle.getLiveData("reportPeriod", null)
- val report: MutableLiveData<Report> = MutableLiveData()
+ private val _report: MutableLiveData<Report> = MutableLiveData()
+ private val _geofences: MutableLiveData<Map<Int, Geofence>> = MutableLiveData()
- val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
+ val deviceId: LiveData<Int> get() = _deviceId
+ val reportType: LiveData<ReportType> get() = _reportType
+ val reportPeriod: LiveData<ReportPeriod> get() = _reportPeriod
+ val report: LiveData<Report> get() = _report
+ val geofences: LiveData<Map<Int, Geofence>> get() = _geofences
+
+ private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
init {
viewModelScope.launch {
@@ -52,47 +59,49 @@ class UnitReportsViewModel(
viewModelScope.launch {
setupPeriodObserver()
}
+ viewModelScope.launch {
+ setupGeofenceObserver()
+ }
}
private suspend fun setupTypeObserver() {
- reportType.asFlow().collect {
+ _reportType.asFlow().collect {
fetchReport()
}
}
private suspend fun setupPeriodObserver() {
- reportPeriod.asFlow().collect {
+ _reportPeriod.asFlow().collect {
fetchReport()
}
}
- private fun fetchReport() {
- if (reportType.value == null || reportPeriod.value == null) {
- return
+ private suspend fun setupGeofenceObserver() {
+ geofenceController.geofencesFlow.collect {
+ _geofences.postValue(it)
}
+ }
- val (currentDate, previousDate) = getDates()
- Log.d("UnitReportsVM", "Current report type: ${reportType.value.toString()}")
- Log.d("UnitReportsVM", "Current report period: ${reportPeriod.value.toString()}")
- Log.d("UnitReportsVM", "Current date:${dateFormat.format(currentDate)}")
- Log.d("UnitReportsVM", "Previous date:${dateFormat.format(previousDate)}")
+ fun setDeviceId (id: Int) {
+ _deviceId.value = id
+ }
- report.postValue(Report.LoadingReport)
- viewModelScope.launch {
- when (reportType.value!!) {
- ReportType.POSITIONS -> fetchPositions(previousDate, currentDate)
- ReportType.EVENTS -> fetchEvents(previousDate, currentDate)
- ReportType.STOPS -> fetchStops(previousDate, currentDate)
- }
- }
+ fun setReportType(reportType: ReportType) {
+ _reportType.value = reportType
+ }
+
+ fun setReportPeriod(reportPeriod: ReportPeriod) {
+ _reportPeriod.value = reportPeriod
}
+ fun getGeofence(id: Int): Geofence? = _geofences.value?.get(id)
+
private fun getDates(): Pair<Date, Date> {
val calendar = Calendar.getInstance()
val currentDate = calendar.time
calendar.add(
- Calendar.DATE, when (reportPeriod.value!!) {
+ Calendar.DATE, when (_reportPeriod.value!!) {
ReportPeriod.DAY -> -1
ReportPeriod.WEEK -> -7
ReportPeriod.MONTH -> -30
@@ -103,30 +112,66 @@ class UnitReportsViewModel(
return Pair(currentDate, previousDate)
}
+ private fun fetchReport() {
+ if (_reportType.value == null || _reportPeriod.value == null) {
+ return
+ }
+
+ val (currentDate, previousDate) = getDates()
+ Log.d("UnitReportsVM", "Current report type: ${_reportType.value.toString()}")
+ Log.d("UnitReportsVM", "Current report period: ${_reportPeriod.value.toString()}")
+ Log.d("UnitReportsVM", "Current date:${dateFormat.format(currentDate)}")
+ Log.d("UnitReportsVM", "Previous date:${dateFormat.format(previousDate)}")
+
+ _report.postValue(Report.LoadingReport)
+ viewModelScope.launch {
+ when (_reportType.value!!) {
+ ReportType.POSITIONS -> fetchPositions(previousDate, currentDate)
+ ReportType.EVENTS -> fetchEvents(previousDate, currentDate)
+ ReportType.STOPS -> fetchStops(previousDate, currentDate)
+ }
+ }
+ }
+
private suspend fun fetchPositions(from: Date, to: Date) {
Log.d("UnitReportsVM", "Fetching positions")
val result = reportsApi.reportsRouteGet(
dateFormat.format(from),
dateFormat.format(to),
- deviceId.value!!
+ _deviceId.value!!
)
Log.d("UnitReportsVM", "Positions report: $result")
- report.postValue(Report.PositionsReport(result))
+ _report.postValue(Report.PositionsReport(result))
}
private suspend fun fetchEvents(from: Date, to: Date) {
Log.d("UnitReportsVM", "Fetching events")
- val result = reportsApi.reportsEventsGet(
+ val positionsResult = reportsApi.reportsRouteGet(
dateFormat.format(from),
dateFormat.format(to),
- deviceId.value!!
+ _deviceId.value!!
)
+ val eventsResult = reportsApi.reportsEventsGet(
+ dateFormat.format(from),
+ dateFormat.format(to),
+ _deviceId.value!!
+ )
+
+ val result = mutableListOf<EventInformation>()
+
+ eventsResult.forEach { event ->
+ result.add(EventInformation(
+ event = event,
+ position = positionsResult.find { it.id == event.positionId }
+ ))
+ }
+
Log.d("UnitReportsVM", "Events report: $result")
- report.postValue(Report.EventsReport(result))
+ _report.postValue(Report.EventsReport(result.toTypedArray()))
}
private suspend fun fetchStops(from: Date, to: Date) {
@@ -135,10 +180,10 @@ class UnitReportsViewModel(
val result = reportsApi.reportsStopsGet(
dateFormat.format(from),
dateFormat.format(to),
- deviceId.value!!
+ _deviceId.value!!
)
Log.d("UnitReportsVM", "Stops report: $result")
- report.postValue(Report.StopsReport(result))
+ _report.postValue(Report.StopsReport(result))
}
} \ No newline at end of file
diff --git a/androidApp/src/main/res/layout/unit_details_reports.xml b/androidApp/src/main/res/layout/unit_details_reports.xml
index 52a3926..1eaf68c 100644
--- a/androidApp/src/main/res/layout/unit_details_reports.xml
+++ b/androidApp/src/main/res/layout/unit_details_reports.xml
@@ -28,29 +28,50 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
- <TableLayout
- android:id="@+id/eventsTable"
+ <HorizontalScrollView
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:isScrollContainer="true"
- android:scrollbars="vertical"
- android:stretchColumns="*">
+ android:layout_height="wrap_content">
+
+ <TableLayout
+ android:id="@+id/eventsTable"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:isScrollContainer="true"
+ android:scrollbars="vertical"
+ android:stretchColumns="*">
+
+ <TableRow android:background="@color/colorPrimary">
+
+ <TextView
+ android:paddingHorizontal="@dimen/padding"
+ android:text="@string/table_datetime"
+ android:textColor="@color/background"
+ android:padding="@dimen/padding" />
+
+ <TextView
+ android:paddingHorizontal="@dimen/padding"
+ android:text="@string/table_event"
+ android:textColor="@color/background"
+ android:padding="@dimen/padding" />
+
+ <TextView
+ android:paddingHorizontal="@dimen/padding"
+ android:text="@string/table_geofence"
+ android:textColor="@color/background"
+ android:padding="@dimen/padding" />
- <TableRow android:background="@color/colorPrimary">
+ <TextView
+ android:paddingHorizontal="@dimen/padding"
+ android:text="@string/table_address"
+ android:textColor="@color/background"
+ android:padding="@dimen/padding" />
- <TextView
- android:paddingHorizontal="@dimen/padding"
- android:text="@string/table_event"
- android:textColor="@color/background" />
+ </TableRow>
- <TextView
- android:paddingHorizontal="@dimen/padding"
- android:text="@string/table_datetime"
- android:textColor="@color/background" />
+ </TableLayout>
- </TableRow>
+ </HorizontalScrollView>
- </TableLayout>
</ScrollView>
<LinearLayout
diff --git a/androidApp/src/main/res/values-es-rMX/strings.xml b/androidApp/src/main/res/values-es-rMX/strings.xml
index 7397599..9429494 100644
--- a/androidApp/src/main/res/values-es-rMX/strings.xml
+++ b/androidApp/src/main/res/values-es-rMX/strings.xml
@@ -50,6 +50,28 @@
<string name="month_period">Mes</string>
<string name="period">Periodo</string>
<string name="select_period">Seleccionar</string>
+
<string name="table_event">Evento</string>
<string name="table_datetime">Fecha y hora</string>
+ <string name="table_geofence">Geocerca</string>
+ <string name="table_address">Dirección</string>
+
+ <string name="event_device_online">Unidad en línea</string>
+ <string name="event_device_unknown">Unidad en estado desconocido</string>
+ <string name="event_device_offline">Unidad fuera de línea</string>
+ <string name="event_device_inactive">Unidad inactiva</string>
+ <string name="event_device_moving">Unidad en movimiento</string>
+ <string name="event_device_stopped">Unidad detenida</string>
+ <string name="event_device_overspeed">Excedido el límite de velocidad</string>
+ <string name="event_device_fuel_drop">Pérdida de combustible</string>
+ <string name="event_command_result">Resultado del comando</string>
+ <string name="event_geofence_enter">Entrada en la geocerca</string>
+ <string name="event_geofence_exit">Salida de la geocerca</string>
+ <string name="event_alarm">Alarma</string>
+ <string name="event_ignition_on">Ignición encendida</string>
+ <string name="event_ignition_off">Ignición apagada</string>
+ <string name="event_maintenance">Se requiere mantenimiento</string>
+ <string name="event_text_message">Mensaje de texto recibido</string>
+ <string name="event_driver_changed">El conductor ha cambiado</string>
+ <string name="event_unknown">Evento desconocido</string>
</resources> \ No newline at end of file
diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml
index 93f088a..0c6a29e 100644
--- a/androidApp/src/main/res/values/strings.xml
+++ b/androidApp/src/main/res/values/strings.xml
@@ -58,6 +58,28 @@
<string name="month_period">Month</string>
<string name="period">Period</string>
<string name="select_period">Select</string>
+
<string name="table_event">Event</string>
<string name="table_datetime">Datetime</string>
+ <string name="table_geofence">Geofence</string>
+ <string name="table_address">Address</string>
+
+ <string name="event_device_online">Status online</string>
+ <string name="event_device_unknown">Status unknown</string>
+ <string name="event_device_offline">Status offline</string>
+ <string name="event_device_inactive">Device inactive</string>
+ <string name="event_device_moving">Device moving</string>
+ <string name="event_device_stopped">Device stopped</string>
+ <string name="event_device_overspeed">Speed limit exceeded</string>
+ <string name="event_device_fuel_drop">Fuel drop</string>
+ <string name="event_command_result">Command result</string>
+ <string name="event_geofence_enter">Geofence entered</string>
+ <string name="event_geofence_exit">Geofence exited</string>
+ <string name="event_alarm">Alarm</string>
+ <string name="event_ignition_on">Ignition on</string>
+ <string name="event_ignition_off">Ignition off</string>
+ <string name="event_maintenance">Maintenance required</string>
+ <string name="event_text_message">Text message received</string>
+ <string name="event_driver_changed">Driver changed</string>
+ <string name="event_unknown">Unknown event</string>
</resources>
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/GeofencesApi.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/GeofencesApi.kt
index ede7586..dd9c89d 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/GeofencesApi.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/apis/GeofencesApi.kt
@@ -15,7 +15,7 @@ import mx.trackermap.TrackerMap.client.models.Geofence
import mx.trackermap.TrackerMap.client.infrastructure.*
-class GeofencesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : ApiClient(basePath) {
+class GeofencesApi(basePath: String = "https://demo.traccar.org/api") : ApiClient(basePath) {
/**
* Fetch a list of Geofences
@@ -28,18 +28,25 @@ class GeofencesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : A
* @return kotlin.Array<Geofence>
*/
@Suppress("UNCHECKED_CAST")
- suspend fun geofencesGet(all: kotlin.Boolean? = null, userId: kotlin.Int? = null, deviceId: kotlin.Int? = null, groupId: kotlin.Int? = null, refresh: kotlin.Boolean? = null): kotlin.Array<Geofence> {
- val localVariableQuery: MultiValueMap = mapOf("all" to listOf("$all"), "userId" to listOf("$userId"), "deviceId" to listOf("$deviceId"), "groupId" to listOf("$groupId"), "refresh" to listOf("$refresh"))
+ suspend fun geofencesGet(all: Boolean? = null, userId: Int? = null, deviceId: Int? = null, groupId: Int? = null, refresh: Boolean? = null): Array<Geofence> {
+ val query: MutableMap<String, List<String>> = mutableMapOf()
+ all?.let { query["all"] = listOf("$it") }
+ userId?.let { query["userId"] = listOf("$it") }
+ deviceId?.let { query["userId"] = listOf("$it") }
+ groupId?.let { query["groupId"] = listOf("$it") }
+ refresh?.let { query["refresh"] = listOf("$it") }
+ val localVariableQuery: MultiValueMap = query
+
val localVariableConfig = RequestConfig(
RequestMethod.GET,
"/geofences", query = localVariableQuery
)
- val response = request<kotlin.Array<Geofence>>(
+ val response = request<Array<Geofence>>(
localVariableConfig
)
return when (response.responseType) {
- ResponseType.Success -> (response as Success<*>).data as kotlin.Array<Geofence>
+ ResponseType.Success -> (response as Success<*>).data as Array<Geofence>
ResponseType.Informational -> TODO()
ResponseType.Redirection -> TODO()
ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error")
@@ -48,12 +55,12 @@ class GeofencesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : A
}
/**
* Delete a Geofence
- *
- * @param id
+ *
+ * @param id
* @return void
*/
- suspend fun geofencesIdDelete(id: kotlin.Int): Unit {
-
+ suspend fun geofencesIdDelete(id: Int) {
+
val localVariableConfig = RequestConfig(
RequestMethod.DELETE,
"/geofences/{id}".replace("{" + "id" + "}", "$id")
@@ -72,15 +79,15 @@ class GeofencesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : A
}
/**
* Update a Geofence
- *
- * @param body
- * @param id
+ *
+ * @param body
+ * @param id
* @return Geofence
*/
@Suppress("UNCHECKED_CAST")
- suspend fun geofencesIdPut(body: Geofence, id: kotlin.Int): Geofence {
- val localVariableBody: kotlin.Any? = body
-
+ suspend fun geofencesIdPut(body: Geofence, id: Int): Geofence {
+ val localVariableBody: Any = body
+
val localVariableConfig = RequestConfig(
RequestMethod.PUT,
"/geofences/{id}".replace("{" + "id" + "}", "$id")
@@ -99,14 +106,14 @@ class GeofencesApi(basePath: kotlin.String = "https://demo.traccar.org/api") : A
}
/**
* Create a Geofence
- *
- * @param body
+ *
+ * @param body
* @return Geofence
*/
@Suppress("UNCHECKED_CAST")
suspend fun geofencesPost(body: Geofence): Geofence {
- val localVariableBody: kotlin.Any? = body
-
+ val localVariableBody: Any = body
+
val localVariableConfig = RequestConfig(
RequestMethod.POST,
"/geofences"
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt
new file mode 100644
index 0000000..1256b8c
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/EventInformation.kt
@@ -0,0 +1,6 @@
+package mx.trackermap.TrackerMap.client.models
+
+data class EventInformation(
+ val event: Event,
+ val position: Position?
+)
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Geofence.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Geofence.kt
index f82ca07..3b4ee9b 100644
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Geofence.kt
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/client/models/Geofence.kt
@@ -11,6 +11,7 @@
*/
package mx.trackermap.TrackerMap.client.models
+import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonPrimitive
@@ -23,6 +24,7 @@ import kotlinx.serialization.json.JsonPrimitive
* @param calendarId
* @param attributes
*/
+@Serializable
data class Geofence (
val id: Int? = null,
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofenceController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofenceController.kt
deleted file mode 100644
index 011d094..0000000
--- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofenceController.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package mx.trackermap.TrackerMap.controllers
-
-import mx.trackermap.TrackerMap.client.apis.GeofencesApi
-import mx.trackermap.TrackerMap.client.models.Geofence
-
-class GeofenceController(val geofencesApi: GeofencesApi) {
- var geofences = emptyArray<Geofence>()
-
- suspend fun getGeofences () {
- geofences = geofencesApi.geofencesGet()
- }
-
- fun getGeofence (id: Int) = geofences.find { it.id == id }
-} \ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofencesController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofencesController.kt
new file mode 100644
index 0000000..fc336d1
--- /dev/null
+++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/GeofencesController.kt
@@ -0,0 +1,30 @@
+package mx.trackermap.TrackerMap.controllers
+
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.apis.GeofencesApi
+import mx.trackermap.TrackerMap.client.models.Geofence
+
+@DelicateCoroutinesApi
+class GeofencesController(
+ private val geofencesApi: GeofencesApi
+) {
+ val geofencesFlow = MutableStateFlow<Map<Int,Geofence>>(emptyMap())
+
+ init {
+ GlobalScope.launch {
+ fetchGeofences()
+ }
+ }
+
+ private suspend fun fetchGeofences() {
+ val geofences = geofencesApi.geofencesGet(all = true)
+ val geofencesMap = mutableMapOf<Int, Geofence>()
+ geofences.forEach {
+ geofencesMap[it.id!!] = it
+ }
+ geofencesFlow.value = geofencesMap
+ }
+} \ No newline at end of file