77 lines
4.3 KiB
C++
77 lines
4.3 KiB
C++
#include "server_app.hpp"
|
|
#include <iostream>
|
|
namespace adminive::example {
|
|
namespace {
|
|
Radio_State make_radio_state(Radio_Mode mode, int port, int buffer_count, int low_watermark, int high_watermark) {
|
|
Radio_State result;
|
|
result.mode = mode;
|
|
result.port = port;
|
|
result.buffer_count = buffer_count;
|
|
result.low_watermark = low_watermark;
|
|
result.high_watermark = high_watermark;
|
|
return result;
|
|
}
|
|
}
|
|
Server_App::Server_App(int port, std::filesystem::path frontend_dist, std::filesystem::path config_file) : port_(port), frontend_dist_(std::move(frontend_dist)), config_store_(std::move(config_file)), state_resource_("/admin/radio_states", make_radio_states()), service_config_resource_(config_store_.data().radio_service, "/admin/config/radio", adminive::make_resource_transaction<Radio_Service_Config>([this](const Radio_Service_Config& value, const Request_Context&) {
|
|
config_store_.write_radio_service_candidate(value);
|
|
}), &config_store_.mutex()), alert_config_resource_(config_store_.data().alerts, "/admin/config/alerts", adminive::make_resource_transaction<Alert_Config>([this](const Alert_Config& value, const Request_Context&) {
|
|
config_store_.write_alerts_candidate(value);
|
|
}), &config_store_.mutex()), device_tables_(config_store_) {
|
|
state_resource_.register_overview_status<Server_Status>("/admin/status", 2000);
|
|
state_resource_.register_status<&Radio_State::status>(2000);
|
|
bind_routes();
|
|
}
|
|
int Server_App::run() {
|
|
if(!server_.set_mount_point("/", frontend_dist_.string())) {
|
|
std::cerr << "frontend build directory does not exist: " << frontend_dist_.string() << '\n';
|
|
std::cerr << "run npm run build from the project root before starting the backend\n";
|
|
return 3;
|
|
}
|
|
std::cout << "Adminive server listening on http://127.0.0.1:" << port_ << '\n';
|
|
std::cout << "Serving frontend from " << frontend_dist_.string() << '\n';
|
|
std::cout << "Configuration file " << config_store_.path().string() << '\n';
|
|
std::cout << std::flush;
|
|
if(!server_.listen("0.0.0.0", port_)) {
|
|
std::cerr << "failed to start server\n";
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
Json Server_App::amis_schema() const {
|
|
Json tabs = Json::array();
|
|
const Json states_schema = state_resource_.amis_schema();
|
|
tabs.push_back(Json{{"title", "无线电状态"}, {"body", states_schema.at("body")}});
|
|
tabs.push_back(Json{{"title", "无线电服务配置"}, {"body", service_config_resource_.amis_schema()}});
|
|
tabs.push_back(Json{{"title", "告警配置"}, {"body", alert_config_resource_.amis_schema()}});
|
|
tabs.push_back(Json{{"title", "多类型设备"}, {"body", device_tables_.amis_schema()}});
|
|
return Json{{"type", "page"}, {"title", "Adminive 完整示例"}, {"subTitle", "列表中文映射、后端排序、拖拽顺序、多态类型表格和持久化配置均由后端定义"}, {"body", Json{{"type", "tabs"}, {"tabs", std::move(tabs)}}}};
|
|
}
|
|
std::vector<Radio_State> Server_App::make_radio_states() {
|
|
return {
|
|
make_radio_state(Radio_Mode::receive, 10001, 2, 16, 64),
|
|
make_radio_state(Radio_Mode::transmit, 10002, 4, 32, 128),
|
|
make_radio_state(Radio_Mode::duplex, 10003, 8, 64, 256)
|
|
};
|
|
}
|
|
void Server_App::bind_routes() {
|
|
state_resource_.bind(server_);
|
|
service_config_resource_.bind(server_);
|
|
alert_config_resource_.bind(server_);
|
|
device_tables_.bind(server_);
|
|
server_.Get("/admin/amis", [this](const httplib::Request&, httplib::Response& response) {
|
|
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", amis_schema()}});
|
|
});
|
|
server_.Get("/admin/status", [this](const httplib::Request&, httplib::Response& response) {
|
|
const auto now = std::chrono::system_clock::now();
|
|
const auto uptime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - started_at_).count();
|
|
Server_Status status;
|
|
status.server_time = format_utc_time(now);
|
|
status.uptime_seconds = static_cast<std::uint64_t>(uptime);
|
|
status.poll_sequence = poll_sequence_.fetch_add(1, std::memory_order_relaxed) + 1;
|
|
status.radio_state_count = state_resource_.size();
|
|
status.listen_port = port_;
|
|
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", to_status_json<Json>(status)}});
|
|
});
|
|
}
|
|
}
|