aboutsummaryrefslogtreecommitdiff
path: root/.config/luastatus-scripts-dwm/bluetooth.lua
diff options
context:
space:
mode:
authorVidhu Kant Sharma <vidhukant@vidhukant.com>2025-05-14 22:50:39 +0530
committerVidhu Kant Sharma <vidhukant@vidhukant.com>2025-05-14 22:50:39 +0530
commit05da0e10926d4ade3b10a55999a0ed1b797caf65 (patch)
tree97cf6a33e5ce90d57e6894b748b1e18ad690643e /.config/luastatus-scripts-dwm/bluetooth.lua
parentf9c150cf57732bb7b42c6b2a5db70039161f8c6d (diff)
added luastatus configHEADmaster
Diffstat (limited to '.config/luastatus-scripts-dwm/bluetooth.lua')
-rw-r--r--.config/luastatus-scripts-dwm/bluetooth.lua177
1 files changed, 177 insertions, 0 deletions
diff --git a/.config/luastatus-scripts-dwm/bluetooth.lua b/.config/luastatus-scripts-dwm/bluetooth.lua
new file mode 100644
index 0000000..f4807a0
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/bluetooth.lua
@@ -0,0 +1,177 @@
+-- A widget to display currently connected and paired bluetooth devices.
+-- To change output format modify reprint_devices function.
+
+separator = " "
+
+-- Object paths look like /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/somethingsomething
+function get_device_mac_address(device_object_path)
+ return device_object_path:gsub("/.*/dev_", ""):gsub("/.*", ""):gsub("_", ":")
+end
+
+-- For reference bluetoothctl devices output looks like that:
+-- Device XX:XX:XX:XX:XX:XX JBL T450BT
+-- Device YY:YY:YY:YY:YY:YY Redmi 8
+--
+-- Function returns mac addresses of all devices.
+function get_devices()
+ local devices = {}
+ local handle = io.popen(string.format("bluetoothctl devices"))
+ for line in handle:lines() do
+ table.insert(devices, string.match(line, "Device ([%x:]+)"))
+ end
+ handle:close()
+ return devices
+end
+
+function get_power_state()
+ local handle = io.popen(string.format("bluetoothctl show"))
+ local power_state = false
+ for line in handle:lines() do
+ local state = string.match(line, "^%s*PowerState:%s*(%w+)")
+ if state then
+ if state == "off" then
+ power_state = false
+ else
+ power_state = true
+ end
+ break
+ end
+ end
+ handle:close()
+
+ return power_state
+end
+
+-- For reference bluetoothctl info output looks like that:
+-- Device XX:XX:XX:XX:XX:XX (public)
+-- Name: JBL T450BT
+-- Alias: JBL T450BT
+-- Class: 0xFFFFFFFF
+-- Icon: audio-card
+-- Paired: yes
+-- Trusted: yes
+-- Blocked: no
+-- Connected: yes
+-- LegacyPairing: no
+-- UUID: Headset (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+-- ...
+-- UUID: Handsfree (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+--
+-- Given this input function returns a following table:
+-- [alias] string JBL T450BT
+-- [blocked] boolean false
+-- [class] string 0x00240404
+-- [connected] boolean true
+-- [icon] string audio
+-- [legacypairing] boolean false
+-- [name] string JBL T450BT
+-- [paired] boolean true
+-- [trusted] boolean true
+function get_device_info(mac_address)
+ if mac_address == nil then
+ mac_address = ""
+ end
+ local device_info = {}
+ local handle = io.popen(string.format("bluetoothctl info %s", mac_address))
+ for line in handle:lines() do
+ local key, value = string.match(line, "(%w+): (.*)")
+ -- Filter junk
+ if key ~= "UUID" and key ~= nil and value ~= nil then
+ key = string.lower(key)
+ if key ~= "name" and key ~= "alias" and key ~= "icon" then
+ if value == "yes" then
+ value = true
+ end
+ if value == "no" then
+ value = false
+ end
+ end
+ device_info[key] = value
+ end
+ end
+ handle:close()
+ return device_info
+end
+
+devices = {}
+
+function reprint_devices(power_state)
+ if power_state then
+ local t = {}
+ for mac_address, device in pairs(devices) do
+ table.insert(t, string.format("󰂱 %s", device["alias"]))
+ end
+ if next(t) == nil then
+ return "󰂯"
+ else
+ return table.concat(t, separator)
+ end
+ else
+ return "󰂲"
+ end
+end
+
+widget = {
+ plugin = "dbus",
+ opts = {
+ greet = true,
+ -- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
+ signals = {
+ {
+ sender = "org.bluez",
+ interface = "org.freedesktop.DBus.Properties",
+ signal = "PropertiesChanged",
+ arg0 = "org.bluez.Device1",
+ bus = "system"
+ }, {
+ sender = "org.bluez",
+ interface = "org.freedesktop.DBus.Properties",
+ signal = "PropertiesChanged",
+ arg0 = "org.bluez.Adapter1",
+ bus = "system"
+ }
+ }
+ },
+ cb = function(t)
+ local power_state = false
+ if t.what == "hello" then
+ power_state = get_power_state()
+ local mac_addresses = get_devices()
+ for i, mac_address in pairs(mac_addresses) do
+ local device = get_device_info(mac_address)
+ if device["connected"] and device["paired"] then
+ devices[mac_address] = device
+ end
+ end
+ elseif t.what == "signal" then
+ -- For reference message from dbus looks like that:
+ -- table
+ -- [1] string org.bluez.Device1
+ -- [2] table
+ -- [2] [1] table
+ -- [2] [1] [1] string SomethingSomething
+ -- [2] [1] [2] boolean false
+ -- [2] [2] table
+ -- [2] [2] [1] string Connected
+ -- [2] [2] [2] boolean true
+ -- [3] table
+ if t.signal == "PropertiesChanged" then
+ power_state = get_power_state()
+ for i, message in pairs(t.parameters[2]) do
+ if message[1] == "Connected" or message[1] == "Paired" then
+ local mac_address = get_device_mac_address(t.object_path)
+ if message[2] then
+ local device = get_device_info(mac_address)
+ if device["paired"] then
+ devices[mac_address] = device
+ end
+ else
+ devices[mac_address] = nil
+ end
+ end
+ end
+ end
+ end
+ return reprint_devices(power_state)
+ end
+}