Files
mg4/app/src/main/java/com/evsuite/abrp/ChargingGraphView.java
T

80 lines
4.0 KiB
Java

package com.evsuite.abrp;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/** Lightweight SOC/power charging curve, avoiding a heavy chart dependency on AAOS 9. */
public final class ChargingGraphView extends View {
private final Paint grid = new Paint(1), line = new Paint(1), text = new Paint(1);
private final List<float[]> points = new ArrayList<>();
private final float[] socPower = new float[101];
public ChargingGraphView(Context c, AttributeSet a) { super(c,a); java.util.Arrays.fill(socPower, Float.NaN); grid.setColor(AccentColor.withAlpha(AccentColor.resolve(c, R.attr.evAccentLight), 0x55)); line.setColor(0xFFFFC857); line.setStrokeWidth(4); text.setColor(0xFFBDC4C6); text.setTextSize(20); }
synchronized void add(Float soc, Float power) {
if (soc == null || power == null || power >= 0) return;
float p = Math.abs(power);
if (!points.isEmpty() && Math.abs(points.get(points.size()-1)[0] - soc) < .1f) points.remove(points.size()-1);
points.add(new float[]{soc,p}); if (points.size() > 500) points.remove(0);
socPower[Math.max(0, Math.min(100, Math.round(soc)))] = p; invalidate();
}
synchronized void setPoints(List<ChargeSessionTracker.Point> values) {
points.clear();
java.util.Arrays.fill(socPower, Float.NaN);
for (ChargeSessionTracker.Point value : values) {
if (value.socPercent == null) continue;
points.add(new float[]{value.socPercent, value.powerKw});
socPower[Math.max(0, Math.min(100, Math.round(value.socPercent)))] = value.powerKw;
}
invalidate();
}
synchronized String tableText() {
StringBuilder out = new StringBuilder("SOC Charge power\n");
boolean found = false;
for (int soc=0; soc<=100; soc++) if (!Float.isNaN(socPower[soc])) {
found = true;
out.append(String.format(Locale.getDefault(), "%3d %% %6.1f kW\n", soc, socPower[soc]));
}
return found ? out.toString().trim() : "No charging measurements yet";
}
/**
* Axes with their labels clear of each other: "kW" in a row of its own above the plot, the
* power values right-aligned against the y axis, and the SOC ticks as "0 %" … "100 %",
* centred under their lines, the last one kept inside the view.
*/
@Override protected synchronized void onDraw(Canvas c) {
super.onDraw(c);
float left = 58, right = getWidth() - 12, top = 36, bottom = getHeight() - 38;
float max = 20; for (float[] p : points) max = Math.max(max, p[1]); max = (float) Math.ceil(max / 20f) * 20f;
text.setTextAlign(Paint.Align.RIGHT);
for (int i = 0; i <= 5; i++) {
float y = bottom - (bottom - top) * i / 5f;
c.drawLine(left, y, right, y, grid);
c.drawText(String.format(Locale.US, "%.0f", max * i / 5f), left - 8, y + 7, text);
}
text.setTextAlign(Paint.Align.LEFT);
c.drawText("kW", 4, 20, text);
for (int soc = 0; soc <= 100; soc += 20) {
float x = left + (right - left) * soc / 100f;
c.drawLine(x, top, x, bottom, grid);
String label = soc + " %";
float half = text.measureText(label) / 2f;
float cx = Math.min(x, getWidth() - 2 - half);
text.setTextAlign(Paint.Align.CENTER);
c.drawText(label, cx, getHeight() - 8, text);
}
text.setTextAlign(Paint.Align.LEFT);
for (int i = 1; i < points.size(); i++) {
float[] a = points.get(i - 1), b = points.get(i);
float ax = left + a[0] * (right - left) / 100, ay = bottom - a[1] * (bottom - top) / max;
float bx = left + b[0] * (right - left) / 100, by = bottom - b[1] * (bottom - top) / max;
c.drawLine(ax, ay, bx, by, line);
c.drawCircle(bx, by, 4, line);
}
}
}