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())