aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-26 09:03:26 +0200
committerDanilo M. <danix@danix.xyz>2026-09-26 09:03:26 +0200
commit14abc878285d961a90f9e56b85c15a091531f6e5 (patch)
tree205067010447c07cf43e89c9bec8a0c4f659f5b8
parentf2eec537da3de403b3201a8631e15ba6c491752d (diff)
downloaddesktop-assistant-14abc878285d961a90f9e56b85c15a091531f6e5.tar.gz
desktop-assistant-14abc878285d961a90f9e56b85c15a091531f6e5.zip
Add bluetooth and vms example tools
Read-only: bluetoothctl show/devices/info and virsh list, domstate, dominfo and domifaddr. Connecting devices and handling VMs are phase 2. The DHCP lease source is empty for bridged guests, so the VM's IP comes from ARP or the guest agent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--README.md4
-rwxr-xr-xexamples/tools/bluetooth.sh46
-rw-r--r--examples/tools/bluetooth.toml2
-rwxr-xr-xexamples/tools/vms.sh48
-rw-r--r--examples/tools/vms.toml7
5 files changed, 107 insertions, 0 deletions
diff --git a/README.md b/README.md
index a9b15e8..de500c1 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,10 @@ The example tools only read:
- `playing`: the current track from `playerctl`, or `mpc`
- `finance`: balances, budgets and spending from Firefly III's `firefly`
list commands
+- `bluetooth`: power, connected devices (battery when reported) and paired
+ ones, through `bluetoothctl show/devices/info`
+- `vms`: libvirt VMs and their state, or one VM's details, through `virsh`
+ read commands
## License
diff --git a/examples/tools/bluetooth.sh b/examples/tools/bluetooth.sh
new file mode 100755
index 0000000..a3af0f9
--- /dev/null
+++ b/examples/tools/bluetooth.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# desktop-assistant tool: bluetooth status (read-only).
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# bluetooth.sh: whether bluetooth is on, the connected devices with their
+# kind (BlueZ icon name) and battery when the device reports one, and the
+# paired devices that are not connected. Only show, devices and info run
+# here: nothing connects, pairs or scans.
+
+set -uo pipefail
+
+power=$(bluetoothctl show | sed -n 's/^\tPowered: //p')
+[ -n "$power" ] || { echo "no bluetooth controller" >&2; exit 1; }
+[ "$power" = yes ] || { echo "bluetooth is off"; exit 0; }
+echo "bluetooth on"
+
+connected=0
+others=()
+while read -r _ mac _; do
+ info=$(bluetoothctl info "$mac")
+ alias=$(sed -n 's/^\tAlias: //p' <<<"$info")
+ if grep -q $'^\tConnected: yes' <<<"$info"; then
+ kind=$(sed -n 's/^\tIcon: //p' <<<"$info")
+ battery=$(sed -n 's/^\tBattery Percentage: .*(\([0-9]*\))$/\1/p' <<<"$info")
+ echo "connected: $alias (${kind:-unknown kind}${battery:+, battery $battery%})"
+ connected=$((connected + 1))
+ else
+ others+=("$alias")
+ fi
+done < <(bluetoothctl devices Paired)
+
+[ "$connected" -gt 0 ] || echo "no device connected"
+[ "${#others[@]}" -eq 0 ] || { printf 'paired, not connected: '; (IFS=,; echo "${others[*]}" | sed 's/,/, /g'); }
diff --git a/examples/tools/bluetooth.toml b/examples/tools/bluetooth.toml
new file mode 100644
index 0000000..af1548e
--- /dev/null
+++ b/examples/tools/bluetooth.toml
@@ -0,0 +1,2 @@
+description = "Bluetooth: whether it is on, which devices are connected (with battery when they report it), and which paired devices are not connected. Read-only."
+command = ["bluetooth.sh"]
diff --git a/examples/tools/vms.sh b/examples/tools/vms.sh
new file mode 100755
index 0000000..3595839
--- /dev/null
+++ b/examples/tools/vms.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# desktop-assistant tool: virtual machine status through virsh (read-only).
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# vms.sh [NAME]: without NAME, every defined VM with its state; with NAME,
+# that VM's state, vCPUs, memory, autostart and IP address when one is
+# known. Only list, domstate, dominfo and domifaddr run here: nothing is
+# started, stopped or edited. Uses libvirt's default URI (LIBVIRT_DEFAULT_URI
+# overrides it).
+
+set -uo pipefail
+
+name="${1:-}"
+if [ -z "$name" ]; then
+ vms=$(virsh list --all --name) || exit 1
+ [ -n "${vms//[[:space:]]/}" ] || { echo "no virtual machines defined"; exit 0; }
+ while read -r vm; do
+ [ -n "$vm" ] && echo "$vm: $(virsh domstate "$vm")"
+ done <<<"$vms"
+ exit 0
+fi
+
+# An unknown name leaves virsh's own error as the last stderr line.
+info=$(virsh dominfo "$name") || exit 1
+field() { sed -n "s/^$1: *//p" <<<"$info"; }
+echo "$name: $(field State), $(field 'CPU(s)') vCPUs," \
+ "$(( $(field 'Max memory' | awk '{print $1}') / 1048576 )) GiB memory," \
+ "autostart $(field Autostart)"
+
+# The DHCP lease is empty for bridged guests; ARP or the guest agent knows.
+for source in lease arp agent; do
+ ip=$(virsh domifaddr "$name" --source "$source" 2>/dev/null \
+ | awk 'NR > 2 && $4 != "" && $4 !~ /^127\./ {sub(/\/.*/, "", $4); print $4}' | paste -sd, -)
+ [ -n "$ip" ] && { echo "IP address: $ip"; break; }
+done
diff --git a/examples/tools/vms.toml b/examples/tools/vms.toml
new file mode 100644
index 0000000..768c7da
--- /dev/null
+++ b/examples/tools/vms.toml
@@ -0,0 +1,7 @@
+description = "Virtual machines (libvirt): which exist and whether they are running, or details of one (vCPUs, memory, autostart, IP address). Read-only."
+command = ["vms.sh", "{name}"]
+timeout = 15
+
+[params.name]
+type = "string"
+description = "VM name for details. Empty to list every VM with its state."