Skip to main content

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

  1. Admin (or a transmitter's audio uplink) opens wss://host/ws/broadcast/{mosque_id}/azaan?token=BROADCAST_TOKEN.
  2. 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).
  3. 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:

  1. Checks three independent signals for "already handled" — the live on-air flag, a recent triggers row, a recent broadcast_audit_logs row — so a live azan (or a server restart mid-window) never causes a duplicate.
  2. 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)

ChannelRecipientDetail
MQTT play command, per deviceEvery stream player and transmitter bound to the mosqueMQTT commands
iOS VoIP push (PushKit)Members' iPhonesRings like a call via CallKit
Android data-only FCMMembers' Android phonesNative call UI
broadcast_audit_logs rowDelivery 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.