bbangert
bluez - bluez over d-bus library
I’ve been working on some Elixir based projects for awhile now, slowly spinning out libraries from the project as they stabilize some and thought this one might be useful for the community. My project is Nerves based and needed bluetooth support, so I originally tried blue_heron, then evaluated whether Bluex had the support I needed, but eventually ended up building this out with claude.
Features
- One supervisor that brings up
dbus-daemon,bluetoothd -E, and (optionally)bluealsad, with crash-isolation and restart ordering (:rest_for_one) already worked out — an audio fault never restarts scanning, a bus restart rebuilds everything above it. - Passive and active BLE scanning, runtime-switchable. Passive mode uses BlueZ’s
AdvertisementMonitor1(no scan requests — peripherals don’t burn battery answering); active mode collects SCAN_RSP data. - Advertisement reconstruction — BlueZ only exposes parsed properties; they’re re-serialized into AD byte structures, emit-gated (first sighting / payload change / RSSI heartbeat) and LRU-capped, then fanned out through your
on_advertisement:fun. - Handle-keyed GATT client — connect / service discovery / read / write / notify / pair / unpair / clear-cache, with a documented, host-agnostic event contract delivered through your
on_gatt_event:function. Generation-stamped so late replies can’t corrupt replaced connections. - Pairing agent that authorizes exactly the pairings your code initiated.
- bluez-alsa integration (optional) — enumerates ready-to-open A2DP playback PCMs and signals your app when the set changes.
- No host coupling — configuration flows exclusively through
start_link/1opts (functions, a PubSub, child specs); noApplication.get_env, no callbacks into named host modules.
While this library is built for Nerves, it should work on a normal linux host. The passive scanning required some additional changes to the rebus library that I’ve opened a PR to upstream, the current 0.1 release of bluez vendors it in. This passive scanning mode is extremely efficient which was the primary reason I went with this approach.
I’ve been using this in deployed code for weeks now where its been very stable, the early version is mainly to reflect that it might still need changes.
For this project I’ve mainly been building out features with the Elixir Phoenix plugin for claude code, with manual and AI reviews as well as frequent audits to try and prevent any AI sloppiness from manifesting. ![]()
Most Liked
quatermain
Hi, creator of that plugin for Elixir/Phoenix development with Agents here. Thanks for using it and mentioning it here. Happy to see users of it. Fyi if you want help to contribute to plugin and even improve experience with Nerves and others, there is way how you (we) can retrospectively analyze your sessions and generate improvements for plugin or new skills at all. Whole framework is (hidden) inside the plugin.
Popular in Announcing
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









