Native Shell
Native Shell은 모든 플랫폼의 앱 안에서 만들어지는 AI UI입니다
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗BlueZ-over-D-Bus client library for Elixir: BLE scanning (passive and active), active GATT connections, pairing, and bluez-alsa A2DP audio — the pieces an ESPHome-style Bluetooth proxy or any BLE-consuming Elixir application needs on embedded Linux.
Built for Nerves devices (read-only rootfs,
MuonTrap-supervised daemons) but has no
Nerves dependency: it runs on any Linux host where your application may own
the system D-Bus instance.
Early extraction from
universal_proxy, where this
code shipped and was hardware-validated as an ESPHome Bluetooth proxy on
Raspberry Pis (passive/active scanning into Home Assistant, GATT
connect/read/write/notify/pair against real peripherals, BT-headphone
audio). Still being iterated on; not a final API.
Start here once you're ready to go beyond the quickstart below:
Bluez.start_link/1 option, the full GATT event
contract with a translator example, audio PCM discovery, and the
runtime radio-switching pattern.olddefconfig gotcha), radio firmware blobs, and the
app-side rootfs overlay.The core modules carry the reference detail:
Bluez — the supervisor and every start optionBluez.Client — scanning, mode switching, adapter enumerationBluez.Gatt — the GATT request API and event contractBluez.Agent — pairing authorizationBluez.BlueAlsa — A2DP playback PCM discoveryBluez.Mgmt — LE advertising with verbatim AD bytes (kernel MGMT)Bluez.Radio — per-controller ownership for advertisingBluez.AdvertReceiver — verbatim advertising reports off the HCI socketBluez.HciUser — exclusive raw HCI access to a dedicated controllerdbus-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.AdvertisementMonitor1 (no scan requests — peripherals
don't burn battery answering); active mode collects SCAN_RSP data.Bluez.Client's rssi_heartbeat_ms: option with default 10 s) and
LRU-capped, then fanned out through your on_advertisement: fun.on_gatt_event:
fun. Generation-stamped so late replies can't corrupt replaced
connections.Bluez.Mgmt puts verbatim AD bytes on
air through the kernel MGMT socket, including layouts BlueZ's D-Bus API
refuses (Flags, names, 128-bit UUID lists, ordered 16-bit UUID lists
with duplicates), with a settable interval and millisecond-precise
durations, on any controller the kernel drives. It sends under a
Bluez.Radio lease: one owner per controller, and everything it sent
goes off air when the lease ends.Bluez.AdvertReceiver reads the
controller's legacy and extended advertising reports off an HCI raw
socket, AD bytes untouched, for protocols that BlueZ's per-device
property merging would destroy. Pure :socket, no NIF or port.Bluez.HciUser takes a
dedicated controller away from bluetoothd over an HCI_CHANNEL_USER
socket and speaks raw HCI: commands with the controller's flow control
and timeouts, advertising reports and errors delivered to an owner
process, and the controller handed back to BlueZ on close. For protocols
that scan and advertise continuously, where bluetoothd would cost more
CPU than the protocol itself.def deps do
[
{:bluez, "~> 0.6"}
]
end
A note on the D-Bus layer: exporting objects (which BlueZ's passive
scanning requires) needs a service-side API that isn't in any released
D-Bus client, so this library ships a vendored, namespaced copy of
rebus as Bluez.Rebus.* (MIT, with
the service-side additions proposed upstream in
ausimian/rebus#9 — see
lib/bluez/rebus/VENDORED.md). The namespacing means this can never
collide with a rebus dependency of your own.
children = [
{Bluez,
client: [on_advertisement: &MyApp.Scanner.on_advertisement/1],
gatt: [on_gatt_event: &MyApp.BLEProxy.gatt_event/2],
desired_adapter: nil, # nil = auto (lowest-index adapter)
exclude_adapters: [], # MACs of radios this stack must never drive
audio: true} # bluealsad + Bluez.BlueAlsa
]
Adverts then arrive at your scanner fun as maps
(%{address:, rss:, address_type:, raw_data:}), and GATT requests are
cast-style with results delivered as events:
Bluez.Gatt.connect(0xAABBCCDDEEFF, [], self())
receive do
{:gatt_connection, addr, {:ok, mtu}} -> Bluez.Gatt.get_services(addr)
{:gatt_connection, _addr, {:error, code}} -> {:error, code}
end
See the host integration guide for the full option surface and event contract.
-E (experimental — needed
for passive scanning and the GATT MTU property).audio: true.CAP_NET_RAW/CAP_NET_ADMIN (root on Nerves) for
Bluez.AdvertReceiver/Bluez.Mgmt/Bluez.HciUser; Linux ≥ 5.17 for Bluez.Mgmt
(extended advertising commands, queued by the kernel instead of refused
as busy while another is pending)./run/dbus and /data/bluetooth; on a read-only rootfs point
/var/lib/bluetooth at /data/bluetooth with an overlay symlink.On Nerves none of this is in the official systems — see the Nerves system guide for the full customization list (buildroot packages, kernel fragment, firmware blobs, overlay).
Apache-2.0 — see the LICENSE file in the repository.
start_link/1 opts (funs, a PubSub, child specs); no
Application.get_env, no callbacks into named host modules.