Data Flow — Azan Delivery
:::info Status
Implemented. Source: docs/azan-flow.md, docs/live-broadcast-flow.md.
:::
Every prayer time, exactly one of two paths delivers the azan to mosque speakers (ESP32), member phones, and web listeners — the scheduler guarantees never both.
Path A — Live azan
- Admin (or a transmitter's audio uplink) opens
wss://host/ws/broadcast/{mosque_id}/azaan?token=BROADCAST_TOKEN. - First connection for that mosque+room sets the in-memory "on air" flag
(
active_broadcasters["{m}:azaan"]), spawns FFmpeg piping stdin to the Icecast mount, and fires the started fan-out (core/live_broadcast.py:notify_icecast_broadcast_started). - Disconnect or
BROADCAST_IDLE_TIMEOUT_SECS(default 60s) of silence ends the broadcast: FFmpeg killed, flag cleared, ended fan-out fires.
Full detail: Azaan Broadcast module.
Path B — Offline azan (scheduler fallback)
core/azan_scheduler.py ticks every AZAN_AUTO_CHECK_INTERVAL_SECS (default
60s), started in the FastAPI lifespan. For each active mosque and enabled
prayer inside the [grace, window] minutes window:
- Checks three independent signals for "already handled" — the live on-air
flag, a recent
triggersrow, a recentbroadcast_audit_logsrow — so a live azan (or a server restart mid-window) never causes a duplicate. - If not handled: picks the mosque's uploaded recording (Fajr voice for
Fajr, general recording otherwise), starts an Icecast file stream via
FFmpeg
-re, then fires the same MQTT + push fan-out a live azan would.
Full detail: Azaan Broadcast module.
Fan-out (both paths, in parallel)
| Channel | Recipient | Detail |
|---|---|---|
MQTT play command, per device | Every stream player and transmitter bound to the mosque | MQTT commands |
| iOS VoIP push (PushKit) | Members' iPhones | Rings like a call via CallKit |
| Android data-only FCM | Members' Android phones | Native call UI |
broadcast_audit_logs row | — | Delivery analytics; see Broadcast Audit module |
Non-azaan live broadcasts (e.g. a khutbah/announcement) skip device MQTT delivery entirely and use ordinary alert/notification push instead of the call-style VoIP/FCM path — see Azaan Broadcast module §fan-out.
Race handling
The scheduler and a live broadcast can never both fire for the same (mosque, date, prayer) slot — see the race table in Azaan Broadcast module.