* [PATCH BlueZ v2] battery: improve the display of the charge level
@ 2025-10-27 15:11 Roman Smirnov
2025-10-27 15:37 ` Bastien Nocera
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Roman Smirnov @ 2025-10-27 15:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Roman Smirnov
The battery charge level may fluctuate due to uncalibrated
sensors. Commit smooths out such fluctuations.
The algorithm for determining uncalibrated sensors consists of
finding the number of changes in charge direction (i.e., "spikes").
If the number of spikes is zero, the device is charging or discharging.
If there is one spike, it may mean that the device has started charging
or has been disconnected from charging. If there are two or more
spikes, this is a clear indication of an uncalibrated sensor.
Check that the battery charge is fluctuating. If the battery charge
is fluctuating, use the average charge value, otherwise use the current
value.
Fixes: https://github.com/bluez/bluez/issues/1612
---
src/battery.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/src/battery.c b/src/battery.c
index 59e4fc570..f97d9b8f3 100644
--- a/src/battery.c
+++ b/src/battery.c
@@ -33,10 +33,16 @@
#define BATTERY_PROVIDER_MANAGER_INTERFACE "org.bluez.BatteryProviderManager1"
#define BATTERY_MAX_PERCENTAGE 100
+#define LAST_CHARGES_SIZE 8
+#define MAX_CHARGE_STEP 5
struct btd_battery {
char *path; /* D-Bus object path */
uint8_t percentage; /* valid between 0 to 100 inclusively */
+ uint8_t *last_charges; /* last charges received */
+ uint8_t lru_charge_id; /* oldest battery charge */
+ float avg_charge; /* average battery charge */
+ bool is_fluctuating; /* true, if the battery sensor fluctuates */
char *source; /* Descriptive source of the battery info */
char *provider_path; /* The provider root path, if any */
};
@@ -92,6 +98,11 @@ static struct btd_battery *battery_new(const char *path, const char *source,
battery = new0(struct btd_battery, 1);
battery->path = g_strdup(path);
battery->percentage = UINT8_MAX;
+ battery->last_charges = new0(uint8_t, LAST_CHARGES_SIZE);
+ battery->lru_charge_id = 0;
+ battery->avg_charge = 0;
+ battery->is_fluctuating = false;
+
if (source)
battery->source = g_strdup(source);
if (provider_path)
@@ -105,6 +116,9 @@ static void battery_free(struct btd_battery *battery)
if (battery->path)
g_free(battery->path);
+ if (battery->last_charges)
+ g_free(battery->last_charges);
+
if (battery->source)
g_free(battery->source);
@@ -217,6 +231,39 @@ bool btd_battery_unregister(struct btd_battery *battery)
return true;
}
+static void check_fluctuations(struct btd_battery *battery)
+{
+ uint8_t spikes = 0;
+ int8_t step = 0;
+ int8_t direction = 0;
+ int8_t prev_direction;
+
+ for (uint8_t id = 0; id < LAST_CHARGES_SIZE - 1; id++) {
+ prev_direction = direction;
+ step = battery->last_charges[id] - battery->last_charges[id + 1];
+
+ /*
+ * The battery charge fluctuates too much,
+ * which may indicate a battery problem, so
+ * the actual value should be displayed.
+ */
+ if (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++;
+ }
+
+ battery->is_fluctuating = (spikes > 1) ? true : false;
+}
+
bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
{
DBG("path = %s", battery->path);
@@ -231,6 +278,21 @@ bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
return false;
}
+ if (!battery->avg_charge)
+ battery->avg_charge = percentage;
+
+ /* exponential smoothing */
+ battery->avg_charge = battery->avg_charge * 0.7 + percentage * 0.3;
+ battery->last_charges[battery->lru_charge_id] = percentage;
+
+ if (battery->lru_charge_id == LAST_CHARGES_SIZE - 1)
+ check_fluctuations(battery);
+
+ battery->lru_charge_id = (battery->lru_charge_id + 1) % LAST_CHARGES_SIZE;
+
+ if (battery->is_fluctuating)
+ percentage = battery->avg_charge;
+
if (battery->percentage == percentage)
return true;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH BlueZ v2] battery: improve the display of the charge level
2025-10-27 15:11 [PATCH BlueZ v2] battery: improve the display of the charge level Roman Smirnov
@ 2025-10-27 15:37 ` Bastien Nocera
2025-10-28 8:54 ` Roman Smirnov
2025-10-27 15:59 ` Luiz Augusto von Dentz
2025-10-27 16:37 ` [BlueZ,v2] " bluez.test.bot
2 siblings, 1 reply; 6+ messages in thread
From: Bastien Nocera @ 2025-10-27 15:37 UTC (permalink / raw)
To: Roman Smirnov, linux-bluetooth
On Mon, 2025-10-27 at 18:11 +0300, Roman Smirnov wrote:
> The battery charge level may fluctuate due to uncalibrated
> sensors. Commit smooths out such fluctuations.
>
> The algorithm for determining uncalibrated sensors consists of
> finding the number of changes in charge direction (i.e., "spikes").
> If the number of spikes is zero, the device is charging or
> discharging.
> If there is one spike, it may mean that the device has started
> charging
> or has been disconnected from charging. If there are two or more
> spikes, this is a clear indication of an uncalibrated sensor.
>
> Check that the battery charge is fluctuating. If the battery charge
> is fluctuating, use the average charge value, otherwise use the
> current
> value.
>
> Fixes: https://github.com/bluez/bluez/issues/1612
When sending a v2, it's customary to add a changelog compared to the
first version. What changed since v1?
> ---
> src/battery.c | 62
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 62 insertions(+)
>
> diff --git a/src/battery.c b/src/battery.c
> index 59e4fc570..f97d9b8f3 100644
> --- a/src/battery.c
> +++ b/src/battery.c
> @@ -33,10 +33,16 @@
> #define BATTERY_PROVIDER_MANAGER_INTERFACE
> "org.bluez.BatteryProviderManager1"
>
> #define BATTERY_MAX_PERCENTAGE 100
> +#define LAST_CHARGES_SIZE 8
> +#define MAX_CHARGE_STEP 5
>
> struct btd_battery {
> char *path; /* D-Bus object path */
> uint8_t percentage; /* valid between 0 to 100 inclusively */
> + uint8_t *last_charges; /* last charges received */
> + uint8_t lru_charge_id; /* oldest battery charge */
> + float avg_charge; /* average battery charge */
> + bool is_fluctuating; /* true, if the battery sensor
> fluctuates */
> char *source; /* Descriptive source of the battery info */
> char *provider_path; /* The provider root path, if any */
> };
> @@ -92,6 +98,11 @@ static struct btd_battery *battery_new(const char
> *path, const char *source,
> battery = new0(struct btd_battery, 1);
> battery->path = g_strdup(path);
> battery->percentage = UINT8_MAX;
> + battery->last_charges = new0(uint8_t, LAST_CHARGES_SIZE);
> + battery->lru_charge_id = 0;
> + battery->avg_charge = 0;
> + battery->is_fluctuating = false;
> +
> if (source)
> battery->source = g_strdup(source);
> if (provider_path)
> @@ -105,6 +116,9 @@ static void battery_free(struct btd_battery
> *battery)
> if (battery->path)
> g_free(battery->path);
>
> + if (battery->last_charges)
> + g_free(battery->last_charges);
> +
> if (battery->source)
> g_free(battery->source);
>
> @@ -217,6 +231,39 @@ bool btd_battery_unregister(struct btd_battery
> *battery)
> return true;
> }
>
> +static void check_fluctuations(struct btd_battery *battery)
> +{
> + uint8_t spikes = 0;
> + int8_t step = 0;
> + int8_t direction = 0;
> + int8_t prev_direction;
> +
> + for (uint8_t id = 0; id < LAST_CHARGES_SIZE - 1; id++) {
> + prev_direction = direction;
> + step = battery->last_charges[id] - battery-
> >last_charges[id + 1];
> +
> + /*
> + * The battery charge fluctuates too much,
> + * which may indicate a battery problem, so
> + * the actual value should be displayed.
> + */
> + if (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++;
> + }
> +
> + battery->is_fluctuating = (spikes > 1) ? true : false;
> +}
> +
> bool btd_battery_update(struct btd_battery *battery, uint8_t
> percentage)
> {
> DBG("path = %s", battery->path);
> @@ -231,6 +278,21 @@ bool btd_battery_update(struct btd_battery
> *battery, uint8_t percentage)
> return false;
> }
>
> + if (!battery->avg_charge)
> + battery->avg_charge = percentage;
> +
> + /* exponential smoothing */
> + battery->avg_charge = battery->avg_charge * 0.7 + percentage
> * 0.3;
> + battery->last_charges[battery->lru_charge_id] = percentage;
> +
> + if (battery->lru_charge_id == LAST_CHARGES_SIZE - 1)
> + check_fluctuations(battery);
> +
> + battery->lru_charge_id = (battery->lru_charge_id + 1) %
> LAST_CHARGES_SIZE;
> +
> + if (battery->is_fluctuating)
> + percentage = battery->avg_charge;
> +
> if (battery->percentage == percentage)
> return true;
>
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH BlueZ v2] battery: improve the display of the charge level
2025-10-27 15:37 ` Bastien Nocera
@ 2025-10-28 8:54 ` Roman Smirnov
0 siblings, 0 replies; 6+ messages in thread
From: Roman Smirnov @ 2025-10-28 8:54 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org, hadess@hadess.net
On Mon, 2025-10-27 at 16:37 +0100, Bastien Nocera wrote:
> On Mon, 2025-10-27 at 18:11 +0300, Roman Smirnov wrote:
> > The battery charge level may fluctuate due to uncalibrated
> > sensors. Commit smooths out such fluctuations.
> >
> > The algorithm for determining uncalibrated sensors consists of
> > finding the number of changes in charge direction (i.e., "spikes").
> > If the number of spikes is zero, the device is charging or
> > discharging.
> > If there is one spike, it may mean that the device has started
> > charging
> > or has been disconnected from charging. If there are two or more
> > spikes, this is a clear indication of an uncalibrated sensor.
> >
> > Check that the battery charge is fluctuating. If the battery charge
> > is fluctuating, use the average charge value, otherwise use the
> > current
> > value.
> >
> > Fixes: https://github.com/bluez/bluez/issues/1612
>
> When sending a v2, it's customary to add a changelog compared to the
> first version. What changed since v1?
>
Sorry, I forgot to attach it.
V1 -> V2: Smoothing is only applied to uncalibrated sensors, the
last 8 values are saved instead of 4, and the average value is
used for smoothing instead of the minimum value.
I will attach it to the next version of the patch.
> > ---
> > src/battery.c | 62
> > +++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 62 insertions(+)
> >
> > diff --git a/src/battery.c b/src/battery.c
> > index 59e4fc570..f97d9b8f3 100644
> > --- a/src/battery.c
> > +++ b/src/battery.c
> > @@ -33,10 +33,16 @@
> > #define BATTERY_PROVIDER_MANAGER_INTERFACE
> > "org.bluez.BatteryProviderManager1"
> >
> > #define BATTERY_MAX_PERCENTAGE 100
> > +#define LAST_CHARGES_SIZE 8
> > +#define MAX_CHARGE_STEP 5
> >
> > struct btd_battery {
> > char *path; /* D-Bus object path */
> > uint8_t percentage; /* valid between 0 to 100 inclusively */
> > + uint8_t *last_charges; /* last charges received */
> > + uint8_t lru_charge_id; /* oldest battery charge */
> > + float avg_charge; /* average battery charge */
> > + bool is_fluctuating; /* true, if the battery sensor
> > fluctuates */
> > char *source; /* Descriptive source of the battery info */
> > char *provider_path; /* The provider root path, if any */
> > };
> > @@ -92,6 +98,11 @@ static struct btd_battery *battery_new(const char
> > *path, const char *source,
> > battery = new0(struct btd_battery, 1);
> > battery->path = g_strdup(path);
> > battery->percentage = UINT8_MAX;
> > + battery->last_charges = new0(uint8_t, LAST_CHARGES_SIZE);
> > + battery->lru_charge_id = 0;
> > + battery->avg_charge = 0;
> > + battery->is_fluctuating = false;
> > +
> > if (source)
> > battery->source = g_strdup(source);
> > if (provider_path)
> > @@ -105,6 +116,9 @@ static void battery_free(struct btd_battery
> > *battery)
> > if (battery->path)
> > g_free(battery->path);
> >
> > + if (battery->last_charges)
> > + g_free(battery->last_charges);
> > +
> > if (battery->source)
> > g_free(battery->source);
> >
> > @@ -217,6 +231,39 @@ bool btd_battery_unregister(struct btd_battery
> > *battery)
> > return true;
> > }
> >
> > +static void check_fluctuations(struct btd_battery *battery)
> > +{
> > + uint8_t spikes = 0;
> > + int8_t step = 0;
> > + int8_t direction = 0;
> > + int8_t prev_direction;
> > +
> > + for (uint8_t id = 0; id < LAST_CHARGES_SIZE - 1; id++) {
> > + prev_direction = direction;
> > + step = battery->last_charges[id] - battery-
> > > last_charges[id + 1];
> > +
> > + /*
> > + * The battery charge fluctuates too much,
> > + * which may indicate a battery problem, so
> > + * the actual value should be displayed.
> > + */
> > + if (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++;
> > + }
> > +
> > + battery->is_fluctuating = (spikes > 1) ? true : false;
> > +}
> > +
> > bool btd_battery_update(struct btd_battery *battery, uint8_t
> > percentage)
> > {
> > DBG("path = %s", battery->path);
> > @@ -231,6 +278,21 @@ bool btd_battery_update(struct btd_battery
> > *battery, uint8_t percentage)
> > return false;
> > }
> >
> > + if (!battery->avg_charge)
> > + battery->avg_charge = percentage;
> > +
> > + /* exponential smoothing */
> > + battery->avg_charge = battery->avg_charge * 0.7 + percentage
> > * 0.3;
> > + battery->last_charges[battery->lru_charge_id] = percentage;
> > +
> > + if (battery->lru_charge_id == LAST_CHARGES_SIZE - 1)
> > + check_fluctuations(battery);
> > +
> > + battery->lru_charge_id = (battery->lru_charge_id + 1) %
> > LAST_CHARGES_SIZE;
> > +
> > + if (battery->is_fluctuating)
> > + percentage = battery->avg_charge;
> > +
> > if (battery->percentage == percentage)
> > return true;
> >
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH BlueZ v2] battery: improve the display of the charge level
2025-10-27 15:11 [PATCH BlueZ v2] battery: improve the display of the charge level Roman Smirnov
2025-10-27 15:37 ` Bastien Nocera
@ 2025-10-27 15:59 ` Luiz Augusto von Dentz
2025-10-28 9:05 ` Roman Smirnov
2025-10-27 16:37 ` [BlueZ,v2] " bluez.test.bot
2 siblings, 1 reply; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2025-10-27 15:59 UTC (permalink / raw)
To: Roman Smirnov; +Cc: linux-bluetooth
Hi Roman,
On Mon, Oct 27, 2025 at 11:19 AM Roman Smirnov <r.smirnov@omp.ru> wrote:
>
> The battery charge level may fluctuate due to uncalibrated
> sensors. Commit smooths out such fluctuations.
>
> The algorithm for determining uncalibrated sensors consists of
> finding the number of changes in charge direction (i.e., "spikes").
> If the number of spikes is zero, the device is charging or discharging.
> If there is one spike, it may mean that the device has started charging
> or has been disconnected from charging. If there are two or more
> spikes, this is a clear indication of an uncalibrated sensor.
>
> Check that the battery charge is fluctuating. If the battery charge
> is fluctuating, use the average charge value, otherwise use the current
> value.
Is this method based on something used already? Or it is yet again
something you came up with?
> Fixes: https://github.com/bluez/bluez/issues/1612
> ---
> src/battery.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 62 insertions(+)
>
> diff --git a/src/battery.c b/src/battery.c
> index 59e4fc570..f97d9b8f3 100644
> --- a/src/battery.c
> +++ b/src/battery.c
> @@ -33,10 +33,16 @@
> #define BATTERY_PROVIDER_MANAGER_INTERFACE "org.bluez.BatteryProviderManager1"
>
> #define BATTERY_MAX_PERCENTAGE 100
> +#define LAST_CHARGES_SIZE 8
> +#define MAX_CHARGE_STEP 5
>
> struct btd_battery {
> char *path; /* D-Bus object path */
> uint8_t percentage; /* valid between 0 to 100 inclusively */
> + uint8_t *last_charges; /* last charges received */
> + uint8_t lru_charge_id; /* oldest battery charge */
> + float avg_charge; /* average battery charge */
> + bool is_fluctuating; /* true, if the battery sensor fluctuates */
> char *source; /* Descriptive source of the battery info */
> char *provider_path; /* The provider root path, if any */
> };
> @@ -92,6 +98,11 @@ static struct btd_battery *battery_new(const char *path, const char *source,
> battery = new0(struct btd_battery, 1);
> battery->path = g_strdup(path);
> battery->percentage = UINT8_MAX;
> + battery->last_charges = new0(uint8_t, LAST_CHARGES_SIZE);
I'd prefer to use a queue rather than an array for looking back.
> + battery->lru_charge_id = 0;
> + battery->avg_charge = 0;
> + battery->is_fluctuating = false;
> +
> if (source)
> battery->source = g_strdup(source);
> if (provider_path)
> @@ -105,6 +116,9 @@ static void battery_free(struct btd_battery *battery)
> if (battery->path)
> g_free(battery->path);
>
> + if (battery->last_charges)
> + g_free(battery->last_charges);
> +
> if (battery->source)
> g_free(battery->source);
>
> @@ -217,6 +231,39 @@ bool btd_battery_unregister(struct btd_battery *battery)
> return true;
> }
>
> +static void check_fluctuations(struct btd_battery *battery)
> +{
> + uint8_t spikes = 0;
> + int8_t step = 0;
> + int8_t direction = 0;
> + int8_t prev_direction;
> +
> + for (uint8_t id = 0; id < LAST_CHARGES_SIZE - 1; id++) {
> + prev_direction = direction;
> + step = battery->last_charges[id] - battery->last_charges[id + 1];
I prefer to avoid this type of construct, even though it seems to be
safe to access id + 1 since the loop is limited to LAST_CHARGES_SIZE -
1, I'd rather use a queue to access elements, anyway I also think it
is probably a good idea to store the direction as well.
> +
> + /*
> + * The battery charge fluctuates too much,
> + * which may indicate a battery problem, so
> + * the actual value should be displayed.
> + */
> + if (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++;
> + }
> +
> + battery->is_fluctuating = (spikes > 1) ? true : false;
> +}
> +
> bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
> {
> DBG("path = %s", battery->path);
> @@ -231,6 +278,21 @@ bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
> return false;
> }
>
> + if (!battery->avg_charge)
> + battery->avg_charge = percentage;
> +
> + /* exponential smoothing */
> + battery->avg_charge = battery->avg_charge * 0.7 + percentage * 0.3;
> + battery->last_charges[battery->lru_charge_id] = percentage;
> +
> + if (battery->lru_charge_id == LAST_CHARGES_SIZE - 1)
> + check_fluctuations(battery);
> +
> + battery->lru_charge_id = (battery->lru_charge_id + 1) % LAST_CHARGES_SIZE;
> +
> + if (battery->is_fluctuating)
> + percentage = battery->avg_charge;
> +
> if (battery->percentage == percentage)
> return true;
>
> --
> 2.43.0
>
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH BlueZ v2] battery: improve the display of the charge level
2025-10-27 15:59 ` Luiz Augusto von Dentz
@ 2025-10-28 9:05 ` Roman Smirnov
0 siblings, 0 replies; 6+ messages in thread
From: Roman Smirnov @ 2025-10-28 9:05 UTC (permalink / raw)
To: luiz.dentz@gmail.com; +Cc: linux-bluetooth@vger.kernel.org
On Mon, 2025-10-27 at 11:59 -0400, Luiz Augusto von Dentz wrote:
> Hi Roman,
>
> On Mon, Oct 27, 2025 at 11:19 AM Roman Smirnov <r.smirnov@omp.ru> wrote:
> >
> > The battery charge level may fluctuate due to uncalibrated
> > sensors. Commit smooths out such fluctuations.
> >
> > The algorithm for determining uncalibrated sensors consists of
> > finding the number of changes in charge direction (i.e., "spikes").
> > If the number of spikes is zero, the device is charging or discharging.
> > If there is one spike, it may mean that the device has started charging
> > or has been disconnected from charging. If there are two or more
> > spikes, this is a clear indication of an uncalibrated sensor.
> >
> > Check that the battery charge is fluctuating. If the battery charge
> > is fluctuating, use the average charge value, otherwise use the current
> > value.
>
> Is this method based on something used already? Or it is yet again
> something you came up with?
>
I looked into the Linux kernel, where I found the use of the average
value instead of the minimum:
1. https://elixir.bootlin.com/linux/v6.17.4/source/drivers/power/supply/cw2015_battery.c#L306
2. https://elixir.bootlin.com/linux/v6.18-rc2/source/drivers/power/supply/adc-battery-helper.c#L121
I couldn't find an algorithm for determining uncalibrated sensors,
so I came up with my own.
> > Fixes: https://github.com/bluez/bluez/issues/1612
> > ---
> > src/battery.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 62 insertions(+)
> >
> > diff --git a/src/battery.c b/src/battery.c
> > index 59e4fc570..f97d9b8f3 100644
> > --- a/src/battery.c
> > +++ b/src/battery.c
> > @@ -33,10 +33,16 @@
> > #define BATTERY_PROVIDER_MANAGER_INTERFACE "org.bluez.BatteryProviderManager1"
> >
> > #define BATTERY_MAX_PERCENTAGE 100
> > +#define LAST_CHARGES_SIZE 8
> > +#define MAX_CHARGE_STEP 5
> >
> > struct btd_battery {
> > char *path; /* D-Bus object path */
> > uint8_t percentage; /* valid between 0 to 100 inclusively */
> > + uint8_t *last_charges; /* last charges received */
> > + uint8_t lru_charge_id; /* oldest battery charge */
> > + float avg_charge; /* average battery charge */
> > + bool is_fluctuating; /* true, if the battery sensor fluctuates */
> > char *source; /* Descriptive source of the battery info */
> > char *provider_path; /* The provider root path, if any */
> > };
> > @@ -92,6 +98,11 @@ static struct btd_battery *battery_new(const char *path, const char *source,
> > battery = new0(struct btd_battery, 1);
> > battery->path = g_strdup(path);
> > battery->percentage = UINT8_MAX;
> > + battery->last_charges = new0(uint8_t, LAST_CHARGES_SIZE);
>
> I'd prefer to use a queue rather than an array for looking back.
>
> > + battery->lru_charge_id = 0;
> > + battery->avg_charge = 0;
> > + battery->is_fluctuating = false;
> > +
> > if (source)
> > battery->source = g_strdup(source);
> > if (provider_path)
> > @@ -105,6 +116,9 @@ static void battery_free(struct btd_battery *battery)
> > if (battery->path)
> > g_free(battery->path);
> >
> > + if (battery->last_charges)
> > + g_free(battery->last_charges);
> > +
> > if (battery->source)
> > g_free(battery->source);
> >
> > @@ -217,6 +231,39 @@ bool btd_battery_unregister(struct btd_battery *battery)
> > return true;
> > }
> >
> > +static void check_fluctuations(struct btd_battery *battery)
> > +{
> > + uint8_t spikes = 0;
> > + int8_t step = 0;
> > + int8_t direction = 0;
> > + int8_t prev_direction;
> > +
> > + for (uint8_t id = 0; id < LAST_CHARGES_SIZE - 1; id++) {
> > + prev_direction = direction;
> > + step = battery->last_charges[id] - battery->last_charges[id + 1];
>
> I prefer to avoid this type of construct, even though it seems to be
> safe to access id + 1 since the loop is limited to LAST_CHARGES_SIZE -
> 1, I'd rather use a queue to access elements, anyway I also think it
> is probably a good idea to store the direction as well.
>
I will prepare the next version, which will use a queue. Thank you for
your review.
> > +
> > + /*
> > + * The battery charge fluctuates too much,
> > + * which may indicate a battery problem, so
> > + * the actual value should be displayed.
> > + */
> > + if (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++;
> > + }
> > +
> > + battery->is_fluctuating = (spikes > 1) ? true : false;
> > +}
> > +
> > bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
> > {
> > DBG("path = %s", battery->path);
> > @@ -231,6 +278,21 @@ bool btd_battery_update(struct btd_battery *battery, uint8_t percentage)
> > return false;
> > }
> >
> > + if (!battery->avg_charge)
> > + battery->avg_charge = percentage;
> > +
> > + /* exponential smoothing */
> > + battery->avg_charge = battery->avg_charge * 0.7 + percentage * 0.3;
> > + battery->last_charges[battery->lru_charge_id] = percentage;
> > +
> > + if (battery->lru_charge_id == LAST_CHARGES_SIZE - 1)
> > + check_fluctuations(battery);
> > +
> > + battery->lru_charge_id = (battery->lru_charge_id + 1) % LAST_CHARGES_SIZE;
> > +
> > + if (battery->is_fluctuating)
> > + percentage = battery->avg_charge;
> > +
> > if (battery->percentage == percentage)
> > return true;
> >
> > --
> > 2.43.0
> >
> >
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [BlueZ,v2] battery: improve the display of the charge level
2025-10-27 15:11 [PATCH BlueZ v2] battery: improve the display of the charge level Roman Smirnov
2025-10-27 15:37 ` Bastien Nocera
2025-10-27 15:59 ` Luiz Augusto von Dentz
@ 2025-10-27 16:37 ` bluez.test.bot
2 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2025-10-27 16:37 UTC (permalink / raw)
To: linux-bluetooth, r.smirnov
[-- Attachment #1: Type: text/plain, Size: 1262 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1016339
---Test result---
Test Summary:
CheckPatch PENDING 0.36 seconds
GitLint PENDING 0.37 seconds
BuildEll PASS 19.88 seconds
BluezMake PASS 2734.99 seconds
MakeCheck PASS 19.70 seconds
MakeDistcheck PASS 185.66 seconds
CheckValgrind PASS 237.78 seconds
CheckSmatch PASS 307.83 seconds
bluezmakeextell PASS 128.50 seconds
IncrementalBuild PENDING 0.40 seconds
ScanBuild PASS 916.66 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-10-28 9:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-27 15:11 [PATCH BlueZ v2] battery: improve the display of the charge level Roman Smirnov
2025-10-27 15:37 ` Bastien Nocera
2025-10-28 8:54 ` Roman Smirnov
2025-10-27 15:59 ` Luiz Augusto von Dentz
2025-10-28 9:05 ` Roman Smirnov
2025-10-27 16:37 ` [BlueZ,v2] " bluez.test.bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox