Have you ever wondered how far can you go in connecting your Android phone to your computer? The Android ecosystem is open source and assuming you use GNU/Linux, what could possibly get in your way? Anyway, I hope you’ve heard of KDEConnect.
In this article, I’ll explain how I’ve managed to create a simple shell function I called sms
that works like this:
Super cool right? In this article I'll explain in full details how this is done.
Basically, this shell function integrates 3 programs:
read
.
KDEConnect is probably the most important peice of the puzzle - it allows you to connect your Android phone to your computer in various ways. You install the app on your phone and the 'server' on your Linux machine (not necessarily running KDE) and while the daemon is running (usually installed here: /usr/lib/kdeconnectd
) you can pair your phone (pairing is only needed in the beginning) and you get all of the following fruits and vegetables:
And this is only a partial list of KDEConnect’s features, to quote from the official website:
KDE Connect is a project to communicate across all your devices. For example, with KDE Connect you can receive your phone notifications on your desktop computer, control music playing on your desktop from your phone, or use your phone as a remote control for your desktop.
I'll put together 3 programs into a puzzle 1 by 1:
khard
: An address book for the Linux console.fzf
: A command-line fuzzy finder.First, allow me to explain about the architecture of KDEConnect:
A proper installation of KDEConnect provides an executable with a daemon called kdeconnectd
. As I said before KDEConnect is mainly intended to be used on Linux machines running the KDE desktop environment and as such it’s native client. Fortunately, anyone can write a client that will communicate with the daemon and make it easier to communicate with your phone through the daemon through a GUI or a CLI.
The basic client for the daemon usually provided with KDEConnect's installation is called kdeconnect-cli
.
kdeconnect-cli
This is it's usage/help output:
$ kdeconnect-cli --help
Usage: kdeconnect-cli [options]
KDE Connect CLI tool
Options:
-l, --list-devices List all devices
-a, --list-available List available (paired and reachable) devices
--id-only Make --list-devices or --list-available print
only the devices id, to ease scripting
--refresh Search for devices in the network and
re-establish connections
--pair Request pairing to a said device
--ring Find the said device by ringing it.
--unpair Stop pairing to a said device
--ping Sends a ping to said device
--ping-msg <message> Same as ping but you can set the message to
display
--share <path> Share a file to a said device
--list-notifications Display the notifications on a said device
--lock Lock the specified device
--send-sms <message> Sends an SMS. Requires destination
--destination <phone number> Phone number to send the message
--device, -d <dev> Device ID
--name, -n <name> Device Name
--encryption-info Get encryption info about said device
--list-commands Lists remote commands and their ids
--execute-command <id> Executes a remote command by id
-k, --send-keys Sends keys to a said device
--my-id Display this device's id and exit
-h, --help Displays this help.
-v, --version Displays version information.
--author Show author information.
--license Show license information.
--desktopfile <file name> The base file name of the desktop entry for
this application.
As you can see, there is a built-in interface to send an SMS message through this command, using --send-sms <message>
together with --destination <phone number>
. So what is there left to do? Just bundle all of these together into a shell function right?
The problem that's still need to be solved is:
Up until this point I’ve never thought I’ll be able to solve this problem gracefully without creating a monolithic daemon client in a compiled language like C or C++ which uses KDEConnect's libraries and that communicating directly with kdeconnectd
. What solved this problem extremely easily and what made me feel like a command line super hero was introducing fzf
and khard
.
khard
: An address book for the Linux consoleQuoting from the github page:
It creates, reads, modifies and removes carddav address book entries at your local machine. Khard is also compatible to the email clients mutt and alot and the SIP client twinkle. You can find more information about khard and the whole synchronization process here.
My setup consists of vdirsyncer syncing my contacts with my Nextcloud instance sitting on my VPS by https://ovh.com/. Read more about the synchronization and usage of the 2 programs in vdirsyncer
's documentation: https://vdirsyncer.pimutils.org/en/stable/.
The command used to display phone numbers only is khard phone
, using the --parsable
flag to produce tab seperated output, comfortable for processing it's output by a shell.
Quoting from the github page:
It's an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.
Originally FZF was intended for finding files in your computer. What it does with any list it receives is opening a curses
user interface in which you type a search term and while you type, if you press Enter while the choice-indicator is placed on the desired result, it is printed on stdout
. Here is an ASCIInema screen cast of fzf
running with an input of the command find /usr/share/
:
The following shell function is used in my dotfiles repository in the file .functions
.
sms(){
local args="$@"
local phone_number name phone_type
khard phone --parsable | sort -u | fzf | IFS=$'\t' read -r phone_number name phone_type
if [[ -z "${phone_number}" ]]; then
echo No recipient was chosen >&2
return
else
echo "${name}"$'\t'"${phone_number}"$'\t'"${phone_type}" > ${_KDECONNECT_SMS_LAST_RECIPIENT}
kdeconnect-cli --device ${_KDECONNECT_DEFAULT_DEVICE} --send-sms "${args}" --destination "${phone_number}" && \
echo sent sms message to ${name} | fribidi
fi
}
In order to conceal the private information of my real contacts, I used a list of randomly generated names as contacts and another list of randomly generated numbers so the actual shell function used to produce the ASCIInema recordings was this:
sms(){
paste -d$'\t' ~/numbers.txt ~/names.txt | fzf | while IFS=$'\t' read -r name number; do
echo sending sms message to $name
done
}
The list of names is sponsored by http://listofrandomnames.com/index.cfm and the list of numbers was generated by shuf -i 100000-999999 -n 150 -o ~/numbers.txt
which is part of GNU's coreutils.