|
@@ -27,9 +27,12 @@ pub mod mexc_spot {
|
|
|
include!(concat!(env!("OUT_DIR"), "/_.rs"));
|
|
include!(concat!(env!("OUT_DIR"), "/_.rs"));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// use mexc_spot::PublicIncreaseDepthsV3Api; // 使用 proto 中定义的消息名
|
|
|
|
|
use mexc_spot::PublicSpotKlineV3ApiMessage;
|
|
use mexc_spot::PublicSpotKlineV3ApiMessage;
|
|
|
use mexc_spot::KlineDataV3;
|
|
use mexc_spot::KlineDataV3;
|
|
|
|
|
+// 引入新的结构体
|
|
|
|
|
+use mexc_spot::PublicIncreaseDepthsV3ApiMessage;
|
|
|
|
|
+use mexc_spot::DepthDataContentV3;
|
|
|
|
|
+use mexc_spot::DepthItemV3;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
@@ -247,7 +250,7 @@ impl MexcSpotWs {
|
|
|
}
|
|
}
|
|
|
//数据解析-二进制
|
|
//数据解析-二进制
|
|
|
pub fn message_binary(po: Vec<u8>) -> Option<Response> {
|
|
pub fn message_binary(po: Vec<u8>) -> Option<Response> {
|
|
|
- info!("Received binary message ({} bytes)", po.len());
|
|
|
|
|
|
|
+ // info!("Received binary message ({} bytes)", po.len());
|
|
|
|
|
|
|
|
// 1. 尝试用新的顶层消息结构 PublicSpotKlineV3ApiMessage 来解析 K 线数据
|
|
// 1. 尝试用新的顶层消息结构 PublicSpotKlineV3ApiMessage 来解析 K 线数据
|
|
|
// 根据 Topic 前缀判断依然有效,但现在是判断是否**可能**是 K 线相关消息
|
|
// 根据 Topic 前缀判断依然有效,但现在是判断是否**可能**是 K 线相关消息
|
|
@@ -312,8 +315,76 @@ impl MexcSpotWs {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 3. 如果都不是已知的 Protobuf 类型,处理未知消息
|
|
|
|
|
|
|
+ // 2. 尝试解析深度数据 (使用新的结构体)
|
|
|
|
|
+ if prefix_string.contains("spot@public.aggre.depth.v3.api.pb") {
|
|
|
|
|
+ // info!("通过 Topic 前缀判断为深度数据");
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试解析为 PublicIncreaseDepthsV3ApiMessage (新的顶层深度消息)
|
|
|
|
|
+ match PublicIncreaseDepthsV3ApiMessage::decode(&po[..]) {
|
|
|
|
|
+ Ok(depth_message) => {
|
|
|
|
|
+ // info!("成功解析为顶层深度消息结构");
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否包含嵌套的 depth_data 字段 (Tag 313)
|
|
|
|
|
+ if let Some(depth_data_content) = depth_message.depth_data {
|
|
|
|
|
+ // info!("找到并成功访问嵌套的 DepthDataContentV3");
|
|
|
|
|
+
|
|
|
|
|
+ // 填充 Response 并返回
|
|
|
|
|
+ let response_data = Response::new(
|
|
|
|
|
+ depth_message.topic_info.clone(), // 使用解析到的 Topic
|
|
|
|
|
+ 200, "OK".to_string(),
|
|
|
|
|
+ serde_json::json!({
|
|
|
|
|
+ // 嵌套消息内部的字段
|
|
|
|
|
+ "asks": depth_data_content.asks.into_iter().map(|item| serde_json::json!({"price": item.price, "quantity": item.quantity})).collect::<Vec<_>>(),
|
|
|
|
|
+ "bids": depth_data_content.bids.into_iter().map(|item| serde_json::json!({"price": item.price, "quantity": item.quantity})).collect::<Vec<_>>(),
|
|
|
|
|
+ "eventType": depth_data_content.event_type,
|
|
|
|
|
+ "version": depth_data_content.version,
|
|
|
|
|
+ "lastUpdateId": depth_data_content.last_update_id, // 新增字段
|
|
|
|
|
+
|
|
|
|
|
+ // 顶层字段
|
|
|
|
|
+ "topic_info": depth_message.topic_info,
|
|
|
|
|
+ "symbol": depth_message.symbol,
|
|
|
|
|
+ "timestamp": depth_message.timestamp, // 新增字段
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+ return Some(response_data);
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ info!("顶层深度消息结构解析成功,但未找到嵌套的 depth_data 字段 (Tag 313)");
|
|
|
|
|
+ // 处理只有顶层字段的深度相关消息
|
|
|
|
|
+ return Some(Response::new(
|
|
|
|
|
+ depth_message.topic_info.clone(),
|
|
|
|
|
+ 200, "OK (Control Message)".to_string(),
|
|
|
|
|
+ serde_json::json!({
|
|
|
|
|
+ "topic_info": depth_message.topic_info,
|
|
|
|
|
+ "symbol": depth_message.symbol,
|
|
|
|
|
+ "timestamp": depth_message.timestamp,
|
|
|
|
|
+ })
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Err(e) => {
|
|
|
|
|
+ error!("解析深度消息 PublicIncreaseDepthsV3ApiMessage 失败: {:?}", e);
|
|
|
|
|
+ // 保存数据以供分析
|
|
|
|
|
+ let file_path = Path::new("depth_error_data.bin");
|
|
|
|
|
+ // ... 保存 po 到文件 ...
|
|
|
|
|
+ return Some(Response::new("".to_string(), 500, format!("Protobuf 深度消息解析出错: {:?}", e), Value::Null));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果都不是已知的 Protobuf 类型,处理未知消息
|
|
|
error!("无法将二进制消息解析为任何已知 Protobuf 类型");
|
|
error!("无法将二进制消息解析为任何已知 Protobuf 类型");
|
|
|
|
|
+ // *** 在这里将原始二进制数据保存到文件 ***
|
|
|
|
|
+ let file_path = Path::new("un_decode.bin");
|
|
|
|
|
+ match File::create(&file_path) {
|
|
|
|
|
+ Ok(mut file) => {
|
|
|
|
|
+ match file.write_all(&po) {
|
|
|
|
|
+ Ok(_) => info!("原始 K 线二进制数据保存到 {:?}", file_path),
|
|
|
|
|
+ Err(write_e) => error!("保存 K 线二进制数据失败: {:?}", write_e),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Err(create_e) => error!("创建文件 {:?} 失败: {:?}", file_path, create_e),
|
|
|
|
|
+ }
|
|
|
Some(Response::new("".to_string(), 400, "无法解析未知二进制消息".to_string(), Value::Null))
|
|
Some(Response::new("".to_string(), 400, "无法解析未知二进制消息".to_string(), Value::Null))
|
|
|
}
|
|
}
|
|
|
//数据解析
|
|
//数据解析
|
|
@@ -393,8 +464,8 @@ mod tests {
|
|
|
let mut ws = MexcSpotWs::new_with_tag("Mexc".to_string(), None, MexcSpotWsType::PublicAndPrivate);
|
|
let mut ws = MexcSpotWs::new_with_tag("Mexc".to_string(), None, MexcSpotWsType::PublicAndPrivate);
|
|
|
|
|
|
|
|
ws.set_subscribe(vec![
|
|
ws.set_subscribe(vec![
|
|
|
- MexcSpotWsSubscribeType::PuFuturesRecords("Min1".to_string()),
|
|
|
|
|
- // MexcSpotWsSubscribeType::PuFuturesDepth
|
|
|
|
|
|
|
+ // MexcSpotWsSubscribeType::PuFuturesRecords("Min1".to_string()),
|
|
|
|
|
+ MexcSpotWsSubscribeType::PuFuturesDepth
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
ws.set_symbols(vec!["BTC_USDT".to_string()]);
|
|
ws.set_symbols(vec!["BTC_USDT".to_string()]);
|