diff --git a/Makefile.am b/Makefile.am
index e8b31a5..8e7721b 100644
--- a/Makefile.am
+++ b/Makefile.am
src/shared/ccp.h src/shared/ccp.c \
src/shared/lc3.h src/shared/tty.h \
src/shared/bap-defs.h \
- src/shared/asha.h src/shared/asha.c
+ src/shared/asha.h src/shared/asha.c \
+ src/shared/battery.h src/shared/battery.c
if READLINE
shared_sources += src/shared/shell.c src/shared/shell.h
diff --git a/src/battery.c b/src/battery.c
index 4c1ea79..fa30fde 100644
--- a/src/battery.c
+++ b/src/battery.c
#include "gdbus/gdbus.h"
#include "bluetooth/bluetooth.h"
+#include "src/shared/battery.h"
#include "src/shared/queue.h"
#include "src/shared/util.h"
#include "battery.h"
uint8_t percentage; /* valid between 0 to 100 inclusively */
char *source; /* Descriptive source of the battery info */
char *provider_path; /* The provider root path, if any */
+ struct bt_battery *filter;
};
struct btd_battery_provider_manager {
battery->source = g_strdup(source);
if (provider_path)
battery->provider_path = g_strdup(provider_path);
+ battery->filter = bt_battery_new();
return battery;
}
if (battery->source)
g_free(battery->source);
+ if (battery->filter) {
+ bt_battery_free(battery->filter);
+ free(battery->filter);
+ }
+
free(battery);
}
if (battery->percentage == percentage)
return true;
- battery->percentage = percentage;
+ battery->percentage = bt_battery_charge(battery->filter, percentage);
g_dbus_emit_property_changed(btd_get_dbus_connection(), battery->path,
BATTERY_INTERFACE, "Percentage");
diff --git a/src/shared/battery.c b/src/shared/battery.c
new file mode 100644
index 0000000..33cec3a
--- /dev/null
+++ b/src/shared/battery.c
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2025 Open Mobile Platform LLC <community@omp.ru>
+ *
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "src/shared/battery.h"
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+
+struct bt_battery {
+ struct queue *last_charges; /* last charges received */
+ uint8_t avg_charge; /* average battery charge */
+ bool is_fluctuating; /* true, if the battery sensor fluctuates */
+};
+
+struct bt_battery *bt_battery_new(void)
+{
+ struct bt_battery *battery;
+
+ battery = new0(struct bt_battery, 1);
+ battery->last_charges = queue_new();
+ battery->avg_charge = 0;
+ battery->is_fluctuating = false;
+
+ return battery;
+}
+
+void bt_battery_free(struct bt_battery *battery)
+{
+ if (battery->last_charges)
+ queue_destroy(battery->last_charges, NULL);
+}
+
+static void bt_battery_check_fluctuations(struct bt_battery *battery)
+{
+ const struct queue_entry *entry;
+ uint8_t spikes = 0;
+ int8_t step;
+ int8_t direction = 0;
+ int8_t prev_direction;
+ uintptr_t prev_charge;
+ uintptr_t next_charge = 0;
+ uint16_t sum_charge = 0;
+
+ for (entry = queue_get_entries(battery->last_charges); entry->next;
+ entry = entry->next) {
+ prev_direction = direction;
+ prev_charge = PTR_TO_UINT(entry->data);
+ next_charge = PTR_TO_UINT(entry->next->data);
+ step = next_charge - prev_charge;
+ sum_charge += prev_charge;
+
+ /*
+ * The battery charge fluctuates too much,
+ * which may indicate a battery problem, so
+ * the actual value should be displayed.
+ */
+ if (abs(step) >= MAX_CHARGE_STEP) {
+ battery->is_fluctuating = false;
+ return;
+ }
+
+ if (step > 0)
+ direction = 1;
+ else if (step < 0)
+ direction = -1;
+
+ if (direction != prev_direction && prev_direction)
+ spikes++;
+ }
+
+ sum_charge += next_charge;
+ battery->avg_charge = sum_charge / LAST_CHARGES_SIZE;
+
+ battery->is_fluctuating = (spikes > 1) ? true : false;
+}
+
+uint8_t bt_battery_charge(struct bt_battery *battery, uint8_t percentage)
+{
+ queue_push_tail(battery->last_charges, UINT_TO_PTR(percentage));
+
+ if (queue_length(battery->last_charges) == LAST_CHARGES_SIZE) {
+ bt_battery_check_fluctuations(battery);
+ queue_pop_head(battery->last_charges);
+ }
+
+ return (battery->is_fluctuating) ? battery->avg_charge : percentage;
+}
diff --git a/src/shared/battery.h b/src/shared/battery.h
new file mode 100644
index 0000000..457acbc
--- /dev/null
+++ b/src/shared/battery.h
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2025 Open Mobile Platform LLC <community@omp.ru>
+ *
+ *
+ */
+
+#include <stdint.h>
+
+#define LAST_CHARGES_SIZE 8
+#define MAX_CHARGE_STEP 5
+
+struct bt_battery;
+
+struct bt_battery *bt_battery_new(void);
+void bt_battery_free(struct bt_battery *battery);
+
+uint8_t bt_battery_charge(struct bt_battery *battery, uint8_t percentage);