[Feature request] Bluetooth module #150

Open
opened 4 months ago by m1s4k1 · 6 comments
m1s4k1 commented 4 months ago

I'd love to have a bluetooth module with power and connection indication.

Probably this can be done with something like this:
bluetoothctl list -> ctrl (default)
bluetoothctl show <ctrl> -> Powered: yes/no
bluetoothctl devices + bluetoothctl info <dev> -> Connected: yes (atleast one device)

But I hope there is a better way then infinite loop script :)

I'd love to have a bluetooth module with power and connection indication. Probably this can be done with something like this: `bluetoothctl list` -> ctrl (default) `bluetoothctl show <ctrl>` -> Powered: yes/no `bluetoothctl devices` + `bluetoothctl info <dev>` -> Connected: yes (atleast one device) But I hope there is a better way then infinite loop script :)

No this is not the right way, this would add up a dependency, using RFkill would be better. I think this is what waybar uses by the way.

No this is not the right way, this would add up a dependency, using RFkill would be better. I think this is what waybar uses by the way.
Owner

If we add native Bluetooth support to yambar, I'd prefer to use an API, not calling out to binaries.

If we add native Bluetooth support to yambar, I'd prefer to use an API, not calling out to binaries.
Poster

Looks like this can be done with DBus API:
https://github.com/greshake/i3status-rust/blob/master/src/blocks/bluetooth.rs

I don't think RFkill is a good idea. I'd like to keep bluetooth unlocked all the time.

Looks like this can be done with DBus API: https://github.com/greshake/i3status-rust/blob/master/src/blocks/bluetooth.rs I don't think RFkill is a good idea. I'd like to keep bluetooth unlocked all the time.
Poster

Some examples of DBus API usage (with busctl and jq):

  • get all info:
busctl --json=pretty call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects
  • get power state:
busctl --json=short call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects | jq '.data[]."/org/bluez/hci0"."org.bluez.Adapter1".Powered.data'
  • get device connection state:
busctl --json=short call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects | jq '.data[]."/org/bluez/hci0/dev_<address>"."org.bluez.Device1".Connected.data'
Some examples of DBus API usage (with busctl and jq): - get all info: ``` busctl --json=pretty call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects ``` - get power state: ``` busctl --json=short call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects | jq '.data[]."/org/bluez/hci0"."org.bluez.Adapter1".Powered.data' ``` - get device connection state: ``` busctl --json=short call org.bluez / org.freedesktop.DBus.ObjectManager GetManagedObjects | jq '.data[]."/org/bluez/hci0/dev_<address>"."org.bluez.Device1".Connected.data' ```

FWIW, I wanted to have a BT connected indicator too and since yambar can run commands and parse stuff I wrote a simple python wrapper for bluetooth for my needs (might tide you over until someone writes native module).

The script listens for changes on udev so it doesn't have to poll and run bluetoothctl repeatedly. But it does actually run it and parse the output (yeah, I know...). Again - more of a stop gap measure.

In my yambar config I then have:

    - script:
        path: <path to yambar-bt.py>
        args: []
        content:
          map:
            tag: status
            values:
              disconnected:
                - string:
                    on-click: blueman-manager
                    text: ""
                    margin: 10
                    font: *awesome
              connected:
                - string:
                    on-click: blueman-manager
                    text: ""
                    font: *awesome
                    foreground: 268bd2ff
                - string:
                    on-click: blueman-manager
                    text: "{name}"
                    margin: 10
FWIW, I wanted to have a BT connected indicator too and since yambar can run commands and parse stuff I wrote a simple python wrapper for bluetooth for my needs (might tide you over until someone writes native module). The script listens for changes on udev so it doesn't have to poll and run bluetoothctl repeatedly. But it does actually run it and parse the output (yeah, I know...). Again - more of a stop gap measure. In my yambar config I then have: ``` - script: path: <path to yambar-bt.py> args: [] content: map: tag: status values: disconnected: - string: on-click: blueman-manager text: "" margin: 10 font: *awesome connected: - string: on-click: blueman-manager text: "" font: *awesome foreground: 268bd2ff - string: on-click: blueman-manager text: "{name}" margin: 10 ```

I'd love to have a bluetooth module with power and connection indication.

Probably this can be done with something like this:
bluetoothctl list -> ctrl (default)
bluetoothctl show <ctrl> -> Powered: yes/no
bluetoothctl devices + bluetoothctl info <dev> -> Connected: yes (atleast one device)

But I hope there is a better way then infinite loop script :)

Wouldn't a script or label be enough for that? I'm using a label and it seems pretty ok:

- label:
    content:
      - string:
          on-click: blueman-manager
          <<: [*materialicons, *active, *bluetooth]

But a script should be fine too, to build on @sochotnicky example, using a ruby one-liner as a script:

path: /sbin/ruby
        args: [-e, '(`bluetoothctl devices`.split("\n").map{|d| d.split(/\s+/)[1..]}.inject([]){|r,d| r << d[1..].join(" ") if `bluetoothctl info #{d[0]}`.match?(/Connected: yes/); r }.then{|d| d.size > 0 ? puts("status|string|connected\nname|string|#{d.join(" ")}\n\n") : puts("status|string|disconnected\n\n") }; sleep 2) while true']
        content:
          map:
            tag: status
            values:
              disconnected:
                - string:
                    on-click: blueman-manager
                    <<: [*bluetoothoff]
              connected:
                - string:
                    on-click: blueman-manager
                    <<: [*bluetoothon]
                - string:
                    on-click: blueman-manager
                    text: "{name}"
                    margin: 10

Or in bash, though this one feels a bit too hack-ish for my taste, as ir relies on bluetoothctl info reporting connected devices if any are present and no address is given, but printing an error when there are no devices connected:

path: /bin/bash
        args: [-c, 'while true; do bluetoothctl info | grep "Missing\|Name" | awk \'{if ($0 == "Missing device address argument") {printf "status|string|disconnected\n\n" } else { printf "status|string|connected\nname|string|%s\n\n", $2 }}\'; sleep 2; done']
        content:
          map:
            tag: status
            values:
              disconnected:
                - string:
                    on-click: blueman-manager
                    <<: [*bluetoothoff]
              connected:
                - string:
                    on-click: blueman-manager
                    <<: [*bluetoothon]
                - string:
                    on-click: blueman-manager
                    text: "{name}"
                    margin: 10

Either way, I don't think it's worth implementing something like this, some people would want the number of connected devices, others would want a list of names, others might want just the name of the first device, then someone would appear asking for a way to show whether bt is Powered etc... It'd just turn into yet another thing to maintain, reducing the time spent on implementing stuf that actually brings something to the table. To give a few examples, tooltips, milti-line strings, hover, clicks with different mouse buttons, scrolling actions, map matchers (i.e., <, > etc, for numbers, regex matchers etc.), taskbar, systray, conditionals, auto-hide... Maybe some of those are actually available, but that's not the point, the point is: There's a lot of stuff that yambar can't do, and a lot of stuff that takes a lot of effort to do in yambar, and I believe trying to generalize stuff that is already possible to do in a reasonably simple way can only result in less flexibility, more complexity and, ultimately, decrease the time available to work on stuff that really matters.

As a side-note, a way to write blocks of code as scripts would be pretty nice, and would allow something like this to be written in a way that is a lot more readable, i.e.:

- script:
    block: |
      while true; do
        connected=()
        for device in $(bluetoothctl devices | awk '{print $2}'); do
          data=( $(bluetoothctl info $device | grep 'Name\|Connected' | awk '{$1="";print $0}' | sed -e 's/^\s*//' -e 's/\s/_/' | tac) )
          if [[ ${data[0]} == "yes" ]]; then connected+=${data[1]}; fi
        done
        if [[ $connected != "" ]]; then
          echo -e "status|string|connected\nname|string|$connected\n"
        else
          echo -e "status|string|disconnected\n"
        fi
        sleep 2
      done

Just to give a small example and reiterate how other features, like such code blocks, have more potential...

> I'd love to have a bluetooth module with power and connection indication. > > Probably this can be done with something like this: > `bluetoothctl list` -> ctrl (default) > `bluetoothctl show <ctrl>` -> Powered: yes/no > `bluetoothctl devices` + `bluetoothctl info <dev>` -> Connected: yes (atleast one device) > > But I hope there is a better way then infinite loop script :) Wouldn't a `script` or `label` be enough for that? I'm using a label and it seems pretty ok: ``` - label: content: - string: on-click: blueman-manager <<: [*materialicons, *active, *bluetooth] ``` But a script should be fine too, to build on @sochotnicky example, using a ruby one-liner as a script: ``` path: /sbin/ruby args: [-e, '(`bluetoothctl devices`.split("\n").map{|d| d.split(/\s+/)[1..]}.inject([]){|r,d| r << d[1..].join(" ") if `bluetoothctl info #{d[0]}`.match?(/Connected: yes/); r }.then{|d| d.size > 0 ? puts("status|string|connected\nname|string|#{d.join(" ")}\n\n") : puts("status|string|disconnected\n\n") }; sleep 2) while true'] content: map: tag: status values: disconnected: - string: on-click: blueman-manager <<: [*bluetoothoff] connected: - string: on-click: blueman-manager <<: [*bluetoothon] - string: on-click: blueman-manager text: "{name}" margin: 10 ``` Or in bash, though this one feels a bit too hack-ish for my taste, as ir relies on `bluetoothctl info` reporting connected devices if any are present and no address is given, but printing an error when there are no devices connected: ``` path: /bin/bash args: [-c, 'while true; do bluetoothctl info | grep "Missing\|Name" | awk \'{if ($0 == "Missing device address argument") {printf "status|string|disconnected\n\n" } else { printf "status|string|connected\nname|string|%s\n\n", $2 }}\'; sleep 2; done'] content: map: tag: status values: disconnected: - string: on-click: blueman-manager <<: [*bluetoothoff] connected: - string: on-click: blueman-manager <<: [*bluetoothon] - string: on-click: blueman-manager text: "{name}" margin: 10 ``` Either way, I don't think it's worth implementing something like this, some people would want the number of connected devices, others would want a list of names, others might want just the name of the first device, then someone would appear asking for a way to show whether bt is Powered etc... It'd just turn into yet another thing to maintain, reducing the time spent on implementing stuf that actually brings something to the table. To give a few examples, tooltips, milti-line strings, hover, clicks with different mouse buttons, scrolling actions, `map` matchers (i.e., `<`, `>` etc, for numbers, regex matchers etc.), taskbar, systray, conditionals, auto-hide... Maybe some of those are actually available, but that's not the point, the point is: There's a lot of stuff that yambar can't do, and a lot of stuff that takes a lot of effort to do in yambar, and I believe trying to generalize stuff that is already possible to do in a reasonably simple way can only result in less flexibility, more complexity and, ultimately, decrease the time available to work on stuff that really matters. As a side-note, a way to write blocks of code as scripts would be pretty nice, and would allow something like this to be written in a way that is a lot more readable, i.e.: ``` - script: block: | while true; do connected=() for device in $(bluetoothctl devices | awk '{print $2}'); do data=( $(bluetoothctl info $device | grep 'Name\|Connected' | awk '{$1="";print $0}' | sed -e 's/^\s*//' -e 's/\s/_/' | tac) ) if [[ ${data[0]} == "yes" ]]; then connected+=${data[1]}; fi done if [[ $connected != "" ]]; then echo -e "status|string|connected\nname|string|$connected\n" else echo -e "status|string|disconnected\n" fi sleep 2 done ``` Just to give a small example and reiterate how other features, like such code blocks, have more potential...
Sign in to join this conversation.
No Milestone
No Assignees
5 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.