2025-10-14 16:45:50 +08:00
|
|
|
|
// main.cpp
|
|
|
|
|
|
|
2025-10-14 11:18:01 +08:00
|
|
|
|
#include "network/tcp_server.h"
|
|
|
|
|
|
#include "mqtt/mqtt_client.h"
|
|
|
|
|
|
#include "mqtt/mqtt_router.h"
|
|
|
|
|
|
#include "systemMonitor/system_monitor.h"
|
2025-09-30 18:34:50 +08:00
|
|
|
|
#include "spdlog/spdlog.h"
|
2025-10-14 18:10:15 +08:00
|
|
|
|
#include "deviceManager/device_manager.h"
|
|
|
|
|
|
#include "dataCache/data_cache.h"
|
|
|
|
|
|
#include "dataCache/cache_uploader.h"
|
2025-10-14 16:06:43 +08:00
|
|
|
|
|
2025-09-30 18:34:50 +08:00
|
|
|
|
#include <boost/asio.hpp>
|
2025-10-14 16:45:50 +08:00
|
|
|
|
#include <boost/asio/steady_timer.hpp>
|
2025-10-11 18:24:56 +08:00
|
|
|
|
#include <csignal>
|
2025-09-30 18:34:50 +08:00
|
|
|
|
#include <iostream>
|
2025-10-14 16:45:50 +08:00
|
|
|
|
#include <functional>
|
2025-09-30 18:34:50 +08:00
|
|
|
|
|
2025-10-13 13:55:15 +08:00
|
|
|
|
// 用于 ASIO 服务的全局 io_context
|
2025-10-11 18:24:56 +08:00
|
|
|
|
boost::asio::io_context g_io_context;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-10-13 13:55:15 +08:00
|
|
|
|
* @brief 处理终止信号 (SIGINT, SIGTERM).
|
2025-10-11 18:24:56 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void signalHandler(int signum) {
|
|
|
|
|
|
spdlog::warn("Interrupt signal ({}) received. Shutting down.", signum);
|
|
|
|
|
|
g_io_context.stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-14 16:45:50 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 周期性轮询系统状态并发布到 MQTT
|
|
|
|
|
|
*/
|
2025-10-14 11:18:01 +08:00
|
|
|
|
void poll_system_metrics(
|
|
|
|
|
|
boost::asio::steady_timer& timer,
|
|
|
|
|
|
SystemMonitor::SystemMonitor& monitor,
|
|
|
|
|
|
MqttClient& mqtt_client
|
|
|
|
|
|
) {
|
2025-10-14 18:10:15 +08:00
|
|
|
|
// ... 此函数内部逻辑保持不变 ...
|
2025-10-14 16:45:50 +08:00
|
|
|
|
auto cpu_util = monitor.getCpuUtilization();
|
2025-10-14 11:18:01 +08:00
|
|
|
|
auto mem_info = monitor.getMemoryInfo();
|
|
|
|
|
|
double mem_total_gb = mem_info.total_kb / 1024.0 / 1024.0;
|
2025-10-14 16:45:50 +08:00
|
|
|
|
|
2025-10-14 11:18:01 +08:00
|
|
|
|
std::string topic = "proxy/system_status";
|
2025-10-14 16:45:50 +08:00
|
|
|
|
std::string payload = "{\"cpu_usage\":" + std::to_string(cpu_util.totalUsagePercentage) +
|
2025-10-14 11:18:01 +08:00
|
|
|
|
",\"mem_total_gb\":" + std::to_string(mem_total_gb) + "}";
|
|
|
|
|
|
mqtt_client.publish(topic, payload);
|
|
|
|
|
|
spdlog::debug("System metrics published.");
|
|
|
|
|
|
|
|
|
|
|
|
timer.expires_at(timer.expiry() + std::chrono::seconds(15));
|
|
|
|
|
|
timer.async_wait(std::bind(poll_system_metrics, std::ref(timer), std::ref(monitor), std::ref(mqtt_client)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-11 18:24:56 +08:00
|
|
|
|
int main(int argc, char* argv[]) {
|
2025-10-13 10:34:20 +08:00
|
|
|
|
|
2025-10-11 18:24:56 +08:00
|
|
|
|
try {
|
2025-10-14 16:45:50 +08:00
|
|
|
|
spdlog::set_level(spdlog::level::debug);
|
2025-10-11 18:24:56 +08:00
|
|
|
|
spdlog::info("Edge Proxy starting up...");
|
|
|
|
|
|
} catch (const spdlog::spdlog_ex& ex) {
|
|
|
|
|
|
std::cerr << "Log initialization failed: " << ex.what() << std::endl;
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
signal(SIGINT, signalHandler);
|
|
|
|
|
|
signal(SIGTERM, signalHandler);
|
|
|
|
|
|
|
2025-10-11 14:06:38 +08:00
|
|
|
|
try {
|
2025-10-14 16:45:50 +08:00
|
|
|
|
// --- 1. 初始化核心服务 ---
|
2025-10-13 13:55:15 +08:00
|
|
|
|
MqttClient mqtt_client("tcp://mqtt-broker:1883", "edge-proxy-main-client");
|
|
|
|
|
|
MqttRouter mqtt_router(mqtt_client);
|
2025-10-14 15:29:13 +08:00
|
|
|
|
std::vector<uint16_t> listen_ports = { 8888 };
|
2025-10-14 14:30:52 +08:00
|
|
|
|
TCPServer tcp_server(g_io_context, listen_ports, mqtt_client);
|
2025-10-14 11:18:01 +08:00
|
|
|
|
SystemMonitor::SystemMonitor monitor;
|
2025-10-13 13:55:15 +08:00
|
|
|
|
|
2025-10-14 18:10:15 +08:00
|
|
|
|
// <<< MODIFIED: 初始化数据缓存和上传器 >>>
|
|
|
|
|
|
DataCache data_cache;
|
|
|
|
|
|
if (!data_cache.open("edge_data_cache.db")) { // 数据库文件将创建在程序运行目录
|
|
|
|
|
|
spdlog::critical("Failed to initialize data cache. Exiting.");
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
CacheUploader cache_uploader(g_io_context, mqtt_client, data_cache);
|
|
|
|
|
|
|
|
|
|
|
|
// <<< MODIFIED: 设置MQTT连接成功的回调,用于触发断点续传 >>>
|
|
|
|
|
|
mqtt_client.set_connected_handler([&](const std::string& cause){
|
|
|
|
|
|
spdlog::info("MQTT client connected: {}", cause);
|
|
|
|
|
|
// 当连接成功时,启动缓存上传
|
|
|
|
|
|
cache_uploader.start_upload();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 现在再连接MQTT
|
2025-10-14 11:18:01 +08:00
|
|
|
|
mqtt_client.connect();
|
2025-10-13 13:55:15 +08:00
|
|
|
|
mqtt_router.start();
|
|
|
|
|
|
|
2025-10-14 16:45:50 +08:00
|
|
|
|
// --- 2. 启动系统状态监控定时器 ---
|
|
|
|
|
|
monitor.getCpuUtilization(); // 首次调用以初始化
|
|
|
|
|
|
boost::asio::steady_timer system_monitor_timer(g_io_context, std::chrono::seconds(15));
|
|
|
|
|
|
system_monitor_timer.async_wait(std::bind(poll_system_metrics, std::ref(system_monitor_timer), std::ref(monitor), std::ref(mqtt_client)));
|
2025-10-14 11:18:01 +08:00
|
|
|
|
|
2025-10-14 18:10:15 +08:00
|
|
|
|
// --- 3. <<< MODIFIED: 创建包含缓存逻辑的统一数据上报回调函数 >>>
|
2025-10-14 15:29:13 +08:00
|
|
|
|
auto report_to_mqtt = [&](const UnifiedData& data) {
|
2025-10-14 18:10:15 +08:00
|
|
|
|
if (mqtt_client.is_connected()) {
|
|
|
|
|
|
// 网络正常,直接上报
|
|
|
|
|
|
std::string topic = "devices/" + data.device_id + "/data";
|
|
|
|
|
|
g_io_context.post([&, topic, payload = data.data_json]() {
|
|
|
|
|
|
mqtt_client.publish(topic, payload, 1, false);
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 网络断开,写入缓存
|
|
|
|
|
|
spdlog::warn("MQTT disconnected. Caching data for device '{}'.", data.device_id);
|
|
|
|
|
|
data_cache.add(data);
|
|
|
|
|
|
}
|
2025-10-14 16:06:43 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-14 18:10:15 +08:00
|
|
|
|
// --- 4. 实例化设备管理器并从文件加载所有设备 (使用新的回调) ---
|
2025-10-14 16:45:50 +08:00
|
|
|
|
DeviceManager device_manager(g_io_context, report_to_mqtt);
|
|
|
|
|
|
// 默认从程序运行目录下的 "devices.json" 文件加载
|
|
|
|
|
|
device_manager.load_and_start("../config/devices.json");
|
2025-10-14 15:29:13 +08:00
|
|
|
|
|
2025-10-14 16:45:50 +08:00
|
|
|
|
// --- 5. 启动主事件循环 (程序将阻塞在这里直到被信号中断) ---
|
2025-10-13 13:55:15 +08:00
|
|
|
|
spdlog::info("All services are running. Press Ctrl+C to exit.");
|
2025-10-11 18:24:56 +08:00
|
|
|
|
g_io_context.run();
|
|
|
|
|
|
|
2025-10-14 16:45:50 +08:00
|
|
|
|
// --- 清理工作 ---
|
2025-10-13 13:55:15 +08:00
|
|
|
|
spdlog::info("Shutting down MQTT client...");
|
|
|
|
|
|
mqtt_client.disconnect();
|
|
|
|
|
|
|
2025-10-11 18:24:56 +08:00
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
|
|
spdlog::critical("An unhandled exception occurred: {}", e.what());
|
|
|
|
|
|
return 1;
|
2025-09-30 18:34:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-11 18:24:56 +08:00
|
|
|
|
spdlog::info("Server has been shut down gracefully. Exiting.");
|
2025-09-30 18:34:50 +08:00
|
|
|
|
return 0;
|
2025-10-14 16:45:50 +08:00
|
|
|
|
}
|