Skip to main content

Events Data Layer

The events data layer provides access to device event data (online/offline, geofence, alarms, ignition, etc.) from the Traccar-based backend.


EventApi​

Package: com.visla.vislagps.data.remote.api

Retrofit interface defining the event HTTP endpoints.

interface EventApi {

@GET("api/events")
suspend fun getEvents(
@Query("deviceId") deviceId: Int? = null,
@Query("from") from: String? = null,
@Query("to") to: String? = null,
@Query("type") types: List<String>? = null,
@Query("limit") limit: Int? = null
): List<EventDto>

@GET("api/events/{id}")
suspend fun getEvent(@Path("id") id: Int): EventDto
}
MethodHTTPPathParametersReturns
getEventsGETapi/eventsdeviceId: Int?, from: String?, to: String?, types: List<String>?, limit: Int?List<EventDto>
getEventGETapi/events/{id}id: Int (path)EventDto

All parameters on getEvents default to null, making them optional query filters.


EventRepository​

Package: com.visla.vislagps.domain.repositories

Domain-level interface. Uses Instant for timestamps instead of raw strings.

interface EventRepository {
suspend fun getEvents(
deviceId: Int? = null,
from: Instant? = null,
to: Instant? = null,
types: List<String>? = null,
limit: Int? = null
): List<DeviceEvent>

suspend fun getEvent(id: Int): DeviceEvent
}
MethodParametersReturns
getEventsdeviceId: Int?, from: Instant?, to: Instant?, types: List<String>?, limit: Int?List<DeviceEvent>
getEventid: IntDeviceEvent

EventRepositoryImpl​

Package: com.visla.vislagps.data.repositories

@Singleton implementation injected via Hilt.

Constructor​

@Singleton
class EventRepositoryImpl @Inject constructor(
private val eventApi: EventApi,
private val eventMapper: EventMapper
) : EventRepository

Implementations​

getEvents​

override suspend fun getEvents(
deviceId: Int?,
from: Instant?,
to: Instant?,
types: List<String>?,
limit: Int?
): List<DeviceEvent>
  1. Formats from/to Instant values to ISO-8601 strings via DateTimeFormatter.ISO_INSTANT.
  2. Delegates to eventApi.getEvents(...).
  3. Maps the DTO list through eventMapper.toDomain(events).
  4. Catches HttpException β†’ NetworkException("HTTP error: {code}").
  5. Catches IOException β†’ NetworkException("Network error fetching events").

getEvent​

override suspend fun getEvent(id: Int): DeviceEvent
  1. Calls eventApi.getEvent(id).
  2. Maps the single DTO via eventMapper.toDomain(event).
  3. Same error handling as getEvents.

Private Helpers​

MethodSignaturePurpose
formatInstant(Instant) β†’ StringFormats an Instant with DateTimeFormatter.ISO_INSTANT
mapHttpException(HttpException) β†’ ExceptionWraps in NetworkException with the HTTP status code

Event DTOs​

EventDto​

Package: com.visla.vislagps.data.remote.dto

data class EventDto(
val id: Int,
val deviceId: Int,
val type: String,
val eventTime: String,
val positionId: Int? = null,
val geofenceId: Int? = null,
val maintenanceId: Int? = null,
val attributes: Map<String, Any>? = null
)

DeviceEvent (Domain Entity)​

Package: com.visla.vislagps.domain.entities

data class DeviceEvent(
val id: Int,
val deviceId: Int,
val type: EventType,
val eventTime: Instant,
val positionId: Int?,
val geofenceId: Int?,
val maintenanceId: Int?,
val attributes: Map<String, Any>
) {
val displayName: String get() = type.displayName
}

Key differences from EventDto:

FieldDTO typeDomain type
typeStringEventType (enum)
eventTimeStringInstant
attributesMap<String, Any>?Map<String, Any> (non-null, defaults to emptyMap())

EventType​

enum class EventType(val value: String, val displayName: String) {
DEVICE_ONLINE("deviceOnline", "Device Online"),
DEVICE_OFFLINE("deviceOffline", "Device Offline"),
DEVICE_MOVING("deviceMoving", "Started Moving"),
DEVICE_STOPPED("deviceStopped", "Stopped"),
GEOFENCE_ENTER("geofenceEnter", "Entered Geofence"),
GEOFENCE_EXIT("geofenceExit", "Exited Geofence"),
ALARM("alarm", "Alarm"),
IGNITION_ON("ignitionOn", "Ignition On"),
IGNITION_OFF("ignitionOff", "Ignition Off"),
OVERSPEED("overspeed", "Overspeed"),
FUEL_DROP("fuelDrop", "Fuel Drop"),
FUEL_INCREASE("fuelIncrease", "Fuel Increase"),
POWER_CUT("powerCut", "Power Cut"),
POWER_RESTORED("powerRestored", "Power Restored"),
UNKNOWN("unknown", "Unknown Event");

companion object {
fun fromString(value: String?): EventType
}
}

fromString performs a case-insensitive lookup against entries and falls back to UNKNOWN.


EventMapper​

Package: com.visla.vislagps.data.mappers

@Singleton class injected via Hilt. Converts DTOs to domain entities.

@Singleton
class EventMapper @Inject constructor() {

fun toDomain(dto: EventDto): DeviceEvent

fun toDomain(dtos: List<EventDto>): List<DeviceEvent>
}
MethodInputOutputNotes
toDomain(EventDto)Single DTODeviceEventParses eventTime string β†’ Instant, converts type via EventType.fromString, defaults attributes to emptyMap() if null
toDomain(List<EventDto>)List of DTOsList<DeviceEvent>Maps each element through the single-DTO overload

Instant Parsing​

parseInstant uses Instant.parse(dateString). On failure it logs a warning via Logger.warn and returns Instant.now() as a fallback.


Data Flow​