#include "app/lidar_manager_app.hpp" #include "auth/auth_service.hpp" #include "mission/mission_enqueue.hpp" #include "mission/mission_queue.hpp" #include "mission/mission_scheduler.hpp" #include "mission/mission_store.hpp" #include "mission/modbus_trigger_service.hpp" #include "robot/robot_runtime.hpp" #include "server/api_server.hpp" #include "server/static_file_server.hpp" #include "storage/dashboard_store.hpp" #include "storage/database.hpp" #include "storage/map_store.hpp" #include "storage/site_store.hpp" #include "storage/sound_store.hpp" #include "storage/transition_store.hpp" #include "storage/state_repository.hpp" #include #include namespace lm { namespace { bool isProjectRootDataPath(const std::filesystem::path& parent) { return parent.empty() || parent == std::filesystem::path("."); } std::filesystem::path resolveDataPath(std::filesystem::path data_path) { if (!isProjectRootDataPath(data_path.parent_path())) return data_path; if (data_path.filename() == "state.json") return std::filesystem::path("data") / "state.json"; return std::filesystem::path("data") / "RBS.db"; } } // namespace LidarManagerApp::LidarManagerApp(int port, std::filesystem::path www_root, std::filesystem::path data_path) : port_(port), www_root_(std::move(www_root)), data_path_(std::move(data_path)) { } int LidarManagerApp::run() { data_path_ = resolveDataPath(data_path_); const std::filesystem::path data_dir = data_path_.parent_path(); Database database(data_dir); std::string db_err; if (!database.init(db_err)) { std::fprintf(stderr, "database init failed: %s\n", db_err.c_str()); return 1; } StateRepository repo(data_path_, database); repo.load(); MapStore map_store(database); TransitionStore transition_store(database); MissionStore mission_store(database); MissionQueue mission_queue(database, map_store, transition_store, mission_store); RobotRuntime robot_runtime(database, mission_queue); SiteStore site_store(database); site_store.ensureDefaultSiteId(); SoundStore sound_store(database); { std::string sound_err; if (!sound_store.ensureSystemDefaults(sound_err)) std::fprintf(stderr, "Warning: sound defaults: %s\n", sound_err.c_str()); } DashboardStore dashboard_store(database); const auto enqueue_fn = [&mission_store, &mission_queue](const nlohmann::json& request, std::string& err) -> bool { nlohmann::json payload; if (!MissionEnqueue::buildPayload(mission_store, request, payload, err)) return false; return static_cast(mission_queue.enqueue(payload, err)); }; ModbusTriggerService modbus(mission_store, enqueue_fn, 5502); MissionScheduler scheduler(mission_store, enqueue_fn); AuthService auth(database); httplib::Server svr; svr.set_pre_routing_handler([&auth](const httplib::Request& req, httplib::Response& res) { return auth.preRoute(req, res); }); ApiServer api(repo, mission_queue, mission_store, modbus, scheduler, robot_runtime, map_store, site_store, sound_store, transition_store, dashboard_store); api.registerRoutes(svr); auth.registerRoutes(svr); StaticFileServer::mount(svr, www_root_); std::fprintf(stderr, "lidar_manager_web listening on http://0.0.0.0:%d (www=%s, db=%s, maps=%s, sounds=%s)\n", port_, www_root_.string().c_str(), database.dbPath().string().c_str(), database.mapsDir().string().c_str(), database.soundsDir().string().c_str()); std::fprintf(stderr, "MiR REST API: http://0.0.0.0:%d/api/v2.0.0/mission_queue\n", port_); std::fprintf(stderr, "Modbus TCP triggers: port 5502 (coils 1001-2000)\n"); svr.listen("0.0.0.0", port_); return 0; } } // namespace lm