83 lines
2.3 KiB
Rust
83 lines
2.3 KiB
Rust
|
|
//! 充电柜矩阵系统 — 后端入口
|
|||
|
|
|
|||
|
|
mod config;
|
|||
|
|
mod db;
|
|||
|
|
mod error;
|
|||
|
|
mod middleware;
|
|||
|
|
mod redis;
|
|||
|
|
mod routes;
|
|||
|
|
mod tcp;
|
|||
|
|
|
|||
|
|
use std::net::SocketAddr;
|
|||
|
|
use tracing_subscriber::EnvFilter;
|
|||
|
|
|
|||
|
|
use tcp::commands::AppState;
|
|||
|
|
use tcp::connection::ConnectionPool;
|
|||
|
|
|
|||
|
|
#[tokio::main]
|
|||
|
|
async fn main() {
|
|||
|
|
// 初始化日志
|
|||
|
|
tracing_subscriber::fmt()
|
|||
|
|
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
|
|||
|
|
.init();
|
|||
|
|
|
|||
|
|
// 加载配置
|
|||
|
|
let cfg = config::Config::from_env();
|
|||
|
|
cfg.validate();
|
|||
|
|
tracing::info!("配置加载完成");
|
|||
|
|
|
|||
|
|
// 初始化 MySQL 连接池
|
|||
|
|
let db_pool = db::init_pool(&cfg.database_url)
|
|||
|
|
.await
|
|||
|
|
.expect("MySQL 连接失败");
|
|||
|
|
tracing::info!("数据库连接成功");
|
|||
|
|
|
|||
|
|
// 执行自动迁移
|
|||
|
|
db::migrate::run(&db_pool)
|
|||
|
|
.await
|
|||
|
|
.expect("数据库迁移失败");
|
|||
|
|
tracing::info!("数据库迁移完成");
|
|||
|
|
|
|||
|
|
// 初始化 Redis 连接(ConnectionManager 内部管理重连,可直接 Clone 共享)
|
|||
|
|
let redis_conn = redis::init_connection(&cfg.redis_url)
|
|||
|
|
.await
|
|||
|
|
.expect("Redis 连接失败");
|
|||
|
|
tracing::info!("Redis 连接成功");
|
|||
|
|
|
|||
|
|
// 初始化设备连接池
|
|||
|
|
let device_pool = ConnectionPool::new();
|
|||
|
|
|
|||
|
|
// 构建共享状态
|
|||
|
|
let state = AppState {
|
|||
|
|
device_pool: device_pool.clone(),
|
|||
|
|
redis: redis_conn.clone(),
|
|||
|
|
mysql: db_pool.clone(),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 启动 TCP 设备服务(后台)
|
|||
|
|
let tcp_addr = format!("{}:{}", cfg.host, cfg.tcp_port);
|
|||
|
|
tracing::info!("TCP 设备服务启动于 {}", tcp_addr);
|
|||
|
|
let tcp_pool = device_pool.clone();
|
|||
|
|
let tcp_redis = redis_conn.clone();
|
|||
|
|
let tcp_mysql = db_pool.clone();
|
|||
|
|
tokio::spawn(async move {
|
|||
|
|
tcp::run_tcp_server(tcp_addr, tcp_pool, tcp_redis, tcp_mysql).await;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 构建 HTTP 路由(包含设备指令下发端点和认证中间件)
|
|||
|
|
let app = routes::build(state);
|
|||
|
|
|
|||
|
|
// 启动 HTTP 服务
|
|||
|
|
let addr: SocketAddr = format!("{}:{}", cfg.host, cfg.port)
|
|||
|
|
.parse()
|
|||
|
|
.expect("无效的监听地址");
|
|||
|
|
tracing::info!("HTTP 服务器启动于 http://{}", addr);
|
|||
|
|
|
|||
|
|
let listener = tokio::net::TcpListener::bind(addr)
|
|||
|
|
.await
|
|||
|
|
.expect("端口绑定失败");
|
|||
|
|
axum::serve(listener, app)
|
|||
|
|
.await
|
|||
|
|
.expect("服务器运行失败");
|
|||
|
|
}
|