Claw 项目完整结构提交
This commit is contained in:
501
Claw/Server/SmartClaw/src/main.rs
Normal file
501
Claw/Server/SmartClaw/src/main.rs
Normal file
@@ -0,0 +1,501 @@
|
||||
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder, middleware::Logger};
|
||||
use std::env;
|
||||
use shared::{TaskRequest, TaskResponse, HealthResponse, utils};
|
||||
|
||||
mod websocket_client;
|
||||
use websocket_client::WebSocketClientManager;
|
||||
|
||||
/// 智能控制核心服务
|
||||
struct SmartClawService;
|
||||
|
||||
impl SmartClawService {
|
||||
/// 处理来自网关服务的任务
|
||||
async fn process_task(task: TaskRequest) -> TaskResponse {
|
||||
println!("🤖 SmartClaw 收到任务:");
|
||||
println!(" 用户ID: {}", task.user_id);
|
||||
println!(" 任务类型: {}", task.task_type);
|
||||
println!(" 内容长度: {} 字符", task.content.len());
|
||||
println!(" 优先级: {}", task.priority);
|
||||
|
||||
// 记录任务开始时间
|
||||
let start_time = std::time::Instant::now();
|
||||
|
||||
// 根据任务类型进行不同的处理
|
||||
let result = match task.task_type {
|
||||
shared::TaskType::TextProcessing => {
|
||||
Self::process_text_task(&task.content).await
|
||||
},
|
||||
shared::TaskType::DataAnalysis => {
|
||||
Self::process_data_analysis_task(&task.content).await
|
||||
},
|
||||
shared::TaskType::AIChat => {
|
||||
Self::process_ai_chat_task(&task.content).await
|
||||
},
|
||||
shared::TaskType::FileProcessing => {
|
||||
Self::process_file_task(&task.content).await
|
||||
},
|
||||
shared::TaskType::Custom(ref custom_type) => {
|
||||
Self::process_custom_task(&task.content, custom_type).await
|
||||
},
|
||||
};
|
||||
|
||||
let processing_time = start_time.elapsed().as_millis() as u64;
|
||||
|
||||
match result {
|
||||
Ok(response_data) => {
|
||||
println!("✅ 任务处理成功,耗时: {}ms", processing_time);
|
||||
let mut response = utils::create_success_response(
|
||||
"任务处理成功",
|
||||
Some(utils::generate_task_id(&task.user_id)),
|
||||
Some(response_data)
|
||||
);
|
||||
response.processing_time = Some(processing_time);
|
||||
response
|
||||
},
|
||||
Err(error_message) => {
|
||||
println!("❌ 任务处理失败: {}", error_message);
|
||||
let mut response = utils::create_error_response(
|
||||
"任务处理失败",
|
||||
Some(error_message)
|
||||
);
|
||||
response.processing_time = Some(processing_time);
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理文本处理任务
|
||||
async fn process_text_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("📝 处理文本任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行文本处理
|
||||
// 模拟处理过程
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
|
||||
|
||||
let word_count = content.split_whitespace().count();
|
||||
let char_count = content.chars().count();
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "text_processing",
|
||||
"word_count": word_count,
|
||||
"char_count": char_count,
|
||||
"processed_content": format!("[已处理] {}", content),
|
||||
"lmstudio_result": "TODO: 集成 LMStudio 处理结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 处理数据分析任务
|
||||
async fn process_data_analysis_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("📊 处理数据分析任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行数据分析
|
||||
// 模拟数据处理
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(200)).await;
|
||||
|
||||
// 简单的数据分析示例
|
||||
let lines: Vec<&str> = content.lines().collect();
|
||||
let line_count = lines.len();
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "data_analysis",
|
||||
"line_count": line_count,
|
||||
"data_summary": {
|
||||
"total_lines": line_count,
|
||||
"sample_data": lines.iter().take(5).collect::<Vec<_>>()
|
||||
},
|
||||
"lmstudio_analysis": "TODO: 集成 LMStudio 分析结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 处理 AI 对话任务
|
||||
async fn process_ai_chat_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("💬 处理 AI 对话任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行 AI 对话
|
||||
// 模拟 AI 处理
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
|
||||
|
||||
let response = format!("这是一个模拟的 AI 回复,您的消息是: {}", content);
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "ai_chat",
|
||||
"user_message": content,
|
||||
"ai_response": response,
|
||||
"lmstudio_response": "TODO: 集成 LMStudio 对话结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 处理文件处理任务
|
||||
async fn process_file_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("📁 处理文件任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行文件内容处理
|
||||
// 模拟文件处理
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(300)).await;
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "file_processing",
|
||||
"file_info": {
|
||||
"content_preview": content.chars().take(100).collect::<String>() + "...",
|
||||
"content_length": content.len()
|
||||
},
|
||||
"processing_result": "文件内容已接收并处理",
|
||||
"lmstudio_processing": "TODO: 集成 LMStudio 文件处理结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 处理自定义任务
|
||||
async fn process_custom_task(content: &str, custom_type: &str) -> Result<serde_json::Value, String> {
|
||||
println!("🔧 处理自定义任务: {}", custom_type);
|
||||
|
||||
// 根据自定义类型进行不同的处理
|
||||
match custom_type {
|
||||
"translation" => {
|
||||
Self::process_translation_task(content).await
|
||||
},
|
||||
"summarization" => {
|
||||
Self::process_summarization_task(content).await
|
||||
},
|
||||
_ => {
|
||||
// 默认处理
|
||||
Ok(serde_json::json!({
|
||||
"task_type": format!("custom_{}", custom_type),
|
||||
"content": content,
|
||||
"result": format!("自定义任务 '{}' 已处理", custom_type),
|
||||
"note": "这是默认的自定义任务处理结果"
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理翻译任务
|
||||
async fn process_translation_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("🌐 处理翻译任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行翻译
|
||||
let translated = format!("[翻译结果] {}", content);
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "custom_translation",
|
||||
"original_text": content,
|
||||
"translated_text": translated,
|
||||
"source_language": "auto",
|
||||
"target_language": "zh-CN",
|
||||
"lmstudio_translation": "TODO: 集成 LMStudio 翻译结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 处理摘要任务
|
||||
async fn process_summarization_task(content: &str) -> Result<serde_json::Value, String> {
|
||||
println!("📋 处理摘要任务");
|
||||
|
||||
// TODO: 集成 LMStudio 进行文本摘要
|
||||
let summary = format!("这是文本的摘要: {}", content.chars().take(50).collect::<String>());
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"task_type": "custom_summarization",
|
||||
"original_text": content,
|
||||
"summary": summary,
|
||||
"summary_length": summary.len(),
|
||||
"lmstudio_summary": "TODO: 集成 LMStudio 摘要结果"
|
||||
}))
|
||||
}
|
||||
|
||||
/// 获取服务状态
|
||||
fn get_service_status() -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"service": "smartclaw",
|
||||
"status": "running",
|
||||
"version": env!("CARGO_PKG_VERSION"),
|
||||
"capabilities": [
|
||||
"text_processing",
|
||||
"data_analysis",
|
||||
"ai_chat",
|
||||
"file_processing",
|
||||
"custom_tasks"
|
||||
],
|
||||
"lmstudio_status": "TODO: 检查 LMStudio 连接状态",
|
||||
"active_tasks": 0, // TODO: 统计当前活跃任务数
|
||||
"queue_length": 0 // TODO: 统计队列长度
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 健康检查处理器
|
||||
async fn health_check() -> impl Responder {
|
||||
let response = HealthResponse {
|
||||
status: "healthy".to_string(),
|
||||
service: "smartclaw".to_string(),
|
||||
timestamp: utils::current_timestamp(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
extra: Some(SmartClawService::get_service_status()),
|
||||
};
|
||||
|
||||
HttpResponse::Ok().json(response)
|
||||
}
|
||||
|
||||
/// 任务处理处理器
|
||||
async fn handle_task(task: web::Json<TaskRequest>) -> impl Responder {
|
||||
let response = SmartClawService::process_task(task.into_inner()).await;
|
||||
HttpResponse::Ok().json(response)
|
||||
}
|
||||
|
||||
/// 系统状态处理器
|
||||
async fn system_status() -> impl Responder {
|
||||
HttpResponse::Ok().json(SmartClawService::get_service_status())
|
||||
}
|
||||
|
||||
/// LMStudio 状态检查
|
||||
async fn lmstudio_status() -> impl Responder {
|
||||
// TODO: 实现 LMStudio 连接状态检查
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"lmstudio": {
|
||||
"connected": false,
|
||||
"status": "not_implemented",
|
||||
"message": "LMStudio 集成尚未实现"
|
||||
},
|
||||
"timestamp": utils::current_timestamp()
|
||||
}))
|
||||
}
|
||||
|
||||
/// WebSocket 断开连接处理器(用于测试)
|
||||
async fn websocket_disconnect(ws_manager: web::Data<WebSocketClientManager>) -> impl Responder {
|
||||
println!("🔌 收到WebSocket断开连接请求");
|
||||
|
||||
// 获取客户端实例
|
||||
let client = ws_manager.get_client();
|
||||
|
||||
if client.is_connected() {
|
||||
println!("🔗 WebSocket客户端当前已连接,准备断开...");
|
||||
|
||||
// 断开连接
|
||||
client.disconnect();
|
||||
|
||||
println!("✅ WebSocket客户端已断开连接");
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"status": "disconnected",
|
||||
"message": "WebSocket客户端已断开连接",
|
||||
"timestamp": utils::current_timestamp()
|
||||
}))
|
||||
} else {
|
||||
println!("⚠️ WebSocket客户端当前未连接");
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"status": "not_connected",
|
||||
"message": "WebSocket客户端当前未连接",
|
||||
"timestamp": utils::current_timestamp()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// WebSocket 停止管理器处理器(用于测试)
|
||||
async fn websocket_stop(ws_manager: web::Data<WebSocketClientManager>) -> impl Responder {
|
||||
println!("🛑 收到WebSocket停止管理器请求");
|
||||
|
||||
// 停止管理器
|
||||
ws_manager.stop();
|
||||
|
||||
println!("✅ WebSocket客户端管理器已停止");
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"status": "stopped",
|
||||
"message": "WebSocket客户端管理器已停止",
|
||||
"timestamp": utils::current_timestamp()
|
||||
}))
|
||||
}
|
||||
|
||||
/// WebSocket 连接处理器(用于与网关服务通信)
|
||||
async fn websocket_handler(req: HttpRequest, _stream: web::Payload) -> impl Responder {
|
||||
// TODO: 实现 WebSocket 通信
|
||||
// 这将用于接收来自网关服务的实时任务
|
||||
println!("📡 WebSocket 连接请求: {:?}", req);
|
||||
|
||||
// 获取WebSocket客户端实例(用于测试和演示)
|
||||
let gateway_url = env::var("GATEWAY_URL").unwrap_or_else(|_| "http://localhost:8000".to_string());
|
||||
let ws_manager = WebSocketClientManager::new(gateway_url);
|
||||
|
||||
// 获取客户端实例(用于测试)
|
||||
let client = ws_manager.get_client();
|
||||
|
||||
// 检查连接状态(用于演示)
|
||||
if client.is_connected() {
|
||||
println!("🔗 WebSocket客户端已连接");
|
||||
|
||||
// 测试发送消息(用于演示)
|
||||
let test_message = serde_json::json!({
|
||||
"type": "test",
|
||||
"message": "来自SmartClaw的测试消息",
|
||||
"timestamp": utils::current_timestamp()
|
||||
}).to_string();
|
||||
|
||||
match client.send_message(test_message).await {
|
||||
Ok(_) => {
|
||||
println!("✅ 测试消息发送成功");
|
||||
},
|
||||
Err(e) => {
|
||||
println!("⚠️ 测试消息发送失败: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试发送任务响应(用于演示)
|
||||
let test_response = shared::TaskResponse {
|
||||
success: true,
|
||||
message: "测试响应".to_string(),
|
||||
task_id: Some("test_task_123".to_string()),
|
||||
result: Some(serde_json::json!({
|
||||
"test_data": "这是测试数据",
|
||||
"websocket_status": "connected"
|
||||
})),
|
||||
processing_time: Some(100),
|
||||
error: None,
|
||||
};
|
||||
|
||||
match client.send_task_response(test_response).await {
|
||||
Ok(_) => {
|
||||
println!("✅ 测试任务响应发送成功");
|
||||
},
|
||||
Err(e) => {
|
||||
println!("⚠️ 测试任务响应发送失败: {}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("⚠️ WebSocket客户端未连接");
|
||||
}
|
||||
|
||||
// 暂时返回不支持的消息
|
||||
HttpResponse::NotImplemented().json(serde_json::json!({
|
||||
"error": "WebSocket not implemented",
|
||||
"message": "WebSocket 功能正在开发中",
|
||||
"websocket_status": if client.is_connected() { "connected" } else { "disconnected" }
|
||||
}))
|
||||
}
|
||||
|
||||
/// 任务队列状态
|
||||
async fn queue_status() -> impl Responder {
|
||||
// TODO: 实现任务队列状态查询
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"queue": {
|
||||
"length": 0,
|
||||
"pending": 0,
|
||||
"processing": 0,
|
||||
"completed": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"timestamp": utils::current_timestamp()
|
||||
}))
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
// 初始化日志
|
||||
env_logger::init_from_env(
|
||||
env_logger::Env::new().default_filter_or("info,actix_web=info")
|
||||
);
|
||||
|
||||
let port = env::var("PORT").unwrap_or_else(|_| "3001".to_string());
|
||||
let bind_address = format!("0.0.0.0:{}", port);
|
||||
|
||||
// 获取网关服务地址
|
||||
let gateway_url = env::var("GATEWAY_URL").unwrap_or_else(|_| "http://localhost:8000".to_string());
|
||||
|
||||
println!("🚀 SmartClaw 服务启动中...");
|
||||
println!("📍 绑定地址: {}", bind_address);
|
||||
println!("🔗 网关服务: {}", gateway_url);
|
||||
println!("📝 日志级别: info");
|
||||
println!("🔧 版本: {}", env!("CARGO_PKG_VERSION"));
|
||||
println!("🎯 环境: {}", env::var("ENVIRONMENT").unwrap_or_else(|_| "development".to_string()));
|
||||
|
||||
// 创建 WebSocket 客户端管理器
|
||||
let ws_manager = WebSocketClientManager::new(gateway_url.clone());
|
||||
|
||||
// 启动 WebSocket 连接(在后台任务中)
|
||||
let ws_manager_for_spawn = ws_manager.clone();
|
||||
std::thread::spawn(move || {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
println!("🔄 正在启动 WebSocket 客户端连接...");
|
||||
match ws_manager_for_spawn.start().await {
|
||||
Ok(_) => {
|
||||
println!("✅ WebSocket 客户端连接成功");
|
||||
}
|
||||
Err(e) => {
|
||||
println!("❌ WebSocket 客户端连接失败: {}", e);
|
||||
// 这里可以添加重试逻辑
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let ws_manager_for_server = ws_manager.clone();
|
||||
let server = HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(ws_manager_for_server.clone()))
|
||||
.wrap(Logger::default())
|
||||
.service(
|
||||
web::scope("/api/v1")
|
||||
// 健康检查
|
||||
.route("/health", web::get().to(health_check))
|
||||
// 系统状态
|
||||
.route("/system", web::get().to(system_status))
|
||||
// 任务处理
|
||||
.route("/task", web::post().to(handle_task))
|
||||
// LMStudio 状态
|
||||
.route("/lmstudio/status", web::get().to(lmstudio_status))
|
||||
// 队列状态
|
||||
.route("/queue/status", web::get().to(queue_status))
|
||||
// WebSocket 连接(用于与网关服务通信)
|
||||
.route("/websocket", web::get().to(websocket_handler))
|
||||
// WebSocket 断开连接(用于测试)
|
||||
.route("/websocket/disconnect", web::post().to(websocket_disconnect))
|
||||
// WebSocket 停止管理器(用于测试)
|
||||
.route("/websocket/stop", web::post().to(websocket_stop))
|
||||
)
|
||||
})
|
||||
.bind(&bind_address)?
|
||||
.run();
|
||||
|
||||
println!("✅ SmartClaw 服务已启动在 {}", bind_address);
|
||||
println!("🔍 可用接口:");
|
||||
println!(" GET /api/v1/health - 健康检查");
|
||||
println!(" GET /api/v1/system - 系统状态");
|
||||
println!(" POST /api/v1/task - 处理任务");
|
||||
println!(" GET /api/v1/lmstudio/status - LMStudio 状态");
|
||||
println!(" GET /api/v1/queue/status - 队列状态");
|
||||
println!(" GET /api/v1/websocket - WebSocket 连接");
|
||||
println!(" POST /api/v1/websocket/disconnect - WebSocket 断开连接(测试)");
|
||||
println!(" POST /api/v1/websocket/stop - WebSocket 停止管理器(测试)");
|
||||
println!("💡 WebSocket 客户端已配置,连接到: {}", gateway_url);
|
||||
|
||||
// 启动优雅关闭处理
|
||||
let ws_manager_clone = ws_manager.clone();
|
||||
tokio::spawn(async move {
|
||||
// 监听关闭信号(这里简化处理,实际应该监听系统信号)
|
||||
match tokio::signal::ctrl_c().await {
|
||||
Ok(_) => {
|
||||
println!("🛑 收到关闭信号,开始优雅关闭...");
|
||||
graceful_shutdown(ws_manager_clone).await;
|
||||
std::process::exit(0);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("⚠️ 监听关闭信号失败: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.await
|
||||
}
|
||||
|
||||
/// 优雅关闭处理
|
||||
async fn graceful_shutdown(ws_manager: WebSocketClientManager) {
|
||||
println!("🛑 开始优雅关闭...");
|
||||
|
||||
// 停止WebSocket客户端
|
||||
ws_manager.stop();
|
||||
println!("🔌 WebSocket客户端已停止");
|
||||
|
||||
// 等待一段时间确保所有连接都已关闭
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
|
||||
|
||||
println!("✅ 优雅关闭完成");
|
||||
}
|
||||
214
Claw/Server/SmartClaw/src/websocket_client.rs
Normal file
214
Claw/Server/SmartClaw/src/websocket_client.rs
Normal file
@@ -0,0 +1,214 @@
|
||||
use tokio_tungstenite::{connect_async, tungstenite::Message};
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time::{interval, Duration};
|
||||
use shared::{TaskRequest, TaskResponse};
|
||||
|
||||
/// WebSocket 客户端连接管理器
|
||||
pub struct WebSocketClient {
|
||||
gateway_url: String,
|
||||
sender: Arc<std::sync::Mutex<Option<mpsc::Sender<String>>>>,
|
||||
is_connected: Arc<std::sync::Mutex<bool>>,
|
||||
}
|
||||
|
||||
impl WebSocketClient {
|
||||
/// 创建新的 WebSocket 客户端
|
||||
pub fn new(gateway_url: String) -> Self {
|
||||
Self {
|
||||
gateway_url,
|
||||
sender: Arc::new(std::sync::Mutex::new(None)),
|
||||
is_connected: Arc::new(std::sync::Mutex::new(false)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 连接到网关服务
|
||||
pub async fn connect(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🔌 正在连接到网关服务: {}", self.gateway_url);
|
||||
|
||||
let ws_url = format!("{}/ws", self.gateway_url.replace("http://", "ws://").replace("https://", "wss://"));
|
||||
println!("🔗 WebSocket URL: {}", ws_url);
|
||||
|
||||
// 建立 WebSocket 连接
|
||||
let (ws_stream, _) = connect_async(&ws_url).await?;
|
||||
println!("✅ WebSocket 连接建立");
|
||||
|
||||
// 设置连接状态
|
||||
*self.is_connected.lock().unwrap() = true;
|
||||
|
||||
// 分割流
|
||||
let (mut write, mut read) = ws_stream.split();
|
||||
|
||||
// 创建消息通道
|
||||
let (tx, mut rx) = mpsc::channel::<String>(100);
|
||||
*self.sender.lock().unwrap() = Some(tx);
|
||||
|
||||
// 启动消息发送循环
|
||||
let _write_handle = tokio::spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
if let Err(e) = write.send(Message::Text(msg)).await {
|
||||
println!("❌ 发送消息失败: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 启动消息接收循环
|
||||
let is_connected_clone = self.is_connected.clone();
|
||||
let _read_handle = tokio::spawn(async move {
|
||||
while let Some(msg) = read.next().await {
|
||||
match msg {
|
||||
Ok(Message::Text(text)) => {
|
||||
println!("📨 收到消息: {}", text);
|
||||
if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(&text) {
|
||||
Self::handle_incoming_message(parsed).await;
|
||||
}
|
||||
}
|
||||
Ok(Message::Close(_)) => {
|
||||
println!("🔚 收到关闭消息");
|
||||
*is_connected_clone.lock().unwrap() = false;
|
||||
break;
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
println!("❌ 接收消息错误: {}", e);
|
||||
*is_connected_clone.lock().unwrap() = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 启动心跳机制
|
||||
let _heartbeat_handle = {
|
||||
let is_connected = self.is_connected.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut heartbeat_interval = interval(Duration::from_secs(30));
|
||||
|
||||
loop {
|
||||
heartbeat_interval.tick().await;
|
||||
|
||||
let connected = *is_connected.lock().unwrap();
|
||||
if !connected {
|
||||
println!("💔 心跳检测到连接已断开");
|
||||
break;
|
||||
}
|
||||
|
||||
let _heartbeat_msg = json!({
|
||||
"type": "heartbeat",
|
||||
"service": "smartclaw",
|
||||
"timestamp": chrono::Utc::now().timestamp()
|
||||
}).to_string();
|
||||
|
||||
// 这里需要重新获取 sender,因为生命周期问题
|
||||
println!("💓 心跳发送");
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// 发送连接确认消息
|
||||
let connect_msg = json!({
|
||||
"type": "connect",
|
||||
"service": "smartclaw",
|
||||
"version": env!("CARGO_PKG_VERSION"),
|
||||
"timestamp": chrono::Utc::now().timestamp()
|
||||
}).to_string();
|
||||
|
||||
if let Some(sender) = &*self.sender.lock().unwrap() {
|
||||
let _ = sender.send(connect_msg).await;
|
||||
}
|
||||
|
||||
println!("🚀 WebSocket 客户端已启动");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 处理接收到的消息
|
||||
async fn handle_incoming_message(message: serde_json::Value) {
|
||||
match message.get("type").and_then(|t| t.as_str()) {
|
||||
Some("task") => {
|
||||
// 处理任务消息
|
||||
if let Ok(task_request) = serde_json::from_value::<TaskRequest>(message) {
|
||||
println!("📝 收到任务请求: {:?}", task_request);
|
||||
// 这里可以调用任务处理逻辑
|
||||
}
|
||||
}
|
||||
Some("heartbeat") => {
|
||||
println!("💓 收到心跳响应");
|
||||
}
|
||||
Some("ack") => {
|
||||
println!("✅ 收到确认消息");
|
||||
}
|
||||
Some(msg_type) => {
|
||||
println!("❓ 收到未知消息类型: {}", msg_type);
|
||||
}
|
||||
None => {
|
||||
println!("❓ 收到无类型消息");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 发送消息
|
||||
pub async fn send_message(&self, message: String) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if let Some(sender) = &*self.sender.lock().unwrap() {
|
||||
sender.send(message).await.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err("WebSocket 连接未建立".into())
|
||||
}
|
||||
}
|
||||
|
||||
/// 发送任务响应
|
||||
pub async fn send_task_response(&self, response: TaskResponse) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let message = json!({
|
||||
"type": "task_response",
|
||||
"task_id": response.task_id,
|
||||
"data": response,
|
||||
"timestamp": chrono::Utc::now().timestamp()
|
||||
}).to_string();
|
||||
|
||||
self.send_message(message).await
|
||||
}
|
||||
|
||||
/// 检查连接状态
|
||||
pub fn is_connected(&self) -> bool {
|
||||
*self.is_connected.lock().unwrap()
|
||||
}
|
||||
|
||||
/// 断开连接
|
||||
pub fn disconnect(&self) {
|
||||
*self.is_connected.lock().unwrap() = false;
|
||||
*self.sender.lock().unwrap() = None;
|
||||
println!("🔌 WebSocket 连接已断开");
|
||||
}
|
||||
}
|
||||
|
||||
/// WebSocket 客户端管理器
|
||||
#[derive(Clone)]
|
||||
pub struct WebSocketClientManager {
|
||||
client: Arc<WebSocketClient>,
|
||||
}
|
||||
|
||||
impl WebSocketClientManager {
|
||||
/// 创建新的管理器
|
||||
pub fn new(gateway_url: String) -> Self {
|
||||
Self {
|
||||
client: Arc::new(WebSocketClient::new(gateway_url)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 启动客户端连接
|
||||
pub async fn start(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
self.client.connect().await
|
||||
}
|
||||
|
||||
/// 获取客户端实例
|
||||
pub fn get_client(&self) -> Arc<WebSocketClient> {
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
/// 停止客户端
|
||||
pub fn stop(&self) {
|
||||
self.client.disconnect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user