MeshDD-Bot/main.py
ppfeiffer 0ca0ffb0d1 feat: NINA BBK Warn-App Integration (v0.8.0)
Neue NINA-Integration: Automatisches Polling der BBK-Warn-API
(warnung.bund.de/api31) und Weiterleitung von Warnmeldungen ins
Meshtastic-Netz. Separate Admin-Konfigurationsseite (/nina) analog
zum Scheduler.

- meshbot/nina.py: NinaBot – Polling, De-Duplikation, Schweregrad-
  und Quellen-Filterung, WebSocket-Broadcast (nina_alert)
- nina.yaml + conf/nina.yaml: Hot-reload-faehige Konfiguration
- static/nina.html + static/js/nina.js: Konfigurationsseite mit
  AGS-Code-Verwaltung, Quellen-Auswahl und Live-Alerts-Tabelle
- webserver.py: GET/PUT /api/nina/config + GET /nina (Admin-only)
- main.py: NinaBot initialisieren, watch/start/stop im Lifecycle
- app.js: NINA-Sidebar-Eintrag (Admin-only, shield-exclamation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 11:21:01 +01:00

84 lines
2.1 KiB
Python

import asyncio
import logging
import signal
import threading
from meshbot import config
from meshbot.database import Database
from meshbot.bot import MeshBot
from meshbot.nina import NinaBot
from meshbot.scheduler import Scheduler
from meshbot.webserver import WebServer, WebSocketManager
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
async def main():
logger.info("Starting %s v%s", config.get("bot.name"), config.get("version"))
# Database
db = Database(config.get("database.path", "meshdd.db"))
await db.connect()
# WebSocket Manager
ws_manager = WebSocketManager()
# Bot
loop = asyncio.get_event_loop()
bot = MeshBot(db, loop)
bot.ws_manager = ws_manager
# Scheduler
scheduler = Scheduler(bot, ws_manager)
# NINA
nina = NinaBot(bot.send_message, ws_manager)
# Webserver
webserver = WebServer(db, ws_manager, bot, scheduler, nina)
runner = await webserver.start(config.get("web.host", "0.0.0.0"), config.get("web.port", 8080))
# Connect Meshtastic in a thread (blocking call)
connect_thread = threading.Thread(target=bot.connect, daemon=True)
connect_thread.start()
# Watch config for changes
asyncio.create_task(config.watch())
# Scheduler tasks
asyncio.create_task(scheduler.watch())
asyncio.create_task(scheduler.run())
# NINA tasks
asyncio.create_task(nina.watch())
await nina.start()
# Wait for shutdown
stop_event = asyncio.Event()
def _signal_handler():
logger.info("Shutdown signal received")
stop_event.set()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, _signal_handler)
try:
await stop_event.wait()
finally:
logger.info("Shutting down...")
await nina.stop()
bot.disconnect()
await ws_manager.close_all()
await runner.cleanup()
await db.close()
logger.info("Shutdown complete")
if __name__ == "__main__":
asyncio.run(main())