feat: add TraccarHttpClient for server communication

This commit is contained in:
fiatcode 2026-04-30 11:02:09 +07:00
parent c1bd51eb48
commit c11a26c09e
No known key found for this signature in database

View file

@ -0,0 +1,80 @@
package com.traccar.traccar_client.network
import android.util.Base64
import com.traccar.traccar_client.model.Location
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.URLEncoder
import java.util.concurrent.TimeUnit
data class TraccarConfig(
val serverUrl: String,
val deviceId: String,
val password: String = ""
)
class TraccarHttpClient {
private val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
suspend fun sendLocation(config: TraccarConfig, location: Location): Result<Unit> = withContext(Dispatchers.IO) {
try {
val url = buildLocationUrl(config, location)
val request = buildRequest(config, url)
val response = client.newCall(request).execute()
if (response.isSuccessful) {
Result.success(Unit)
} else {
Result.failure(Exception("HTTP ${response.code}: ${response.message}"))
}
} catch (e: Exception) {
Result.failure(e)
}
}
suspend fun sendLocations(config: TraccarConfig, locations: List<Location>): Result<Int> = withContext(Dispatchers.IO) {
var successCount = 0
for (location in locations) {
val result = sendLocation(config, location)
if (result.isSuccess) {
successCount++
}
}
Result.success(successCount)
}
private fun buildLocationUrl(config: TraccarConfig, location: Location): String {
val baseUrl = config.serverUrl.trimEnd('/')
val timestamp = location.timestamp
return "$baseUrl/?" +
"id=${URLEncoder.encode(config.deviceId, "UTF-8")}" +
"&lat=${location.latitude}" +
"&lon=${location.longitude}" +
"&timestamp=$timestamp" +
(location.speed?.let { "&speed=${it * 3.6}" } ?: "") +
(location.heading?.let { "&bearing=$it" } ?: "") +
(location.accuracy?.let { "&accuracy=$it" } ?: "") +
(location.altitude?.let { "&altitude=$it" } ?: "") +
"&is_moving=${if (location.isMoving) 1 else 0}"
}
private fun buildRequest(config: TraccarConfig, url: String): Request {
val builder = Request.Builder().url(url).get()
if (config.password.isNotEmpty()) {
val credentials = "${config.deviceId}:${config.password}"
val encoded = Base64.encodeToString(credentials.toByteArray(), Base64.NO_WRAP)
builder.addHeader("Authorization", "Basic $encoded")
}
return builder.build()
}
}