bonus-edge-proxy/src/web/web_server.cc

157 lines
4.8 KiB
C++

// 文件名: src/web/web_server.cc
#include "web_server.h"
#include <fstream>
#include <sstream>
#include "config/config_manager.h"
#include "spdlog/spdlog.h"
WebServer::WebServer(SystemMonitor::SystemMonitor& monitor,
DeviceManager& deviceManager, LiveDataCache& liveDataCache,
AlarmService& alarm_service, uint16_t port)
: crow::Crow<crow::CORSHandler>(),
m_monitor(monitor),
m_device_manager(deviceManager),
m_live_data_cache(liveDataCache),
m_alarm_service(alarm_service),
m_port(port) {
auto& cors = this->get_middleware<crow::CORSHandler>();
cors.global()
.origin("*")
.headers("Content-Type", "Authorization")
.methods("GET"_method, "POST"_method, "OPTIONS"_method);
this->loglevel(crow::LogLevel::Warning);
setup_routes();
}
WebServer::~WebServer() { stop(); }
void WebServer::start() {
if (m_thread.joinable()) {
spdlog::warn("Web server is already running.");
return;
}
m_thread = std::thread([this]() {
spdlog::info("Starting Web server on port {}", m_port);
this->bindaddr("0.0.0.0").port(m_port).run();
spdlog::info("Web server has stopped.");
});
}
void WebServer::stop() {
crow::Crow<crow::CORSHandler>::stop();
if (m_thread.joinable()) {
m_thread.join();
}
}
void WebServer::setup_routes() {
CROW_ROUTE((*this), "/api/system/id").methods("GET"_method)([this] {
auto deviceID = ConfigManager::getInstance().getDeviceID();
crow::json::wvalue response;
response["deviceID"] = deviceID;
return response;
});
CROW_ROUTE((*this), "/api/system/status").methods("GET"_method)([this] {
auto cpu_util = m_monitor.getCpuUtilization();
auto mem_info = m_monitor.getMemoryInfo();
crow::json::wvalue response;
response["cpu_usage_percentage"] = cpu_util.totalUsagePercentage;
response["memory_total_kb"] = mem_info.total_kb;
response["memory_free_kb"] = mem_info.available_kb;
response["memory_usage_percentage"] =
(mem_info.total_kb > 0)
? (1.0 -
static_cast<double>(mem_info.available_kb) / mem_info.total_kb) *
100.0
: 0.0;
return response;
});
CROW_ROUTE((*this), "/api/devices").methods("GET"_method)([this] {
auto devices_info = m_device_manager.get_all_device_info();
std::vector<crow::json::wvalue> devices_json;
for (const auto& info : devices_info) {
crow::json::wvalue device_obj;
device_obj["id"] = info.id;
device_obj["type"] = info.type;
device_obj["is_running"] = info.is_running;
crow::json::wvalue details_obj;
for (const auto& pair : info.connection_details) {
details_obj[pair.first] = pair.second;
}
device_obj["connection_details"] = std::move(details_obj);
devices_json.push_back(std::move(device_obj));
}
return crow::json::wvalue(devices_json);
});
CROW_ROUTE((*this), "/api/data/latest").methods("GET"_method)([this] {
auto latest_data_map = m_live_data_cache.get_all_data();
crow::json::wvalue response;
for (const auto& pair : latest_data_map) {
response[pair.first] = crow::json::load(pair.second);
}
return response;
});
CROW_ROUTE((*this), "/api/alarms/active").methods("GET"_method)([this] {
try {
auto json_string = m_alarm_service.getActiveAlarmsJson().dump();
auto res = crow::response(200, json_string);
res.set_header("Content-Type", "application/json");
return res;
} catch (const std::exception& e) {
spdlog::error("Error processing /api/alarms/active: {}", e.what());
crow::json::wvalue error_resp;
error_resp["error"] = "Failed to retrieve active alarms.";
auto res = crow::response(500, error_resp.dump());
res.set_header("Content-Type", "application/json");
return res;
}
});
CROW_ROUTE((*this), "/api/alarms/history")
.methods("GET"_method)([this](const crow::request& req) {
int limit = 100;
if (req.url_params.get("limit")) {
try {
limit = std::stoi(req.url_params.get("limit"));
} catch (const std::exception&) { /* ignore invalid */
}
}
if (limit <= 0) limit = 100;
try {
auto json_string = m_alarm_service.getAlarmHistoryJson(limit).dump();
auto res = crow::response(200, json_string);
res.set_header("Content-Type", "application/json");
return res;
} catch (const std::exception& e) {
spdlog::error("Error processing /api/alarms/history: {}", e.what());
crow::json::wvalue error_resp;
error_resp["error"] = "Failed to retrieve alarm history.";
auto res = crow::response(500, error_resp.dump());
res.set_header("Content-Type", "application/json");
return res;
}
});
}