Full rewrite of bee-debug-app as ADAMaps data proxy. - Detection forwarder to ADAMaps API (polls landmarks/last/200, dedup by id+ts) - 30s camera snapshot with 4-endpoint auto-detect - GPS mini-map via osmdroid/OpenStreetMap - Device status panel (firmware, GPS, AI ready flags) - Connection status bar + forwarding toggle - Foreground service with persistent notification - Dark amber theme, no Google Play Services - Package: com.adamaps.varroa, minSdk 26
65 lines
2.1 KiB
Kotlin
65 lines
2.1 KiB
Kotlin
package com.adamaps.varroa.api
|
|
|
|
import com.adamaps.varroa.data.AdaMapsIngestRequest
|
|
import com.adamaps.varroa.data.ApiResult
|
|
import com.google.gson.Gson
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.withContext
|
|
import okhttp3.MediaType.Companion.toMediaType
|
|
import okhttp3.OkHttpClient
|
|
import okhttp3.Request
|
|
import okhttp3.RequestBody.Companion.toRequestBody
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
class AdaMapsApiClient(
|
|
private var apiUrl: String = "https://api.adamaps.org",
|
|
private var apiKey: String = "***REMOVED***"
|
|
) {
|
|
|
|
private val client = OkHttpClient.Builder()
|
|
.connectTimeout(15, TimeUnit.SECONDS)
|
|
.readTimeout(30, TimeUnit.SECONDS)
|
|
.writeTimeout(30, TimeUnit.SECONDS)
|
|
.build()
|
|
|
|
private val gson = Gson()
|
|
private val json = "application/json; charset=utf-8".toMediaType()
|
|
|
|
fun updateConfig(url: String, key: String) {
|
|
apiUrl = url.trimEnd('/')
|
|
apiKey = key
|
|
}
|
|
|
|
suspend fun ingest(request: AdaMapsIngestRequest): ApiResult<String> = withContext(Dispatchers.IO) {
|
|
try {
|
|
val body = gson.toJson(request).toRequestBody(json)
|
|
val req = Request.Builder()
|
|
.url("$apiUrl/api/ingest")
|
|
.addHeader("X-MapNet-Key", apiKey)
|
|
.addHeader("Content-Type", "application/json")
|
|
.post(body)
|
|
.build()
|
|
client.newCall(req).execute().use { resp ->
|
|
val respBody = resp.body?.string() ?: ""
|
|
if (resp.isSuccessful) ApiResult.Success(respBody)
|
|
else ApiResult.Error("HTTP ${resp.code}: ${resp.message}", resp.code)
|
|
}
|
|
} catch (e: Exception) {
|
|
ApiResult.Error(e.message ?: "Network error")
|
|
}
|
|
}
|
|
|
|
suspend fun checkReachability(): Boolean = withContext(Dispatchers.IO) {
|
|
try {
|
|
val req = Request.Builder()
|
|
.url("$apiUrl/health")
|
|
.head()
|
|
.build()
|
|
client.newCall(req).execute().use { resp ->
|
|
resp.code < 500
|
|
}
|
|
} catch (e: Exception) {
|
|
false
|
|
}
|
|
}
|
|
}
|