Track rolling 7 and 30 day consumption

This commit is contained in:
TCFDONMEZ
2026-09-30 12:08:54 +03:00
parent 81483e7f48
commit 1709fdf1ac
5 changed files with 33 additions and 31 deletions
-1
View File
@@ -1 +0,0 @@
c2c11f712ebc3052d30725b536a7efee06ad9de9e1700e852e10264fe083f8eb FatihsMG4-unstable-2.2.24.apk
+1
View File
@@ -0,0 +1 @@
e16113c3dd3d83492b0807836e01520323e5cc7e5a33a4e2c13b904e0152c2a8 FatihsMG4-unstable-2.2.25.apk
+2 -2
View File
@@ -34,8 +34,8 @@ android {
applicationId "com.evsuite.abrp" applicationId "com.evsuite.abrp"
minSdk 27 minSdk 27
targetSdk 36 targetSdk 36
versionCode 41 versionCode 42
versionName "2.2.24" versionName "2.2.25"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -5,10 +5,7 @@ import android.content.SharedPreferences;
import com.evsuite.hardware.telemetry.EnergySnapshot; import com.evsuite.hardware.telemetry.EnergySnapshot;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.WeekFields;
/** Persistent, read-only trip/lifetime integration patterned after DriveHub_Dort. */ /** Persistent, read-only trip/lifetime integration patterned after DriveHub_Dort. */
final class ConsumptionTracker { final class ConsumptionTracker {
@@ -29,23 +26,18 @@ final class ConsumptionTracker {
} }
private final SharedPreferences prefs; private final SharedPreferences prefs;
private Totals lifetime, week, month, tripA, tripB; private Totals lifetime, tripA, tripB;
private String weekId, monthId;
private long lastMs; private long lastMs;
private Float lastSpeed, lastPower, lastSoc; private Float lastSpeed, lastPower, lastSoc;
private ConsumptionTracker(Context context) { private ConsumptionTracker(Context context) {
prefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE); prefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
lifetime = load("life"); week = load("week"); month = load("month"); lifetime = load("life"); tripA = load("a"); tripB = load("b");
tripA = load("a"); tripB = load("b"); migrateCalendarCounters();
weekId = prefs.getString("week_id", "");
monthId = prefs.getString("month_id", "");
rollPeriods(System.currentTimeMillis());
} }
synchronized void sample(EnergySnapshot s) { synchronized void sample(EnergySnapshot s) {
long now = s.getTimestampMs(); long now = s.getTimestampMs();
rollPeriods(now);
if (lastMs > 0 && now > lastMs) { if (lastMs > 0 && now > lastMs) {
double hours = (now - lastMs) / 3_600_000d; double hours = (now - lastMs) / 3_600_000d;
// Never bridge a process pause/sleep into invented driving data. // Never bridge a process pause/sleep into invented driving data.
@@ -59,8 +51,10 @@ final class ConsumptionTracker {
double dsoc = (lastSoc == null || s.getSocPercent() == null || double dsoc = (lastSoc == null || s.getSocPercent() == null ||
Boolean.TRUE.equals(s.getChargePortConnected())) ? 0d : lastSoc - s.getSocPercent(); Boolean.TRUE.equals(s.getChargePortConnected())) ? 0d : lastSoc - s.getSocPercent();
lifetime = add(lifetime, km, kwh, hours, dsoc); lifetime = add(lifetime, km, kwh, hours, dsoc);
week = add(week, km, kwh, hours, dsoc); String dayKey = "day_" + LocalDate.now();
month = add(month, km, kwh, hours, dsoc); SharedPreferences.Editor daily = prefs.edit();
save(daily, dayKey, add(load(dayKey), km, kwh, hours, dsoc));
daily.commit();
tripA = add(tripA, km, kwh, hours, dsoc); tripA = add(tripA, km, kwh, hours, dsoc);
tripB = add(tripB, km, kwh, hours, dsoc); tripB = add(tripB, km, kwh, hours, dsoc);
persist(); persist();
@@ -72,7 +66,7 @@ final class ConsumptionTracker {
synchronized Totals totals(Period period) { synchronized Totals totals(Period period) {
switch (period) { switch (period) {
case WEEK: return week; case MONTH: return month; case TRIP_A: return tripA; case WEEK: return rollingDays(7); case MONTH: return rollingDays(30); case TRIP_A: return tripA;
case TRIP_B: return tripB; default: return lifetime; case TRIP_B: return tripB; default: return lifetime;
} }
} }
@@ -86,21 +80,29 @@ final class ConsumptionTracker {
synchronized void persist() { synchronized void persist() {
SharedPreferences.Editor e = prefs.edit(); SharedPreferences.Editor e = prefs.edit();
save(e, "life", lifetime); save(e, "week", week); save(e, "month", month); save(e, "life", lifetime);
save(e, "a", tripA); save(e, "b", tripB); save(e, "a", tripA); save(e, "b", tripB);
e.putString("week_id", weekId).putString("month_id", monthId);
e.commit(); e.commit();
} }
private void rollPeriods(long nowMs) { private Totals rollingDays(int days) {
LocalDate date = Instant.ofEpochMilli(nowMs).atZone(ZoneId.systemDefault()).toLocalDate(); Totals result = zero();
WeekFields iso = WeekFields.ISO; LocalDate today = LocalDate.now();
String currentWeek = date.get(iso.weekBasedYear()) + "-W" + date.get(iso.weekOfWeekBasedYear()); for (int i = 0; i < days; i++) {
String currentMonth = date.getYear() + "-" + date.getMonthValue(); Totals day = load("day_" + today.minusDays(i));
boolean changed = false; result = add(result, day.km, day.kwh, day.hours, day.soc);
if (!currentWeek.equals(weekId)) { weekId = currentWeek; week = zero(); changed = true; } }
if (!currentMonth.equals(monthId)) { monthId = currentMonth; month = zero(); changed = true; } return result;
if (changed) persist(); }
/** Preserve anything gathered by 2.2.24 by treating its just-created counter as today. */
private void migrateCalendarCounters() {
if (prefs.getBoolean("rolling_days_migrated", false)) return;
Totals old = load("week");
SharedPreferences.Editor e = prefs.edit();
if (old.km != 0 || old.kwh != 0 || old.hours != 0 || old.soc != 0)
save(e, "day_" + LocalDate.now(), old);
e.putBoolean("rolling_days_migrated", true).commit();
} }
private Totals load(String key) { return new Totals(bits(key,"km"), bits(key,"kwh"), bits(key,"h"), bits(key,"soc")); } private Totals load(String key) { return new Totals(bits(key,"km"), bits(key,"kwh"), bits(key,"h"), bits(key,"soc")); }
+3 -3
View File
@@ -6,8 +6,8 @@
<HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:scrollbars="none"> <HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:scrollbars="none">
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_lifetime" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:text="Tüm zamanlar"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_lifetime" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:text="Tüm zamanlar"/>
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_week" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Bu hafta"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_week" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Son 7 gün"/>
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_month" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Bu ay"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_month" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Son 30 gün"/>
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_a" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip A"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_a" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip A"/>
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_b" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip B"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_trip_b" style="@style/Widget.EV.Button.Outlined" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_marginStart="8dp" android:text="Trip B"/>
</LinearLayout> </LinearLayout>
@@ -22,6 +22,6 @@
</GridLayout> </GridLayout>
<com.google.android.material.button.MaterialButton android:id="@+id/consumption_reset" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="64dp" android:layout_marginTop="12dp" android:text="Seçili tripi sıfırla" android:visibility="gone"/> <com.google.android.material.button.MaterialButton android:id="@+id/consumption_reset" style="@style/Widget.EV.Button.Outlined" android:layout_width="match_parent" android:layout_height="64dp" android:layout_marginTop="12dp" android:text="Seçili tripi sıfırla" android:visibility="gone"/>
</LinearLayout> </LinearLayout>
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="Hafta, ay, tüm zamanlar ve Trip A/B cihazda kalıcı saklanır; uygulama ve OTA güncellemeleriyle silinmez." android:textAppearance="@style/Text.EV.Secondary"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="Son 7/30 gün, tüm zamanlar ve Trip A/B cihazda kalıcı saklanır; uygulama ve OTA güncellemeleriyle silinmez." android:textAppearance="@style/Text.EV.Secondary"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>