Headless HTTP + WebSocket control service for Uniden BC125AT and SR30C handheld scanners
Project description
bearpaw-daemon
Headless control and telemetry service for Uniden BC125AT and SR30C handheld scanners. Exposes an HTTP + WebSocket API designed as a first-class contract for any client that wants to drive a scanner — dashboards, kiosks, voice assistants, custom integrations.
The daemon's HTTP API (documented via OpenAPI at /openapi.json and
/docs) is the public contract. Any consumer that speaks HTTP and
WebSocket can use it.
Install
pip install bearpaw-daemon
# or
uv pip install bearpaw-daemon
Requires Python 3.10+. On Linux you'll need libusb-1.0 available at
runtime; apt install libusb-1.0-0 covers it on Debian-family systems.
Running
bearpaw --print-example-config > config.yaml # tune as needed
bearpaw --config ./config.yaml
The example config ships inside the package; --print-example-config
writes it to stdout so you can pipe it to wherever you want.
The daemon starts on 127.0.0.1:8000 by default. Browse /docs for
the live OpenAPI UI, or /openapi.json for the raw schema.
Generating typed clients
The OpenAPI document is the canonical contract. Generate clients with your tool of choice:
# Python
openapi-python-client generate --url http://localhost:8000/openapi.json
# TypeScript
npx openapi-typescript http://localhost:8000/openapi.json -o bearpaw.d.ts
Linux systemd installation
For a production Linux deployment (Debian, Ubuntu, Raspberry Pi OS, or any Debian-family host), use the installer:
git clone https://github.com/jeremyfuksa/bearpaw-daemon.git
cd bearpaw-daemon
sudo ./scripts/install-linux.sh
The installer is idempotent — safe to re-run after updates. It:
- Installs system packages (
libusb-1.0-0-dev,python3-venv) - Creates a
scannersystem user withdialoutgroup membership (for/dev/ttyACM0access) - Installs the daemon into
/opt/bearpaw/venv - Creates
/usr/local/bin/bearpawas a wrapper pointing at the venv - Seeds
/etc/bearpaw/config.yamlfromconfig.example.yaml(only if it doesn't already exist — your config is never clobbered) - Installs the systemd unit and enables it (does not start it)
After install, edit /etc/bearpaw/config.yaml (at minimum, pick the
right serial port for your scanner), then:
sudo systemctl start bearpaw
sudo journalctl -u bearpaw -f # watch logs
To upgrade: git pull, then re-run the installer.
A Raspberry Pi (3 or newer) running Raspberry Pi OS is the typical
deployment target, but nothing in the daemon or installer is
Pi-specific — any Debian-family Linux box with a USB port and Python
3.10+ works the same way. For non-Debian distros, install
libusb-1.0 and python3-venv (or equivalents) manually, then
pip install bearpaw-daemon into a venv and adapt
packaging/systemd/bearpaw.service to your paths.
Hardware and host notes
- Scanner cable: USB-A to mini-B (BC125AT) or USB-C (SR30C).
- PC mode: Some Uniden scanners need to be put into "PC/IF" mode manually before they accept serial commands. Consult your scanner's manual.
- Permissions on Linux: The daemon needs read/write access to the
scanner's serial device (typically
/dev/ttyACM0). Either add your user to thedialoutgroup or run via the systemd unit, which uses thescannersystem user. - USB transport: USB transport is the default and preferred path
on the BC125AT. Use
transport: serialinconfig.yamlonly if you have a specific reason. - ALSA discovery for audio consumers:
arecord -llists capture devices; the typical USB audio adapter shows up ashw:1,0.
Audio
The daemon does not stream audio. Scanner audio is hardware passthrough
from the scanner's headphone jack to whatever you want — speakers
directly, an ALSA loopback into another process, an Icecast encoder,
etc. Consumers that want software-gated audio can subscribe to the
squelch_open event on the WebSocket and gate their own pipeline.
API
OpenAPI docs are served at /docs when the daemon is running.
Endpoints are grouped by tag (status, commands, memory, settings,
analytics, preferences) for discoverability.
Config
See the full schema in
src/bearpaw/config.example.yaml,
or run bearpaw --print-example-config once installed.
Development
git clone https://github.com/jeremyfuksa/bearpaw-daemon.git
cd bearpaw-daemon
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip install pytest pytest-asyncio pytest-cov ruff
pytest
See TESTING.md for the test layout and hardware-in-the-loop guidance.
License
MIT.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bearpaw_daemon-1.1.0.tar.gz.
File metadata
- Download URL: bearpaw_daemon-1.1.0.tar.gz
- Upload date:
- Size: 54.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93f6b8190f4394b85f49d0050de1bbcdec2a88e0738b0a981c004eb538bcf066
|
|
| MD5 |
c48d12ad84af37f4f8c58f106470d5ce
|
|
| BLAKE2b-256 |
113dc68b8716082c3bf6fc042d1fd0717460d4b8cbaafc92a7fdb00e7b998143
|
Provenance
The following attestation bundles were made for bearpaw_daemon-1.1.0.tar.gz:
Publisher:
release.yml on jeremyfuksa/bearpaw-daemon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bearpaw_daemon-1.1.0.tar.gz -
Subject digest:
93f6b8190f4394b85f49d0050de1bbcdec2a88e0738b0a981c004eb538bcf066 - Sigstore transparency entry: 1466499905
- Sigstore integration time:
-
Permalink:
jeremyfuksa/bearpaw-daemon@a7b1f6780818f3c651aca0286f40246e849d9f0d -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/jeremyfuksa
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a7b1f6780818f3c651aca0286f40246e849d9f0d -
Trigger Event:
push
-
Statement type:
File details
Details for the file bearpaw_daemon-1.1.0-py3-none-any.whl.
File metadata
- Download URL: bearpaw_daemon-1.1.0-py3-none-any.whl
- Upload date:
- Size: 58.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e001a23fcc54c4c754ca4599ed198ecaf46b4042c6b1631bd01f78108cec323e
|
|
| MD5 |
fbfdc7651fc2a6cba2b17bdfc0834398
|
|
| BLAKE2b-256 |
bb894fcc4384c6e2f1d0699efe18b2ca869505ccfb0cbb6ccf717a375cd07899
|
Provenance
The following attestation bundles were made for bearpaw_daemon-1.1.0-py3-none-any.whl:
Publisher:
release.yml on jeremyfuksa/bearpaw-daemon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bearpaw_daemon-1.1.0-py3-none-any.whl -
Subject digest:
e001a23fcc54c4c754ca4599ed198ecaf46b4042c6b1631bd01f78108cec323e - Sigstore transparency entry: 1466500006
- Sigstore integration time:
-
Permalink:
jeremyfuksa/bearpaw-daemon@a7b1f6780818f3c651aca0286f40246e849d9f0d -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/jeremyfuksa
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a7b1f6780818f3c651aca0286f40246e849d9f0d -
Trigger Event:
push
-
Statement type: