led_ticker — Python library & CLI for the LED Ticker
led_ticker speaks the same BLE service as the companion mobile app, so you can drive the
device — or build your own tools — from any machine with Bluetooth. The device
advertises as LED-Ticker-XXXX.
Install
pip install led-ticker # or: uv add led-ticker
This installs the importable led_ticker package and the led command.
Running the CLI
How you invoke the CLI depends on how it was installed:
led <cmd> # pip install into an active venv → on PATH
uv run led <cmd> # uv add led-ticker → script is in .venv/bin, not on PATH
uv run tools/led.py <cmd> # from a checkout of this repo → uses ./src directly
The examples below use led; prefix with uv run if you installed via uv add.
Library
from led_ticker import LedTicker, scan
# Scan for available devices (returns DeviceInfo with name, address, rssi):
for d in scan():
print(d.name, d.address, d.rssi)
# Reuse one connection for several operations:
with LedTicker(pin="482913") as d:
d.set_tickers(["AAPL", "MSFT"])
d.set_status("BUSY", minutes=30)
print(d.get_version()) # -> "0.7.0"
s = d.get_status() # -> Status(text="BUSY", seconds=1800)
# Or a one-shot for a single call (opens and closes its own connection):
import led_ticker
led_ticker.set_mode(["stocks", "weather"])
LedTicker(select=None, address=None, name_prefix="LED-Ticker", scan_timeout=4.0, timeout=15.0, pin=None).
By default the first LED-Ticker-* in range is used; if several are in range it raises
AmbiguousDeviceError (whose .candidates is a list of DeviceInfo). Pass select= to
choose a specific unit (see Selecting a device), or address= to
target a known address directly (skips the scan). Methods raise
ValidationError, AuthError, DeviceNotFoundError, AmbiguousDeviceError, or
ProtocolError (all subclasses of LedTickerError).
pin=None does not mean "no auth" — it falls back to the same resolution the
CLI uses (LED_TICKER_PIN env var, then the ~/.config/led-ticker/pin cache),
so a saved PIN is picked up automatically. Pass pin="482913" to override.
Selecting a device
With more than one LED-Ticker in range, list them and target one explicitly:
led devices # list units: name, address, signal
led --device A1B2 status "BUSY" 30 # target by name suffix
--device matches a unit by its name suffix (the XXXX in LED-Ticker-XXXX),
its full name, or its Bluetooth address. If you run a command with several units
in range and no --device, an interactive terminal prompts you to choose; in a
script (no TTY) it lists the candidates and exits non-zero so you can re-run with
--device.
CLI
# Sign mode
led status "BUSY" 30 # show for 30 min, then auto-clear
led status "ON AIR" # indefinite
led status clear
# Timer mode (countdown sign — random animation at zero, then resumes ambient)
led timer 10 # 10-minute countdown
led timer cancel
# Ambient mode (subset of stocks/weather/clock, 'all', or 'none' for sign-only)
led mode stocks weather
led mode clock
led mode all
led mode none
# Power (volatile — power cycle returns to on)
led power on
led power off
# Display settings (persisted on the device)
led display # show current brightness + scroll speed
led display brightness 8 # brightness 0-15
led display speed 50 # scroll ms/step 20-500 (lower = faster)
led display 8 50 # both at once
# Timezone (persisted; POSIX TZ string — companion apps have a friendly picker)
led timezone # show current
led timezone "EST5EDT,M3.2.0,M11.1.0" # US Eastern
# Data
led tickers AAPL TSLA NVDA SPY
led locations "47.61,-122.33,Seattle" # lat,lon,label (look up coords online)
led apikey your-finnhub-key
led wifi My Network Name password
# Inspect
led get version # firmware version on the device
led get wifi|apikey|tickers|status|locations|mode|power|display|timezone|version # read other settings
# Auth
led pin 482913 # save the device's PIN locally (~/.config/led-ticker/pin)
led pin clear # forget the saved PIN
led --pin 482913 status "BUSY" 30 # use a PIN for one call, without saving it
led pin-enforce on # device: require PIN for writes (default after a fresh flash)
led pin-enforce off # device: stop requiring PIN (escape hatch)
# Maintenance
led reload # force stock refresh
led reset # wipe NVS, rotate PIN, revert to config.h defaults
Save once, every platform: run led pin <6 digits> a single time and it's replayed on each connection automatically — no per-command --pin, on Linux, Windows, and macOS alike. (Companion mobile apps instead use OS-level Bluetooth bonding — the phone prompts for the PIN once and the OS remembers it; the CLI never bonds.)
PIN resolution: every command (and the library) looks for the PIN in this order — --pin XXXXXX flag → LED_TICKER_PIN env var → the saved cache file (~/.config/led-ticker/pin). The env var suits CI or anyone who'd rather not write the PIN to disk. If none is found and the device has enforcement on, writes fail with a clear AuthError.
Stale-PIN safety: every write probes the device after sending the PIN and exits with a clear error if the PIN was rotated by a factory reset — a write never fails silently because of an out-of-date local PIN.
License
Apache-2.0 — free to use, including commercially, with attribution. (The firmware in the parent repo is also Apache-2.0; the hardware design files are CC BY 4.0 — see the repo root.)
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 led_ticker-0.3.1.tar.gz.
File metadata
- Download URL: led_ticker-0.3.1.tar.gz
- Upload date:
- Size: 74.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2755d10168ee6e857775a8ef535b72c1de70a28a385cb66b3965717e54814c33
|
|
| MD5 |
e302a98be5221bd50105f1451a0b5ad7
|
|
| BLAKE2b-256 |
fc6ad79e8c1ed709d925af11f6f210db85feb598ebdbebc8c0bd3da1328cd9c5
|
Provenance
The following attestation bundles were made for led_ticker-0.3.1.tar.gz:
Publisher:
publish.yml on ssayala/led-ticker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
led_ticker-0.3.1.tar.gz -
Subject digest:
2755d10168ee6e857775a8ef535b72c1de70a28a385cb66b3965717e54814c33 - Sigstore transparency entry: 2074551599
- Sigstore integration time:
-
Permalink:
ssayala/led-ticker@2b83e7ccbc8ca905d83c43cba6ec785425293b9c -
Branch / Tag:
refs/tags/led-ticker-v0.3.1 - Owner: https://github.com/ssayala
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2b83e7ccbc8ca905d83c43cba6ec785425293b9c -
Trigger Event:
push
-
Statement type:
File details
Details for the file led_ticker-0.3.1-py3-none-any.whl.
File metadata
- Download URL: led_ticker-0.3.1-py3-none-any.whl
- Upload date:
- Size: 19.8 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 |
802da562cfaf6dbfe7a087d385ad089ea71a3fe3f40788d3e101e3eedd867613
|
|
| MD5 |
3c66fa25d4238d35fc3c1f71f95bda2c
|
|
| BLAKE2b-256 |
45b8c0da45ded154b6f307aa678d25abcb6ea4923c55ad31d197b1739e78e637
|
Provenance
The following attestation bundles were made for led_ticker-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on ssayala/led-ticker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
led_ticker-0.3.1-py3-none-any.whl -
Subject digest:
802da562cfaf6dbfe7a087d385ad089ea71a3fe3f40788d3e101e3eedd867613 - Sigstore transparency entry: 2074551650
- Sigstore integration time:
-
Permalink:
ssayala/led-ticker@2b83e7ccbc8ca905d83c43cba6ec785425293b9c -
Branch / Tag:
refs/tags/led-ticker-v0.3.1 - Owner: https://github.com/ssayala
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2b83e7ccbc8ca905d83c43cba6ec785425293b9c -
Trigger Event:
push
-
Statement type: