Files
mg4/app/src/main/java/com/evsuite/abrp/TelemetryQueue.java
T
nilsandClaude Opus 5.5 6145736c97 App 2.3.0: Server tab, live telemetry to the car server
- New Server tab: server URL, ingest token and installation id, with
  Save, Test connection (health, then a read-only token check) and the
  config-file import that upstream removed (app folder / USB stick first,
  document picker as fallback). Settings are kept encrypted and read on
  every use, so the service picks up a change without a restart. Each
  installation generates its own id; the inherited upstream UUID and
  the baked-in CONSUMPTION_API_* build fields are gone.
- Live telemetry restored from before ea8032a (TelemetryPayload,
  UploadCadence, UploadSettings, GPS) and sent in batches to
  POST /v1/telemetry instead of ABRP; the server forwards to ABRP. Adds
  ext_temp, voltage and current. Unsent samples queue in memory (about
  8 h) while offline.
- Upload tab: the live-telemetry switch and cadence controls work again;
  the dead service and autostart switches are removed.
- Manifest: location permissions and foreground service types.
- Unit tests compile again: 114 (stable) / 136 (unstable) pass. Tests
  for the deleted AbrpApi and HeadUnitWeather removed; new tests for
  ServerConfig and TelemetryQueue. Lint passes.

Not yet tried on the car.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:23:04 +02:00

60 lines
2.0 KiB
Java

package com.evsuite.abrp;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
/**
* Live samples waiting to reach the server, oldest first.
*
* Bounded: while the car is offline the oldest samples are dropped once {@link #capacity}
* is reached, so a long dead spot costs the start of the gap, never the head unit's memory.
* Held in memory only — a process restart loses what is queued, which is the price of not
* writing to flash every 15 seconds.
*
* Free of Android types so the policy is unit-tested on the JVM.
*/
final class TelemetryQueue {
/** About eight hours at one sample per 15-second tick. */
static final int DEFAULT_CAPACITY = 2000;
/** The server takes at most 500 samples per request. */
static final int MAX_BATCH = 500;
private final int capacity;
private final ArrayDeque<String> samples = new ArrayDeque<>();
private int dropped;
TelemetryQueue() { this(DEFAULT_CAPACITY); }
TelemetryQueue(int capacity) { this.capacity = capacity; }
synchronized void add(String sampleJson) {
if (samples.size() >= capacity) {
samples.removeFirst();
dropped++;
}
samples.addLast(sampleJson);
}
/** Up to {@link #MAX_BATCH} of the oldest samples, still queued until {@link #remove}. */
synchronized List<String> peekBatch() {
List<String> batch = new ArrayList<>(Math.min(samples.size(), MAX_BATCH));
for (String sample : samples) {
if (batch.size() >= MAX_BATCH) break;
batch.add(sample);
}
return batch;
}
/** Drops the oldest {@code count} samples once the server has confirmed them. */
synchronized void remove(int count) {
for (int i = 0; i < count && !samples.isEmpty(); i++) samples.removeFirst();
}
synchronized int size() { return samples.size(); }
/** Samples lost to the capacity limit since the queue was created. */
synchronized int dropped() { return dropped; }
}