v6: fix detection send queue
Root cause: Server expects flat array of detections with device_id on each
item, but client was sending nested {device_id, detections: [...]}.
The /health endpoint worked (ADAMaps showed green) but /api/ingest failed
validation: 'Missing required fields: device_id, lat, lon' on every request.
Items queued indefinitely, sent=0.
Fixed by:
- Adding device_id field to AdaMapsDetection
- Changed AdaMapsIngestRequest to typealias for List<AdaMapsDetection>
- Updated toAdaMapsDetection() to accept deviceId parameter
- Updated ForwardingService to send flat array format
This commit is contained in:
parent
c4e44250d0
commit
b8334ac9d5
3 changed files with 17 additions and 18 deletions
|
|
@ -53,9 +53,10 @@ class AdaMapsApiClient(
|
||||||
apiKey = key
|
apiKey = key
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun ingest(request: AdaMapsIngestRequest): ApiResult<String> = withContext(Dispatchers.IO) {
|
suspend fun ingest(detections: AdaMapsIngestRequest): ApiResult<String> = withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val body = gson.toJson(request).toRequestBody(json)
|
// Server expects flat array of detections, each with device_id
|
||||||
|
val body = gson.toJson(detections).toRequestBody(json)
|
||||||
val req = Request.Builder()
|
val req = Request.Builder()
|
||||||
.url("$apiUrl/api/ingest")
|
.url("$apiUrl/api/ingest")
|
||||||
.addHeader("X-MapNet-Key", apiKey)
|
.addHeader("X-MapNet-Key", apiKey)
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ data class BeeDeviceInfo(
|
||||||
// ── ADAMaps ingest ────────────────────────────────────────────────────────────
|
// ── ADAMaps ingest ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
data class AdaMapsDetection(
|
data class AdaMapsDetection(
|
||||||
|
@SerializedName("device_id") val deviceId: String,
|
||||||
@SerializedName("id") val id: Long,
|
@SerializedName("id") val id: Long,
|
||||||
@SerializedName("class_label") val classLabel: String?,
|
@SerializedName("class_label") val classLabel: String?,
|
||||||
@SerializedName("class_label_confidence") val classLabelConfidence: Double?,
|
@SerializedName("class_label_confidence") val classLabelConfidence: Double?,
|
||||||
|
|
@ -63,12 +64,12 @@ data class AdaMapsDetection(
|
||||||
@SerializedName("azimuth") val azimuth: Double?
|
@SerializedName("azimuth") val azimuth: Double?
|
||||||
)
|
)
|
||||||
|
|
||||||
data class AdaMapsIngestRequest(
|
// Server expects flat array of detections, each with device_id
|
||||||
@SerializedName("device_id") val deviceId: String,
|
// (NOT nested {device_id, detections: [...]})
|
||||||
@SerializedName("detections") val detections: List<AdaMapsDetection>
|
typealias AdaMapsIngestRequest = List<AdaMapsDetection>
|
||||||
)
|
|
||||||
|
|
||||||
fun BeeDetection.toAdaMapsDetection() = AdaMapsDetection(
|
fun BeeDetection.toAdaMapsDetection(deviceId: String) = AdaMapsDetection(
|
||||||
|
deviceId = deviceId,
|
||||||
id = id,
|
id = id,
|
||||||
classLabel = classLabel,
|
classLabel = classLabel,
|
||||||
classLabelConfidence = classLabelConfidence,
|
classLabelConfidence = classLabelConfidence,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import com.adamaps.varroa.MainActivity
|
||||||
import com.adamaps.varroa.R
|
import com.adamaps.varroa.R
|
||||||
import com.adamaps.varroa.api.AdaMapsApiClient
|
import com.adamaps.varroa.api.AdaMapsApiClient
|
||||||
import com.adamaps.varroa.api.BeeApiClient
|
import com.adamaps.varroa.api.BeeApiClient
|
||||||
import com.adamaps.varroa.data.AdaMapsIngestRequest
|
import com.adamaps.varroa.data.AdaMapsDetection
|
||||||
import com.adamaps.varroa.data.ApiResult
|
import com.adamaps.varroa.data.ApiResult
|
||||||
import com.adamaps.varroa.data.BeeDetection
|
import com.adamaps.varroa.data.BeeDetection
|
||||||
import com.adamaps.varroa.data.SessionStats
|
import com.adamaps.varroa.data.SessionStats
|
||||||
|
|
@ -241,15 +241,14 @@ class ForwardingService : LifecycleService() {
|
||||||
private suspend fun sendToADAMaps(detections: List<BeeDetection>) {
|
private suspend fun sendToADAMaps(detections: List<BeeDetection>) {
|
||||||
// Get device ID from device info (best effort)
|
// Get device ID from device info (best effort)
|
||||||
val deviceId = try {
|
val deviceId = try {
|
||||||
(beeClient.getDeviceInfo() as? ApiResult.Success)?.data?.deviceId
|
val info = beeClient.getDeviceInfo()
|
||||||
?: (beeClient.getDeviceInfo() as? ApiResult.Success)?.data?.serial
|
(info as? ApiResult.Success)?.data?.deviceId
|
||||||
|
?: (info as? ApiResult.Success)?.data?.serial
|
||||||
?: "unknown"
|
?: "unknown"
|
||||||
} catch (e: Exception) { "unknown" }
|
} catch (e: Exception) { "unknown" }
|
||||||
|
|
||||||
val request = AdaMapsIngestRequest(
|
// Server expects flat array of detections, each with device_id embedded
|
||||||
deviceId = deviceId,
|
val request = detections.map { it.toAdaMapsDetection(deviceId) }
|
||||||
detections = detections.map { it.toAdaMapsDetection() }
|
|
||||||
)
|
|
||||||
|
|
||||||
_stats.update { it.copy(queued = it.queued + detections.size) }
|
_stats.update { it.copy(queued = it.queued + detections.size) }
|
||||||
|
|
||||||
|
|
@ -277,10 +276,8 @@ class ForwardingService : LifecycleService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (item in toRetry) {
|
for (item in toRetry) {
|
||||||
val request = AdaMapsIngestRequest(
|
// Server expects flat array of detections, each with device_id embedded
|
||||||
deviceId = item.deviceId,
|
val request = item.detections.map { it.toAdaMapsDetection(item.deviceId) }
|
||||||
detections = item.detections.map { it.toAdaMapsDetection() }
|
|
||||||
)
|
|
||||||
|
|
||||||
when (val result = adamapsClient.ingest(request)) {
|
when (val result = adamapsClient.ingest(request)) {
|
||||||
is ApiResult.Success -> {
|
is ApiResult.Success -> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue