diff mbox series

[v2] client: Add battery command

Message ID 20200630184629.95013-1-sonnysasaka@chromium.org (mailing list archive)
State Superseded
Headers show
Series [v2] client: Add battery command | expand

Commit Message

Sonny Sasaka June 30, 2020, 6:46 p.m. UTC
This adds the "battery" command to show battery information of a peer
device based on org.bluez.Battery1 API. Example usage:

[bluetooth]# battery XX:XX:XX:XX:XX:XX
Percentage: 100%
---
 client/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

Comments

Luiz Augusto von Dentz July 1, 2020, 5:56 p.m. UTC | #1
Hi Sonny,

On Tue, Jun 30, 2020 at 1:48 PM Sonny Sasaka <sonnysasaka@chromium.org> wrote:
>
> This adds the "battery" command to show battery information of a peer
> device based on org.bluez.Battery1 API. Example usage:
>
> [bluetooth]# battery XX:XX:XX:XX:XX:XX
> Percentage: 100%

It might be better to put the battery level under info command.

> ---
>  client/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>
> diff --git a/client/main.c b/client/main.c
> index 422da5593..8c1ed00fb 100644
> --- a/client/main.c
> +++ b/client/main.c
> @@ -65,6 +65,7 @@ static struct adapter *default_ctrl;
>  static GDBusProxy *default_dev;
>  static GDBusProxy *default_attr;
>  static GList *ctrl_list;
> +static GList *battery_proxies;
>
>  static const char *agent_arguments[] = {
>         "on",
> @@ -107,7 +108,9 @@ static void disconnect_handler(DBusConnection *connection, void *user_data)
>         bt_shell_set_prompt(PROMPT_OFF);
>
>         g_list_free_full(ctrl_list, proxy_leak);
> +       g_list_free_full(battery_proxies, proxy_leak);
>         ctrl_list = NULL;
> +       battery_proxies = NULL;
>
>         default_ctrl = NULL;
>  }
> @@ -445,6 +448,16 @@ done:
>         g_free(desc);
>  }
>
> +static void battery_added(GDBusProxy *proxy)
> +{
> +       battery_proxies = g_list_append(battery_proxies, proxy);
> +}
> +
> +static void battery_removed(GDBusProxy *proxy)
> +{
> +       battery_proxies = g_list_remove(battery_proxies, proxy);
> +}
> +
>  static void device_added(GDBusProxy *proxy)
>  {
>         DBusMessageIter iter;
> @@ -539,6 +552,8 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
>                 gatt_add_manager(proxy);
>         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
>                 ad_manager_added(proxy);
> +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> +               battery_added(proxy);
>         }
>  }
>
> @@ -630,6 +645,8 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
>                 gatt_remove_manager(proxy);
>         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
>                 ad_unregister(dbus_conn, NULL);
> +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> +               battery_removed(proxy);
>         }
>  }
>
> @@ -763,6 +780,20 @@ static struct adapter *find_ctrl_by_address(GList *source, const char *address)
>         return NULL;
>  }
>
> +static GDBusProxy *find_battery_by_path(GList *source, const char *path)
> +{
> +       GList *list;
> +
> +       for (list = g_list_first(source); list; list = g_list_next(list)) {
> +               GDBusProxy *proxy = list->data;
> +
> +               if (strcmp(g_dbus_proxy_get_path(proxy), path) == 0)
> +                       return proxy;
> +       }
> +
> +       return NULL;
> +}
> +
>  static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
>  {
>         GList *list;
> @@ -1650,6 +1681,35 @@ static void cmd_info(int argc, char *argv[])
>         return bt_shell_noninteractive_quit(EXIT_SUCCESS);
>  }
>
> +static void cmd_battery(int argc, char *argv[])
> +{
> +       DBusMessageIter iter;
> +       GDBusProxy *device_proxy;
> +       GDBusProxy *battery_proxy;
> +       unsigned char percentage;
> +
> +       device_proxy = find_device(argc, argv);
> +       if (!device_proxy)
> +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +
> +       battery_proxy = find_battery_by_path(battery_proxies,
> +                                       g_dbus_proxy_get_path(device_proxy));
> +       if (!battery_proxy) {
> +               bt_shell_printf("Device %s does not have battery information\n",
> +                               argv[1]);
> +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +       }
> +
> +       if (g_dbus_proxy_get_property(battery_proxy, "Percentage", &iter) ==
> +                                                                       FALSE)
> +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +
> +       dbus_message_iter_get_basic(&iter, &percentage);
> +       bt_shell_printf("Percentage: %d%%\n", percentage);
> +
> +       return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> +}
> +
>  static void pair_reply(DBusMessage *message, void *user_data)
>  {
>         DBusError error;
> @@ -2785,6 +2845,8 @@ static const struct bt_shell_menu main_menu = {
>                                                         dev_generator },
>         { "disconnect",   "[dev]",    cmd_disconn, "Disconnect device",
>                                                         dev_generator },
> +       { "battery",      "[dev]",    cmd_battery, "Show device battery",
> +                                                       dev_generator },
>         { } },
>  };
>
> --
> 2.26.2
>
Sonny Sasaka July 1, 2020, 7:23 p.m. UTC | #2
Hi Luiz,

I thought of doing that (combining with info command). But we foresee
that the Battery API will get more complex (such as support of
multiple batteries like Pixel Buds and Airpods) and deserve its own
command. Furthermore, it's a different API (org.bluez.Device1 vs
org.bluez.Battery1) and its inner working uses a specific profile (BAS
over GATT), so I think that it deserves its own command. But anyway I
sent another patch that combines this into the "info" command and if
you think this is more appropriate we can combine it for now and
separate it in the future when needed.


On Wed, Jul 1, 2020 at 10:56 AM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Sonny,
>
> On Tue, Jun 30, 2020 at 1:48 PM Sonny Sasaka <sonnysasaka@chromium.org> wrote:
> >
> > This adds the "battery" command to show battery information of a peer
> > device based on org.bluez.Battery1 API. Example usage:
> >
> > [bluetooth]# battery XX:XX:XX:XX:XX:XX
> > Percentage: 100%
>
> It might be better to put the battery level under info command.
>
> > ---
> >  client/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 62 insertions(+)
> >
> > diff --git a/client/main.c b/client/main.c
> > index 422da5593..8c1ed00fb 100644
> > --- a/client/main.c
> > +++ b/client/main.c
> > @@ -65,6 +65,7 @@ static struct adapter *default_ctrl;
> >  static GDBusProxy *default_dev;
> >  static GDBusProxy *default_attr;
> >  static GList *ctrl_list;
> > +static GList *battery_proxies;
> >
> >  static const char *agent_arguments[] = {
> >         "on",
> > @@ -107,7 +108,9 @@ static void disconnect_handler(DBusConnection *connection, void *user_data)
> >         bt_shell_set_prompt(PROMPT_OFF);
> >
> >         g_list_free_full(ctrl_list, proxy_leak);
> > +       g_list_free_full(battery_proxies, proxy_leak);
> >         ctrl_list = NULL;
> > +       battery_proxies = NULL;
> >
> >         default_ctrl = NULL;
> >  }
> > @@ -445,6 +448,16 @@ done:
> >         g_free(desc);
> >  }
> >
> > +static void battery_added(GDBusProxy *proxy)
> > +{
> > +       battery_proxies = g_list_append(battery_proxies, proxy);
> > +}
> > +
> > +static void battery_removed(GDBusProxy *proxy)
> > +{
> > +       battery_proxies = g_list_remove(battery_proxies, proxy);
> > +}
> > +
> >  static void device_added(GDBusProxy *proxy)
> >  {
> >         DBusMessageIter iter;
> > @@ -539,6 +552,8 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
> >                 gatt_add_manager(proxy);
> >         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
> >                 ad_manager_added(proxy);
> > +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> > +               battery_added(proxy);
> >         }
> >  }
> >
> > @@ -630,6 +645,8 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
> >                 gatt_remove_manager(proxy);
> >         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
> >                 ad_unregister(dbus_conn, NULL);
> > +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> > +               battery_removed(proxy);
> >         }
> >  }
> >
> > @@ -763,6 +780,20 @@ static struct adapter *find_ctrl_by_address(GList *source, const char *address)
> >         return NULL;
> >  }
> >
> > +static GDBusProxy *find_battery_by_path(GList *source, const char *path)
> > +{
> > +       GList *list;
> > +
> > +       for (list = g_list_first(source); list; list = g_list_next(list)) {
> > +               GDBusProxy *proxy = list->data;
> > +
> > +               if (strcmp(g_dbus_proxy_get_path(proxy), path) == 0)
> > +                       return proxy;
> > +       }
> > +
> > +       return NULL;
> > +}
> > +
> >  static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
> >  {
> >         GList *list;
> > @@ -1650,6 +1681,35 @@ static void cmd_info(int argc, char *argv[])
> >         return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> >  }
> >
> > +static void cmd_battery(int argc, char *argv[])
> > +{
> > +       DBusMessageIter iter;
> > +       GDBusProxy *device_proxy;
> > +       GDBusProxy *battery_proxy;
> > +       unsigned char percentage;
> > +
> > +       device_proxy = find_device(argc, argv);
> > +       if (!device_proxy)
> > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > +
> > +       battery_proxy = find_battery_by_path(battery_proxies,
> > +                                       g_dbus_proxy_get_path(device_proxy));
> > +       if (!battery_proxy) {
> > +               bt_shell_printf("Device %s does not have battery information\n",
> > +                               argv[1]);
> > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > +       }
> > +
> > +       if (g_dbus_proxy_get_property(battery_proxy, "Percentage", &iter) ==
> > +                                                                       FALSE)
> > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > +
> > +       dbus_message_iter_get_basic(&iter, &percentage);
> > +       bt_shell_printf("Percentage: %d%%\n", percentage);
> > +
> > +       return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> > +}
> > +
> >  static void pair_reply(DBusMessage *message, void *user_data)
> >  {
> >         DBusError error;
> > @@ -2785,6 +2845,8 @@ static const struct bt_shell_menu main_menu = {
> >                                                         dev_generator },
> >         { "disconnect",   "[dev]",    cmd_disconn, "Disconnect device",
> >                                                         dev_generator },
> > +       { "battery",      "[dev]",    cmd_battery, "Show device battery",
> > +                                                       dev_generator },
> >         { } },
> >  };
> >
> > --
> > 2.26.2
> >
>
>
> --
> Luiz Augusto von Dentz
Luiz Augusto von Dentz July 2, 2020, 12:42 a.m. UTC | #3
Hi Sonny,

On Wed, Jul 1, 2020 at 12:23 PM Sonny Sasaka <sonnysasaka@chromium.org> wrote:
>
> Hi Luiz,
>
> I thought of doing that (combining with info command). But we foresee
> that the Battery API will get more complex (such as support of
> multiple batteries like Pixel Buds and Airpods) and deserve its own
> command. Furthermore, it's a different API (org.bluez.Device1 vs
> org.bluez.Battery1) and its inner working uses a specific profile (BAS
> over GATT), so I think that it deserves its own command. But anyway I
> sent another patch that combines this into the "info" command and if
> you think this is more appropriate we can combine it for now and
> separate it in the future when needed.

It should be a problem to combine different interfaces, and if the
Battery1 start to have more properties we just list them as well, our
D-Bus client will have them cached anything since we do get the
properties of all interface due to use of ObjectManager.

>
> On Wed, Jul 1, 2020 at 10:56 AM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Sonny,
> >
> > On Tue, Jun 30, 2020 at 1:48 PM Sonny Sasaka <sonnysasaka@chromium.org> wrote:
> > >
> > > This adds the "battery" command to show battery information of a peer
> > > device based on org.bluez.Battery1 API. Example usage:
> > >
> > > [bluetooth]# battery XX:XX:XX:XX:XX:XX
> > > Percentage: 100%
> >
> > It might be better to put the battery level under info command.
> >
> > > ---
> > >  client/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 62 insertions(+)
> > >
> > > diff --git a/client/main.c b/client/main.c
> > > index 422da5593..8c1ed00fb 100644
> > > --- a/client/main.c
> > > +++ b/client/main.c
> > > @@ -65,6 +65,7 @@ static struct adapter *default_ctrl;
> > >  static GDBusProxy *default_dev;
> > >  static GDBusProxy *default_attr;
> > >  static GList *ctrl_list;
> > > +static GList *battery_proxies;
> > >
> > >  static const char *agent_arguments[] = {
> > >         "on",
> > > @@ -107,7 +108,9 @@ static void disconnect_handler(DBusConnection *connection, void *user_data)
> > >         bt_shell_set_prompt(PROMPT_OFF);
> > >
> > >         g_list_free_full(ctrl_list, proxy_leak);
> > > +       g_list_free_full(battery_proxies, proxy_leak);
> > >         ctrl_list = NULL;
> > > +       battery_proxies = NULL;
> > >
> > >         default_ctrl = NULL;
> > >  }
> > > @@ -445,6 +448,16 @@ done:
> > >         g_free(desc);
> > >  }
> > >
> > > +static void battery_added(GDBusProxy *proxy)
> > > +{
> > > +       battery_proxies = g_list_append(battery_proxies, proxy);
> > > +}
> > > +
> > > +static void battery_removed(GDBusProxy *proxy)
> > > +{
> > > +       battery_proxies = g_list_remove(battery_proxies, proxy);
> > > +}
> > > +
> > >  static void device_added(GDBusProxy *proxy)
> > >  {
> > >         DBusMessageIter iter;
> > > @@ -539,6 +552,8 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
> > >                 gatt_add_manager(proxy);
> > >         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
> > >                 ad_manager_added(proxy);
> > > +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> > > +               battery_added(proxy);
> > >         }
> > >  }
> > >
> > > @@ -630,6 +645,8 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
> > >                 gatt_remove_manager(proxy);
> > >         } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
> > >                 ad_unregister(dbus_conn, NULL);
> > > +       } else if (!strcmp(interface, "org.bluez.Battery1")) {
> > > +               battery_removed(proxy);
> > >         }
> > >  }
> > >
> > > @@ -763,6 +780,20 @@ static struct adapter *find_ctrl_by_address(GList *source, const char *address)
> > >         return NULL;
> > >  }
> > >
> > > +static GDBusProxy *find_battery_by_path(GList *source, const char *path)
> > > +{
> > > +       GList *list;
> > > +
> > > +       for (list = g_list_first(source); list; list = g_list_next(list)) {
> > > +               GDBusProxy *proxy = list->data;
> > > +
> > > +               if (strcmp(g_dbus_proxy_get_path(proxy), path) == 0)
> > > +                       return proxy;
> > > +       }
> > > +
> > > +       return NULL;
> > > +}
> > > +
> > >  static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
> > >  {
> > >         GList *list;
> > > @@ -1650,6 +1681,35 @@ static void cmd_info(int argc, char *argv[])
> > >         return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> > >  }
> > >
> > > +static void cmd_battery(int argc, char *argv[])
> > > +{
> > > +       DBusMessageIter iter;
> > > +       GDBusProxy *device_proxy;
> > > +       GDBusProxy *battery_proxy;
> > > +       unsigned char percentage;
> > > +
> > > +       device_proxy = find_device(argc, argv);
> > > +       if (!device_proxy)
> > > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > > +
> > > +       battery_proxy = find_battery_by_path(battery_proxies,
> > > +                                       g_dbus_proxy_get_path(device_proxy));
> > > +       if (!battery_proxy) {
> > > +               bt_shell_printf("Device %s does not have battery information\n",
> > > +                               argv[1]);
> > > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > > +       }
> > > +
> > > +       if (g_dbus_proxy_get_property(battery_proxy, "Percentage", &iter) ==
> > > +                                                                       FALSE)
> > > +               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> > > +
> > > +       dbus_message_iter_get_basic(&iter, &percentage);
> > > +       bt_shell_printf("Percentage: %d%%\n", percentage);
> > > +
> > > +       return bt_shell_noninteractive_quit(EXIT_SUCCESS);
> > > +}
> > > +
> > >  static void pair_reply(DBusMessage *message, void *user_data)
> > >  {
> > >         DBusError error;
> > > @@ -2785,6 +2845,8 @@ static const struct bt_shell_menu main_menu = {
> > >                                                         dev_generator },
> > >         { "disconnect",   "[dev]",    cmd_disconn, "Disconnect device",
> > >                                                         dev_generator },
> > > +       { "battery",      "[dev]",    cmd_battery, "Show device battery",
> > > +                                                       dev_generator },
> > >         { } },
> > >  };
> > >
> > > --
> > > 2.26.2
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
diff mbox series

Patch

diff --git a/client/main.c b/client/main.c
index 422da5593..8c1ed00fb 100644
--- a/client/main.c
+++ b/client/main.c
@@ -65,6 +65,7 @@  static struct adapter *default_ctrl;
 static GDBusProxy *default_dev;
 static GDBusProxy *default_attr;
 static GList *ctrl_list;
+static GList *battery_proxies;
 
 static const char *agent_arguments[] = {
 	"on",
@@ -107,7 +108,9 @@  static void disconnect_handler(DBusConnection *connection, void *user_data)
 	bt_shell_set_prompt(PROMPT_OFF);
 
 	g_list_free_full(ctrl_list, proxy_leak);
+	g_list_free_full(battery_proxies, proxy_leak);
 	ctrl_list = NULL;
+	battery_proxies = NULL;
 
 	default_ctrl = NULL;
 }
@@ -445,6 +448,16 @@  done:
 	g_free(desc);
 }
 
+static void battery_added(GDBusProxy *proxy)
+{
+	battery_proxies = g_list_append(battery_proxies, proxy);
+}
+
+static void battery_removed(GDBusProxy *proxy)
+{
+	battery_proxies = g_list_remove(battery_proxies, proxy);
+}
+
 static void device_added(GDBusProxy *proxy)
 {
 	DBusMessageIter iter;
@@ -539,6 +552,8 @@  static void proxy_added(GDBusProxy *proxy, void *user_data)
 		gatt_add_manager(proxy);
 	} else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
 		ad_manager_added(proxy);
+	} else if (!strcmp(interface, "org.bluez.Battery1")) {
+		battery_added(proxy);
 	}
 }
 
@@ -630,6 +645,8 @@  static void proxy_removed(GDBusProxy *proxy, void *user_data)
 		gatt_remove_manager(proxy);
 	} else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) {
 		ad_unregister(dbus_conn, NULL);
+	} else if (!strcmp(interface, "org.bluez.Battery1")) {
+		battery_removed(proxy);
 	}
 }
 
@@ -763,6 +780,20 @@  static struct adapter *find_ctrl_by_address(GList *source, const char *address)
 	return NULL;
 }
 
+static GDBusProxy *find_battery_by_path(GList *source, const char *path)
+{
+	GList *list;
+
+	for (list = g_list_first(source); list; list = g_list_next(list)) {
+		GDBusProxy *proxy = list->data;
+
+		if (strcmp(g_dbus_proxy_get_path(proxy), path) == 0)
+			return proxy;
+	}
+
+	return NULL;
+}
+
 static GDBusProxy *find_proxy_by_address(GList *source, const char *address)
 {
 	GList *list;
@@ -1650,6 +1681,35 @@  static void cmd_info(int argc, char *argv[])
 	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
 }
 
+static void cmd_battery(int argc, char *argv[])
+{
+	DBusMessageIter iter;
+	GDBusProxy *device_proxy;
+	GDBusProxy *battery_proxy;
+	unsigned char percentage;
+
+	device_proxy = find_device(argc, argv);
+	if (!device_proxy)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	battery_proxy = find_battery_by_path(battery_proxies,
+					g_dbus_proxy_get_path(device_proxy));
+	if (!battery_proxy) {
+		bt_shell_printf("Device %s does not have battery information\n",
+				argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (g_dbus_proxy_get_property(battery_proxy, "Percentage", &iter) ==
+									FALSE)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	dbus_message_iter_get_basic(&iter, &percentage);
+	bt_shell_printf("Percentage: %d%%\n", percentage);
+
+	return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
 static void pair_reply(DBusMessage *message, void *user_data)
 {
 	DBusError error;
@@ -2785,6 +2845,8 @@  static const struct bt_shell_menu main_menu = {
 							dev_generator },
 	{ "disconnect",   "[dev]",    cmd_disconn, "Disconnect device",
 							dev_generator },
+	{ "battery",      "[dev]",    cmd_battery, "Show device battery",
+							dev_generator },
 	{ } },
 };