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
}
| Method | HTTP | Path | Parameters | Returns |
|---|---|---|---|---|
getEvents | GET | api/events | deviceId: Int?, from: String?, to: String?, types: List<String>?, limit: Int? | List<EventDto> |
getEvent | GET | api/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
}
| Method | Parameters | Returns |
|---|---|---|
getEvents | deviceId: Int?, from: Instant?, to: Instant?, types: List<String>?, limit: Int? | List<DeviceEvent> |
getEvent | id: Int | DeviceEvent |
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>
- Formats
from/toInstantvalues to ISO-8601 strings viaDateTimeFormatter.ISO_INSTANT. - Delegates to
eventApi.getEvents(...). - Maps the DTO list through
eventMapper.toDomain(events). - Catches
HttpExceptionβNetworkException("HTTP error: {code}"). - Catches
IOExceptionβNetworkException("Network error fetching events").
getEventβ
override suspend fun getEvent(id: Int): DeviceEvent
- Calls
eventApi.getEvent(id). - Maps the single DTO via
eventMapper.toDomain(event). - Same error handling as
getEvents.
Private Helpersβ
| Method | Signature | Purpose |
|---|---|---|
formatInstant | (Instant) β String | Formats an Instant with DateTimeFormatter.ISO_INSTANT |
mapHttpException | (HttpException) β Exception | Wraps 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:
| Field | DTO type | Domain type |
|---|---|---|
type | String | EventType (enum) |
eventTime | String | Instant |
attributes | Map<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>
}
| Method | Input | Output | Notes |
|---|---|---|---|
toDomain(EventDto) | Single DTO | DeviceEvent | Parses eventTime string β Instant, converts type via EventType.fromString, defaults attributes to emptyMap() if null |
toDomain(List<EventDto>) | List of DTOs | List<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.