新增复合管控器(pCCU) + 惯导数据解析 + 设备控制页增强 + 0824协议文档归档
- 新增 pCCU 复合管控器程序(src/pCCU):FC/PM 双链路(UDP)、协议编解码器 (FcProtocol/PmProtocol/Frame/Message/MessageRegistry)、快照与落库(DbStore)、 内置 WebServer;挂入 src/CMakeLists.txt 与板卡 mission(h100.moos) - 惯导/深度数据:新增 uDevice_insData 消息解析,接入 UpperCommManager, pPowerMangerHost 注册监视,UpmsgTest 覆盖 - pPowerMangerHost 设备控制页增强(web/index.html) - 部署/运维脚本改为 4 个 systemd 服务(moosdb/pPowerManger/pPowerMangerHost/pCCU): deploy/clean-data/fetch-data 同步适配 - 协议文档:归档 0824 控制主机与复合管控器通信协议 xlsx 及关联 docx,移除旧 md - 测试:新增 pccu 单元/集成测试与 disSysTest Python 配电仿真 - 清理:移除未使用的 CCU 状态调试打印 coutMsg;.gitignore 补充编译产物/临时文件忽略
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#include "WebServer.h"
|
||||
#include "pages/index.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace ccu {
|
||||
|
||||
//---------------------------------------------------------
|
||||
// 事件处理:HTTP 路由 + WebSocket 收发
|
||||
|
||||
void WebServer::handleEvent(struct mg_connection* c, int ev, void* ev_data) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message* hm = (struct mg_http_message*)ev_data;
|
||||
|
||||
// WebSocket 升级
|
||||
if (mg_match(hm->uri, mg_str("/ws"), NULL)) {
|
||||
mg_ws_upgrade(c, hm, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// /api/* 接口:交给宿主程序处理,返回 JSON
|
||||
std::string path(hm->uri.buf, hm->uri.len);
|
||||
if (path.rfind("/api/", 0) == 0) {
|
||||
std::string body;
|
||||
if (m_apiHandler) {
|
||||
std::string query(hm->query.buf, hm->query.len);
|
||||
body = m_apiHandler(path, query);
|
||||
}
|
||||
if (!body.empty()) {
|
||||
mg_http_reply(c, 200, "Content-Type: application/json\r\n",
|
||||
"%.*s", (int)body.size(), body.c_str());
|
||||
} else {
|
||||
mg_http_reply(c, 404, "Content-Type: text/plain\r\n", "Not Found\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 监控页面
|
||||
if (path == "/" || path == "/index.html") {
|
||||
mg_http_reply(c, 200, "Content-Type: text/html; charset=utf-8\r\n",
|
||||
"%.*s", (int)INDEX_HTML.size(), INDEX_HTML.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
mg_http_reply(c, 404, "Content-Type: text/plain\r\n", "Not Found\n");
|
||||
} else if (ev == MG_EV_WS_OPEN) {
|
||||
std::lock_guard<std::mutex> lock(m_wsMutex);
|
||||
m_wsConnections.push_back(c);
|
||||
if (m_onOpen) {
|
||||
std::string welcome = m_onOpen();
|
||||
if (!welcome.empty()) {
|
||||
mg_ws_send(c, welcome.c_str(), welcome.size(), WEBSOCKET_OP_TEXT);
|
||||
}
|
||||
}
|
||||
} else if (ev == MG_EV_CLOSE || ev == MG_EV_ERROR) {
|
||||
std::lock_guard<std::mutex> lock(m_wsMutex);
|
||||
for (auto it = m_wsConnections.begin(); it != m_wsConnections.end(); ++it) {
|
||||
if (*it == c) {
|
||||
m_wsConnections.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (ev == MG_EV_WS_MSG) {
|
||||
// 纯监控,忽略客户端消息
|
||||
}
|
||||
}
|
||||
|
||||
WebServer::WebServer() {
|
||||
mg_mgr_init(&m_mgr);
|
||||
}
|
||||
|
||||
WebServer::~WebServer() {
|
||||
stop();
|
||||
mg_mgr_free(&m_mgr);
|
||||
}
|
||||
|
||||
void WebServer::setOnOpen(std::function<std::string()> handler) {
|
||||
m_onOpen = std::move(handler);
|
||||
}
|
||||
|
||||
void WebServer::setApiHandler(std::function<std::string(const std::string&, const std::string&)> handler) {
|
||||
m_apiHandler = std::move(handler);
|
||||
}
|
||||
|
||||
bool WebServer::start(int port) {
|
||||
if (m_running) return true;
|
||||
m_port = port;
|
||||
|
||||
std::string addr = "http://0.0.0.0:" + std::to_string(port);
|
||||
mg_http_listen(&m_mgr, addr.c_str(), [](mg_connection* c, int ev, void* ev_data) {
|
||||
WebServer* server = static_cast<WebServer*>(c->fn_data);
|
||||
if (server) server->handleEvent(c, ev, ev_data);
|
||||
}, this);
|
||||
|
||||
m_running = true;
|
||||
m_thread = std::thread([this]() { serverThreadFunc(); });
|
||||
|
||||
std::cout << "pCCU web UI listening on " << addr << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebServer::stop() {
|
||||
if (!m_running) return;
|
||||
m_running = false;
|
||||
if (m_thread.joinable()) m_thread.join();
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_wsMutex);
|
||||
for (auto c : m_wsConnections) {
|
||||
mg_ws_send(c, "", 0, WEBSOCKET_OP_CLOSE);
|
||||
}
|
||||
m_wsConnections.clear();
|
||||
}
|
||||
|
||||
bool WebServer::serverThreadCB(void* pParam) {
|
||||
WebServer* pThis = static_cast<WebServer*>(pParam);
|
||||
return pThis->serverThreadFunc();
|
||||
}
|
||||
|
||||
bool WebServer::serverThreadFunc() {
|
||||
while (m_running) {
|
||||
mg_mgr_poll(&m_mgr, 200);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebServer::broadcast(const std::string& text) {
|
||||
std::lock_guard<std::mutex> lock(m_wsMutex);
|
||||
for (auto c : m_wsConnections) {
|
||||
mg_ws_send(c, text.c_str(), text.size(), WEBSOCKET_OP_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ccu
|
||||
Reference in New Issue
Block a user