A small, extensible command-line toolkit for interacting with iTag-style BLE trackers. Includes a plugin-based action system, vendor profile support, and a clean CLI for scanning, alerting, reading battery levels, and listening for button presses.
- BLE device discovery (
itag_cli.discovery.find_device) - Plugin-based actions (alert, stop-alert, battery, listen-button, etc.)
- Vendor profile system with capability validation
- Async BLE operations powered by bleak
- Unit-tested with pytest and pytest-asyncio, run in CI on every push with no hardware attached
- Installed as a real CLI command:
itag-cli - Extensible: add your own actions or vendor profiles without modifying the core
-
Create and activate a virtual environment:
python3 -m venv venv source venv/bin/activate -
Install dependencies:
pip install -r requirements.txt
-
Install the project in editable mode (enables the
itag-clicommand):pip install -e .
Dependencies include:
- bleak
- pytest
- pytest-asyncio
All tests live in the tests/ directory.
Run the full suite:
pytest -qAsync tests require the plugin to be loaded. This is handled automatically via pytest.ini:
[pytest]
pythonpath = itag_cli
addopts = -p pytest_asyncioThe CLI can automatically find an iTag-like device using:
from itag_cli.discovery import find_deviceDiscovery logic matches devices whose names contain "itag" or "tag" (case-insensitive).
You can also explicitly scan for a device from the CLI:
itag-cli --discoverAfter installation, the CLI is available as the itag-cli command.
View help:
itag-cli --helpAlert the device:
itag-cli alert --mac AA:BB:CC:DD:EE:FFStop alerting:
itag-cli stop-alert --mac AA:BB:CC:DD:EE:FFRead battery level:
itag-cli battery --mac AA:BB:CC:DD:EE:FFListen for button presses:
itag-cli listen-button --mac AA:BB:CC:DD:EE:FFAuto-discover device (no --mac needed):
itag-cli alertExplicit discovery:
itag-cli --discoverVendor profiles define the BLE characteristics required by actions.
Example default profile (itag_cli/gatt_uuids/itag.py):
class iTag:
ALERT_CHAR = "00002a06-0000-1000-8000-00805f9b34fb"
BUTTON_CHAR = "0000ffe1-0000-1000-8000-00805f9b34fb"
BATTERY_CHAR = "00002a19-0000-1000-8000-00805f9b34fb"Using a custom vendor file:
itag-cli alert --vendor-file my_vendor.py --profile MyVendorActions live in itag_cli/actions/ and follow a simple pattern:
- declare required vendor capabilities
- implement an async run() method
- register via load_actions()
This makes the system easy to extend without modifying the core.
-
All imports inside the package use absolute imports:
from itag_cli.actions import load_actions from itag_cli.discovery import find_device from itag_cli.gatt_uuids import itag as builtin_itag
-
Tests rely on pytest.ini to treat itag_cli/ as the import root.
-
The CLI entry point is defined in pyproject.toml:
[project.scripts] itag-cli = "itag_cli.cli:main"