Skip to content

KR8MER/eas-station

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8,584 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EAS Station™ EAS Station™

License: AGPL v3 Commercial License Version Raspberry Pi Python Flask Werkzeug Jinja2 Socket.IO SQLAlchemy Alembic PostgreSQL + PostGIS Redis Gunicorn gevent Nginx Let's Encrypt Systemd Icecast SoapySDR FFmpeg pydub eSpeak NG NumPy SciPy Numba lxml Pillow Bootstrap Font Awesome Leaflet Chart.js PyOTP cryptography Twilio chrony gpsd GPS Stratum 1

An open, software-defined Emergency Alert System platform — the kind of infrastructure that used to cost $5,000–$7,000 per appliance, now running on a $80 Raspberry Pi at roughly 12 watts.

EAS Station™ is a complete CAP-to-broadcast research and training platform: it pulls Common Alerting Protocol feeds from NOAA/NWS and FEMA IPAWS, encodes FCC-Part-11-compliant SAME audio, verifies the result on the air with a software-defined radio, geofences every message against PostGIS-backed boundary data, disciplines its own clock from GPS satellites to stratum 1, and records every operator action into a cryptographically tamper-evident audit ledger. It does all of this from a single Raspberry Pi 5 — or any Linux server — wired together from boring, battle-tested open-source components instead of a proprietary appliance.

The project's long-term goal is to be a credible, auditable, drop-in alternative to commercial encoder/decoder hardware for laboratories, training programs, and broadcasters who want to understand and own the stack instead of leasing a black box.


⚠️ Laboratory / Research Use Only — EAS Station™ generates valid SAME headers and attention tones that will trigger downstream EAS equipment. It is not FCC-certified and must only be operated in controlled test environments. Never connect it to on-air RF, an STL path, or a public streaming chain without explicit authorization. See Legal & Compliance.


🎯 Who This Is For, and What It's For

EAS Station™ was built because the existing EAS appliance market is closed, expensive, and impossible to audit. The platform reframes the same workflows as transparent, inspectable, programmable infrastructure — useful across several distinct audiences:

Public-Safety Agencies & Emergency Management Offices

Use it to: stand up a non-production training rig that mirrors the agency's real CAP/IPAWS workflow, validate FIPS-code and NWS-zone coverage before an exercise, run tabletop drills with realistic alert ingestion and replay, and prototype custom alert distribution (LED signage in EOCs, GPIO triggers to siren controllers, SMS/email/SNMP notifications to on-call staff) without touching the production warning system.

Broadcasters & Engineering Departments

Use it to: experiment with CAP-to-SAME workflows in a bench environment that costs less than a single appliance service contract, evaluate SDR-based off-air verification against an existing encoder, document Required Weekly Test (RWT) and Required Monthly Test (RMT) compliance for audit purposes, and pilot ideas — multi-receiver coordination, alert geofencing, audit-trail integrity — that an operations team can later take to vendors as a requirement spec.

Amateur Radio: ARES, RACES, SKYWARN, Public-Service Nets

Use it to: run realistic CAP-to-EAS training exercises during nets, integrate EAS audio with two-way LMR systems via MDC1200 selective calling (PTT-ID, Emergency, Voice Selective Call), build SKYWARN spotter feedback loops with PostGIS-targeted alert subscription, and operate a stratum-1 GPS-disciplined NTP server for the rest of the club's lab — all on the same Pi.

Universities, Research Labs & Standards Work

Use it to: teach FCC Part 11 / NRSC-4-B SAME modulation hands-on, study CAP 1.2 schema parsing and IPAWS authentication, instrument an end-to-end alert pipeline for software-engineering coursework, or use the running system as the test article in research on alert latency, integrity, geographic targeting accuracy, or social-science studies of alert effectiveness.

Telecom / Utility / Critical Infrastructure Operators

Use it to: subscribe to weather and infrastructure alerts for an operations center, drive site-local signage and PA chains via the GPIO/serial display layer, integrate compliance-health monitoring into existing NMS via SNMP traps, and treat alert ingestion as auditable infrastructure rather than a manual-watch role.

Software Engineers & Open-Source Contributors

Use it as: a non-trivial, full-stack reference application — Flask + SQLAlchemy + PostGIS + Redis + Socket.IO + SoapySDR + systemd — with real DSP, real spatial queries, real hardware I/O, real cryptographic audit chaining, and a meaningful test suite. Build CAP integrations against the REST API, or contribute upstream.


🧭 What the Platform Actually Does

Rather than a feature checklist, here is the platform organized around the real operational responsibilities it takes off the operator's plate.

Alert Ingestion — A Reliable Front Door for CAP

The poller subsystem maintains continuous, deduplicated subscriptions to NOAA/NWS and FEMA IPAWS CAP feeds, plus any number of additional CAP 1.2 endpoints an organization wants to add (state warning points, municipal feeds, internal test sources). Alerts are parsed with lxml (5–10× faster than the stdlib parser), normalized, deduplicated, and committed to PostgreSQL/PostGIS with full geographic context. A stalled feed is detected and auto-resumed rather than silently dropping events. For agencies validating their footprint, a built-in setup wizard walks operators through finding their FIPS county codes and NWS forecast zones.

Why it matters institutionally: The most common operational failure in alert systems is silent feed loss. The poller is built to make that visible — on the dashboard, in the logs, in the audit trail — instead of hiding it.

SAME Encoding & On-Air Broadcast Workflow

The encoder generates bit-perfect Specific Area Message Encoding headers per FCC Part 11 and NRSC-4-B, complete with the 853/960 Hz two-tone attention sequence, optional eSpeak NG (or Azure Cognitive Services) text-to-speech voice-over with operator-tunable phonetic normalization for road numbers and abbreviations, and an EOM bookend. A manual EAS workflow lets training staff print custom drill messages, an RWT/RMT scheduler automates the FCC-required weekly and monthly tests, and the EAS Compliance dashboard surfaces the cadence so gaps are caught before an audit.

Beyond the broadcast chain, the encoder also supports a family of pre/post-alert signaling profiles designed for forwarding EAS audio over a Motorola-style two-way LMR network: MDC1200 (PTT-ID Pre/Post, Emergency, Request-to-Talk, Remote Monitor, Call Alert, Voice Selective Call), Quick-Call II, and DTMF. This makes the platform usable as a CAP-to-LMR bridge for public-safety voice systems that already exist on a county or campus.

SDR Verification — Closing the Loop Off-Air

A separate eas-station-sdr service uses RTL-SDR, Airspy, or SDRplay receivers (via the SoapySDR abstraction) to demodulate the actual RF, decode received SAME headers in real time, and prove that what went out of the transmitter is what the encoder commanded. Verification cross-checks have been validated against multimon-ng for decoding parity. A live, continuously-updating waterfall on the Radio Receiver Diagnostics page lets an engineer watch a frequency the way they would on a benchtop spectrum analyzer; a one-click "Capture IQ" button records a one-second complex64 .npy recording per receiver and streams it to the browser via a single-use download URL — feed it straight into scripts/rbds_diagnose.py, inspectrum, or GNU Radio for offline forensic work without SSH-ing into the host. The same SDR pipeline also carries a full RBDS / RDS decoder (PTYN, AF method-B, Linkage Actuator, Slow Labelling, Open Data Applications, Fast Switching) and an Icecast streaming layer so any number of remote listeners can monitor demodulated audio over HTTP.

Why it matters institutionally: Most encoder vendors do not publish how they verify their own output, and there's no second pair of ears in the rack. This subsystem makes off-air verification a property of the platform, not the operator's headphones.

Geographic Intelligence — Alerts Matched to a Real Footprint

PostGIS is treated as a first-class component, not an optional add-on. County and NWS zone boundaries are loaded from authoritative sources (U.S. Census TIGER/Line, NOAA/NWS, and contributed local GIS offices), and every incoming alert is matched against the station's coverage polygon with real spatial queries. Custom shapefile import lets organizations add their own service-area definitions (utility territories, school district boundaries, campus polygons), and the interactive Leaflet maps in the dashboard let operators see the alert area and the station footprint together at a glance.

Timekeeping — A Broadcast-Grade Time Source Built In

Every EAS event is timestamped, geofenced, and audited — and a station that drifts seconds against NIST is a station whose RWT logs and CAP sent/effective/expires math eventually cease to match the real world. The reference build pairs a u-blox MAX-M8Q multi-GNSS GPS HAT (or Adafruit MTK3339 as a drop-in alternative) with hardware Pulse-Per-Second and a battery-backed RTC. chrony consumes the NMEA fix and the PPS edge as a kernel refclock, so the station serves NTP at true stratum 1 with no upstream internet time required and survives complete network isolation. A dedicated GPS & Time Dashboard at /admin/gps-dashboard presents a polar sky plot coloured by constellation, full chronyc tracking parsing, per-PRN signal-level bars, parsed chronyc sources, and a logarithmic sync-health meter — modelled visually on W0CHP's chrogps-dash. A one-click checklist under Admin → Hardware probes every prerequisite (RTC overlay, PPS device, package state, /boot/firmware/config.txt) and offers a single Run button per remediation step, so the system can be brought up by an operator who has never edited chrony.conf by hand.

Beyond compliance, this is a useful capability in its own right — the platform serves NTP to the rest of a lab, EOC, or campus rack as a side effect of being a correctly-clocked EAS encoder.

Tamper-Evident Audit Ledger — Integrity You Can Prove

Every alert insert, encoder action, and operator change is recorded into the existing audit_logs table — but with a tamper-evidence layer that was added in v2.75. Each row carries the SHA-256 of its predecessor's entry_hash, an SHA-256 over its own canonical-JSON content (including the prev-link), and an Ed25519 signature over that hash. The signing key is loaded from a configured path in production, with documented fallbacks. Verification is exposed via AuditLogger.verify_chain(), which walks the table, checks every signed row's prev-link, recomputes its content hash, and verifies the signature — returning a structured result that includes the index of the first bad row if integrity has been broken.

Why it matters institutionally: This is the difference between "we logged it" and "we can prove the log hasn't been edited." For incident reviews, regulator interaction, training-program documentation, or research integrity, that distinction is the whole point.

Hardware Integration — The Things the System Actually Has to Drive

The platform was designed under the assumption that an EAS station is not a pure software product — it has to flip relays and drive signs. The hardware service exposes:

  • GPIO relay control for transmitter PTT lines and external equipment
  • OLED status panels (Argon, generic SSD1306/SH1106) for at-a-glance current-alert state
  • VFD displays with a custom screen editor and bitmap support
  • Scrolling LED signage over RS-232 (and RS-232-over-Ethernet) for EOC and lobby installations
  • NeoPixel / WS2812B addressable strips for status walls
  • Zigbee (via Argon40 ZNP) for optional wireless sensor and device control
  • GPIO pin map in the web UI so what's wired and what's firing is never a mystery

Security, Notifications & Operations

The web tier is built for organizations that have to share operator credentials safely: role-based access control (admin / operator / viewer), TOTP multi-factor authentication with QR-code enrollment, scoped API keys for automation, Redis-backed rate limiting on login and webhook endpoints, CSRF protection on every state-changing endpoint, and nginx HTTPS with optional automatic Let's Encrypt provisioning. Tailscale integration offers a one-tab path to private-network access for distributed teams.

Outbound notifications cover email (SMTP, with an optional bundled local Postfix relay), SMS (Twilio), and SNMP v2c traps for integration with existing NMS platforms.

Day-to-day operations are made survivable by a whiptail TUI configurator (sudo eas-config), automatic Alembic migrations with a recovery script for half-applied schema changes, pre-flight backup tooling (tools/create_backup.py), one-button in-place upgrades (tools/inplace_upgrade.py), a comprehensive web diagnostics page plus CLI scripts, and an in-browser journalctl log viewer and documentation reader that renders the full 90+ document library.

Web Dashboard & REST API

The UI is a responsive Bootstrap 5 application with 11 built-in themes (every page including the Changelog viewer driven by theme CSS custom properties), live Socket.IO push for alert / radio / GPS updates, a full alert timeline with search and filter, an Analytics dashboard with Chart.js visualizations and one-click client-side PDF export of the full statistics report, an audio monitoring view with playback and live receive history, operator-selectable display units (coordinate format, altitude, speed, distance) saved per browser, and a System Health panel surfacing CPU/memory/disk/temperature.

Everything in the UI is reachable from a REST API namespaced under /api/, with X-API-Key header authentication and a vendored JavaScript client for browser-side integrations.


🏗️ Architecture

The platform is intentionally split into focused systemd services so a web crash never affects audio, and a hardware fault never brings down the dashboard.

graph TB
    subgraph External["External Sources"]
        SRC[Alert Sources<br/>NOAA · IPAWS · CAP]
        RF[RF Signals<br/>162 MHz · SDR]
        GPS_IN[GPS Satellites<br/>NMEA + PPS]
    end

    subgraph Services["Systemd Services"]
        POLL[eas-station-poller<br/>CAP Feed Polling]
        WEB[eas-station-web<br/>Flask · Gunicorn]
        SDR_SVC[eas-station-sdr<br/>SDR Hardware]
        AUDIO_SVC[eas-station-audio<br/>EAS Monitoring]
        HW_SVC[eas-station-hardware<br/>GPIO · Displays]
        CHRONY[chrony + gpsd<br/>Stratum 1 NTP]
    end

    subgraph Infrastructure["Infrastructure"]
        DB[(PostgreSQL 17<br/>+ PostGIS 3.4)]
        REDIS[(Redis 7<br/>Cache · Pub/Sub)]
        NGINX[nginx<br/>HTTPS · Proxy]
        AUDIT[(Tamper-Evident<br/>Audit Ledger<br/>Ed25519)]
    end

    subgraph Output["Outputs"]
        TX[FM Transmitter<br/>GPIO Relay]
        UI[Web Browser<br/>HTTPS]
        LED[LED · OLED · VFD<br/>Displays]
        STREAM[Icecast<br/>Audio Stream]
        NTP[NTP Stratum 1<br/>LAN Time Serving]
    end

    SRC -->|CAP XML| POLL
    RF --> SDR_SVC
    GPS_IN --> CHRONY

    POLL -->|Store Alerts| DB
    WEB -->|Query Data| DB
    WEB -->|Commands| REDIS
    SDR_SVC -->|IQ + Spectrum| REDIS
    AUDIO_SVC -->|Decode| REDIS
    DB -->|Hash-chain insert| AUDIT

    NGINX -->|Reverse Proxy| WEB
    WEB --> UI
    HW_SVC -->|Relay Control| TX
    HW_SVC -->|Messages| LED
    SDR_SVC -->|Demod Audio| STREAM
    CHRONY --> NTP

    style External fill:#3b82f6,color:#fff
    style DB fill:#8b5cf6,color:#fff
    style AUDIT fill:#dc2626,color:#fff
    style WEB fill:#10b981,color:#fff
    style AUDIO_SVC fill:#f59e0b,color:#000
    style UI fill:#6366f1,color:#fff
    style CHRONY fill:#0f766e,color:#fff
Loading
Service Responsibility
eas-station-web Flask UI, REST API, dashboards — no direct hardware access
eas-station-poller CAP feed polling, XML parsing, deduplication, database writes
eas-station-sdr SDR capture, FM demodulation, SAME decoding, RBDS, Icecast streaming, IQ capture
eas-station-hardware GPIO relays, OLED/VFD/LED displays, NeoPixel, Zigbee
eas-station-audio Audio processing, EAS monitoring, Redis pub/sub
chrony + gpsd GPS-disciplined kernel refclock; stratum-1 NTP serving

Infrastructure: PostgreSQL 17 + PostGIS 3.4 for persistent storage · Redis 7 for real-time metrics and inter-service messaging · nginx for HTTPS termination · chrony + gpsd for stratum-1 time.

Frontend libraries (all vendored locally under static/vendor/): Bootstrap 5, jQuery, Font Awesome, Leaflet (maps), Mermaid (diagrams), Chart.js 3 with the datalabels, matrix and date-fns adapter plugins (dashboards), and jsPDF + html2canvas (client-side PDF report export).


🚀 Quick Start

One-Command Install

git clone https://github.com/KR8MER/eas-station.git
cd eas-station
sudo bash install.sh

The interactive whiptail TUI installer is built for the case where the person installing the station is not the person who wrote the software. It guides operators through every option and handles the rest automatically:

What you configure What the installer does for you
Admin account (user / pass / email) Installs PostgreSQL, Redis, Python, nginx
Hostname, domain, callsign, EAS originator Generates a secure 64-char SECRET_KEY
State, county, FIPS / NWS zone codes Runs Alembic database migrations
Alert sources (NOAA, IPAWS) Creates your administrator account
Icecast streaming passwords Generates the Ed25519 audit-log signing key
Hardware (GPIO, LED, VFD, Zigbee, GPS HAT) Starts all systemd services
Tailscale / SSL preferences Configures nginx with SSL (Let's Encrypt optional)

Then open https://your-server-ip and log in — the station is live.

💡 Debian 13 (Trixie) and Python 3.13 are fully supported. The installer auto-detects the host OS and selects the right packages.

Update an Existing Installation

cd /opt/eas-station
sudo bash update.sh

Optional backup → stop services → pull latest code → preserve .env → run Alembic migrations (and refuse to fall back to db.create_all() if a migration fails, so a clean error is never traded for a half-migrated database) → restart everything.

Reconfigure After Install

sudo eas-config        # interactive whiptail TUI for any .env setting

Or visit /settings in the web UI for hardware, Icecast, notifications, TTS, FIPS codes, broadcast settings, and more. Anything that was historically an .env variable but is now a runtime concern (poller cadence, broadcast settings, notifications, application logging) lives in dedicated DB tables — .env is reserved for boot-time infrastructure only.

Uninstall

sudo bash uninstall.sh   # stops services, removes files, optionally removes PostgreSQL/Redis/nginx

⚙️ System Requirements

Category Minimum Recommended
Compute 2-core CPU, 2 GB RAM Raspberry Pi 5 (8 GB) or x86 server
Storage 20 GB 50 GB+ SSD (alerts database grows over time)
OS Debian 12 / Ubuntu 22.04 Debian 13 (Trixie) · Raspberry Pi OS
Python 3.11 3.12 or 3.13
SDR (optional) RTL-SDR v3 Airspy R2/Mini · SDRplay
GPS (optional) any NMEA UART Uputronics MAX-M8Q HAT + PPS
GPIO (optional) any relay HAT Multi-relay HAT + USB sound card

Typical power draw at the reference Pi 5 build with SDR + GPS HAT: ~12 W. See requirements.txt for the full Python dependency list.


📈 Where the Project Is Today

Status Capability
✅ Done Multi-source CAP ingestion (NOAA, IPAWS, custom) with PostGIS targeting
✅ Done FCC Part 11 / NRSC-4-B SAME encoding with manual workflow and TTS narration
✅ Done SDR off-air verification with live waterfall and one-click IQ capture
✅ Done RBDS / RDS decoder with full Group 1A / 7A / 13A / 15B parsing
✅ Done MDC1200 / Quick-Call II / DTMF pre/post-alert signaling for LMR forwarding
✅ Done Stratum 1 GPS-disciplined time source + dedicated GPS & Time Dashboard
✅ Done Tamper-evident Ed25519-signed audit ledger with chain verification
✅ Done RBAC, TOTP MFA, scoped API keys, rate limiting, CSRF, HTTPS
✅ Done Automated RWT/RMT scheduling and EAS Compliance dashboard
✅ Done LED / OLED / VFD / NeoPixel / GPIO / Zigbee hardware integration
✅ Done Settings Hub, web diagnostics, one-button upgrade, journalctl viewer
🔄 In Progress Advanced relay control, multi-receiver coordination
⏳ Planned FCC Part 11 certification documentation track
⏳ Planned Time-series performance graphs on the GPS & Time dashboard
⏳ Planned Cloud sync, mobile app, multi-site coordination

See the Changelog and the feature roadmap in docs/roadmap/ for details.


📚 Documentation

Topic Link
Setup & Installation docs/guides/SETUP_INSTRUCTIONS
Quickstart docs/installation/QUICKSTART
SDR Configuration docs/hardware/SDR_SETUP
GPS HAT / Stratum 1 docs/hardware/GPS_HAT_SETUP
Hardware Quickstart docs/guides/HARDWARE_QUICKSTART
Alert Signals (MDC1200 / QC-II / DTMF) docs/guides/ALERT_SIGNALS
Audit Log Review docs/guides/AUDIT_LOG_REVIEW
MFA / TOTP Setup docs/guides/MFA_TOTP_SETUP
Icecast Streaming docs/guides/ICECAST_STREAMING_SETUP
Tailscale Setup docs/guides/TAILSCALE_SETUP
Daily Operations docs/guides/HELP
REST / JS API Reference docs/frontend/JAVASCRIPT_API
System Architecture docs/architecture/SYSTEM_ARCHITECTURE
Theory of Operation docs/architecture/THEORY_OF_OPERATION
SAME Protocol Reference docs/reference/protocols/SAME
MDC1200 Protocol Reference docs/reference/protocols/MDC1200
Developer Guide docs/development/AGENTS
Changelog docs/reference/CHANGELOG

🤝 Contributing

git clone https://github.com/KR8MER/eas-station.git
cd eas-station
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env   # edit with local DB settings
python app.py

See the Contributing Guide and the Code Standards. When bumping any dependency in requirements.txt, also update the matching badge above and the live footer partial at templates/partials/tech_stack_badges.html — the drift guard tests/test_tech_stack_badges.py will fail CI otherwise.


⚖️ Legal & Compliance

🚨 EAS Station™ generates valid SAME headers and attention tones. These signals will trigger downstream EAS equipment if coupled to any RF, STL, or streaming chain.

  • Not FCC-certified — for laboratory, research, and training use only.
  • Never connect to on-air infrastructure without explicit authorization.
  • Real operational semantics only — no fictional or entertainment use. EAS Station™ is built to emulate the actual behavior of certified EAS encoder/decoder equipment for research, training, and Part 97 amateur-radio experimentation. It is not a content-creation toolkit. Do not use it to author fictional or fabricated EAS workflows (invented event codes, mock CAP feeds presented as real, joke RWT/RMT cycles, "what-if" alert scenarios) and do not use its output in films, TV, trailers, advertising, podcasts, streaming, video games, livestream stunts, prank/creepypasta content, ARGs, or any other entertainment or media production. Labeling content as fiction does not cure the violation — 47 C.F.R. § 11.45 applies regardless of intent (see the Olympus Has Fallen trailer case below).
  • Unauthorized broadcast has real consequences: iHeartMedia paid a $1M settlement (2015); the Olympus Has Fallen trailer misuse cost $1.9M.
  • The maintainer will cooperate fully with authorities against any misuse.

See Terms of Use, Privacy Policy, FCC Compliance / About, and the Trademark Policy.


📜 License

EAS Station™ is dual-licensed:

Open Source — AGPL v3

Free to use, modify, and distribute under the GNU Affero General Public License v3. Modifications to network-deployed versions must be made available as source.

Commercial License

For proprietary or closed-source use without AGPL obligations — no source disclosure required, priority support, custom development assistance. See LICENSE-COMMERCIAL.

Copyright (c) 2025-2026 Timothy Kramer (KR8MER)
EAS Station™ — https://github.com/KR8MER/eas-station

Branding governed by the Trademark Policy. See NOTICE for required attribution details.


📚 Attributions & Open‑Source Credits

EAS Station™ stands on the shoulders of an enormous open‑source ecosystem. The badges at the top of this README are a curated highlight; this section is the exhaustive list of every third‑party library, system package, and CDN asset the project relies on. Each entry explains what role that library plays inside EAS Station™, not just what the upstream project is. Versions track requirements.txt and the system‑package install scripts in scripts/.

The drift guard tests/test_tech_stack_badges.py and the workflow .github/workflows/release-metadata.yml enforce that the curated badge subset in this README, in templates/partials/tech_stack_badges.html (the live page footer), and in requirements.txt stay aligned. Bumping a dependency means updating all three.

Python runtime, framework & extensions

Library Version License Purpose in EAS Station™ Project
Flask 3.1.2 BSD‑3‑Clause The web framework. Every dashboard, admin page, and JSON endpoint is a Flask route. https://flask.palletsprojects.com/
Werkzeug 3.1.4 BSD‑3‑Clause WSGI request/response plumbing under Flask — URL routing, cookies, exceptions, request parsing. https://werkzeug.palletsprojects.com/
Jinja2 3.1.6 BSD‑3‑Clause Server‑side HTML templates (templates/*.html), including the footer badge partial. https://jinja.palletsprojects.com/
itsdangerous 2.2.0 BSD‑3‑Clause Cryptographic signing for session cookies, CSRF tokens, and one‑use download URLs. https://itsdangerous.palletsprojects.com/
Flask‑SQLAlchemy 3.1.1 BSD‑3‑Clause Thin Flask integration over SQLAlchemy — wires the engine to the app and request scope. https://flask-sqlalchemy.palletsprojects.com/
Flask‑SocketIO 5.5.1 MIT Server side of the WebSocket layer that pushes live alert / radio / GPS updates to the dashboard. https://flask-socketio.readthedocs.io/
Flask‑WTF 1.2.2 BSD‑3‑Clause CSRF protection on every POST form and JSON endpoint. https://flask-wtf.readthedocs.io/
Flask‑Limiter 4.1.1 MIT Rate limiting on login, API key, and webhook endpoints (Redis or in‑memory backend). https://flask-limiter.readthedocs.io/
Flask‑Caching 2.3.1 BSD‑3‑Clause Response and view caching for expensive admin pages and read‑heavy JSON endpoints. https://flask-caching.readthedocs.io/
python‑socketio 5.15.0 MIT Core Socket.IO protocol implementation that Flask‑SocketIO builds on. https://python-socketio.readthedocs.io/

Database & ORM

Library Version License Purpose in EAS Station™ Project
SQLAlchemy 2.0.45 MIT ORM for every persisted entity — alerts, settings, audit logs, RBAC, GPS samples. https://www.sqlalchemy.org/
Alembic 1.17.2 MIT Schema migrations (app_core/migrations/versions/*); alembic upgrade head runs on install/update. https://alembic.sqlalchemy.org/
psycopg2‑binary 2.9.11 LGPL‑3.0 Sync PostgreSQL driver SQLAlchemy talks to. https://www.psycopg.org/
GeoAlchemy2 0.18.1 MIT SQLAlchemy types and ST_* function bindings for PostGIS geometry/geography columns. https://geoalchemy-2.readthedocs.io/
PostgreSQL 17 PostgreSQL Primary database (alerts, users, audit, configuration). https://www.postgresql.org/
PostGIS 3.4 GPL‑2.0+ Spatial extension — county/zone boundary matching, polygon containment, alert geo‑filtering. https://postgis.net/
greenlet 3.3.0 MIT / PSF Required for SQLAlchemy 2.0 sync I/O when running under the gevent worker. https://greenlet.readthedocs.io/

Caching, queueing & runtime servers

Component Version License Purpose in EAS Station™ Project
Redis (server) 7.1 RSAL/SSPL/AGPL (per upstream) Pub/sub bus between the web app and the SDR / hardware services; cache; rate‑limit store; capture registry; live spectrum + waterfall feed. https://redis.io/
redis (Python) 7.1.0 MIT Python client for the Redis server. https://github.com/redis/redis-py
hiredis 3.3.0 BSD‑3‑Clause C parser accelerator for redis‑py (faster pub/sub fan‑out). https://github.com/redis/hiredis-py
Gunicorn 23.0.0 MIT Production WSGI server fronting the Flask app. https://gunicorn.org/
gevent 25.9.1+ MIT Async worker class for Gunicorn so Flask‑SocketIO can hold thousands of concurrent WebSocket connections. https://www.gevent.org/
Nginx Alpine BSD‑2‑Clause Reverse proxy / TLS terminator / static file server in front of Gunicorn and Icecast. https://nginx.org/
systemd system LGPL‑2.1+ Process supervisor for eas-station, sdr_hardware_service, hardware_service, gps_manager, Icecast, Redis. https://systemd.io/
Let's Encrypt / Certbot Apache‑2.0 / ISRG Automated TLS certificate issuance and renewal for the public HTTPS endpoint. https://letsencrypt.org/

HTTP, serialization & utilities

Library Version License Purpose in EAS Station™ Project
requests 2.32.5 Apache‑2.0 Sync HTTP client used by the CAP/IPAWS pollers and most outbound integrations. https://requests.readthedocs.io/
httpx 0.28.1 BSD‑3‑Clause Modern async HTTP client with connection pooling for high‑throughput CAP fetches. https://www.python-httpx.org/
certifi 2025.11.12 MPL‑2.0 Up‑to‑date CA bundle for SSL verification (mandatory for IPAWS over TLS). https://github.com/certifi/python-certifi
feedparser 6.0.11 BSD‑2‑Clause Parses RSS/Atom feeds used by the LED‑sign news ticker. https://github.com/kurtmckee/feedparser
orjson 3.11.5 Apache‑2.0 / MIT Fast C‑backed JSON encoder/decoder for the live data feeds and Redis payloads. https://github.com/ijl/orjson
ujson 5.11.0 BSD‑3‑Clause Fallback fast JSON parser when orjson is unavailable. https://github.com/ultrajson/ultrajson
PyYAML 6.0.3 MIT Reads screen editor definitions and config templates. https://pyyaml.org/
lxml 6.0.2 BSD‑3‑Clause High‑performance XML parser for CAP alert ingestion (5–10× faster than stdlib). https://lxml.de/
mistune 3.1.4 BSD‑3‑Clause Renders the in‑app documentation viewer (/docs/*) from project markdown. https://mistune.lepture.com/
python‑dateutil 2.9.0.post0 Apache‑2.0 / BSD‑3 Robust parsing of CAP timestamp fields with mixed offsets and tz abbreviations. https://dateutil.readthedocs.io/
pytz 2025.2 MIT Time‑zone database for local display of alert effective/expire times and audit logs. https://pythonhosted.org/pytz/
python‑dotenv 1.2.1 BSD‑3‑Clause Loads .env configuration at startup. https://github.com/theskumar/python-dotenv
psutil 7.1.3 BSD‑3‑Clause System‑health snapshot: CPU/mem/disk/load/temperature shields and the System Health dashboard. https://github.com/giampaolo/psutil
openpyxl 3.1.5 MIT XLSX export of alert history and audit reports. https://openpyxl.readthedocs.io/

Audio, SDR & signal processing

Component Version License Purpose in EAS Station™ Project
NumPy 2.3.5 BSD‑3‑Clause Foundation for every IQ buffer, FM demod, FFT, and SAME bit slicer. Also drives the one‑click IQ capture (numpy.save to .npy). https://numpy.org/
SciPy 1.16.3 BSD‑3‑Clause DSP filter design (signal.lfilter, FIR/IIR design) for the interference notch, deemphasis, and channel filters. https://scipy.org/
Numba ≥ 0.61.0, < 0.64 BSD‑2‑Clause JIT‑compiles the inner SAME DLL and RBDS workers; ~6× faster real‑time demod on a Pi. https://numba.pydata.org/
pydub 0.25.1 MIT Decodes MP3/AAC/OGG Icecast streams for the EAS audio monitor. https://github.com/jiaaro/pydub
pyttsx3 2.99 MPL‑2.0 Offline TTS engine option for voice‑over narration of alert text. https://github.com/nateshmbhat/pyttsx3
audioop‑lts 0.2.2 Python‑2.0 Drop‑in replacement for audioop, removed from the Python 3.13 stdlib but still needed by pydub. https://github.com/AbstractUmbra/audioop
SoapySDR system BSL‑1.0 Vendor‑agnostic SDR abstraction layer driving RTL‑SDR, Airspy, and SDRplay receivers. https://github.com/pothosware/SoapySDR
Icecast 2.4.4 GPL‑2.0 Streams the demodulated FM/AM audio over HTTP for remote monitoring and stream‑profile mounts. https://icecast.org/
FFmpeg system LGPL‑2.1+ / GPL‑2+ Underlying codec backend that pydub shells out to for MP3/AAC decode/encode. https://ffmpeg.org/
eSpeak NG system GPL‑3.0 System TTS used to narrate CAP alert summaries into the SAME envelope. https://github.com/espeak-ng/espeak-ng

Hardware / I/O

Library Version License Purpose in EAS Station™ Project
pyserial 3.5 BSD‑3‑Clause Serial transport for the VFD display, RS‑232 LED signs, and UART NMEA GPS. https://github.com/pyserial/pyserial
gpiozero 2.0.1 BSD‑3‑Clause High‑level GPIO control for relay HATs, PTT lines, and transmitter keying. https://gpiozero.readthedocs.io/
rpi‑ws281x ≥ 0.0.5 MIT WS2812B / NeoPixel addressable LED strip driver (DMA‑backed on the Pi). https://github.com/rpi-ws281x/rpi-ws281x-python
luma.oled 3.14.0 MIT I2C SSD1306/SH1106 driver for the Argon OLED status panel. https://github.com/rm-hull/luma.oled
Pillow 12.0.0 MIT‑CMU Rasterizes glyphs and bitmaps for the VFD screen editor and OLED frames. https://python-pillow.org/
zigpy ≥ 0.60 GPL‑3.0 Core Zigbee protocol stack for optional wireless sensor / device control. https://github.com/zigpy/zigpy
zigpy‑znp ≥ 0.11 GPL‑3.0 TI Z‑Stack (CC2652P / CC1352P) radio driver under zigpy. https://github.com/zigpy/zigpy-znp
pynmea2 1.19.0 MIT Parses NMEA‑0183 sentences (GGA, GSA, GSV, RMC) from the GPS HAT. https://github.com/Knio/pynmea2

Timekeeping (stratum 1)

Component Version License Purpose in EAS Station™ Project
chrony system GPL‑2.0 NTP daemon that consumes the GPS NMEA + PPS edge as a kernel refclock; serves stratum 1 NTP. https://chrony-project.org/
gpsd system BSD‑2‑Clause Multiplexes the GPS UART so chrony, the dashboard, and the GPS dashboard can all read the fix simultaneously. https://gpsd.gitlab.io/gpsd/

Security / auth / notifications

Library Version License Purpose in EAS Station™ Project
PyOTP 2.9.0 MIT TOTP generation and verification for the MFA login flow. https://pyauth.github.io/pyotp/
cryptography ≥ 46.0.5 Apache‑2.0 / BSD‑3‑Clause Ed25519 signing and SHA‑256 hashing for the tamper‑evident audit_logs chain — every audit row is hash‑chained to its predecessor and signed so post‑hoc DB edits are detectable via AuditLogger.verify_chain(). https://cryptography.io/
qrcode 8.2 BSD‑3‑Clause Renders the QR code shown during MFA enrollment. https://github.com/lincolnloop/python-qrcode
Twilio ≥ 9.0 MIT SMS delivery for alert‑forwarding and compliance‑health notifications. https://www.twilio.com/
pysnmp ≥ 6.2 BSD‑2‑Clause Sends SNMP v2c traps when compliance health degrades (optional; gracefully absent). https://pysnmp.readthedocs.io/

Geospatial

Library Version License Purpose in EAS Station™ Project
pyshp 3.0.3 MIT Reads ESRI shapefiles when importing custom county/zone boundaries into PostGIS. https://github.com/GeospatialPython/pyshp
pyproj 3.7.1 MIT Reprojects shapefile CRSes to WGS84 during boundary import. https://pyproj4.github.io/pyproj/

Testing & QA

Library Version License Purpose in EAS Station™ Project
pytest 9.0.2 MIT Test runner for the whole suite (tests/). https://pytest.org/
pytest‑asyncio 1.3.0 Apache‑2.0 Lets async coroutines run as pytest test functions. https://pytest-asyncio.readthedocs.io/

Front‑end vendored / CDN assets

Library Version License Purpose in EAS Station™ Project
Bootstrap 5.3.0 MIT CSS grid + component library underlying every dashboard layout. https://getbootstrap.com/
Font Awesome (Free) 6.4.0 CC BY 4.0 / SIL OFL / MIT Icon set used throughout navigation, status pills, and badges. https://fontawesome.com/
Leaflet 1.9.4 BSD‑2‑Clause Interactive maps for alert polygons, coverage zones, and county boundaries. https://leafletjs.com/
Chart.js 3.9.1 MIT Time‑series charts on the Analytics, System Health, and GPS dashboards. https://www.chartjs.org/
Socket.IO client 4.5.4 MIT Browser WebSocket client that receives the live alert / radio / GPS push updates. https://socket.io/
jsPDF + html2canvas latest MIT Client‑side PDF export of the full Statistics dashboard. https://github.com/parallax/jsPDF
Mermaid latest MIT In‑browser rendering of architecture and data‑flow diagrams in the docs viewer. https://mermaid.js.org/

Data sources & boundary data

NOAA/NWS CAP API · FEMA IPAWS · U.S. Census Bureau (TIGER/Line) · PostGIS Team · Putnam County GIS · Allen County GIS

License identifiers above are best‑effort summaries — always consult the upstream project's own licensing files for the canonical terms. If you spot a discrepancy or a missing attribution, please open an issue.


🙏 Acknowledgments

NOAA/NWS · FEMA/IPAWS · PostGIS Team · U.S. Census Bureau (TIGER/Line) · Putnam County GIS Office · Allen County GIS Office · Flask Community · RTL-SDR Project · W0CHP (chrogps-dash visual reference) · Amateur Radio Community

Resource Link
NOAA CAP API https://www.weather.gov/documentation/services-web-api
FEMA IPAWS https://www.fema.gov/emergency-managers/practitioners/integrated-public-alert-warning-system
FCC Part 11 https://www.ecfr.gov/current/title-47/chapter-I/subchapter-A/part-11
PostGIS Docs https://postgis.net/documentation/

Made with ☕ and 📻 for Amateur Radio Emergency Communications
73 de KR8MER 📡