Skip to content

dgarcoe/QuendAward

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

201 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸŽ™οΈ QuendAward

Special Callsign Operator Coordination Tool for Ham Radio

A web application for coordinating multiple operators activating the same special callsign. Avoid conflicts by blocking band/mode combinations in real-time.

Streamlit Python License


✨ Features

Feature Description
πŸ“Š Real-time Heatmap Interactive visualization of band/mode availability
πŸ”’ Band/Mode Blocking Reserve combinations while you're active
πŸ’¬ Real-time Chat MQTT-powered instant messaging between operators (no page refresh)
πŸ“‘ DX Cluster Spotting Send spots to DX Cluster nodes via Telnet to announce activity
πŸ“’ Announcements Admin announcements with notification badges
πŸ† Multi-Award Support Manage multiple special callsigns/events
🌍 Multi-Language English, Spanish, Galician
πŸ“± Mobile-Friendly Responsive design for smartphones
πŸ‘₯ Multi-Operator Secure authentication for teams
πŸ’Ύ Backup/Restore Database management for admins
πŸ€– Telegram Bot Block/unblock bands and receive notifications via Telegram

πŸš€ Quick Start

Docker (Recommended)

# Clone and configure
git clone <repository-url>
cd award_planner
cp .env.example .env
# Edit .env with your admin credentials

# Run
docker-compose up -d

# Access at http://localhost:8501

Manual Installation

pip install -r requirements.txt
export ADMIN_CALLSIGN=EA1RFI
export ADMIN_PASSWORD=YourSecurePassword
streamlit run app.py

βš™οΈ Configuration

Variable Description Required
ADMIN_CALLSIGN Super admin callsign Yes
ADMIN_PASSWORD Super admin password Yes
DATABASE_PATH SQLite database path No (default: ham_coordinator.db)
MQTT_WS_URL MQTT WebSocket URL for real-time chat (e.g. wss://yourdomain.com/mqtt) No (chat disabled when unset)
MQTT_BROKER_HOST MQTT broker hostname (internal) No (default: mosquitto)
MQTT_BROKER_PORT MQTT broker port (internal) No (default: 1883)
DX_CLUSTER_HOST DX Cluster node hostname (e.g. dxfun.com) No (spotting disabled when unset)
DX_CLUSTER_PORT DX Cluster Telnet port No (default: 7300)
DX_CLUSTER_CALLSIGN Callsign used to log in to the cluster No
DX_CLUSTER_PASSWORD Password for cluster authentication (if required) No
TELEGRAM_BOT_TOKEN Telegram bot API token from @BotFather No (bot disabled when unset)

πŸ’¬ Real-time Chat

QuendAward includes a real-time chat system powered by MQTT over WebSockets. Messages are delivered instantly between operators β€” no page refresh needed.

How it works

Browser A ──(MQTT/WS)──► Mosquitto Broker ──(MQTT/WS)──► Browser B
                                β”‚
                         Python subscriber ──► SQLite (history)
  • Mosquitto MQTT broker runs as a Docker sidecar, handling pub/sub routing
  • mqtt.js in the browser connects via WebSocket for instant message delivery
  • A Python MQTT subscriber thread persists messages to SQLite for chat history
  • Chat rooms are per-award β€” each special callsign has its own channel

Enabling chat

Set the MQTT_WS_URL environment variable to enable the chat tab:

# In .env
MQTT_WS_URL=wss://yourdomain.com/mqtt

When MQTT_WS_URL is not set, the chat tab is hidden and no MQTT connections are made. The nginx config included in the standalone deployment already proxies /mqtt to Mosquitto's WebSocket port.


πŸ“‘ DX Cluster Spotting

Operators can send spots to a DX Cluster node directly from the activity dashboard, announcing that a special callsign is active on a specific frequency.

How it works

  1. An operator blocks a band/mode on the heatmap (spotting requires an active block)
  2. The DX Cluster Spot section appears below the heatmap with band/mode autofilled from the block
  3. The operator enters the spotted callsign, frequency, and an optional comment
  4. QuendAward connects to the configured DX Cluster node via Telnet and sends the spot command
DX de EA1RFI:    14025.0  EG90IARU     QRV CW                        1423Z
     └─ cluster login      └─ spotted    └─ comment

Configuration

Set the following environment variables to enable spotting:

# In .env
DX_CLUSTER_HOST=dxfun.com
DX_CLUSTER_PORT=8000
DX_CLUSTER_CALLSIGN=EA1RFI
DX_CLUSTER_PASSWORD=           # Only if the cluster requires authentication

When DX_CLUSTER_HOST is not set, the send button shows a configuration error. The spot section is always visible but requires an active block to use. Clusters that require password authentication after the callsign login are supported via the optional DX_CLUSTER_PASSWORD variable.


πŸ€– Telegram Bot

QuendAward includes an optional Telegram bot that allows operators to manage band/mode blocks and receive real-time notifications directly from Telegram.

Features

  • Link operator accounts to Telegram via /link command
  • Block/unblock bands interactively with inline keyboards
  • View current blocks for your selected award
  • Real-time notifications when other operators block, unblock, or switch bands
  • Chat mention alerts when someone @mentions you in the web chat
  • Multi-language support (English, Spanish, Galician)
  • Per-user settings for default award, notifications, and language

Setup

  1. Create a Telegram bot:

    • Open Telegram and message @BotFather
    • Send /newbot and follow the prompts
    • Copy the bot token (looks like 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
  2. Configure the bot token:

    # In .env
    TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
  3. Run the bot (via Docker Compose or manually):

    # Included automatically in docker-compose up
    # OR manually:
    python services/telegram_bot.py

Using the bot

  1. Link your account: Open your bot on Telegram and send:

    /link <your_callsign> <your_password>
    
  2. Set your default award:

    /awards              # List available awards
    /setaward <id>       # Set your default award
    
  3. Manage blocks:

    /block               # Interactive block selection
    /myblocks            # View your blocks
    /unblock             # Release all your blocks
    /blocks              # View all blocks for current award
    
  4. Configure preferences:

    /notifications on    # Enable notifications
    /lang en             # Set language (en/es/gl)
    /status              # View your settings
    

How notifications work

When linked operators have notifications enabled:

  • Get notified when other operators block, unblock, or switch bands in your default award
  • Receive alerts when someone @mentions your callsign in the web chat
  • Notifications respect your language preference

Set your default award with /setaward <id> to receive relevant block notifications for that special callsign.


πŸ“ Project Structure

award_planner/
β”œβ”€β”€ app.py               # Main application entry point
β”œβ”€β”€ config.py            # Configuration constants
β”œβ”€β”€ database.py          # Database compatibility layer
β”œβ”€β”€ Dockerfile
β”‚
β”œβ”€β”€ core/                # Core modules
β”‚   β”œβ”€β”€ database.py      # SQLite connection & schema
β”‚   └── auth.py          # Authentication & password hashing
β”‚
β”œβ”€β”€ features/            # Feature modules
β”‚   β”œβ”€β”€ announcements.py # Admin announcements
β”‚   β”œβ”€β”€ awards.py        # Special callsign management
β”‚   β”œβ”€β”€ blocks.py        # Band/mode blocking logic
β”‚   β”œβ”€β”€ chat.py          # Chat message persistence
β”‚   β”œβ”€β”€ dx_cluster.py    # DX Cluster Telnet spotting
β”‚   └── backup.py        # Database backup/restore
β”‚
β”œβ”€β”€ services/            # Background services
β”‚   └── mqtt_subscriber.py  # MQTT listener for chat persistence
β”‚
β”œβ”€β”€ ui/                  # User interface components
β”‚   β”œβ”€β”€ admin_panel.py   # Admin panel tabs
β”‚   β”œβ”€β”€ components.py    # Reusable UI components
β”‚   β”œβ”€β”€ charts.py        # Plotly visualizations
β”‚   β”œβ”€β”€ chat_widget.py   # Real-time chat (HTML/JS/CSS)
β”‚   └── styles.py        # Responsive CSS/JS
β”‚
β”œβ”€β”€ i18n/                # Internationalization
β”‚   └── translations.py  # Translations (EN/ES/GL)
β”‚
β”œβ”€β”€ mosquitto/           # MQTT broker config
β”‚   └── config/
β”‚       └── mosquitto.conf
β”‚
β”œβ”€β”€ nginx/               # Reverse proxy config
β”‚   └── nginx.conf
β”‚
β”œβ”€β”€ docker-compose.yml
└── docker-compose-standalone.yml

πŸ“» Supported Bands & Modes

Bands: 160m, 80m, 60m, 40m, 30m, 20m, 17m, 15m, 12m, 10m, 8m, 6m, 2m, 70cm, SAT

Modes: SSB, CW, FT8, FT4, RTTY


πŸ” User Roles

Role Capabilities
Super Admin Full access, configured via environment variables
Admin Create operators, manage awards, announcements
Operator Block/unblock bands, view dashboard, chat

πŸ“– Usage

For Admins

  1. Login with admin credentials
  2. Create Operators: Admin Panel β†’ Create Operator
  3. Create Awards: Admin Panel β†’ Special Callsigns
  4. Post Announcements: Admin Panel β†’ Announcements

For Operators

  1. Login with provided credentials
  2. Select the active award/special callsign
  3. Click on heatmap cells to block/unblock
  4. Check πŸ”” for announcements
  5. Use the πŸ’¬ Chat tab to communicate with other operators in real time

🌍 Languages

  • πŸ‡¬πŸ‡§ English
  • πŸ‡ͺπŸ‡Έ EspaΓ±ol
  • πŸ‡¬πŸ‡± Galego (default)

Select language on the login page.


πŸ“„ License

This project is licensed under the GNU General Public License v3.0 (GPLv3).

See LICENSE for details.


πŸ‘¨β€πŸ’» Author

Daniel GarcΓ­a Coego (EA1RFI)


🀝 Contributing

Contributions welcome! Please open an issue or pull request.

About

Tool to help coordination in teams for ham radio awards

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors