Selaa lähdekoodia

替换了tungstenite 版本,以往的ws代码都注释了,新的tungstenite文件用 async后缀区分,先使用,确定可行再全部逐一替换

hl 1 vuosi sitten
vanhempi
commit
5c735a5682

+ 2 - 1
exchanges/Cargo.toml

@@ -8,7 +8,7 @@ edition = "2021"
 [dependencies]
 # json
 serde_json = "1.0.104"
-tungstenite = { git = "https://github.com/PrivateRookie/tungstenite-rs.git", rev = "1d9289276518e5ab7e5194126d40b441d8938375" }
+#tungstenite = { git = "https://github.com/PrivateRookie/tungstenite-rs.git", rev = "1d9289276518e5ab7e5194126d40b441d8938375" }
 #tungstenite = { git = "https://github.com/PrivateRookie/tungstenite-rs.git", rev = "f368f3087d50d97658fda5337550e587bb1ba1b6" }
 
 tokio-tungstenite= { git = "https://github.com/HonestHouLiang/tokio-tungstenite.git",rev = "208fc9b09bcc2e2c8cb52e1cde5087446464fc91"  }
@@ -40,5 +40,6 @@ rust_decimal_macros = "1.32.0"
 global = { path="../global" }
 tracing = "0.1"
 tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
+log = "0.4.20"
 
 ##

+ 183 - 184
exchanges/src/binance_spot_ws.rs

@@ -1,18 +1,13 @@
-use std::collections::{BTreeMap};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use std::collections::BTreeMap;
 use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
+use std::sync::atomic::AtomicBool;
+
 use tokio::sync::mpsc::Sender;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
+use tracing::{info, trace};
+
+use crate::proxy;
 use crate::proxy::ParsingDetail;
 use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
 
 pub enum BinanceSpotWsType {
     //订阅频道类型
@@ -153,187 +148,191 @@ impl BinanceSpotWs {
     /*******************************************************************************************************/
     async fn run(&mut self, bool_v1: Arc<AtomicBool>)
     {
-        //订阅信息组装
-
-        let params = self.get_subscription();
-        let subscription_str = if params.len() > 0 {
-            serde_json::json!({
-                "method": "SUBSCRIBE",
-                "params":serde_json::Value::from(params),
-                "id": 1
-            }).to_string()
-        } else {
-            "".to_string()
-        };
-        trace!("订阅内容:{}",subscription_str);
-
-        let request_url = self.request_url.clone();
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            info!("要连接咯~~!!{}", request_url);
-            let request_url = Url::parse(request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription_str.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription_str.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
+        // //订阅信息组装
+        //
+        // let params = self.get_subscription();
+        // let subscription_str = if params.len() > 0 {
+        //     serde_json::json!({
+        //         "method": "SUBSCRIBE",
+        //         "params":serde_json::Value::from(params),
+        //         "id": 1
+        //     }).to_string()
+        // } else {
+        //     "".to_string()
+        // };
+        // trace!("订阅内容:{}",subscription_str);
+        //
+        // let request_url = self.request_url.clone();
+        // loop {
+        //     tokio::time::sleep(Duration::from_millis(5000)).await;
+        //     info!("要连接咯~~!!{}", request_url);
+        //     let request_url = Url::parse(request_url.as_str()).unwrap();
+        //     //1. 判断是否需要代理,根据代理地址是否存来选择
+        //     if self.proxy.ip_address.len() > 0 {
+        //         let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+        //         let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+        //             ip_array[0].parse().unwrap(),
+        //             ip_array[1].parse().unwrap(),
+        //             ip_array[2].parse().unwrap(),
+        //             ip_array[3].parse().unwrap())
+        //         ), self.proxy.port.parse().unwrap());
+        //         let websocket_config = Some(WebSocketConfig {
+        //             max_send_queue: Some(16),
+        //             max_message_size: Some(16 * 1024 * 1024),
+        //             max_frame_size: Some(16 * 1024 * 1024),
+        //             accept_unmasked_frames: false,
+        //         });
+        //         let max_redirects = 5;
+        //         match connect_with_proxy(request_url.clone(),
+        //                                  proxy_address, websocket_config, max_redirects) {
+        //             Ok(ws) => {
+        //                 let bool_v1_clone = Arc::clone(&bool_v1);
+        //                 self.proxy_subscription(bool_v1_clone, ws.0, subscription_str.clone()).await;
+        //             }
+        //             Err(err) => {
+        //                 error!("Can't connect(无法连接): {}", err);
+        //             }
+        //         };
+        //     } else {
+        //         match connect(request_url.clone()) {
+        //             Ok(ws) => {
+        //                 let bool_v1_clone = Arc::clone(&bool_v1);
+        //                 self.subscription(bool_v1_clone, ws.0, subscription_str.clone()).await;
+        //             }
+        //             Err(err) => {
+        //                 // 连接失败时执行的操作
+        //                 error!("Can't connect(无法连接): {}", err);
+        //                 // 返回一个默认的 WebSocket 对象或其他适当的值
+        //                 // 或者根据需要触发 panic 或返回错误信息
+        //             }
+        //         };
+        //     }
+        //     trace!("退出来咯");
+        //
+        //     let bool_v1_clone = Arc::clone(&bool_v1);
+        //     let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+        //     if !bool_v1_v {
+        //         break;
+        //     }
+        // }
     }
 
     //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: String)
+    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>,
+                                // mut web_socket: WebSocket<ProxyAutoStream>,
+                                subscription: String)
     {
-        info!("走代理-链接成功!开始数据读取");
-        let lable = self.label.clone();
-        /*****订阅消息**/
-        if subscription.len() > 0 {
-            web_socket.write_message(Message::Text(subscription)).unwrap();
-        }
-        /*****消息溜***/
-        loop {
-            // tokio::time::sleep(Duration::from_nanos(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!("Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!("Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
+        // info!("走代理-链接成功!开始数据读取");
+        // let lable = self.label.clone();
+        // /*****订阅消息**/
+        // if subscription.len() > 0 {
+        //     web_socket.write_message(Message::Text(subscription)).unwrap();
+        // }
+        // /*****消息溜***/
+        // loop {
+        //     // tokio::time::sleep(Duration::from_nanos(1)).await;
+        //     let msg = web_socket.read_message();
+        //     match msg {
+        //         Ok(Message::Text(text)) => {
+        //             // trace!("获取推送:{}",text.clone());
+        //             let mut res_data = Self::ok_text(lable.to_string(), text);
+        //             res_data.time = get_time_microsecond();
+        //             if res_data.code == "-200" {
+        //                 trace!("订阅成功:{:?}", res_data.data);
+        //             } else {
+        //                 let sender = self.sender.clone();
+        //                 tokio::spawn(async move {
+        //                     sender.send(res_data).await.unwrap();
+        //                 });
+        //                 tokio::spawn(async move {});
+        //             }
+        //         }
+        //         Ok(Message::Ping(s)) => {
+        //             trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+        //             // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+        //             trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+        //         }
+        //         Ok(Message::Pong(s)) => {
+        //             // trace!("Pong-响应--{:?}", String::from_utf8(s));
+        //             trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+        //         }
+        //         Ok(Message::Close(_)) => {
+        //             // trace!("socket 关闭: ");
+        //             trace!("Close-响应");
+        //         }
+        //         Err(error) => {
+        //             // trace!("Error receiving message: {}", error);
+        //             error!("Err-响应{}", error);
+        //             break;
+        //         }
+        //         _ => {}
+        //     }
+        //
+        //     let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+        //     if !bool_v1_v {
+        //         break;
+        //     }
+        // }
+        // web_socket.close(None).unwrap();
     }
 
     //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>, subscription: String)
+    async fn subscription(&self, bool_v1: Arc<AtomicBool>,
+                          // mut web_socket: WebSocket<AutoStream>,
+                          subscription: String)
     {
-        info!("链接成功!开始数据读取");
-        let lable = self.label.clone();
-        /*****订阅消息**/
-        if subscription.len() > 0 {
-            web_socket.write_message(Message::Text(subscription.clone())).unwrap();
-        }
-        /*****消息溜***/
-        loop {
-            // tokio::time::sleep(Duration::from_nanos(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", subscription.clone());
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
+        // info!("链接成功!开始数据读取");
+        // let lable = self.label.clone();
+        // /*****订阅消息**/
+        // if subscription.len() > 0 {
+        //     web_socket.write_message(Message::Text(subscription.clone())).unwrap();
+        // }
+        // /*****消息溜***/
+        // loop {
+        //     // tokio::time::sleep(Duration::from_nanos(1)).await;
+        //     let msg = web_socket.read_message();
+        //     match msg {
+        //         Ok(Message::Text(text)) => {
+        //             // trace!("获取推送:{}",text.clone());
+        //             let mut res_data = Self::ok_text(lable.to_string(), text);
+        //             res_data.time = get_time_microsecond();
+        //             if res_data.code == "-200" {
+        //                 trace!("订阅成功:{:?}", subscription.clone());
+        //             } else {
+        //                 let sender = self.sender.clone();
+        //                 tokio::spawn(async move {
+        //                     sender.send(res_data).await.unwrap();
+        //                 });
+        //                 tokio::spawn(async move {});
+        //             }
+        //         }
+        //         Ok(Message::Ping(s)) => {
+        //             trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+        //             // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+        //             trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+        //         }
+        //         Ok(Message::Pong(s)) => {
+        //             // trace!("Pong-响应--{:?}", String::from_utf8(s));
+        //             trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+        //         }
+        //         Ok(Message::Close(_)) => {
+        //             // trace!("socket 关闭: ");
+        //             trace!( "Close-响应");
+        //         }
+        //         Err(error) => {
+        //             // trace!("Error receiving message: {}", error);
+        //             error!( "Err-响应{}", error);
+        //             break;
+        //         }
+        //         _ => {}
+        //     }
+        //
+        //     let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+        //     if !bool_v1_v {
+        //         break;
+        //     }
+        // }
+        // web_socket.close(None).unwrap();
     }
 
     //数据解析

+ 359 - 362
exchanges/src/binance_swap_ws.rs

@@ -1,362 +1,359 @@
-use std::collections::{BTreeMap};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use tokio::sync::mpsc::Sender;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-pub enum BinanceWsType {
-    //订阅频道类型
-    PublicAndPrivate,
-}
-
-
-#[derive(Clone)]                        //订阅枚举
-pub enum BinanceSubscribeType {
-    PuBookTicker,
-    PuAggTrade,
-    PuDepth20levels100ms,
-}
-
-#[derive(Clone)]
-pub struct BinanceSwapWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //账号信息
-    login_param: BTreeMap<String, String>,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<BinanceSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,
-    //数据通道
-}
-
-impl BinanceSwapWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub fn new(is_colo: bool,
-               login_param: BTreeMap<String, String>,
-               ws_type: BinanceWsType,
-               sender: Sender<ResponseData>,
-    ) -> BinanceSwapWs
-    {
-        return BinanceSwapWs::new_label("default-BinanceSwapWs".to_string(), is_colo, login_param, ws_type, sender);
-    }
-    pub fn new_label(label: String, is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: BinanceWsType,
-                     sender: Sender<ResponseData>,
-    ) -> BinanceSwapWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-        /*******公共频道-私有频道数据组装*/
-        let request_url = match ws_type {
-            BinanceWsType::PublicAndPrivate => {
-                "wss://fstream.binance.com/stream".to_string()
-            }
-        };
-
-        if is_colo {
-            info!("开启高速(未配置,走普通:{})通道",request_url);
-        } else {
-            info!("走普通通道:{}",request_url);
-        }
-        /*****返回结构体*******/
-        BinanceSwapWs {
-            label,
-            request_url,
-            proxy: parsing_detail,
-            login_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<BinanceSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        let mut symbol_s = b_array.clone();
-        for symbol in symbol_s.iter_mut() {
-            // 大写
-            *symbol = symbol.to_lowercase();
-            // 字符串替换
-            *symbol = symbol.replace("_", "");
-            *symbol = symbol.replace("-", "");
-        }
-        self.symbol_s = symbol_s;
-        let log_in = self.login_param.clone();
-        trace!(?log_in);
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-
-
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: BinanceSubscribeType) -> String {
-        match subscribe_type {
-            BinanceSubscribeType::PuAggTrade => {
-                format!("{}@aggTrade", symbol)
-            }
-            BinanceSubscribeType::PuDepth20levels100ms => {
-                format!("{}@depth20@100ms", symbol)
-            }
-            BinanceSubscribeType::PuBookTicker => {
-                format!("{}@bookTicker", symbol)
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> String {
-        let mut str = "".to_string();
-        // let mut args = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
-                // args.push(ty_str);
-                if str.len() > 0 {
-                    str = format!("{}/", str)
-                }
-                str = format!("{}{}", str, ty_str.clone().to_string());
-            }
-        }
-
-        trace!("订阅信息:{}", str.to_string());
-        str.to_string()
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&mut self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        let request_url = if subscription.len() > 0 {
-            format!("{}?streams={}", self.request_url, subscription)
-            // format!("{}", self.request_url)
-        } else {
-            format!("{}", self.request_url)
-        };
-
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            info!("要连接咯~~!!{}", request_url);
-            let request_url = Url::parse(request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address,
-                                         websocket_config,
-                                         max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, _subscription: String)
-    {
-        info!("走代理-链接成功!开始数据读取");
-        let lable = self.label.clone();
-        /*****消息溜***/
-        loop {
-            // 如果不暂停,还给cpu,这个loop会吃cpu,不还给操作系统
-            // 如果暂停,还给cpu,这个ws就会堵塞数据
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!("Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!("Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>, _subscription: String)
-    {
-        info!("链接成功!开始数据读取");
-        let lable = self.label.clone();
-        /*****消息溜***/
-        loop {
-            // tokio::time::sleep(Duration::from_nanos(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(lable: String, text: String) -> ResponseData
-    {
-        // trace!("原始数据");
-        // trace!(?text);
-        let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-
-        if json_value.get("error").is_some() {//订阅返回
-            res_data.code = json_value["error"]["code"].to_string();
-            res_data.message = json_value["error"]["msg"].to_string();
-        } else if json_value.get("stream").is_some() {//订阅返回
-            res_data.data = format!("{}", json_value.get("data").as_ref().unwrap());
-            res_data.code = "200".to_string();
-
-            let channel = format!("{}", json_value.get("stream").as_ref().unwrap());
-            if channel.contains("@aggTrade") {
-                res_data.channel = "aggTrade".to_string();
-            } else if channel.contains("@depth20@100ms") {
-                res_data.channel = "depth".to_string();
-            } else if channel.contains("@bookTicker") {
-                res_data.channel = "bookTicker".to_string();
-            } else {
-                res_data.channel = "未知的频道".to_string();
-            }
-        } else {
-            res_data.data = text
-        }
-        res_data
-    }
-}
+// use std::collections::{BTreeMap};
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::time::Duration;
+// use tokio::sync::mpsc::Sender;
+// use tracing::{error, info, trace};
+// use crate::{proxy};
+// use url::Url;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+// pub enum BinanceWsType {
+//     //订阅频道类型
+//     PublicAndPrivate,
+// }
+//
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum BinanceSubscribeType {
+//     PuBookTicker,
+//     PuAggTrade,
+//     PuDepth20levels100ms,
+// }
+//
+// #[derive(Clone)]
+// pub struct BinanceSwapWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //账号信息
+//     login_param: BTreeMap<String, String>,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<BinanceSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,
+//     //数据通道
+// }
+//
+// impl BinanceSwapWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub fn new(is_colo: bool,
+//                login_param: BTreeMap<String, String>,
+//                ws_type: BinanceWsType,
+//                sender: Sender<ResponseData>,
+//     ) -> BinanceSwapWs
+//     {
+//         return BinanceSwapWs::new_label("default-BinanceSwapWs".to_string(), is_colo, login_param, ws_type, sender);
+//     }
+//     pub fn new_label(label: String, is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: BinanceWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> BinanceSwapWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//         /*******公共频道-私有频道数据组装*/
+//         let request_url = match ws_type {
+//             BinanceWsType::PublicAndPrivate => {
+//                 "wss://fstream.binance.com/stream".to_string()
+//             }
+//         };
+//
+//         if is_colo {
+//             info!("开启高速(未配置,走普通:{})通道",request_url);
+//         } else {
+//             info!("走普通通道:{}",request_url);
+//         }
+//         /*****返回结构体*******/
+//         BinanceSwapWs {
+//             label,
+//             request_url,
+//             proxy: parsing_detail,
+//             login_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<BinanceSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         let mut symbol_s = b_array.clone();
+//         for symbol in symbol_s.iter_mut() {
+//             // 大写
+//             *symbol = symbol.to_lowercase();
+//             // 字符串替换
+//             *symbol = symbol.replace("_", "");
+//             *symbol = symbol.replace("-", "");
+//         }
+//         self.symbol_s = symbol_s;
+//         let log_in = self.login_param.clone();
+//         trace!(?log_in);
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//
+//
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: BinanceSubscribeType) -> String {
+//         match subscribe_type {
+//             BinanceSubscribeType::PuAggTrade => {
+//                 format!("{}@aggTrade", symbol)
+//             }
+//             BinanceSubscribeType::PuDepth20levels100ms => {
+//                 format!("{}@depth20@100ms", symbol)
+//             }
+//             BinanceSubscribeType::PuBookTicker => {
+//                 format!("{}@bookTicker", symbol)
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> String {
+//         let mut str = "".to_string();
+//         // let mut args = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+//                 // args.push(ty_str);
+//                 if str.len() > 0 {
+//                     str = format!("{}/", str)
+//                 }
+//                 str = format!("{}{}", str, ty_str.clone().to_string());
+//             }
+//         }
+//
+//         trace!("订阅信息:{}", str.to_string());
+//         str.to_string()
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&mut self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         let request_url = if subscription.len() > 0 {
+//             format!("{}?streams={}", self.request_url, subscription)
+//             // format!("{}", self.request_url)
+//         } else {
+//             format!("{}", self.request_url)
+//         };
+//
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(5000)).await;
+//             info!("要连接咯~~!!{}", request_url);
+//             let request_url = Url::parse(request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 match connect_with_proxy(request_url.clone(),
+//                                          proxy_address,
+//                                          websocket_config,
+//                                          max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         error!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         error!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, _subscription: String)
+//     {
+//         info!("走代理-链接成功!开始数据读取");
+//         let lable = self.label.clone();
+//         /*****消息溜***/
+//         loop {
+//             // 如果不暂停,还给cpu,这个loop会吃cpu,不还给操作系统
+//             // 如果暂停,还给cpu,这个ws就会堵塞数据
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     // trace!("获取推送:{}",text.clone());
+//                     let mut res_data = Self::ok_text(lable.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!("Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!("Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>, _subscription: String)
+//     {
+//         info!("链接成功!开始数据读取");
+//         let lable = self.label.clone();
+//         /*****消息溜***/
+//         loop {
+//             // tokio::time::sleep(Duration::from_nanos(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     // trace!("获取推送:{}",text.clone());
+//                     let mut res_data = Self::ok_text(lable.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     // let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(lable: String, text: String) -> ResponseData
+//     {
+//         // trace!("原始数据");
+//         // trace!(?text);
+//         let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//
+//         if json_value.get("error").is_some() {//订阅返回
+//             res_data.code = json_value["error"]["code"].to_string();
+//             res_data.message = json_value["error"]["msg"].to_string();
+//         } else if json_value.get("stream").is_some() {//订阅返回
+//             res_data.data = format!("{}", json_value.get("data").as_ref().unwrap());
+//             res_data.code = "200".to_string();
+//
+//             let channel = format!("{}", json_value.get("stream").as_ref().unwrap());
+//             if channel.contains("@aggTrade") {
+//                 res_data.channel = "aggTrade".to_string();
+//             } else if channel.contains("@depth20@100ms") {
+//                 res_data.channel = "depth".to_string();
+//             } else if channel.contains("@bookTicker") {
+//                 res_data.channel = "bookTicker".to_string();
+//             } else {
+//                 res_data.channel = "未知的频道".to_string();
+//             }
+//         } else {
+//             res_data.data = text
+//         }
+//         res_data
+//     }
+// }

+ 88 - 34
exchanges/src/binance_swap_ws_async.rs

@@ -1,12 +1,14 @@
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool};
+use std::sync::{Arc, Mutex};
+use std::sync::atomic::AtomicBool;
+
 use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
 use serde_json::json;
+use tokio_tungstenite::tungstenite::{Error, Message};
 use tracing::{info, trace};
+
 use crate::response_base::ResponseData;
+use crate::socket_tool::{AbstractWsMode, HeartbeatType};
 use crate::utils::get_time_microsecond;
-use tokio_tungstenite::tungstenite::{Error, Message};
-use crate::socket_tool::AbstractWsMode;
 
 pub enum BinanceSwapWsType {
     //订阅频道类型
@@ -29,14 +31,18 @@ pub struct BinanceSwapLogin {
 
 #[derive(Clone)]
 pub struct BinanceSwapWs {
-    label: String,
+    //类型
+    lable: String,
+    //地址
     address_url: String,
-    //账号信息
+    //账号
     login_param: Option<BinanceSwapLogin>,
-    //kuconis特殊参数
+    //币对
     symbol_s: Vec<String>,
-    //订阅币对
+    //订阅
     subscribe_types: Vec<BinanceSwapSubscribeType>,
+    //心跳间隔
+    heartbeat_time: u64,
 }
 
 impl BinanceSwapWs {
@@ -44,13 +50,14 @@ impl BinanceSwapWs {
     /*****************************************获取一个对象****************************************************/
     /*******************************************************************************************************/
     pub fn new(is_colo: bool, login_param: Option<BinanceSwapLogin>, ws_type: BinanceSwapWsType) -> BinanceSwapWs {
-        return BinanceSwapWs::new_label("default-BinanceSwapWs".to_string(), is_colo, login_param, ws_type);
+        return BinanceSwapWs::new_lable("default-BinanceSwapWs".to_string(), is_colo, login_param, ws_type);
     }
-    pub fn new_label(label: String, is_colo: bool, login_param: Option<BinanceSwapLogin>, ws_type: BinanceSwapWsType) -> BinanceSwapWs {
+    pub fn new_lable(lable: String, is_colo: bool, login_param: Option<BinanceSwapLogin>, ws_type: BinanceSwapWsType) -> BinanceSwapWs {
         /*******公共频道-私有频道数据组装*/
         let address_url = match ws_type {
             BinanceSwapWsType::PublicAndPrivate => {
-                "wss://fstream.binance.com/stream?streams=btcusdt@depth20@100ms".to_string()
+                // "wss://fstream.binance.com/stream?streams=btcusdt@depth20@100ms".to_string(),
+                "wss://fstream.binance.com/stream".to_string()
             }
         };
 
@@ -60,11 +67,12 @@ impl BinanceSwapWs {
             info!("走普通通道:{}",address_url);
         }
         BinanceSwapWs {
-            label,
+            lable,
             address_url,
             login_param,
             symbol_s: vec![],
             subscribe_types: vec![],
+            heartbeat_time: 1000,
         }
     }
 
@@ -140,7 +148,7 @@ impl BinanceSwapWs {
     pub fn analysis_message(message: Result<Message, Error>) -> Option<ResponseData> {
         let mut code = "00".to_string();
         let mut message_str = "".to_string();
-        let  data = "".to_string();
+        let data = "".to_string();
         match message {
             Ok(Message::Text(text)) => {
                 // trace!("Text:{}",text);
@@ -149,72 +157,113 @@ impl BinanceSwapWs {
                 response_data.time = get_time_microsecond();
                 if response_data.code == "-201" {
                     trace!("订阅成功:{:?}", response_data);
-                    return None
+                    return None;
                 } else if response_data.code == "-202" {
                     trace!("无用数据:{:?}", response_data);
-                    return None
+                    return None;
                 } else {
                     return Option::from(response_data);
                 }
             }
+
             Ok(Message::Binary(s)) => {
-                trace!("Binary:{:?}",s);
+                trace!("服务器响应:Binary:{:?}",s);
             }
             Ok(Message::Ping(pi)) => {
-                trace!("Ping:{:?}",pi);
+                trace!("服务器响应:Ping:{:?}",pi);
                 code = "200".to_string();
                 message_str = format!("服务器响应ping:{:?}", String::from_utf8(pi));
             }
             Ok(Message::Pong(po)) => {
-                trace!("Pong:{:?}",po);
+                trace!("服务器响应:Pong:{:?}",po);
                 //原始帧 正常读取数据不会读取到该 信息类型
                 code = "200".to_string();
                 message_str = format!("服务器响应pong:{:?}", String::from_utf8(po));
             }
             Ok(Message::Close(c)) => {
-                trace!("Close:{:?}",c);
+                trace!("服务器响应:Close:{:?}",c);
                 //原始帧 正常读取数据不会读取到该 信息类型
                 code = "0".to_string();
                 message_str = format!("关闭指令:{:?}", c);
             }
             Ok(Message::Frame(f)) => {
-                trace!("Frame:{:?}",f);
+                trace!("服务器响应:Frame:{:?}",f);
                 //原始帧 正常读取数据不会读取到该 信息类型
                 code = "-2".to_string();
                 message_str = format!("意外读取到原始帧:{:?}", f);
             }
             Err(e) => {
-                trace!("Err:{:?}",e);
+                trace!("服务器响应:Err:{:?}",e);
                 code = "-1".to_string();
                 message_str = format!("币安-数据解析 未知错误:{:?}", e);
             }
         }
-        return Option::from(ResponseData::new("".to_string(), code, message_str, data));
+        let zz = ResponseData::new("".to_string(), code, message_str, data);
+        // println!("??{:?}", zz);
+        return Option::from(zz);
     }
 
     /*******************************************************************************************************/
     /*****************************************socket基本*****************************************************/
     /*******************************************************************************************************/
     //链接
-    pub async fn ws_connect_async(&self,
+    pub async fn ws_connect_async(&mut self,
                                   bool_v1: Arc<AtomicBool>,
+                                  write_tx_am: &Arc<Mutex<UnboundedSender<Message>>>,
                                   write_rx: UnboundedReceiver<Message>,
-                                  read_tx: &UnboundedSender<ResponseData>) -> Result<(), Error> {
-        AbstractWsMode::ws_connect_async(self.address_url.clone(), bool_v1, write_rx, read_tx, self.label.clone(), BinanceSwapWs::analysis_message).await
-    }
-    //发出指令
-    pub fn write_message(&self, write_tx: UnboundedSender<Message>, str: String) {
-        trace!("发送指令:{}",str);
-        write_tx.unbounded_send(Message::Text(str.to_string())).expect(format!("发送失败:{}", str).as_str());
+                                  read_tx: UnboundedSender<ResponseData>,
+    ) -> Result<(), Error>
+    {
+        let login_is = self.contains_pr();
+        let subscription = self.get_subscription();
+        let address_url = self.address_url.clone();
+        let lable = self.lable.clone();
+        let heartbeat_time = self.heartbeat_time.clone();
+
+
+        //心跳-- 方法内部线程启动
+        let write_tx_clone1 = Arc::clone(write_tx_am);
+        tokio::spawn(async move {
+            trace!("线程-异步心跳-开始");
+            AbstractWsMode::ping_or_pong(bool_v1, write_tx_clone1, HeartbeatType::Pong, heartbeat_time).await;
+            trace!("线程-异步心跳-结束");
+        });
+
+
+        //设置订阅
+        let mut subscribe_array = vec![];
+        if login_is {
+            //登录相关
+        }
+        subscribe_array.push(subscription.to_string());
+
+
+        //1 链接
+
+        let t2 = tokio::spawn(async move {
+            trace!("线程-异步链接-开始");
+            AbstractWsMode::ws_connect_async(address_url.clone(),
+                                             lable.clone(), subscribe_array,
+                                             write_rx, read_tx, BinanceSwapWs::analysis_message,
+            ).await.expect("币安");
+            trace!("线程-异步链接-结束");
+        });
+        tokio::try_join!(t2).unwrap();
+        trace!("线程-心跳与链接-结束");
+
+
+        Ok(())
     }
-    //发出指令-订阅频道
-    pub fn send_subscribe(&self, write_tx: UnboundedSender<Message>) {
+    //主动订阅
+    pub fn send_subscribe(self, write_tx: Arc<Mutex<UnboundedSender<Message>>>) {
+        trace!("发起订阅");
         if self.contains_pr() {
             //有订阅需要登录
         }
         //发送订阅
         let subscribe = self.get_subscription();
-        self.write_message(write_tx, subscribe);
+        let message = Message::Text(subscribe.to_string());
+        AbstractWsMode::send_subscribe(write_tx, message);
     }
 
 
@@ -226,7 +275,12 @@ impl BinanceSwapWs {
         let mut res_data = ResponseData::new("".to_string(), "200".to_string(), "success".to_string(), "".to_string());
         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
 
-        if json_value.get("error").is_some() {//订阅返回
+        if json_value.get("result").is_some() && json_value.get("id").is_some() &&
+            json_value.get("id").unwrap() == 1
+        {
+            res_data.code = "-201".to_string();
+            res_data.message = "订阅成功".to_string();
+        } else if json_value.get("error").is_some() {//订阅返回
             res_data.code = json_value["error"]["code"].to_string();
             res_data.message = json_value["error"]["msg"].to_string();
         } else if json_value.get("stream").is_some() {//订阅返回

+ 501 - 504
exchanges/src/bitget_spot_ws.rs

@@ -1,504 +1,501 @@
-use std::collections::{BTreeMap};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::thread;
-use std::time::Duration;
-use chrono::Utc;
-use tokio::sync::mpsc::Sender;
-use serde_json::{json, Value};
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-use ring::hmac;
-
-pub enum BitgetWsType {
-    //频道类型
-    Public,
-    Private,
-}
-
-
-#[derive(Clone)]                        //订阅枚举
-pub enum BitgetSubscribeType {
-    PuTicker,
-    PuCandle1m,
-    PuTrade,
-    PuBooks5,
-
-    PrAccount,
-    PrOrders,
-}
-
-#[derive(Clone)]
-pub struct BitgetSpotWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //账号信息
-    login_param: BTreeMap<String, String>,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<BitgetSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,     //数据通道
-}
-
-impl BitgetSpotWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub fn new(is_colo: bool,
-               login_param: BTreeMap<String, String>,
-               ws_type: BitgetWsType,
-               sender: Sender<ResponseData>,
-    ) -> BitgetSpotWs
-    {
-        return BitgetSpotWs::new_label("default-BitgetSpotWs".to_string(), is_colo, login_param, ws_type, sender);
-    }
-    pub fn new_label(label: String, is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: BitgetWsType,
-                     sender: Sender<ResponseData>,
-    ) -> BitgetSpotWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-
-        let request_url = match ws_type {
-            BitgetWsType::Public => {
-                format!("wss://ws.bitget.com/v2/ws/public")
-            }
-            BitgetWsType::Private => {
-                format!("wss://ws.bitget.com/v2/ws/private")
-            }
-        };
-
-        if is_colo {
-            info!("开启高速(未配置,走普通:{})通道",request_url);
-        } else {
-            info!("走普通通道:{}",request_url);
-        }
-        /*****返回结构体*******/
-        BitgetSpotWs {
-            label,
-            request_url,
-            proxy: parsing_detail,
-            login_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<BitgetSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        let mut symbol_s = b_array.clone();
-        for symbol in symbol_s.iter_mut() {
-            // 大写
-            *symbol = symbol.to_uppercase();
-            // 字符串替换
-            *symbol = symbol.replace("-", "");
-            *symbol = symbol.replace("_", "");
-        }
-        self.symbol_s = symbol_s;
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: BitgetSubscribeType) -> Value {
-        match subscribe_type {
-            BitgetSubscribeType::PuTicker => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "ticker",
-                    "instId": symbol,
-                })
-            }
-            BitgetSubscribeType::PuCandle1m => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "candle1m",
-                    "instId": symbol,
-                })
-            }
-            BitgetSubscribeType::PuTrade => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "trade",
-                    "instId": symbol,
-                })
-            }
-            BitgetSubscribeType::PuBooks5 => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "books5",
-                    "instId": symbol,
-                })
-            }
-            BitgetSubscribeType::PrAccount => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "account",
-                    "coin": "default"
-                })
-            }
-            BitgetSubscribeType::PrOrders => {
-                json!({
-                    "instType": "SPOT",
-                    "channel": "orders",
-                    "instId": symbol
-                })
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> String {
-        let mut args = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
-                args.push(ty_str);
-            }
-        }
-        let str = json!({
-            "op": "subscribe",
-            "args": args
-        });
-
-        str.to_string()
-    }
-
-    // fn sign(secret_key: String, channel: String, event: String, time: String) -> String {
-    //     let message = format!("channel={}&event={}&time={}", channel, event, time);
-    //     let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
-    //     mac.update(message.as_bytes());
-    //     let result = mac.finalize().into_bytes();
-    //     let sign = hex::encode(result);
-    //     sign
-    // }
-
-    //组装登陆数据
-    fn log_in_to_str(&self) -> String {
-        let mut login_json_str = "".to_string();
-
-        let mut access_key: String = "".to_string();
-        let mut secret_key: String = "".to_string();
-        let mut passphrase: String = "".to_string();
-        for (key, value) in &self.login_param {
-            if key == "access_key" {
-                access_key = value.parse().unwrap();
-            } else if key == "secret_key" {
-                secret_key = value.parse().unwrap();
-            } else if key == "pass_key" {
-                passphrase = value.parse().unwrap();
-            }
-        }
-        if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
-            let timestamp = Utc::now().timestamp().to_string();
-            // 时间戳 + 请求类型+ 请求参数字符串
-            let message = format!("{}GET{}", timestamp, "/user/verify");
-            let hmac_key = ring::hmac::Key::new(hmac::HMAC_SHA256, secret_key.as_bytes());
-            let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
-            let sign = base64::encode(result);
-
-            let login_json = json!({
-                              "op": "login",
-                              "args": [{
-                                "apiKey": access_key,
-                                "passphrase": passphrase,
-                                "timestamp": timestamp,
-                                "sign": sign
-                              }]
-                        });
-
-            trace!("---login_json:{0}", login_json.to_string());
-            trace!("--登陆:{}", login_json.to_string());
-            login_json_str = login_json.to_string();
-        }
-        login_json_str
-    }
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&mut self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            trace!("要连接咯~~!!{}", self.request_url);
-
-            let request_url = Url::parse(self.request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: String)
-    {
-        info!("走代理-链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****登陆***/
-        let login_str = self.log_in_to_str();
-        if login_str != "" {
-            let _ = web_socket.write_message(Message::Text(login_str));
-            tokio::time::sleep(Duration::from_secs(3)).await;
-        }
-        /*****订阅***/
-        if subscription.len() > 0 {
-            info!("订阅信息:{}", subscription);
-            web_socket.write_message(Message::Text(subscription.clone()))
-                .unwrap();
-        }
-        /*****消息溜***/
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    if (get_time - ping_timeout) >= (1000 * 30) {
-                        trace!("30s 一次主动发送心跳包!");
-                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
-                        ping_timeout = get_time;
-                    }
-
-                    // let st_time = get_time_microsecond();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    // trace!("解析数据耗时::{}", st_time  - get_time_microsecond());
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else if res_data.code == "-201" {
-                        trace!("登陆:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("空数据不予返回:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        // let prev_time = Utc::now().timestamp_millis();
-                        tokio::spawn(async move {
-                            // info!("{:04} {}", Utc::now().timestamp_millis() - prev_time, res_data.channel);
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                    break;
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
-                          subscription: String)
-    {
-        info!("链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****登陆***/
-        let login_str = self.log_in_to_str();
-        if login_str != "" {
-            let _ = web_socket.write_message(Message::Text(login_str));
-            thread::sleep(Duration::from_secs(3));
-        }
-        /*****订阅***/
-        if subscription.len() > 0 {
-            trace!("订阅信息:{}",subscription);
-            web_socket.write_message(Message::Text(subscription))
-                .unwrap();
-        }
-        /*****消息溜***/
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    if (get_time - ping_timeout) >= (1000 * 30) {
-                        trace!("30s 一次主动发送心跳包!");
-                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
-                        ping_timeout = get_time;
-                    }
-
-                    // let st_time = get_time_microsecond();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    // trace!("解析数据耗时::{}", st_time  - get_time_microsecond());
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else if res_data.code == "-201" {
-                        trace!("登陆:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("空数据不予返回:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                    break;
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(label: String, text: String) -> ResponseData
-    {
-        // trace!("原始数据:{}", text);
-        // trace!("大小:{}", text.capacity());
-        let mut res_data = ResponseData::new(label.to_string(), "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-
-        // {"event":"login","code":0}
-        if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("login") {
-            if json_value.get("code").is_some() && json_value["code"] == 0 {
-                res_data.message = format!("登陆成功");
-            } else {
-                res_data.message = format!("登陆失败:({},{})", json_value.get("code").as_ref().unwrap(), json_value.get("msg").as_ref().unwrap());
-            }
-            res_data.channel = format!("login");
-            res_data.code = "-201".to_string();
-            res_data
-        } else if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("subscribe") {
-            // trace!("解析-订阅反馈:{}", text);
-            res_data.code = "-200".to_string();
-            res_data.data = text;
-            res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
-            res_data
-        } else if json_value.get("action").is_some() {
-            // trace!("解析-推送数据:{}", text);
-            res_data.data = json_value["data"].to_string();
-            if res_data.data == "[]" {
-                res_data.code = "-202".to_string();
-            } else {
-                res_data.code = "200".to_string();
-            }
-            res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
-            res_data.reach_time = json_value["ts"].as_i64().unwrap() * 1000;
-            res_data
-        } else {
-            res_data
-        }
-    }
-}
+// use std::collections::{BTreeMap};
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::thread;
+// use std::time::Duration;
+// use chrono::Utc;
+// use tokio::sync::mpsc::Sender;
+// use serde_json::{json, Value};
+// use tracing::{error, info, trace};
+// use crate::{proxy};
+// use url::Url;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+// use ring::hmac;
+//
+// pub enum BitgetWsType {
+//     //频道类型
+//     Public,
+//     Private,
+// }
+//
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum BitgetSubscribeType {
+//     PuTicker,
+//     PuCandle1m,
+//     PuTrade,
+//     PuBooks5,
+//
+//     PrAccount,
+//     PrOrders,
+// }
+//
+// #[derive(Clone)]
+// pub struct BitgetSpotWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //账号信息
+//     login_param: BTreeMap<String, String>,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<BitgetSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,     //数据通道
+// }
+//
+// impl BitgetSpotWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub fn new(is_colo: bool,
+//                login_param: BTreeMap<String, String>,
+//                ws_type: BitgetWsType,
+//                sender: Sender<ResponseData>,
+//     ) -> BitgetSpotWs
+//     {
+//         return BitgetSpotWs::new_label("default-BitgetSpotWs".to_string(), is_colo, login_param, ws_type, sender);
+//     }
+//     pub fn new_label(label: String, is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: BitgetWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> BitgetSpotWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//
+//         let request_url = match ws_type {
+//             BitgetWsType::Public => {
+//                 format!("wss://ws.bitget.com/v2/ws/public")
+//             }
+//             BitgetWsType::Private => {
+//                 format!("wss://ws.bitget.com/v2/ws/private")
+//             }
+//         };
+//
+//         if is_colo {
+//             info!("开启高速(未配置,走普通:{})通道",request_url);
+//         } else {
+//             info!("走普通通道:{}",request_url);
+//         }
+//         /*****返回结构体*******/
+//         BitgetSpotWs {
+//             label,
+//             request_url,
+//             proxy: parsing_detail,
+//             login_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<BitgetSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         let mut symbol_s = b_array.clone();
+//         for symbol in symbol_s.iter_mut() {
+//             // 大写
+//             *symbol = symbol.to_uppercase();
+//             // 字符串替换
+//             *symbol = symbol.replace("-", "");
+//             *symbol = symbol.replace("_", "");
+//         }
+//         self.symbol_s = symbol_s;
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: BitgetSubscribeType) -> Value {
+//         match subscribe_type {
+//             BitgetSubscribeType::PuTicker => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "ticker",
+//                     "instId": symbol,
+//                 })
+//             }
+//             BitgetSubscribeType::PuCandle1m => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "candle1m",
+//                     "instId": symbol,
+//                 })
+//             }
+//             BitgetSubscribeType::PuTrade => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "trade",
+//                     "instId": symbol,
+//                 })
+//             }
+//             BitgetSubscribeType::PuBooks5 => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "books5",
+//                     "instId": symbol,
+//                 })
+//             }
+//             BitgetSubscribeType::PrAccount => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "account",
+//                     "coin": "default"
+//                 })
+//             }
+//             BitgetSubscribeType::PrOrders => {
+//                 json!({
+//                     "instType": "SPOT",
+//                     "channel": "orders",
+//                     "instId": symbol
+//                 })
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> String {
+//         let mut args = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+//                 args.push(ty_str);
+//             }
+//         }
+//         let str = json!({
+//             "op": "subscribe",
+//             "args": args
+//         });
+//
+//         str.to_string()
+//     }
+//
+//     // fn sign(secret_key: String, channel: String, event: String, time: String) -> String {
+//     //     let message = format!("channel={}&event={}&time={}", channel, event, time);
+//     //     let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
+//     //     mac.update(message.as_bytes());
+//     //     let result = mac.finalize().into_bytes();
+//     //     let sign = hex::encode(result);
+//     //     sign
+//     // }
+//
+//     //组装登陆数据
+//     fn log_in_to_str(&self) -> String {
+//         let mut login_json_str = "".to_string();
+//
+//         let mut access_key: String = "".to_string();
+//         let mut secret_key: String = "".to_string();
+//         let mut passphrase: String = "".to_string();
+//         for (key, value) in &self.login_param {
+//             if key == "access_key" {
+//                 access_key = value.parse().unwrap();
+//             } else if key == "secret_key" {
+//                 secret_key = value.parse().unwrap();
+//             } else if key == "pass_key" {
+//                 passphrase = value.parse().unwrap();
+//             }
+//         }
+//         if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
+//             let timestamp = Utc::now().timestamp().to_string();
+//             // 时间戳 + 请求类型+ 请求参数字符串
+//             let message = format!("{}GET{}", timestamp, "/user/verify");
+//             let hmac_key = ring::hmac::Key::new(hmac::HMAC_SHA256, secret_key.as_bytes());
+//             let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
+//             let sign = base64::encode(result);
+//
+//             let login_json = json!({
+//                               "op": "login",
+//                               "args": [{
+//                                 "apiKey": access_key,
+//                                 "passphrase": passphrase,
+//                                 "timestamp": timestamp,
+//                                 "sign": sign
+//                               }]
+//                         });
+//
+//             trace!("---login_json:{0}", login_json.to_string());
+//             trace!("--登陆:{}", login_json.to_string());
+//             login_json_str = login_json.to_string();
+//         }
+//         login_json_str
+//     }
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&mut self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(5000)).await;
+//             trace!("要连接咯~~!!{}", self.request_url);
+//
+//             let request_url = Url::parse(self.request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 match connect_with_proxy(request_url.clone(),
+//                                          proxy_address, websocket_config, max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         error!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         error!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: String)
+//     {
+//         info!("走代理-链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****登陆***/
+//         let login_str = self.log_in_to_str();
+//         if login_str != "" {
+//             let _ = web_socket.write_message(Message::Text(login_str));
+//             tokio::time::sleep(Duration::from_secs(3)).await;
+//         }
+//         /*****订阅***/
+//         if subscription.len() > 0 {
+//             info!("订阅信息:{}", subscription);
+//             web_socket.write_message(Message::Text(subscription.clone()))
+//                 .unwrap();
+//         }
+//         /*****消息溜***/
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     if (get_time - ping_timeout) >= (1000 * 30) {
+//                         trace!("30s 一次主动发送心跳包!");
+//                         let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+//                         ping_timeout = get_time;
+//                     }
+//
+//                     // let st_time = get_time_microsecond();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     // trace!("解析数据耗时::{}", st_time  - get_time_microsecond());
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else if res_data.code == "-201" {
+//                         trace!("登陆:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("空数据不予返回:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         // let prev_time = Utc::now().timestamp_millis();
+//                         tokio::spawn(async move {
+//                             // info!("{:04} {}", Utc::now().timestamp_millis() - prev_time, res_data.channel);
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                     break;
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+//                           subscription: String)
+//     {
+//         info!("链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****登陆***/
+//         let login_str = self.log_in_to_str();
+//         if login_str != "" {
+//             let _ = web_socket.write_message(Message::Text(login_str));
+//             thread::sleep(Duration::from_secs(3));
+//         }
+//         /*****订阅***/
+//         if subscription.len() > 0 {
+//             trace!("订阅信息:{}",subscription);
+//             web_socket.write_message(Message::Text(subscription))
+//                 .unwrap();
+//         }
+//         /*****消息溜***/
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     if (get_time - ping_timeout) >= (1000 * 30) {
+//                         trace!("30s 一次主动发送心跳包!");
+//                         let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+//                         ping_timeout = get_time;
+//                     }
+//
+//                     // let st_time = get_time_microsecond();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     // trace!("解析数据耗时::{}", st_time  - get_time_microsecond());
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else if res_data.code == "-201" {
+//                         trace!("登陆:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("空数据不予返回:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                     break;
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(label: String, text: String) -> ResponseData
+//     {
+//         // trace!("原始数据:{}", text);
+//         // trace!("大小:{}", text.capacity());
+//         let mut res_data = ResponseData::new(label.to_string(), "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//
+//         // {"event":"login","code":0}
+//         if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("login") {
+//             if json_value.get("code").is_some() && json_value["code"] == 0 {
+//                 res_data.message = format!("登陆成功");
+//             } else {
+//                 res_data.message = format!("登陆失败:({},{})", json_value.get("code").as_ref().unwrap(), json_value.get("msg").as_ref().unwrap());
+//             }
+//             res_data.channel = format!("login");
+//             res_data.code = "-201".to_string();
+//             res_data
+//         } else if json_value.get("event").is_some() && json_value["event"].as_str() == Option::from("subscribe") {
+//             // trace!("解析-订阅反馈:{}", text);
+//             res_data.code = "-200".to_string();
+//             res_data.data = text;
+//             res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+//             res_data
+//         } else if json_value.get("action").is_some() {
+//             // trace!("解析-推送数据:{}", text);
+//             res_data.data = json_value["data"].to_string();
+//             if res_data.data == "[]" {
+//                 res_data.code = "-202".to_string();
+//             } else {
+//                 res_data.code = "200".to_string();
+//             }
+//             res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+//             res_data.reach_time = json_value["ts"].as_i64().unwrap() * 1000;
+//             res_data
+//         } else {
+//             res_data
+//         }
+//     }
+// }

+ 472 - 472
exchanges/src/gate_swap_ws.rs

@@ -1,472 +1,472 @@
-use std::collections::{BTreeMap};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use tokio::sync::mpsc::Sender;
-use serde_json::{json, Value};
-use hex;
-use hmac::{Hmac, Mac, NewMac};
-use sha2::Sha512;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-pub enum GateWsType {
-    //频道类型
-    PublicAndPrivate(String),
-}
-
-
-#[derive(Clone)]                        //订阅枚举
-pub enum GateSubscribeType {
-    PuFuturesOrderBook,
-    PuFuturesCandlesticks,
-    PuFuturesTrades,
-    //
-    PrFuturesOrders(String),
-    PrFuturesPositions(String),
-    PrFuturesBalances(String),
-
-}
-
-#[derive(Clone)]
-pub struct GateSwapWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //账号信息
-    login_param: BTreeMap<String, String>,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<GateSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,     //数据通道
-}
-
-impl GateSwapWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub fn new(is_colo: bool,
-               login_param: BTreeMap<String, String>,
-               ws_type: GateWsType,
-               sender: Sender<ResponseData>,
-    ) -> GateSwapWs
-    {
-        return GateSwapWs::new_label("default-GateSwapWs".to_string(), is_colo, login_param, ws_type, sender);
-    }
-    pub fn new_label(label: String, is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: GateWsType,
-                     sender: Sender<ResponseData>,
-    ) -> GateSwapWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-
-        let request_url = match ws_type {
-            GateWsType::PublicAndPrivate(name) => {
-                format!("wss://fx-ws.gateio.ws/v4/ws/{}", name.to_string())
-            }
-        };
-
-        if is_colo {
-            info!("开启高速(未配置,走普通:{})通道",request_url);
-        } else {
-            info!("走普通通道:{}",request_url);
-        }
-        /*****返回结构体*******/
-        GateSwapWs {
-            label,
-            request_url,
-            proxy: parsing_detail,
-            login_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<GateSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        let mut symbol_s = b_array.clone();
-        for symbol in symbol_s.iter_mut() {
-            // 大写
-            *symbol = symbol.to_uppercase();
-            // 字符串替换
-            *symbol = symbol.replace("-", "_");
-        }
-        self.symbol_s = symbol_s;
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: GateSubscribeType, login_param: BTreeMap<String, String>) -> Value {
-        let time = chrono::Utc::now().timestamp();
-        let mut access_key = "".to_string();
-        if login_param.contains_key("access_key") {
-            access_key = login_param.get("access_key").unwrap().to_string();
-        }
-        let mut secret_key = "".to_string();
-        if login_param.contains_key("secret_key") {
-            secret_key = login_param.get("secret_key").unwrap().to_string();
-        }
-
-        match subscribe_type {
-            GateSubscribeType::PuFuturesOrderBook => {
-                json!({
-                    "time": time,
-                    "channel": "futures.order_book",
-                    "event": "subscribe",
-                    "payload":  [symbol, "20", "0"]
-                })
-            }
-            GateSubscribeType::PuFuturesCandlesticks => {
-                json!({
-                    "time": time,
-                    "channel": "futures.candlesticks",
-                    "event": "subscribe",
-                    "payload":  ["1m", symbol]
-                })
-            }
-            GateSubscribeType::PrFuturesOrders(user_id) => {
-                json!({
-                    "time": time,
-                    "channel": "futures.orders",
-                    "event": "subscribe",
-                    "payload":  [user_id, symbol],
-                    "auth": {
-                        "method": "api_key",
-                        "KEY": access_key,
-                        "SIGN":Self::sign(secret_key.to_string(),
-                              "futures.orders".to_string(),
-                              "subscribe".to_string(),
-                              time.to_string())
-                    }
-                })
-            }
-            GateSubscribeType::PrFuturesPositions(user_id) => {
-                json!({
-                    "time": time,
-                    "channel": "futures.positions",
-                    "event": "subscribe",
-                    "payload":  [user_id, symbol],
-                    "auth": {
-                        "method": "api_key",
-                        "KEY": access_key,
-                        "SIGN":Self::sign(secret_key.to_string(),
-                              "futures.positions".to_string(),
-                              "subscribe".to_string(),
-                              time.to_string())
-                    }
-                })
-            }
-            GateSubscribeType::PrFuturesBalances(user_id) => {
-                json!({
-                    "time": time,
-                    "channel": "futures.balances",
-                    "event": "subscribe",
-                    "payload":  [user_id],
-                    "auth": {
-                        "method": "api_key",
-                        "KEY": access_key,
-                        "SIGN":Self::sign(secret_key.to_string(),
-                              "futures.balances".to_string(),
-                              "subscribe".to_string(),
-                              time.to_string())
-                    }
-                })
-            }
-            GateSubscribeType::PuFuturesTrades => {
-                json!({
-                    "time": time,
-                    "channel": "futures.trades",
-                    "event": "subscribe",
-                    "payload":  [symbol]
-                })
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> Vec<Value> {
-        let mut args = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(),
-                                                  subscribe_type.clone(),
-                                                  self.login_param.clone(),
-                );
-                args.push(ty_str);
-            }
-        }
-        args
-    }
-
-    fn sign(secret_key: String, channel: String, event: String, time: String) -> String {
-        let message = format!("channel={}&event={}&time={}", channel, event, time);
-        let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
-        mac.update(message.as_bytes());
-        let result = mac.finalize().into_bytes();
-        let sign = hex::encode(result);
-        sign
-    }
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&mut self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            trace!("要连接咯~~!!{}", self.request_url);
-
-            let request_url = Url::parse(self.request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: Vec<Value>)
-    {
-        info!("走代理-链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****订阅***/
-        for sub in &subscription {
-            trace!("订阅信息:{}", sub.to_string());
-            web_socket.write_message(Message::Text(sub.to_string()))
-                .unwrap();
-        }
-        /*****消息溜***/
-        let mut start_ping = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        // self.sender.send(res_data).await.unwrap();
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-
-                        //主动ping 服务器
-                        let new_time = chrono::Utc::now().timestamp_millis();
-                        // let tr = format!("判断-ping {}--{},{},{}",new_time,start_ping,(new_time - start_ping), (new_time - start_ping) > 10000);
-                        // trace!(tr);
-                        if (new_time - start_ping) > 10000 {
-                            let t = chrono::Utc::now().timestamp();
-                            let ping_str = serde_json::json!({
-                                "time" :t, "channel" : "futures.ping"
-                            });
-                            let _ = web_socket.write_message(Message::Ping(Vec::from(ping_str.to_string())));
-                            start_ping = new_time;
-                        }
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                    break;
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
-                          subscription: Vec<Value>)
-    {
-        info!("链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****订阅***/
-        for sub in &subscription {
-            trace!("订阅信息:{}", sub.to_string());
-            web_socket.write_message(Message::Text(sub.to_string()))
-                .unwrap();
-        }
-        /*****消息溜***/
-        let mut start_ping = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    // trace!("获取推送:{}",text.clone());
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        // self.sender.send(res_data).await.unwrap();
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-
-                        //主动ping 服务器
-                        let new_time = chrono::Utc::now().timestamp_millis();
-                        // let tr = format!("判断-ping {}--{},{},{}",new_time,start_ping,(new_time - start_ping), (new_time - start_ping) > 10000);
-                        // trace!(tr);
-                        if (new_time - start_ping) > 10000 {
-                            let t = chrono::Utc::now().timestamp();
-                            let ping_str = serde_json::json!({
-                                "time" :t, "channel" : "futures.ping"
-                            });
-                            let _ = web_socket.write_message(Message::Ping(Vec::from(ping_str.to_string())));
-                            start_ping = new_time;
-                        }
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                    break;
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(label: String, text: String) -> ResponseData
-    {
-        // trace!("原始数据:{}", text);
-        let mut res_data = ResponseData::new(label.to_string(), "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-
-        if json_value.get("error").is_some() {
-            let message = json_value["error"]["message"].as_str().unwrap().to_string();
-            let mes = message.trim_end_matches('\n');
-
-            // let mes_json_value: serde_json::Value = serde_json::from_str(mes).unwrap();
-            // // trace!("错误信息:{}", mes_json_value.to_string());
-            res_data.code = json_value["error"]["code"].to_string();
-            res_data.message = mes.to_string();
-        } else if json_value["result"]["status"].as_str() == Option::from("success") {//订阅返回
-            res_data.code = "-200".to_string();
-            res_data.data = text;
-        } else {
-            res_data.channel = format!("{}", json_value["channel"].as_str().unwrap());
-            res_data.code = "200".to_string();
-            res_data.data = json_value["result"].to_string();
-        }
-        res_data
-    }
-}
+// use std::collections::BTreeMap;
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::time::Duration;
+//
+// use hex;
+// use hmac::{Hmac, Mac, NewMac};
+// use serde_json::{json, Value};
+// use sha2::Sha512;
+// use tokio::sync::mpsc::Sender;
+// use tracing::{error, info, trace};
+// use url::Url;
+//
+//
+// use crate::proxy;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+// pub enum GateWsType {
+//     //频道类型
+//     PublicAndPrivate(String),
+// }
+//
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum GateSubscribeType {
+//     PuFuturesOrderBook,
+//     PuFuturesCandlesticks,
+//     PuFuturesTrades,
+//     //
+//     PrFuturesOrders(String),
+//     PrFuturesPositions(String),
+//     PrFuturesBalances(String),
+//
+// }
+//
+// #[derive(Clone)]
+// pub struct GateSwapWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //账号信息
+//     login_param: BTreeMap<String, String>,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<GateSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,     //数据通道
+// }
+//
+// impl GateSwapWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub fn new(is_colo: bool,
+//                login_param: BTreeMap<String, String>,
+//                ws_type: GateWsType,
+//                sender: Sender<ResponseData>,
+//     ) -> GateSwapWs
+//     {
+//         return GateSwapWs::new_label("default-GateSwapWs".to_string(), is_colo, login_param, ws_type, sender);
+//     }
+//     pub fn new_label(label: String, is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: GateWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> GateSwapWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//
+//         let request_url = match ws_type {
+//             GateWsType::PublicAndPrivate(name) => {
+//                 format!("wss://fx-ws.gateio.ws/v4/ws/{}", name.to_string())
+//             }
+//         };
+//
+//         if is_colo {
+//             info!("开启高速(未配置,走普通:{})通道",request_url);
+//         } else {
+//             info!("走普通通道:{}",request_url);
+//         }
+//         /*****返回结构体*******/
+//         GateSwapWs {
+//             label,
+//             request_url,
+//             proxy: parsing_detail,
+//             login_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<GateSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         let mut symbol_s = b_array.clone();
+//         for symbol in symbol_s.iter_mut() {
+//             // 大写
+//             *symbol = symbol.to_uppercase();
+//             // 字符串替换
+//             *symbol = symbol.replace("-", "_");
+//         }
+//         self.symbol_s = symbol_s;
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: GateSubscribeType, login_param: BTreeMap<String, String>) -> Value {
+//         let time = chrono::Utc::now().timestamp();
+//         let mut access_key = "".to_string();
+//         if login_param.contains_key("access_key") {
+//             access_key = login_param.get("access_key").unwrap().to_string();
+//         }
+//         let mut secret_key = "".to_string();
+//         if login_param.contains_key("secret_key") {
+//             secret_key = login_param.get("secret_key").unwrap().to_string();
+//         }
+//
+//         match subscribe_type {
+//             GateSubscribeType::PuFuturesOrderBook => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.order_book",
+//                     "event": "subscribe",
+//                     "payload":  [symbol, "20", "0"]
+//                 })
+//             }
+//             GateSubscribeType::PuFuturesCandlesticks => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.candlesticks",
+//                     "event": "subscribe",
+//                     "payload":  ["1m", symbol]
+//                 })
+//             }
+//             GateSubscribeType::PrFuturesOrders(user_id) => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.orders",
+//                     "event": "subscribe",
+//                     "payload":  [user_id, symbol],
+//                     "auth": {
+//                         "method": "api_key",
+//                         "KEY": access_key,
+//                         "SIGN":Self::sign(secret_key.to_string(),
+//                               "futures.orders".to_string(),
+//                               "subscribe".to_string(),
+//                               time.to_string())
+//                     }
+//                 })
+//             }
+//             GateSubscribeType::PrFuturesPositions(user_id) => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.positions",
+//                     "event": "subscribe",
+//                     "payload":  [user_id, symbol],
+//                     "auth": {
+//                         "method": "api_key",
+//                         "KEY": access_key,
+//                         "SIGN":Self::sign(secret_key.to_string(),
+//                               "futures.positions".to_string(),
+//                               "subscribe".to_string(),
+//                               time.to_string())
+//                     }
+//                 })
+//             }
+//             GateSubscribeType::PrFuturesBalances(user_id) => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.balances",
+//                     "event": "subscribe",
+//                     "payload":  [user_id],
+//                     "auth": {
+//                         "method": "api_key",
+//                         "KEY": access_key,
+//                         "SIGN":Self::sign(secret_key.to_string(),
+//                               "futures.balances".to_string(),
+//                               "subscribe".to_string(),
+//                               time.to_string())
+//                     }
+//                 })
+//             }
+//             GateSubscribeType::PuFuturesTrades => {
+//                 json!({
+//                     "time": time,
+//                     "channel": "futures.trades",
+//                     "event": "subscribe",
+//                     "payload":  [symbol]
+//                 })
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> Vec<Value> {
+//         let mut args = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(),
+//                                                   subscribe_type.clone(),
+//                                                   self.login_param.clone(),
+//                 );
+//                 args.push(ty_str);
+//             }
+//         }
+//         args
+//     }
+//
+//     fn sign(secret_key: String, channel: String, event: String, time: String) -> String {
+//         let message = format!("channel={}&event={}&time={}", channel, event, time);
+//         let mut mac = Hmac::<Sha512>::new_varkey(secret_key.as_bytes()).expect("Failed to create HMAC");
+//         mac.update(message.as_bytes());
+//         let result = mac.finalize().into_bytes();
+//         let sign = hex::encode(result);
+//         sign
+//     }
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&mut self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(5000)).await;
+//             trace!("要连接咯~~!!{}", self.request_url);
+//
+//             let request_url = Url::parse(self.request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 match connect_with_proxy(request_url.clone(),
+//                                          proxy_address, websocket_config, max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         error!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         error!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>, subscription: Vec<Value>)
+//     {
+//         info!("走代理-链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****订阅***/
+//         for sub in &subscription {
+//             trace!("订阅信息:{}", sub.to_string());
+//             web_socket.write_message(Message::Text(sub.to_string()))
+//                 .unwrap();
+//         }
+//         /*****消息溜***/
+//         let mut start_ping = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     // trace!("获取推送:{}",text.clone());
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         // self.sender.send(res_data).await.unwrap();
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//
+//                         //主动ping 服务器
+//                         let new_time = chrono::Utc::now().timestamp_millis();
+//                         // let tr = format!("判断-ping {}--{},{},{}",new_time,start_ping,(new_time - start_ping), (new_time - start_ping) > 10000);
+//                         // trace!(tr);
+//                         if (new_time - start_ping) > 10000 {
+//                             let t = chrono::Utc::now().timestamp();
+//                             let ping_str = serde_json::json!({
+//                                 "time" :t, "channel" : "futures.ping"
+//                             });
+//                             let _ = web_socket.write_message(Message::Ping(Vec::from(ping_str.to_string())));
+//                             start_ping = new_time;
+//                         }
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                     break;
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+//                           subscription: Vec<Value>)
+//     {
+//         info!("链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****订阅***/
+//         for sub in &subscription {
+//             trace!("订阅信息:{}", sub.to_string());
+//             web_socket.write_message(Message::Text(sub.to_string()))
+//                 .unwrap();
+//         }
+//         /*****消息溜***/
+//         let mut start_ping = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     // trace!("获取推送:{}",text.clone());
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         // self.sender.send(res_data).await.unwrap();
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//
+//                         //主动ping 服务器
+//                         let new_time = chrono::Utc::now().timestamp_millis();
+//                         // let tr = format!("判断-ping {}--{},{},{}",new_time,start_ping,(new_time - start_ping), (new_time - start_ping) > 10000);
+//                         // trace!(tr);
+//                         if (new_time - start_ping) > 10000 {
+//                             let t = chrono::Utc::now().timestamp();
+//                             let ping_str = serde_json::json!({
+//                                 "time" :t, "channel" : "futures.ping"
+//                             });
+//                             let _ = web_socket.write_message(Message::Ping(Vec::from(ping_str.to_string())));
+//                             start_ping = new_time;
+//                         }
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                     break;
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(label: String, text: String) -> ResponseData
+//     {
+//         // trace!("原始数据:{}", text);
+//         let mut res_data = ResponseData::new(label.to_string(), "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//
+//         if json_value.get("error").is_some() {
+//             let message = json_value["error"]["message"].as_str().unwrap().to_string();
+//             let mes = message.trim_end_matches('\n');
+//
+//             // let mes_json_value: serde_json::Value = serde_json::from_str(mes).unwrap();
+//             // // trace!("错误信息:{}", mes_json_value.to_string());
+//             res_data.code = json_value["error"]["code"].to_string();
+//             res_data.message = mes.to_string();
+//         } else if json_value["result"]["status"].as_str() == Option::from("success") {//订阅返回
+//             res_data.code = "-200".to_string();
+//             res_data.data = text;
+//         } else {
+//             res_data.channel = format!("{}", json_value["channel"].as_str().unwrap());
+//             res_data.code = "200".to_string();
+//             res_data.data = json_value["result"].to_string();
+//         }
+//         res_data
+//     }
+// }

+ 506 - 509
exchanges/src/kucoin_spot_ws.rs

@@ -1,509 +1,506 @@
-use std::collections::{BTreeMap, HashSet};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use tokio::sync::mpsc::Sender;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::kucoin_spot_rest::KucoinSpotRest;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-
-pub enum KucoinWsType {
-    Public,
-    Private,
-}
-
-#[derive(Debug)]
-#[derive(Clone)]
-pub struct KucoinWsParam {
-    pub token: String,
-    pub ws_url: String,
-    pub ws_ping_interval: i64,
-    pub ws_ping_timeout: i64,
-}
-
-#[derive(Clone)]                        //订阅枚举
-pub enum KucoinSubscribeType {
-    PuSpotMarketLevel2Depth50,
-    PuMarketMatch,
-    PuMarketTicker,
-
-    PrSpotMarketTradeOrders,
-    PrAccountBalance,
-}
-
-#[derive(Clone)]
-pub struct KucoinSpotWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //代理信息
-    // login_param: BTreeMap<String, String>,
-    //登陆数据
-    ws_param: KucoinWsParam,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<KucoinSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,     //数据通道
-}
-
-impl KucoinSpotWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub async fn new(is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: KucoinWsType,
-                     sender: Sender<ResponseData>,
-    ) -> KucoinSpotWs {
-        return KucoinSpotWs::new_label("default-KucoinSpotWs".to_string(), is_colo, login_param, ws_type, sender).await;
-    }
-    pub async fn new_label(label: String, _is_colo: bool,
-                           login_param: BTreeMap<String, String>,
-                           ws_type: KucoinWsType,
-                           sender: Sender<ResponseData>,
-    ) -> KucoinSpotWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-        /*******公共频道-私有频道数据组装*/
-        let mut ws_param = KucoinWsParam {
-            token: "".to_string(),
-            ws_url: "".to_string(),
-            ws_ping_interval: 0,
-            ws_ping_timeout: 0,
-        };
-        let res_data = KucoinSpotWs::get_rul_token(ws_type, login_param.clone()).await;
-        match res_data {
-            Ok(param) => {
-                ws_param = param
-            }
-            Err(error) => {
-                error!("-链接地址等参数错误:{:?}", error)
-            }
-        }
-
-
-        /*****返回结构体*******/
-        KucoinSpotWs {
-            label,
-            request_url: "".to_string(),
-            proxy: parsing_detail,
-            // login_param,
-            ws_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<KucoinSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //根据当前类型获取对应的频道 地址 与 token
-    async fn get_rul_token(ws_type: KucoinWsType, login_param: BTreeMap<String, String>) -> Result<KucoinWsParam, reqwest::Error> {
-        let mut kucoin_exc = KucoinSpotRest::new(false, login_param.clone());
-        let res_data = match ws_type {
-            KucoinWsType::Public => {
-                kucoin_exc.get_public_token().await
-            }
-            KucoinWsType::Private => {
-                kucoin_exc.get_private_token().await
-            }
-        };
-
-        trace!("kucoin-spot-rest 获取ws连接地址:{:?}",res_data);
-
-        if res_data.code == "200" {
-            let mut ws_url = "".to_string();
-            let mut ws_token = "".to_string();
-            let mut ws_ping_interval: i64 = 0;
-            let mut ws_ping_timeout: i64 = 0;
-
-
-            //数据解析
-            let parsed_json: serde_json::Value = serde_json::from_str(res_data.data.as_str()).unwrap();
-            if let Some(value) = parsed_json.get("token") {
-                let formatted_value = match value {
-                    serde_json::Value::String(s) => s.clone(),
-                    _ => value.to_string()
-                };
-                ws_token = format!("{}", formatted_value);
-            }
-            if let Some(endpoint) = parsed_json["instanceServers"][0]["endpoint"].as_str() {
-                ws_url = format!("{}", endpoint);
-            }
-            if let Some(ping_interval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
-                ws_ping_interval = ping_interval;
-            }
-            if let Some(ping_timeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
-                ws_ping_timeout = ping_timeout;
-            }
-
-
-            Ok(KucoinWsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
-        } else {
-            error!("公共/私有-频道获取失败:{:?}", res_data);
-            panic!("公共/私有-频道获取失败:{:?}", res_data);
-        }
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        let mut symbol_s = b_array.clone();
-        for symbol in symbol_s.iter_mut() {
-            // 大写
-            *symbol = symbol.to_uppercase();
-            // 字符串替换
-            *symbol = symbol.replace("_", "-");
-        }
-        self.symbol_s = symbol_s.clone();
-        self.request_url = format!("{}?token={}", self.ws_param.ws_url, self.ws_param.token);
-        info!("走普通通道:{}",  self.request_url);
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: KucoinSubscribeType) -> serde_json::Value {
-        match subscribe_type {
-            KucoinSubscribeType::PuSpotMarketLevel2Depth50 => {//level2
-                serde_json::json!({
-                     "topic": format!("/spotMarket/level2Depth50:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-            KucoinSubscribeType::PuMarketMatch => {//match
-                serde_json::json!({
-                     "topic": format!("/market/match:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-            KucoinSubscribeType::PuMarketTicker => {//ticker
-                serde_json::json!({
-                     "topic": format!("/market/ticker:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-
-            KucoinSubscribeType::PrSpotMarketTradeOrders => {//market.tradeOrders
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": "/spotMarket/tradeOrders",
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-            KucoinSubscribeType::PrAccountBalance => {//account.balance
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": "/account/balance",
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> Vec<String> {
-        let mut array = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
-                array.push(ty_str.to_string());
-            }
-        }
-        array
-    }
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        let subscription: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            trace!("要连接咯~~!!{}", self.request_url);
-            //币安-登陆流程-rest请求获取k然后拿到 key 拼接地址
-            // if self.is_login { //暂时没看到有订阅的频道需要登陆 所以暂时不做
-            // }
-
-            let request_url = Url::parse(self.request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                let _ = match connect_with_proxy(request_url.clone(),
-                                                 proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                let _ = match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
-                                subscription: Vec<String>)
-    {
-        info!("走代理-链接成功!开始数据读取");
-        info!(?subscription);
-        let label = self.label.clone();
-        /*****消息溜***/
-        let mut ping_interval = chrono::Utc::now().timestamp_millis();
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    //心跳-一定时间间隔发送心跳
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
-                    //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
-                    if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
-                        web_socket.write_message(Message::Ping(Vec::from("ping")))
-                            .unwrap();
-                        trace!("--发送心跳-ping");
-                        ping_interval = get_time;
-                        ping_timeout = get_time;
-                    } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
-                        //心跳超时-发送心跳之后 一定时间没有响应
-                        trace!("--心跳相应超时-重连");
-                        break;
-                    }
-
-                    // trace!("获取推送:{}",text.clone());
-                    // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    // trace!("获取推送:{:?}", res_data);
-                    if res_data.code == "-200" {//表示链接成功
-                        for sub in &subscription {
-                            trace!("--发起订阅:{:?}", sub);
-                            web_socket.write_message(Message::Text(sub.parse().unwrap()))
-                                .unwrap();
-                        }
-                    } else if res_data.code == "-201" {
-                        trace!("订阅成功:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("无用数据:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                    ping_timeout = chrono::Utc::now().timestamp_millis();
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
-                          subscription: Vec<String>)
-    {
-        info!("链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****消息溜***/
-        let mut ping_interval = chrono::Utc::now().timestamp_millis();
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    //心跳-一定时间间隔发送心跳
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
-                    //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
-                    if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
-                        web_socket.write_message(Message::Ping(Vec::from("ping")))
-                            .unwrap();
-                        trace!("--发送心跳-ping");
-                        ping_interval = get_time;
-                        ping_timeout = get_time;
-                    } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
-                        //心跳超时-发送心跳之后 一定时间没有响应
-                        trace!("--心跳相应超时-重连");
-                        break;
-                    }
-
-                    // trace!("获取推送:{}",text.clone());
-                    // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    // trace!("获取推送:{:?}", res_data);
-                    if res_data.code == "-200" {//表示链接成功
-                        for sub in &subscription {
-                            trace!("--发起订阅:{:?}", sub);
-                            web_socket.write_message(Message::Text(sub.parse().unwrap()))
-                                .unwrap();
-                        }
-                    } else if res_data.code == "-201" {
-                        trace!("订阅成功:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("无用数据:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                    ping_timeout = chrono::Utc::now().timestamp_millis();
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(lable: String, text: String) -> ResponseData
-    {
-        let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-        //订阅 相应
-        if json_value["type"].as_str() == Option::from("welcome") {
-            //链接成功
-            res_data.code = "-200".to_string();
-            res_data.message = "链接成功,主动发起订阅".to_string();
-            trace!("链接成功,主动发起订阅:");
-        } else if json_value["type"].as_str() == Option::from("ack") {
-            res_data.code = "-201".to_string();
-            res_data.message = "订阅成功".to_string();
-        } else if json_value["type"].as_str() == Option::from("error") {
-            res_data.code = format!("{}", json_value["code"]);
-            res_data.message = format!("{}", json_value["data"].as_str().unwrap());
-        } else if json_value.get("topic").is_some() {
-            res_data.channel = format!("{}", json_value["subject"].as_str().unwrap());
-
-            if json_value["topic"].as_str() == Option::from("/contractAccount/wallet") {
-                res_data.code = "-202".to_string();
-                if json_value["subject"].as_str() == Option::from("availableBalance.change") {
-                    res_data.code = "200".to_string();
-                    res_data.data = json_value["data"].to_string();
-                } else {}
-            } else {
-                res_data.data = json_value["data"].to_string();
-            }
-        } else {
-            res_data.code = "-1".to_string();
-            res_data.message = "未知解析".to_string();
-        }
-        res_data
-    }
-}
+// use std::collections::{BTreeMap, HashSet};
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::time::Duration;
+// use tokio::sync::mpsc::Sender;
+// use tracing::{error, info, trace};
+// use crate::{proxy};
+// use url::Url;
+// use crate::kucoin_spot_rest::KucoinSpotRest;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+//
+// pub enum KucoinWsType {
+//     Public,
+//     Private,
+// }
+//
+// #[derive(Debug)]
+// #[derive(Clone)]
+// pub struct KucoinWsParam {
+//     pub token: String,
+//     pub ws_url: String,
+//     pub ws_ping_interval: i64,
+//     pub ws_ping_timeout: i64,
+// }
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum KucoinSubscribeType {
+//     PuSpotMarketLevel2Depth50,
+//     PuMarketMatch,
+//     PuMarketTicker,
+//
+//     PrSpotMarketTradeOrders,
+//     PrAccountBalance,
+// }
+//
+// #[derive(Clone)]
+// pub struct KucoinSpotWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //代理信息
+//     // login_param: BTreeMap<String, String>,
+//     //登陆数据
+//     ws_param: KucoinWsParam,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<KucoinSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,     //数据通道
+// }
+//
+// impl KucoinSpotWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub async fn new(is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: KucoinWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> KucoinSpotWs {
+//         return KucoinSpotWs::new_label("default-KucoinSpotWs".to_string(), is_colo, login_param, ws_type, sender).await;
+//     }
+//     pub async fn new_label(label: String, _is_colo: bool,
+//                            login_param: BTreeMap<String, String>,
+//                            ws_type: KucoinWsType,
+//                            sender: Sender<ResponseData>,
+//     ) -> KucoinSpotWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//         /*******公共频道-私有频道数据组装*/
+//         let mut ws_param = KucoinWsParam {
+//             token: "".to_string(),
+//             ws_url: "".to_string(),
+//             ws_ping_interval: 0,
+//             ws_ping_timeout: 0,
+//         };
+//         let res_data = KucoinSpotWs::get_rul_token(ws_type, login_param.clone()).await;
+//         match res_data {
+//             Ok(param) => {
+//                 ws_param = param
+//             }
+//             Err(error) => {
+//                 error!("-链接地址等参数错误:{:?}", error)
+//             }
+//         }
+//
+//
+//         /*****返回结构体*******/
+//         KucoinSpotWs {
+//             label,
+//             request_url: "".to_string(),
+//             proxy: parsing_detail,
+//             // login_param,
+//             ws_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<KucoinSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //根据当前类型获取对应的频道 地址 与 token
+//     async fn get_rul_token(ws_type: KucoinWsType, login_param: BTreeMap<String, String>) -> Result<KucoinWsParam, reqwest::Error> {
+//         let mut kucoin_exc = KucoinSpotRest::new(false, login_param.clone());
+//         let res_data = match ws_type {
+//             KucoinWsType::Public => {
+//                 kucoin_exc.get_public_token().await
+//             }
+//             KucoinWsType::Private => {
+//                 kucoin_exc.get_private_token().await
+//             }
+//         };
+//
+//         trace!("kucoin-spot-rest 获取ws连接地址:{:?}",res_data);
+//
+//         if res_data.code == "200" {
+//             let mut ws_url = "".to_string();
+//             let mut ws_token = "".to_string();
+//             let mut ws_ping_interval: i64 = 0;
+//             let mut ws_ping_timeout: i64 = 0;
+//
+//
+//             //数据解析
+//             let parsed_json: serde_json::Value = serde_json::from_str(res_data.data.as_str()).unwrap();
+//             if let Some(value) = parsed_json.get("token") {
+//                 let formatted_value = match value {
+//                     serde_json::Value::String(s) => s.clone(),
+//                     _ => value.to_string()
+//                 };
+//                 ws_token = format!("{}", formatted_value);
+//             }
+//             if let Some(endpoint) = parsed_json["instanceServers"][0]["endpoint"].as_str() {
+//                 ws_url = format!("{}", endpoint);
+//             }
+//             if let Some(ping_interval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
+//                 ws_ping_interval = ping_interval;
+//             }
+//             if let Some(ping_timeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
+//                 ws_ping_timeout = ping_timeout;
+//             }
+//
+//
+//             Ok(KucoinWsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
+//         } else {
+//             error!("公共/私有-频道获取失败:{:?}", res_data);
+//             panic!("公共/私有-频道获取失败:{:?}", res_data);
+//         }
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         let mut symbol_s = b_array.clone();
+//         for symbol in symbol_s.iter_mut() {
+//             // 大写
+//             *symbol = symbol.to_uppercase();
+//             // 字符串替换
+//             *symbol = symbol.replace("_", "-");
+//         }
+//         self.symbol_s = symbol_s.clone();
+//         self.request_url = format!("{}?token={}", self.ws_param.ws_url, self.ws_param.token);
+//         info!("走普通通道:{}",  self.request_url);
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: KucoinSubscribeType) -> serde_json::Value {
+//         match subscribe_type {
+//             KucoinSubscribeType::PuSpotMarketLevel2Depth50 => {//level2
+//                 serde_json::json!({
+//                      "topic": format!("/spotMarket/level2Depth50:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//             KucoinSubscribeType::PuMarketMatch => {//match
+//                 serde_json::json!({
+//                      "topic": format!("/market/match:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//             KucoinSubscribeType::PuMarketTicker => {//ticker
+//                 serde_json::json!({
+//                      "topic": format!("/market/ticker:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//
+//             KucoinSubscribeType::PrSpotMarketTradeOrders => {//market.tradeOrders
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": "/spotMarket/tradeOrders",
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//             KucoinSubscribeType::PrAccountBalance => {//account.balance
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": "/account/balance",
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> Vec<String> {
+//         let mut array = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+//                 array.push(ty_str.to_string());
+//             }
+//         }
+//         array
+//     }
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         let subscription: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(5000)).await;
+//             trace!("要连接咯~~!!{}", self.request_url);
+//             //币安-登陆流程-rest请求获取k然后拿到 key 拼接地址
+//             // if self.is_login { //暂时没看到有订阅的频道需要登陆 所以暂时不做
+//             // }
+//
+//             let request_url = Url::parse(self.request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 let _ = match connect_with_proxy(request_url.clone(),
+//                                                  proxy_address, websocket_config, max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         error!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 let _ = match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         error!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
+//                                 subscription: Vec<String>)
+//     {
+//         info!("走代理-链接成功!开始数据读取");
+//         info!(?subscription);
+//         let label = self.label.clone();
+//         /*****消息溜***/
+//         let mut ping_interval = chrono::Utc::now().timestamp_millis();
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     //心跳-一定时间间隔发送心跳
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
+//                     //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
+//                     if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
+//                         web_socket.write_message(Message::Ping(Vec::from("ping")))
+//                             .unwrap();
+//                         trace!("--发送心跳-ping");
+//                         ping_interval = get_time;
+//                         ping_timeout = get_time;
+//                     } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
+//                         //心跳超时-发送心跳之后 一定时间没有响应
+//                         trace!("--心跳相应超时-重连");
+//                         break;
+//                     }
+//
+//                     // trace!("获取推送:{}",text.clone());
+//                     // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     // trace!("获取推送:{:?}", res_data);
+//                     if res_data.code == "-200" {//表示链接成功
+//                         for sub in &subscription {
+//                             trace!("--发起订阅:{:?}", sub);
+//                             web_socket.write_message(Message::Text(sub.parse().unwrap()))
+//                                 .unwrap();
+//                         }
+//                     } else if res_data.code == "-201" {
+//                         trace!("订阅成功:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("无用数据:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                     ping_timeout = chrono::Utc::now().timestamp_millis();
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+//                           subscription: Vec<String>)
+//     {
+//         info!("链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****消息溜***/
+//         let mut ping_interval = chrono::Utc::now().timestamp_millis();
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     //心跳-一定时间间隔发送心跳
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
+//                     //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
+//                     if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
+//                         web_socket.write_message(Message::Ping(Vec::from("ping")))
+//                             .unwrap();
+//                         trace!("--发送心跳-ping");
+//                         ping_interval = get_time;
+//                         ping_timeout = get_time;
+//                     } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
+//                         //心跳超时-发送心跳之后 一定时间没有响应
+//                         trace!("--心跳相应超时-重连");
+//                         break;
+//                     }
+//
+//                     // trace!("获取推送:{}",text.clone());
+//                     // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     // trace!("获取推送:{:?}", res_data);
+//                     if res_data.code == "-200" {//表示链接成功
+//                         for sub in &subscription {
+//                             trace!("--发起订阅:{:?}", sub);
+//                             web_socket.write_message(Message::Text(sub.parse().unwrap()))
+//                                 .unwrap();
+//                         }
+//                     } else if res_data.code == "-201" {
+//                         trace!("订阅成功:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("无用数据:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                     ping_timeout = chrono::Utc::now().timestamp_millis();
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(lable: String, text: String) -> ResponseData
+//     {
+//         let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//         //订阅 相应
+//         if json_value["type"].as_str() == Option::from("welcome") {
+//             //链接成功
+//             res_data.code = "-200".to_string();
+//             res_data.message = "链接成功,主动发起订阅".to_string();
+//             trace!("链接成功,主动发起订阅:");
+//         } else if json_value["type"].as_str() == Option::from("ack") {
+//             res_data.code = "-201".to_string();
+//             res_data.message = "订阅成功".to_string();
+//         } else if json_value["type"].as_str() == Option::from("error") {
+//             res_data.code = format!("{}", json_value["code"]);
+//             res_data.message = format!("{}", json_value["data"].as_str().unwrap());
+//         } else if json_value.get("topic").is_some() {
+//             res_data.channel = format!("{}", json_value["subject"].as_str().unwrap());
+//
+//             if json_value["topic"].as_str() == Option::from("/contractAccount/wallet") {
+//                 res_data.code = "-202".to_string();
+//                 if json_value["subject"].as_str() == Option::from("availableBalance.change") {
+//                     res_data.code = "200".to_string();
+//                     res_data.data = json_value["data"].to_string();
+//                 } else {}
+//             } else {
+//                 res_data.data = json_value["data"].to_string();
+//             }
+//         } else {
+//             res_data.code = "-1".to_string();
+//             res_data.message = "未知解析".to_string();
+//         }
+//         res_data
+//     }
+// }

+ 516 - 519
exchanges/src/kucoin_swap_ws.rs

@@ -1,519 +1,516 @@
-use std::collections::{BTreeMap, HashSet};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use tokio::sync::mpsc::Sender;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::kucoin_swap_rest::KucoinSwapRest;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-
-pub enum KucoinWsType {
-    Public,
-    Private,
-}
-
-#[derive(Debug)]
-#[derive(Clone)]
-pub struct KucoinWsParam {
-    pub token: String,
-    pub ws_url: String,
-    pub ws_ping_interval: i64,
-    pub ws_ping_timeout: i64,
-}
-
-#[derive(Clone)]                        //订阅枚举
-pub enum KucoinSubscribeType {
-    PuContractMarketLevel2Depth50,
-    PuContractMarketExecution,
-    PuContractMarkettickerV2,
-
-    PrContractAccountWallet,
-    PrContractPosition,
-    PrContractMarketTradeOrdersSys,
-    PrContractMarketTradeOrders,
-}
-
-#[derive(Clone)]
-pub struct KucoinSwapWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //代理信息
-    // login_param: BTreeMap<String, String>,
-    //登陆数据
-    ws_param: KucoinWsParam,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<KucoinSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,     //数据通道
-}
-
-impl KucoinSwapWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub async fn new(is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: KucoinWsType,
-                     sender: Sender<ResponseData>,
-    ) -> KucoinSwapWs {
-        return KucoinSwapWs::new_label("default-KucoinSwapWs".to_string(), is_colo, login_param, ws_type, sender).await;
-    }
-    pub async fn new_label(label: String, _is_colo: bool,
-                           login_param: BTreeMap<String, String>,
-                           ws_type: KucoinWsType,
-                           sender: Sender<ResponseData>,
-    ) -> KucoinSwapWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-        /*******公共频道-私有频道数据组装*/
-        let mut ws_param = KucoinWsParam {
-            token: "".to_string(),
-            ws_url: "".to_string(),
-            ws_ping_interval: 0,
-            ws_ping_timeout: 0,
-        };
-        let res_data = KucoinSwapWs::get_rul_token(ws_type, login_param.clone()).await;
-        match res_data {
-            Ok(param) => {
-                ws_param = param
-            }
-            Err(error) => {
-                error!("-链接地址等参数错误:{:?}", error)
-            }
-        }
-
-
-        /*****返回结构体*******/
-        KucoinSwapWs {
-            label,
-            request_url: "".to_string(),
-            proxy: parsing_detail,
-            // login_param,
-            ws_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<KucoinSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //根据当前类型获取对应的频道 地址 与 token
-    async fn get_rul_token(ws_type: KucoinWsType, login_param: BTreeMap<String, String>) -> Result<KucoinWsParam, reqwest::Error> {
-        let mut kucoin_exc = KucoinSwapRest::new(false, login_param.clone());
-        let res_data = match ws_type {
-            KucoinWsType::Public => {
-                kucoin_exc.get_public_token().await
-            }
-            KucoinWsType::Private => {
-                kucoin_exc.get_private_token().await
-            }
-        };
-
-        trace!("kucoin-swap-rest 获取ws连接地址:{:?}",res_data);
-
-        if res_data.code == "200" {
-            let mut ws_url = "".to_string();
-            let mut ws_token = "".to_string();
-            let mut ws_ping_interval: i64 = 0;
-            let mut ws_ping_timeout: i64 = 0;
-
-
-            //数据解析
-            let parsed_json: serde_json::Value = serde_json::from_str(res_data.data.as_str()).unwrap();
-            if let Some(value) = parsed_json.get("token") {
-                let formatted_value = match value {
-                    serde_json::Value::String(s) => s.clone(),
-                    _ => value.to_string()
-                };
-                ws_token = format!("{}", formatted_value);
-            }
-            if let Some(endpoint) = parsed_json["instanceServers"][0]["endpoint"].as_str() {
-                ws_url = format!("{}", endpoint);
-            }
-            if let Some(ping_interval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
-                ws_ping_interval = ping_interval;
-            }
-            if let Some(ping_timeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
-                ws_ping_timeout = ping_timeout;
-            }
-
-
-            Ok(KucoinWsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
-        } else {
-            error!("公共/私有-频道获取失败:{:?}", res_data);
-            panic!("公共/私有-频道获取失败:{:?}", res_data);
-        }
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        self.symbol_s = b_array.clone();
-        self.request_url = format!("{}?token={}", self.ws_param.ws_url, self.ws_param.token);
-        info!("走普通通道:{}",  self.request_url);
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: KucoinSubscribeType) -> serde_json::Value {
-        match subscribe_type {
-            KucoinSubscribeType::PuContractMarketLevel2Depth50 => {//level2
-                serde_json::json!({
-                     "topic": format!("/contractMarket/level2Depth50:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-            KucoinSubscribeType::PuContractMarketExecution => {//match
-                serde_json::json!({
-                     "topic": format!("/contractMarket/execution:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-            KucoinSubscribeType::PuContractMarkettickerV2 => {//tickerV2
-                serde_json::json!({
-                     "topic": format!("/contractMarket/tickerV2:{}", symbol),
-                     "type": "subscribe",
-                     "response": true
-                })
-            }
-            KucoinSubscribeType::PrContractAccountWallet => {//orderMargin.change
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": "/contractAccount/wallet",
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-            KucoinSubscribeType::PrContractPosition => {//position.change
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": format!("/contract/position:{}", symbol),
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-            KucoinSubscribeType::PrContractMarketTradeOrdersSys => {//orderChange
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": format!("/contractMarket/tradeOrders"),
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-            KucoinSubscribeType::PrContractMarketTradeOrders => {//symbolOrderChange
-                serde_json::json!({
-                    "type": "subscribe",
-                    "topic": format!("/contractMarket/tradeOrders:{}", symbol),
-                    "privateChannel":true,
-                    "response":true,
-                })
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> Vec<String> {
-        let mut array = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
-                array.push(ty_str.to_string());
-            }
-        }
-        array
-    }
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        let subscription: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            trace!("要连接咯~~!!{}", self.request_url);
-            //币安-登陆流程-rest请求获取k然后拿到 key 拼接地址
-            // if self.is_login { //暂时没看到有订阅的频道需要登陆 所以暂时不做
-            // }
-
-            let request_url = Url::parse(self.request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                let _ = match connect_with_proxy(request_url.clone(),
-                                                 proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        error!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                let _ = match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        error!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
-                                subscription: Vec<String>)
-    {
-        info!("走代理-链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****消息溜***/
-        let mut ping_interval = chrono::Utc::now().timestamp_millis();
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    //心跳-一定时间间隔发送心跳
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
-                    //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
-                    if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
-                        web_socket.write_message(Message::Ping(Vec::from("ping")))
-                            .unwrap();
-                        trace!("--发送心跳-ping");
-                        ping_interval = get_time;
-                        ping_timeout = get_time;
-                    } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
-                        //心跳超时-发送心跳之后 一定时间没有响应
-                        trace!("--心跳相应超时-重连");
-                        break;
-                    }
-
-                    trace!("获取推送:{}",text.clone());
-                    // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    // trace!("获取推送:{:?}", res_data);
-                    if res_data.code == "-200" {//表示链接成功
-                        for sub in &subscription {
-                            trace!("--发起订阅:{:?}", sub);
-                            web_socket.write_message(Message::Text(sub.parse().unwrap()))
-                                .unwrap();
-                        }
-                    } else if res_data.code == "-201" {
-                        trace!("订阅成功:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("无用数据:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        // let prev_time = Utc::now().timestamp_millis();
-                        tokio::spawn(async move {
-                            // info!("{:04} {}", Utc::now().timestamp_millis() - prev_time, res_data.channel);
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                    ping_timeout = chrono::Utc::now().timestamp_millis();
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
-                          subscription: Vec<String>)
-    {
-        info!("链接成功!开始数据读取");
-        let label = self.label.clone();
-        /*****消息溜***/
-        let mut ping_interval = chrono::Utc::now().timestamp_millis();
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    //心跳-一定时间间隔发送心跳
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
-                    //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
-                    if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
-                        web_socket.write_message(Message::Ping(Vec::from("ping")))
-                            .unwrap();
-                        trace!("--发送心跳-ping");
-                        ping_interval = get_time;
-                        ping_timeout = get_time;
-                    } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
-                        //心跳超时-发送心跳之后 一定时间没有响应
-                        trace!("--心跳相应超时-重连");
-                        break;
-                    }
-
-                    trace!("获取推送:{}",text.clone());
-                    // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
-                    let mut res_data = Self::ok_text(label.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    // trace!("获取推送:{:?}", res_data);
-                    if res_data.code == "-200" {//表示链接成功
-                        for sub in &subscription {
-                            trace!("--发起订阅:{:?}", sub);
-                            web_socket.write_message(Message::Text(sub.parse().unwrap()))
-                                .unwrap();
-                        }
-                    } else if res_data.code == "-201" {
-                        trace!("订阅成功:{:?}", res_data);
-                    } else if res_data.code == "-202" {
-                        trace!("无用数据:{:?}", res_data);
-                    } else {
-                        let sender = self.sender.clone();
-                        tokio::spawn(async move {
-                            sender.send(res_data).await.unwrap();
-                        });
-                        tokio::spawn(async move {});
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!("Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
-                    ping_timeout = chrono::Utc::now().timestamp_millis();
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(error) => {
-                    // trace!("Error receiving message: {}", error);
-                    error!( "Err-响应{}", error);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(lable: String, text: String) -> ResponseData
-    {
-        let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-        //订阅 相应
-        if json_value["type"].as_str() == Option::from("welcome") {
-            //链接成功
-            res_data.code = "-200".to_string();
-            res_data.message = "链接成功,主动发起订阅".to_string();
-            trace!("链接成功,主动发起订阅:");
-        } else if json_value["type"].as_str() == Option::from("ack") {
-            res_data.code = "-201".to_string();
-            res_data.message = "订阅成功".to_string();
-        } else if json_value["type"].as_str() == Option::from("error") {
-            res_data.code = format!("{}", json_value["code"]);
-            res_data.message = format!("{}", json_value["data"].as_str().unwrap());
-        } else if json_value.get("topic").is_some() {
-            res_data.channel = format!("{}", json_value["subject"].as_str().unwrap());
-
-            if json_value["topic"].as_str() == Option::from("/contractAccount/wallet") {
-                res_data.code = "-202".to_string();
-                if json_value["subject"].as_str() == Option::from("availableBalance.change") {
-                    res_data.code = "200".to_string();
-                    res_data.data = json_value["data"].to_string();
-                } else {}
-            } else {
-                res_data.data = json_value["data"].to_string();
-            }
-        } else {
-            res_data.code = "-1".to_string();
-            res_data.message = "未知解析".to_string();
-        }
-        res_data
-    }
-}
+// use std::collections::{BTreeMap, HashSet};
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::time::Duration;
+// use tokio::sync::mpsc::Sender;
+// use tracing::{error, info, trace};
+// use crate::{proxy};
+// use url::Url;
+// use crate::kucoin_swap_rest::KucoinSwapRest;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+//
+// pub enum KucoinWsType {
+//     Public,
+//     Private,
+// }
+//
+// #[derive(Debug)]
+// #[derive(Clone)]
+// pub struct KucoinWsParam {
+//     pub token: String,
+//     pub ws_url: String,
+//     pub ws_ping_interval: i64,
+//     pub ws_ping_timeout: i64,
+// }
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum KucoinSubscribeType {
+//     PuContractMarketLevel2Depth50,
+//     PuContractMarketExecution,
+//     PuContractMarkettickerV2,
+//
+//     PrContractAccountWallet,
+//     PrContractPosition,
+//     PrContractMarketTradeOrdersSys,
+//     PrContractMarketTradeOrders,
+// }
+//
+// #[derive(Clone)]
+// pub struct KucoinSwapWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //代理信息
+//     // login_param: BTreeMap<String, String>,
+//     //登陆数据
+//     ws_param: KucoinWsParam,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<KucoinSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,     //数据通道
+// }
+//
+// impl KucoinSwapWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub async fn new(is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: KucoinWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> KucoinSwapWs {
+//         return KucoinSwapWs::new_label("default-KucoinSwapWs".to_string(), is_colo, login_param, ws_type, sender).await;
+//     }
+//     pub async fn new_label(label: String, _is_colo: bool,
+//                            login_param: BTreeMap<String, String>,
+//                            ws_type: KucoinWsType,
+//                            sender: Sender<ResponseData>,
+//     ) -> KucoinSwapWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//         /*******公共频道-私有频道数据组装*/
+//         let mut ws_param = KucoinWsParam {
+//             token: "".to_string(),
+//             ws_url: "".to_string(),
+//             ws_ping_interval: 0,
+//             ws_ping_timeout: 0,
+//         };
+//         let res_data = KucoinSwapWs::get_rul_token(ws_type, login_param.clone()).await;
+//         match res_data {
+//             Ok(param) => {
+//                 ws_param = param
+//             }
+//             Err(error) => {
+//                 error!("-链接地址等参数错误:{:?}", error)
+//             }
+//         }
+//
+//
+//         /*****返回结构体*******/
+//         KucoinSwapWs {
+//             label,
+//             request_url: "".to_string(),
+//             proxy: parsing_detail,
+//             // login_param,
+//             ws_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<KucoinSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //根据当前类型获取对应的频道 地址 与 token
+//     async fn get_rul_token(ws_type: KucoinWsType, login_param: BTreeMap<String, String>) -> Result<KucoinWsParam, reqwest::Error> {
+//         let mut kucoin_exc = KucoinSwapRest::new(false, login_param.clone());
+//         let res_data = match ws_type {
+//             KucoinWsType::Public => {
+//                 kucoin_exc.get_public_token().await
+//             }
+//             KucoinWsType::Private => {
+//                 kucoin_exc.get_private_token().await
+//             }
+//         };
+//
+//         trace!("kucoin-swap-rest 获取ws连接地址:{:?}",res_data);
+//
+//         if res_data.code == "200" {
+//             let mut ws_url = "".to_string();
+//             let mut ws_token = "".to_string();
+//             let mut ws_ping_interval: i64 = 0;
+//             let mut ws_ping_timeout: i64 = 0;
+//
+//
+//             //数据解析
+//             let parsed_json: serde_json::Value = serde_json::from_str(res_data.data.as_str()).unwrap();
+//             if let Some(value) = parsed_json.get("token") {
+//                 let formatted_value = match value {
+//                     serde_json::Value::String(s) => s.clone(),
+//                     _ => value.to_string()
+//                 };
+//                 ws_token = format!("{}", formatted_value);
+//             }
+//             if let Some(endpoint) = parsed_json["instanceServers"][0]["endpoint"].as_str() {
+//                 ws_url = format!("{}", endpoint);
+//             }
+//             if let Some(ping_interval) = parsed_json["instanceServers"][0]["pingInterval"].as_i64() {
+//                 ws_ping_interval = ping_interval;
+//             }
+//             if let Some(ping_timeout) = parsed_json["instanceServers"][0]["pingTimeout"].as_i64() {
+//                 ws_ping_timeout = ping_timeout;
+//             }
+//
+//
+//             Ok(KucoinWsParam { ws_url, token: ws_token, ws_ping_interval, ws_ping_timeout })
+//         } else {
+//             error!("公共/私有-频道获取失败:{:?}", res_data);
+//             panic!("公共/私有-频道获取失败:{:?}", res_data);
+//         }
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         self.symbol_s = b_array.clone();
+//         self.request_url = format!("{}?token={}", self.ws_param.ws_url, self.ws_param.token);
+//         info!("走普通通道:{}",  self.request_url);
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: KucoinSubscribeType) -> serde_json::Value {
+//         match subscribe_type {
+//             KucoinSubscribeType::PuContractMarketLevel2Depth50 => {//level2
+//                 serde_json::json!({
+//                      "topic": format!("/contractMarket/level2Depth50:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//             KucoinSubscribeType::PuContractMarketExecution => {//match
+//                 serde_json::json!({
+//                      "topic": format!("/contractMarket/execution:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//             KucoinSubscribeType::PuContractMarkettickerV2 => {//tickerV2
+//                 serde_json::json!({
+//                      "topic": format!("/contractMarket/tickerV2:{}", symbol),
+//                      "type": "subscribe",
+//                      "response": true
+//                 })
+//             }
+//             KucoinSubscribeType::PrContractAccountWallet => {//orderMargin.change
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": "/contractAccount/wallet",
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//             KucoinSubscribeType::PrContractPosition => {//position.change
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": format!("/contract/position:{}", symbol),
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//             KucoinSubscribeType::PrContractMarketTradeOrdersSys => {//orderChange
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": format!("/contractMarket/tradeOrders"),
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//             KucoinSubscribeType::PrContractMarketTradeOrders => {//symbolOrderChange
+//                 serde_json::json!({
+//                     "type": "subscribe",
+//                     "topic": format!("/contractMarket/tradeOrders:{}", symbol),
+//                     "privateChannel":true,
+//                     "response":true,
+//                 })
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> Vec<String> {
+//         let mut array = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+//                 array.push(ty_str.to_string());
+//             }
+//         }
+//         array
+//     }
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         let subscription: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(5000)).await;
+//             trace!("要连接咯~~!!{}", self.request_url);
+//             //币安-登陆流程-rest请求获取k然后拿到 key 拼接地址
+//             // if self.is_login { //暂时没看到有订阅的频道需要登陆 所以暂时不做
+//             // }
+//
+//             let request_url = Url::parse(self.request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 let _ = match connect_with_proxy(request_url.clone(),
+//                                                  proxy_address, websocket_config, max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         error!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 let _ = match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         error!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
+//                                 subscription: Vec<String>)
+//     {
+//         info!("走代理-链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****消息溜***/
+//         let mut ping_interval = chrono::Utc::now().timestamp_millis();
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     //心跳-一定时间间隔发送心跳
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
+//                     //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
+//                     if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
+//                         web_socket.write_message(Message::Ping(Vec::from("ping")))
+//                             .unwrap();
+//                         trace!("--发送心跳-ping");
+//                         ping_interval = get_time;
+//                         ping_timeout = get_time;
+//                     } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
+//                         //心跳超时-发送心跳之后 一定时间没有响应
+//                         trace!("--心跳相应超时-重连");
+//                         break;
+//                     }
+//
+//                     trace!("获取推送:{}",text.clone());
+//                     // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     // trace!("获取推送:{:?}", res_data);
+//                     if res_data.code == "-200" {//表示链接成功
+//                         for sub in &subscription {
+//                             trace!("--发起订阅:{:?}", sub);
+//                             web_socket.write_message(Message::Text(sub.parse().unwrap()))
+//                                 .unwrap();
+//                         }
+//                     } else if res_data.code == "-201" {
+//                         trace!("订阅成功:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("无用数据:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         // let prev_time = Utc::now().timestamp_millis();
+//                         tokio::spawn(async move {
+//                             // info!("{:04} {}", Utc::now().timestamp_millis() - prev_time, res_data.channel);
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                     ping_timeout = chrono::Utc::now().timestamp_millis();
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+//                           subscription: Vec<String>)
+//     {
+//         info!("链接成功!开始数据读取");
+//         let label = self.label.clone();
+//         /*****消息溜***/
+//         let mut ping_interval = chrono::Utc::now().timestamp_millis();
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     //心跳-一定时间间隔发送心跳
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     // trace!("--心跳-{}-{}-{}-{}-{}", get_time, ping_interval
+//                     //          , (get_time - ping_interval), self.ws_param.ws_ping_interval, (get_time - ping_interval) >= self.ws_param.ws_ping_interval);
+//                     if (get_time - ping_interval) >= self.ws_param.ws_ping_interval {
+//                         web_socket.write_message(Message::Ping(Vec::from("ping")))
+//                             .unwrap();
+//                         trace!("--发送心跳-ping");
+//                         ping_interval = get_time;
+//                         ping_timeout = get_time;
+//                     } else if (get_time - ping_timeout) > (self.ws_param.ws_ping_timeout + self.ws_param.ws_ping_interval) {
+//                         //心跳超时-发送心跳之后 一定时间没有响应
+//                         trace!("--心跳相应超时-重连");
+//                         break;
+//                     }
+//
+//                     trace!("获取推送:{}",text.clone());
+//                     // trace!(stdout, "Text-响应--{:?}", text.clone()).unwrap();
+//                     let mut res_data = Self::ok_text(label.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     // trace!("获取推送:{:?}", res_data);
+//                     if res_data.code == "-200" {//表示链接成功
+//                         for sub in &subscription {
+//                             trace!("--发起订阅:{:?}", sub);
+//                             web_socket.write_message(Message::Text(sub.parse().unwrap()))
+//                                 .unwrap();
+//                         }
+//                     } else if res_data.code == "-201" {
+//                         trace!("订阅成功:{:?}", res_data);
+//                     } else if res_data.code == "-202" {
+//                         trace!("无用数据:{:?}", res_data);
+//                     } else {
+//                         let sender = self.sender.clone();
+//                         tokio::spawn(async move {
+//                             sender.send(res_data).await.unwrap();
+//                         });
+//                         tokio::spawn(async move {});
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!("Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!("Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                     ping_timeout = chrono::Utc::now().timestamp_millis();
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(error) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     error!( "Err-响应{}", error);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(lable: String, text: String) -> ResponseData
+//     {
+//         let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//         //订阅 相应
+//         if json_value["type"].as_str() == Option::from("welcome") {
+//             //链接成功
+//             res_data.code = "-200".to_string();
+//             res_data.message = "链接成功,主动发起订阅".to_string();
+//             trace!("链接成功,主动发起订阅:");
+//         } else if json_value["type"].as_str() == Option::from("ack") {
+//             res_data.code = "-201".to_string();
+//             res_data.message = "订阅成功".to_string();
+//         } else if json_value["type"].as_str() == Option::from("error") {
+//             res_data.code = format!("{}", json_value["code"]);
+//             res_data.message = format!("{}", json_value["data"].as_str().unwrap());
+//         } else if json_value.get("topic").is_some() {
+//             res_data.channel = format!("{}", json_value["subject"].as_str().unwrap());
+//
+//             if json_value["topic"].as_str() == Option::from("/contractAccount/wallet") {
+//                 res_data.code = "-202".to_string();
+//                 if json_value["subject"].as_str() == Option::from("availableBalance.change") {
+//                     res_data.code = "200".to_string();
+//                     res_data.data = json_value["data"].to_string();
+//                 } else {}
+//             } else {
+//                 res_data.data = json_value["data"].to_string();
+//             }
+//         } else {
+//             res_data.code = "-1".to_string();
+//             res_data.message = "未知解析".to_string();
+//         }
+//         res_data
+//     }
+// }

+ 80 - 17
exchanges/src/kucoin_swap_ws_async.rs

@@ -1,5 +1,5 @@
 use std::collections::BTreeMap;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 use std::sync::atomic::AtomicBool;
 
 use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
@@ -8,7 +8,7 @@ use tracing::{error, info, trace};
 
 use crate::kucoin_swap_rest::KucoinSwapRest;
 use crate::response_base::ResponseData;
-use crate::socket_tool::AbstractWsMode;
+use crate::socket_tool::{AbstractWsMode, HeartbeatType};
 
 pub enum KucoinSwapWsType {
     //订阅频道类型
@@ -48,16 +48,20 @@ pub struct KucoinSwapLogin {
 
 #[derive(Clone)]
 pub struct KucoinSwapWs {
-    label: String,
+    //类型
+    lable: String,
+    //地址
     address_url: String,
     //账号信息
     login_param: Option<KucoinSwapLogin>,
     //登陆数据
     ws_param: KucoinSwapWsParam,
-    //kuconis特殊参数
+    //币对
     symbol_s: Vec<String>,
-    //订阅币对
+    //订阅
     subscribe_types: Vec<KucoinSwapSubscribeType>,
+    //心跳间隔
+    heartbeat_time: u64,
 }
 
 impl KucoinSwapWs {
@@ -65,9 +69,9 @@ impl KucoinSwapWs {
     /*****************************************获取一个对象****************************************************/
     /*******************************************************************************************************/
     pub async fn new(is_colo: bool, login_param: Option<KucoinSwapLogin>, ws_type: KucoinSwapWsType) -> KucoinSwapWs {
-        return Self::new_label("default-KucoinSwapWs".to_string(), is_colo, login_param, ws_type).await;
+        return Self::new_lable("default-KucoinSwapWs".to_string(), is_colo, login_param, ws_type).await;
     }
-    pub async fn new_label(label: String, is_colo: bool, login_param: Option<KucoinSwapLogin>, ws_type: KucoinSwapWsType) -> KucoinSwapWs {
+    pub async fn new_lable(lable: String, is_colo: bool, login_param: Option<KucoinSwapLogin>, ws_type: KucoinSwapWsType) -> KucoinSwapWs {
         /*******公共频道-私有频道数据组装*/
         let mut ws_param = KucoinSwapWsParam {
             token: "".to_string(),
@@ -97,12 +101,13 @@ impl KucoinSwapWs {
         }
 
         KucoinSwapWs {
-            label,
+            lable,
             address_url,
             login_param,
             ws_param,
             symbol_s: vec![],
             subscribe_types: vec![],
+            heartbeat_time: 1000,
         }
     }
 
@@ -187,7 +192,23 @@ impl KucoinSwapWs {
         self.symbol_s = b_array;
         trace!("币对??:{:?}",self.symbol_s);
     }
+    fn contains_pr(&self) -> bool {
+        for t in self.subscribe_types.clone() {
+            if match t {
+                KucoinSwapSubscribeType::PuContractMarketLevel2Depth50 => false,
+                KucoinSwapSubscribeType::PuContractMarketExecution => false,
+                KucoinSwapSubscribeType::PuContractMarkettickerV2 => false,
 
+                KucoinSwapSubscribeType::PrContractAccountWallet => true,
+                KucoinSwapSubscribeType::PrContractPosition => true,
+                KucoinSwapSubscribeType::PrContractMarketTradeOrdersSys => true,
+                KucoinSwapSubscribeType::PrContractMarketTradeOrders => true,
+            } {
+                return true;
+            }
+        }
+        false
+    }
     /*******************************************************************************************************/
     /*****************************************工具函数********************************************************/
     /*******************************************************************************************************/
@@ -269,15 +290,19 @@ impl KucoinSwapWs {
             Ok(Message::Text(text)) => {
                 let response_data = Self::ok_text(text);
                 if response_data.code == "-200" {
-                    // trace!("链接成功允许订阅:{:?}", response_data);
-                    return None
+                    trace!("链接成功允许订阅:{:?}", response_data);
+                    return None;
                 } else if response_data.code == "-201" {
                     trace!("订阅成功:{:?}", response_data);
-                    return None
+                    return None;
+                } else if response_data.code == "-202" {
+                    trace!("未知数据:{:?}", response_data);
+                    return None;
                 } else {
                     return Option::from(response_data);
                 }
             }
+
             Ok(Message::Binary(s)) => {
                 trace!("Binary:{:?}",s);
             }
@@ -311,7 +336,7 @@ impl KucoinSwapWs {
             }
         }
         let zz = ResponseData::new("".to_string(), code, message_str, data);
-        println!("??{:?}", zz);
+        // println!("??{:?}", zz);
         return Option::from(zz);
     }
 
@@ -319,11 +344,50 @@ impl KucoinSwapWs {
     /*****************************************socket基本*****************************************************/
     /*******************************************************************************************************/
     //链接
-    pub async fn ws_connect_async(&self,
+    pub async fn ws_connect_async(&mut self,
                                   bool_v1: Arc<AtomicBool>,
+                                  write_tx_am: &Arc<Mutex<UnboundedSender<Message>>>,
                                   write_rx: UnboundedReceiver<Message>,
-                                  read_tx: &UnboundedSender<ResponseData>) -> Result<(), Error> {
-        AbstractWsMode::ws_connect_async(self.address_url.clone(), bool_v1, write_rx, read_tx, self.label.clone(), KucoinSwapWs::analysis_message).await
+                                  read_tx: UnboundedSender<ResponseData>,
+    ) -> Result<(), Error>
+    {
+        let login_is = self.contains_pr();
+        let subscription = self.get_subscription();
+        let address_url = self.address_url.clone();
+        let lable = self.lable.clone();
+        let heartbeat_time = self.heartbeat_time.clone();
+
+        //心跳-- 方法内部线程启动
+        let write_tx_clone1 = Arc::clone(write_tx_am);
+       tokio::spawn(async move {
+            trace!("线程-异步心跳-开始");
+            AbstractWsMode::ping_or_pong(bool_v1, write_tx_clone1, HeartbeatType::Ping, heartbeat_time).await;
+            trace!("线程-异步心跳-结束");
+        });
+
+
+        //设置订阅
+        let  subscribe_array =  subscription.clone();
+        if login_is {
+            //登录相关
+        }
+
+
+        //1 链接
+
+        let t2 = tokio::spawn(async move {
+            trace!("线程-异步链接-开始");
+            AbstractWsMode::ws_connect_async(address_url.clone(),
+                                             lable.clone(), subscribe_array,
+                                             write_rx, read_tx, KucoinSwapWs::analysis_message,
+            ).await.expect("kucoin");
+            trace!("线程-异步链接-结束");
+        });
+        tokio::try_join!(t2).unwrap();
+        trace!("线程-心跳与链接-结束");
+
+
+        Ok(())
     }
     //发出指令
     pub fn write_message(&self, write_tx: UnboundedSender<Message>, str: String) {
@@ -334,7 +398,7 @@ impl KucoinSwapWs {
     //数据解析
     pub fn ok_text(text: String) -> ResponseData
     {
-        trace!("原始数据:{:?}",text);
+        // trace!("原始数据:{:?}",text);
         let mut res_data = ResponseData::new("".to_string(), "200".to_string(), "success".to_string(), "".to_string());
         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
 
@@ -343,7 +407,6 @@ impl KucoinSwapWs {
             //链接成功
             res_data.code = "-200".to_string();
             res_data.message = "链接成功,主动发起订阅".to_string();
-            trace!("链接成功,主动发起订阅:");
         } else if json_value["type"].as_str() == Option::from("ack") {
             res_data.code = "-201".to_string();
             res_data.message = "订阅成功".to_string();

+ 476 - 479
exchanges/src/okx_swap_ws.rs

@@ -1,479 +1,476 @@
-use std::collections::{BTreeMap};
-use std::{thread};
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use chrono::Utc;
-use serde_json::{json, Value};
-use ring::hmac;
-use tokio::sync::mpsc::Sender;
-use tracing::{error, info, trace};
-use crate::{proxy};
-use tungstenite::client::{AutoStream, connect_with_proxy, ProxyAutoStream};
-use tungstenite::{connect, Message, WebSocket};
-use tungstenite::protocol::WebSocketConfig;
-use url::Url;
-use crate::proxy::ParsingDetail;
-use crate::response_base::ResponseData;
-use crate::utils::get_time_microsecond;
-
-pub enum OkxWsType {
-    //订阅频道类型
-    Public,
-    Private,
-    Business,
-}
-
-
-#[derive(Clone)]                        //订阅枚举
-pub enum OkxSubscribeType {
-    PuIndexTickers,
-    PuBooks5,
-    Putrades,
-    PuBooks50L2tbt,
-    //
-    BuIndexCandle30m,
-    //
-    PrBalanceAndPosition,
-    PrAccount(String),
-    PrOrders,
-    PrPositions,
-
-}
-
-#[derive(Clone)]
-pub struct OkxSwapWs {
-    pub label: String,
-    request_url: String,
-    //实际ws 链接地址
-    proxy: ParsingDetail,
-    //账号信息
-    login_param: BTreeMap<String, String>,
-    //kuconis特殊参数
-    symbol_s: Vec<String>,
-    //订阅币对
-    subscribe_types: Vec<OkxSubscribeType>,
-    //订阅信息
-    sender: Sender<ResponseData>,     //数据通道
-}
-
-impl OkxSwapWs {
-    /*******************************************************************************************************/
-    /*****************************************获取一个对象****************************************************/
-    /*******************************************************************************************************/
-    pub fn new(is_colo: bool,
-               login_param: BTreeMap<String, String>,
-               ws_type: OkxWsType,
-               sender: Sender<ResponseData>,
-    ) -> OkxSwapWs
-    {
-        return OkxSwapWs::new_label("default-OkxSwapWs".to_string(), is_colo, login_param, ws_type, sender);
-    }
-    pub fn new_label(label: String, is_colo: bool,
-                     login_param: BTreeMap<String, String>,
-                     ws_type: OkxWsType,
-                     sender: Sender<ResponseData>,
-    ) -> OkxSwapWs
-    {
-        /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
-        let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
-
-        /*******公共频道-私有频道数据组装*/
-        let request_url = match ws_type {
-            OkxWsType::Public => {
-                "wss://ws.okx.com:8443/ws/v5/public".to_string()
-            }
-            OkxWsType::Private => {
-                "wss://ws.okx.com:8443/ws/v5/private".to_string()
-            }
-            OkxWsType::Business => {
-                "wss://ws.okx.com:8443/ws/v5/business".to_string()
-            }
-        };
-
-        if is_colo {
-            info!("开启高速(未配置,走普通:{})通道",request_url);
-        } else {
-            info!("走普通通道:{}",request_url);
-        }
-        /*****返回结构体*******/
-        OkxSwapWs {
-            label,
-            request_url,
-            proxy: parsing_detail,
-            login_param,
-            symbol_s: vec![],
-            subscribe_types: vec![],
-            sender,
-        }
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************订阅函数********************************************************/
-    /*******************************************************************************************************/
-    //手动添加订阅信息
-    pub fn set_subscribe(&mut self, subscribe_types: Vec<OkxSubscribeType>) {
-        self.subscribe_types.extend(subscribe_types);
-    }
-    //自定义
-    pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
-    {
-        let mut symbol_s = b_array.clone();
-        for symbol in symbol_s.iter_mut() {
-            // 大写
-            *symbol = symbol.to_uppercase();
-            // 字符串替换
-            *symbol = symbol.replace("_", "-");
-        }
-        self.symbol_s = symbol_s;
-        self.run(bool_v1).await;
-    }
-
-    /*******************************************************************************************************/
-    /*****************************************工具函数********************************************************/
-    /*******************************************************************************************************/
-    //订阅枚举解析
-    pub fn enum_to_string(symbol: String, subscribe_type: OkxSubscribeType) -> Value {
-        match subscribe_type {
-            OkxSubscribeType::PuIndexTickers => {
-                json!({
-                    "channel":"index-tickers",
-                    "instId":symbol
-                })
-            }
-
-            OkxSubscribeType::PuBooks5 => {
-                json!({
-                    "channel":"books5",
-                    "instId":symbol
-                })
-            }
-            OkxSubscribeType::Putrades => {
-                json!({
-                    "channel":"trades",
-                    "instId":symbol
-                })
-            }
-
-            OkxSubscribeType::BuIndexCandle30m => {
-                json!({
-                    "channel":"index-candle30m",
-                    "instId":symbol
-                })
-            }
-
-            OkxSubscribeType::PrAccount(ccy) => {
-                json!({
-                    "channel":"account",
-                    "ccy":ccy
-                })
-            }
-            OkxSubscribeType::PuBooks50L2tbt => {
-                json!({
-                    "channel":"books50-l2-tbt",
-                    "instId":symbol
-                })
-            }
-            OkxSubscribeType::PrBalanceAndPosition => {
-                json!({
-                    "channel":"balance_and_position"
-                })
-            }
-            OkxSubscribeType::PrOrders => {
-                json!({
-                    "channel":"orders",
-                    "instType":"SWAP",
-                    "instFamily":symbol
-                })
-            }
-            OkxSubscribeType::PrPositions => {
-                json!({
-                    "channel":"positions",
-                    "instType":"SWAP",
-                })
-            }
-        }
-    }
-    //组装订阅数据
-    pub fn get_subscription(&self) -> String {
-        let mut args = vec![];
-        for symbol in &self.symbol_s {
-            for subscribe_type in &self.subscribe_types {
-                let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
-                args.push(ty_str);
-            }
-        }
-        let str = json!({
-            "op": "subscribe",
-            "args": args
-        });
-
-        trace!("订阅信息:{}", str.to_string());
-
-        str.to_string()
-    }
-
-    //组装登陆数据
-    fn log_in_to_str(&self) -> String {
-        let mut login_json_str = "".to_string();
-
-        let mut access_key: String = "".to_string();
-        let mut secret_key: String = "".to_string();
-        let mut passphrase: String = "".to_string();
-        for (key, value) in &self.login_param {
-            if key == "access_key" {
-                access_key = value.parse().unwrap();
-            } else if key == "secret_key" {
-                secret_key = value.parse().unwrap();
-            } else if key == "pass_key" {
-                passphrase = value.parse().unwrap();
-            }
-        }
-        if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
-            let timestamp = Utc::now().timestamp().to_string();
-            // 时间戳 + 请求类型+ 请求参数字符串
-            let message = format!("{}GET{}", timestamp, "/users/self/verify");
-            let hmac_key = ring::hmac::Key::new(hmac::HMAC_SHA256, secret_key.as_bytes());
-            let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
-            let sign = base64::encode(result);
-
-            let login_json = json!({
-                              "op": "login",
-                                "args": [{
-                                "apiKey": access_key,
-                                "passphrase": passphrase,
-                                "timestamp": timestamp,
-                                "sign": sign  }]
-                        });
-
-            trace!("---login_json:{0}", login_json.to_string());
-            trace!("--登陆:{}", login_json.to_string());
-            login_json_str = login_json.to_string();
-        }
-        login_json_str
-    }
-    /*******************************************************************************************************/
-    /*****************************************socket基本*****************************************************/
-    /*******************************************************************************************************/
-    async fn run(&mut self, bool_v1: Arc<AtomicBool>)
-    {
-        //订阅信息组装
-        let subscription = self.get_subscription();
-        loop {
-            trace!("要连接咯~~!!{}", self.request_url);
-
-            let request_url = Url::parse(self.request_url.as_str()).unwrap();
-            //1. 判断是否需要代理,根据代理地址是否存来选择
-            if self.proxy.ip_address.len() > 0 {
-                let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
-                let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
-                    ip_array[0].parse().unwrap(),
-                    ip_array[1].parse().unwrap(),
-                    ip_array[2].parse().unwrap(),
-                    ip_array[3].parse().unwrap())
-                ), self.proxy.port.parse().unwrap());
-                let websocket_config = Some(WebSocketConfig {
-                    max_send_queue: Some(16),
-                    max_message_size: Some(16 * 1024 * 1024),
-                    max_frame_size: Some(16 * 1024 * 1024),
-                    accept_unmasked_frames: false,
-                });
-                let max_redirects = 5;
-                match connect_with_proxy(request_url.clone(),
-                                         proxy_address, websocket_config, max_redirects) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        trace!("Can't connect(无法连接): {}", err);
-                    }
-                };
-            } else {
-                match connect(request_url.clone()) {
-                    Ok(ws) => {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
-                    }
-                    Err(err) => {
-                        // 连接失败时执行的操作
-                        trace!("Can't connect(无法连接): {}", err);
-                        // 返回一个默认的 WebSocket 对象或其他适当的值
-                        // 或者根据需要触发 panic 或返回错误信息
-                    }
-                };
-            }
-            trace!("退出来咯");
-
-            let bool_v1_clone = Arc::clone(&bool_v1);
-            let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-    }
-
-    //代理
-    async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
-                                subscription: String)
-    {
-        let lable = self.label.clone();
-        /*****登陆***/
-        let login_str = self.log_in_to_str();
-        if login_str != "" {
-            let _ = web_socket.write_message(Message::Text(login_str));
-            thread::sleep(Duration::from_secs(3));
-        }
-        /*****订阅***/
-        web_socket.write_message(Message::Text(subscription))
-            .unwrap();
-        /*****消息溜***/
-        let mut ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    if (get_time - ping_timeout) >= (1000 * 30) {
-                        trace!("30s 一次主动发送心跳包!");
-                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
-                        ping_timeout = get_time;
-                    }
-
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-201" {
-                        trace!("登陆成功!");
-                    } else if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        self.sender.send(res_data).await.unwrap();
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(e) => {
-                    // trace!("Error receiving message: {}", error);
-                    trace!("Err-响应{}", e);
-                    error!( "Err-响应{}", e);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //非代理
-    async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
-                          subscription: String)
-    {
-        let lable = self.label.clone();
-        /*****订阅***/
-        web_socket.write_message(Message::Text(subscription))
-            .unwrap();
-        /*****消息溜***/
-        let mut  ping_timeout = chrono::Utc::now().timestamp_millis();
-        loop {
-            tokio::time::sleep(Duration::from_millis(1)).await;
-            let msg = web_socket.read_message();
-            match msg {
-                Ok(Message::Text(text)) => {
-                    let get_time = chrono::Utc::now().timestamp_millis();
-                    if (get_time - ping_timeout) >= (1000 * 30) {
-                        trace!("30s 一次主动发送心跳包!");
-                        let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
-                        ping_timeout = get_time;
-                    }
-
-                    let mut res_data = Self::ok_text(lable.to_string(), text);
-                    res_data.time = get_time_microsecond();
-                    if res_data.code == "-201" {
-                        trace!("登陆成功!");
-                    } else if res_data.code == "-200" {
-                        trace!("订阅成功:{:?}", res_data.data);
-                    } else {
-                        self.sender.send(res_data).await.unwrap();
-                    }
-                }
-                Ok(Message::Ping(s)) => {
-                    trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
-                    let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
-                    trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Pong(s)) => {
-                    // trace!("Pong-响应--{:?}", String::from_utf8(s));
-                    trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
-                }
-                Ok(Message::Close(_)) => {
-                    // trace!("socket 关闭: ");
-                    trace!( "Close-响应");
-                }
-                Err(e) => {
-                    // trace!("Error receiving message: {}", error);
-                    trace!("Err-响应{}", e);
-                    error!( "Err-响应{}", e);
-                    break;
-                }
-                _ => {}
-            }
-
-            let bool_v1_v = bool_v1.load(Ordering::SeqCst);
-            if !bool_v1_v {
-                break;
-            }
-        }
-        web_socket.close(None).unwrap();
-    }
-
-    //数据解析
-    pub fn ok_text(lable: String, text: String) -> ResponseData
-    {
-        // trace!("元数据:{}",text);
-        let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
-        let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
-        if json_value.get("event").is_some() {//订阅返回
-            if json_value["event"].as_str() == Option::from("login") &&
-                json_value["code"].as_str() == Option::from("0") {
-                res_data.code = "-201".to_string();
-                res_data.message = format!("登陆成功!");
-            } else if json_value["event"].as_str() == Option::from("error") {
-                res_data.code = json_value["code"].to_string();
-                res_data.message = format!("错误:{}", json_value["msg"].to_string());
-            } else if json_value["event"].as_str() == Option::from("subscribe") {
-                res_data.code = "-200".to_string();
-                res_data.data = text;
-            } else {
-                res_data.data = text;
-            }
-        } else {
-            if json_value.get("arg").is_some() && json_value.get("data").is_some() {
-                res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
-                res_data.data = json_value["data"].to_string();
-                res_data.reach_time = json_value["data"][0]["ts"].as_str().unwrap().parse().unwrap()
-            } else {
-                res_data.data = text;
-                res_data.channel = "未知频道".to_string();
-            }
-        }
-        res_data
-    }
-}
+// use std::collections::{BTreeMap};
+// use std::{thread};
+// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+// use std::sync::Arc;
+// use std::sync::atomic::{AtomicBool, Ordering};
+// use std::time::Duration;
+// use chrono::Utc;
+// use serde_json::{json, Value};
+// use ring::hmac;
+// use tokio::sync::mpsc::Sender;
+// use tracing::{error, info, trace};
+// use crate::{proxy};
+// use url::Url;
+// use crate::proxy::ParsingDetail;
+// use crate::response_base::ResponseData;
+// use crate::utils::get_time_microsecond;
+//
+// pub enum OkxWsType {
+//     //订阅频道类型
+//     Public,
+//     Private,
+//     Business,
+// }
+//
+//
+// #[derive(Clone)]                        //订阅枚举
+// pub enum OkxSubscribeType {
+//     PuIndexTickers,
+//     PuBooks5,
+//     Putrades,
+//     PuBooks50L2tbt,
+//     //
+//     BuIndexCandle30m,
+//     //
+//     PrBalanceAndPosition,
+//     PrAccount(String),
+//     PrOrders,
+//     PrPositions,
+//
+// }
+//
+// #[derive(Clone)]
+// pub struct OkxSwapWs {
+//     pub label: String,
+//     request_url: String,
+//     //实际ws 链接地址
+//     proxy: ParsingDetail,
+//     //账号信息
+//     login_param: BTreeMap<String, String>,
+//     //kuconis特殊参数
+//     symbol_s: Vec<String>,
+//     //订阅币对
+//     subscribe_types: Vec<OkxSubscribeType>,
+//     //订阅信息
+//     sender: Sender<ResponseData>,     //数据通道
+// }
+//
+// impl OkxSwapWs {
+//     /*******************************************************************************************************/
+//     /*****************************************获取一个对象****************************************************/
+//     /*******************************************************************************************************/
+//     pub fn new(is_colo: bool,
+//                login_param: BTreeMap<String, String>,
+//                ws_type: OkxWsType,
+//                sender: Sender<ResponseData>,
+//     ) -> OkxSwapWs
+//     {
+//         return OkxSwapWs::new_label("default-OkxSwapWs".to_string(), is_colo, login_param, ws_type, sender);
+//     }
+//     pub fn new_label(label: String, is_colo: bool,
+//                      login_param: BTreeMap<String, String>,
+//                      ws_type: OkxWsType,
+//                      sender: Sender<ResponseData>,
+//     ) -> OkxSwapWs
+//     {
+//         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+//         let parsing_detail = proxy::ParsingDetail::parsing_environment_variables();
+//
+//         /*******公共频道-私有频道数据组装*/
+//         let request_url = match ws_type {
+//             OkxWsType::Public => {
+//                 "wss://ws.okx.com:8443/ws/v5/public".to_string()
+//             }
+//             OkxWsType::Private => {
+//                 "wss://ws.okx.com:8443/ws/v5/private".to_string()
+//             }
+//             OkxWsType::Business => {
+//                 "wss://ws.okx.com:8443/ws/v5/business".to_string()
+//             }
+//         };
+//
+//         if is_colo {
+//             info!("开启高速(未配置,走普通:{})通道",request_url);
+//         } else {
+//             info!("走普通通道:{}",request_url);
+//         }
+//         /*****返回结构体*******/
+//         OkxSwapWs {
+//             label,
+//             request_url,
+//             proxy: parsing_detail,
+//             login_param,
+//             symbol_s: vec![],
+//             subscribe_types: vec![],
+//             sender,
+//         }
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************订阅函数********************************************************/
+//     /*******************************************************************************************************/
+//     //手动添加订阅信息
+//     pub fn set_subscribe(&mut self, subscribe_types: Vec<OkxSubscribeType>) {
+//         self.subscribe_types.extend(subscribe_types);
+//     }
+//     //自定义
+//     pub async fn custom_subscribe(&mut self, bool_v1: Arc<AtomicBool>, b_array: Vec<String>)
+//     {
+//         let mut symbol_s = b_array.clone();
+//         for symbol in symbol_s.iter_mut() {
+//             // 大写
+//             *symbol = symbol.to_uppercase();
+//             // 字符串替换
+//             *symbol = symbol.replace("_", "-");
+//         }
+//         self.symbol_s = symbol_s;
+//         self.run(bool_v1).await;
+//     }
+//
+//     /*******************************************************************************************************/
+//     /*****************************************工具函数********************************************************/
+//     /*******************************************************************************************************/
+//     //订阅枚举解析
+//     pub fn enum_to_string(symbol: String, subscribe_type: OkxSubscribeType) -> Value {
+//         match subscribe_type {
+//             OkxSubscribeType::PuIndexTickers => {
+//                 json!({
+//                     "channel":"index-tickers",
+//                     "instId":symbol
+//                 })
+//             }
+//
+//             OkxSubscribeType::PuBooks5 => {
+//                 json!({
+//                     "channel":"books5",
+//                     "instId":symbol
+//                 })
+//             }
+//             OkxSubscribeType::Putrades => {
+//                 json!({
+//                     "channel":"trades",
+//                     "instId":symbol
+//                 })
+//             }
+//
+//             OkxSubscribeType::BuIndexCandle30m => {
+//                 json!({
+//                     "channel":"index-candle30m",
+//                     "instId":symbol
+//                 })
+//             }
+//
+//             OkxSubscribeType::PrAccount(ccy) => {
+//                 json!({
+//                     "channel":"account",
+//                     "ccy":ccy
+//                 })
+//             }
+//             OkxSubscribeType::PuBooks50L2tbt => {
+//                 json!({
+//                     "channel":"books50-l2-tbt",
+//                     "instId":symbol
+//                 })
+//             }
+//             OkxSubscribeType::PrBalanceAndPosition => {
+//                 json!({
+//                     "channel":"balance_and_position"
+//                 })
+//             }
+//             OkxSubscribeType::PrOrders => {
+//                 json!({
+//                     "channel":"orders",
+//                     "instType":"SWAP",
+//                     "instFamily":symbol
+//                 })
+//             }
+//             OkxSubscribeType::PrPositions => {
+//                 json!({
+//                     "channel":"positions",
+//                     "instType":"SWAP",
+//                 })
+//             }
+//         }
+//     }
+//     //组装订阅数据
+//     pub fn get_subscription(&self) -> String {
+//         let mut args = vec![];
+//         for symbol in &self.symbol_s {
+//             for subscribe_type in &self.subscribe_types {
+//                 let ty_str = Self::enum_to_string(symbol.clone(), subscribe_type.clone());
+//                 args.push(ty_str);
+//             }
+//         }
+//         let str = json!({
+//             "op": "subscribe",
+//             "args": args
+//         });
+//
+//         trace!("订阅信息:{}", str.to_string());
+//
+//         str.to_string()
+//     }
+//
+//     //组装登陆数据
+//     fn log_in_to_str(&self) -> String {
+//         let mut login_json_str = "".to_string();
+//
+//         let mut access_key: String = "".to_string();
+//         let mut secret_key: String = "".to_string();
+//         let mut passphrase: String = "".to_string();
+//         for (key, value) in &self.login_param {
+//             if key == "access_key" {
+//                 access_key = value.parse().unwrap();
+//             } else if key == "secret_key" {
+//                 secret_key = value.parse().unwrap();
+//             } else if key == "pass_key" {
+//                 passphrase = value.parse().unwrap();
+//             }
+//         }
+//         if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
+//             let timestamp = Utc::now().timestamp().to_string();
+//             // 时间戳 + 请求类型+ 请求参数字符串
+//             let message = format!("{}GET{}", timestamp, "/users/self/verify");
+//             let hmac_key = ring::hmac::Key::new(hmac::HMAC_SHA256, secret_key.as_bytes());
+//             let result = ring::hmac::sign(&hmac_key, &message.as_bytes());
+//             let sign = base64::encode(result);
+//
+//             let login_json = json!({
+//                               "op": "login",
+//                                 "args": [{
+//                                 "apiKey": access_key,
+//                                 "passphrase": passphrase,
+//                                 "timestamp": timestamp,
+//                                 "sign": sign  }]
+//                         });
+//
+//             trace!("---login_json:{0}", login_json.to_string());
+//             trace!("--登陆:{}", login_json.to_string());
+//             login_json_str = login_json.to_string();
+//         }
+//         login_json_str
+//     }
+//     /*******************************************************************************************************/
+//     /*****************************************socket基本*****************************************************/
+//     /*******************************************************************************************************/
+//     async fn run(&mut self, bool_v1: Arc<AtomicBool>)
+//     {
+//         //订阅信息组装
+//         let subscription = self.get_subscription();
+//         loop {
+//             trace!("要连接咯~~!!{}", self.request_url);
+//
+//             let request_url = Url::parse(self.request_url.as_str()).unwrap();
+//             //1. 判断是否需要代理,根据代理地址是否存来选择
+//             if self.proxy.ip_address.len() > 0 {
+//                 let ip_array: Vec<&str> = self.proxy.ip_address.split(".").collect();
+//                 let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
+//                     ip_array[0].parse().unwrap(),
+//                     ip_array[1].parse().unwrap(),
+//                     ip_array[2].parse().unwrap(),
+//                     ip_array[3].parse().unwrap())
+//                 ), self.proxy.port.parse().unwrap());
+//                 let websocket_config = Some(WebSocketConfig {
+//                     max_send_queue: Some(16),
+//                     max_message_size: Some(16 * 1024 * 1024),
+//                     max_frame_size: Some(16 * 1024 * 1024),
+//                     accept_unmasked_frames: false,
+//                 });
+//                 let max_redirects = 5;
+//                 match connect_with_proxy(request_url.clone(),
+//                                          proxy_address, websocket_config, max_redirects) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.proxy_subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         trace!("Can't connect(无法连接): {}", err);
+//                     }
+//                 };
+//             } else {
+//                 match connect(request_url.clone()) {
+//                     Ok(ws) => {
+//                         let bool_v1_clone = Arc::clone(&bool_v1);
+//                         self.subscription(bool_v1_clone, ws.0, subscription.clone()).await;
+//                     }
+//                     Err(err) => {
+//                         // 连接失败时执行的操作
+//                         trace!("Can't connect(无法连接): {}", err);
+//                         // 返回一个默认的 WebSocket 对象或其他适当的值
+//                         // 或者根据需要触发 panic 或返回错误信息
+//                     }
+//                 };
+//             }
+//             trace!("退出来咯");
+//
+//             let bool_v1_clone = Arc::clone(&bool_v1);
+//             let bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//     }
+//
+//     //代理
+//     async fn proxy_subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<ProxyAutoStream>,
+//                                 subscription: String)
+//     {
+//         let lable = self.label.clone();
+//         /*****登陆***/
+//         let login_str = self.log_in_to_str();
+//         if login_str != "" {
+//             let _ = web_socket.write_message(Message::Text(login_str));
+//             thread::sleep(Duration::from_secs(3));
+//         }
+//         /*****订阅***/
+//         web_socket.write_message(Message::Text(subscription))
+//             .unwrap();
+//         /*****消息溜***/
+//         let mut ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     if (get_time - ping_timeout) >= (1000 * 30) {
+//                         trace!("30s 一次主动发送心跳包!");
+//                         let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+//                         ping_timeout = get_time;
+//                     }
+//
+//                     let mut res_data = Self::ok_text(lable.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-201" {
+//                         trace!("登陆成功!");
+//                     } else if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         self.sender.send(res_data).await.unwrap();
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(e) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     trace!("Err-响应{}", e);
+//                     error!( "Err-响应{}", e);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //非代理
+//     async fn subscription(&self, bool_v1: Arc<AtomicBool>, mut web_socket: WebSocket<AutoStream>,
+//                           subscription: String)
+//     {
+//         let lable = self.label.clone();
+//         /*****订阅***/
+//         web_socket.write_message(Message::Text(subscription))
+//             .unwrap();
+//         /*****消息溜***/
+//         let mut  ping_timeout = chrono::Utc::now().timestamp_millis();
+//         loop {
+//             tokio::time::sleep(Duration::from_millis(1)).await;
+//             let msg = web_socket.read_message();
+//             match msg {
+//                 Ok(Message::Text(text)) => {
+//                     let get_time = chrono::Utc::now().timestamp_millis();
+//                     if (get_time - ping_timeout) >= (1000 * 30) {
+//                         trace!("30s 一次主动发送心跳包!");
+//                         let _ = web_socket.write_message(Message::Ping(Vec::from("ping")));
+//                         ping_timeout = get_time;
+//                     }
+//
+//                     let mut res_data = Self::ok_text(lable.to_string(), text);
+//                     res_data.time = get_time_microsecond();
+//                     if res_data.code == "-201" {
+//                         trace!("登陆成功!");
+//                     } else if res_data.code == "-200" {
+//                         trace!("订阅成功:{:?}", res_data.data);
+//                     } else {
+//                         self.sender.send(res_data).await.unwrap();
+//                     }
+//                 }
+//                 Ok(Message::Ping(s)) => {
+//                     trace!( "Ping-响应--{:?}", String::from_utf8(s.clone()));
+//                     let _ = web_socket.write_message(Message::Pong(Vec::from("pong")));
+//                     trace!( "回应-pong---{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Pong(s)) => {
+//                     // trace!("Pong-响应--{:?}", String::from_utf8(s));
+//                     trace!( "Pong-响应--{:?}", String::from_utf8(s.clone()));
+//                 }
+//                 Ok(Message::Close(_)) => {
+//                     // trace!("socket 关闭: ");
+//                     trace!( "Close-响应");
+//                 }
+//                 Err(e) => {
+//                     // trace!("Error receiving message: {}", error);
+//                     trace!("Err-响应{}", e);
+//                     error!( "Err-响应{}", e);
+//                     break;
+//                 }
+//                 _ => {}
+//             }
+//
+//             let bool_v1_v = bool_v1.load(Ordering::SeqCst);
+//             if !bool_v1_v {
+//                 break;
+//             }
+//         }
+//         web_socket.close(None).unwrap();
+//     }
+//
+//     //数据解析
+//     pub fn ok_text(lable: String, text: String) -> ResponseData
+//     {
+//         // trace!("元数据:{}",text);
+//         let mut res_data = ResponseData::new(lable, "200".to_string(), "success".to_string(), "".to_string());
+//         let json_value: serde_json::Value = serde_json::from_str(&text).unwrap();
+//         if json_value.get("event").is_some() {//订阅返回
+//             if json_value["event"].as_str() == Option::from("login") &&
+//                 json_value["code"].as_str() == Option::from("0") {
+//                 res_data.code = "-201".to_string();
+//                 res_data.message = format!("登陆成功!");
+//             } else if json_value["event"].as_str() == Option::from("error") {
+//                 res_data.code = json_value["code"].to_string();
+//                 res_data.message = format!("错误:{}", json_value["msg"].to_string());
+//             } else if json_value["event"].as_str() == Option::from("subscribe") {
+//                 res_data.code = "-200".to_string();
+//                 res_data.data = text;
+//             } else {
+//                 res_data.data = text;
+//             }
+//         } else {
+//             if json_value.get("arg").is_some() && json_value.get("data").is_some() {
+//                 res_data.channel = format!("{}", json_value["arg"]["channel"].as_str().unwrap());
+//                 res_data.data = json_value["data"].to_string();
+//                 res_data.reach_time = json_value["data"][0]["ts"].as_str().unwrap().parse().unwrap()
+//             } else {
+//                 res_data.data = text;
+//                 res_data.channel = "未知频道".to_string();
+//             }
+//         }
+//         res_data
+//     }
+// }

+ 209 - 82
exchanges/src/socket_tool.rs

@@ -1,68 +1,100 @@
 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::{Arc, Mutex};
+use std::sync::atomic::AtomicBool;
 use std::time::Duration;
 
 use chrono::Utc;
 use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
-use futures_util::{future, pin_mut, StreamExt};
+use futures_util::{future, pin_mut,  SinkExt, StreamExt};
 use futures_util::stream::{SplitSink, SplitStream};
 use ring::hmac;
 use serde_json::json;
 use tokio::net::TcpStream;
 use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
 use tokio_tungstenite::tungstenite::{Error, Message};
-use tokio_tungstenite::tungstenite::error::UrlError;
 use tracing::trace;
 
 use crate::proxy;
 use crate::proxy::{ProxyEnum, ProxyResponseEnum};
 use crate::response_base::ResponseData;
 
-// pub struct OkxSwapModel {
-//     // ws: AbstractWsMode,
-//     address_url: String,
-// }
+#[derive(Debug)]
+pub enum HeartbeatType {
+    Ping,
+    Pong,
+}
 
-// impl OkxSwapModel {
-//     pub fn new() -> OkxSwapModel {
-//         OkxSwapModel {
-//             // ws: AbstractWsMode::new(),
-//             address_url: "wss://ws.okx.com:8443/ws/v5/public".to_string(),
-//         }
-//     }
-//     //链接
-//     pub async fn ws_connect_async(&self, write_rx: UnboundedReceiver<Message>, read_tx: UnboundedSender<ResponseData>) -> Result<(), Error> {
-//         AbstractWsMode::ws_connect_async(self.address_url.clone(), write_rx,read_tx,"".to_string(), read_tx).await
-//     }
-//
-//
-//     // //心跳包发送
-//     // pub fn send_ping_or_pong(){
-//     // }
-// }
+pub struct AbstractWsMode {
+}
 
-// // 抽象ws 接口
-// pub trait AbstractWs {
-//     fn new() -> Self;
-//     //创建链接
-//     fn ws_connect_async(&mut self) -> Pin<Box<dyn Future<Output=Result<bool, Error>> + Send>>;
-//     //返回通道(发送指令通道)
-//     fn send_message(&self, text: String);
-//     //返回通道(数据接受通道)
-//     // fn get_read_rx(&self) -> UnboundedReceiver<Message>;
-// }
+impl AbstractWsMode {
+    // pub fn new(write_rx: UnboundedReceiver<Message>,
+    //            read_tx: UnboundedSender<ResponseData>) -> AbstractWsMode {
+    //     AbstractWsMode {
+    //         write_rx,
+    //         read_tx,
+    //     }
+    // }
+    // pub async fn ws_connect_async2<F>(&mut self,
+    //                                   address_url: String,
+    //                                   lable: String,
+    //                                   func: F) -> Result<(), Error>
+    //     where F: Fn(Result<Message, Error>) -> Option<ResponseData>,
+    // {
+    //     //1.是否走代理
+    //     /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
+    //     let proxy = match proxy::ParsingDetail::env_proxy(ProxyEnum::WS) {
+    //         ProxyResponseEnum::NO => {
+    //             // trace!("非 代理");
+    //             None
+    //         }
+    //         ProxyResponseEnum::YES(proxy) => {
+    //             // trace!("代理");
+    //             Option::from(proxy)
+    //         }
+    //     };
+    //
+    //     let (ws_stream, _) = connect_async(address_url.clone(), proxy).await.expect("链接失败");
+    //     trace!("WebSocket 握手完成。");
+    //     let (mut write, mut read) = ws_stream.split();
+    //
+    //     //将socket 的写操作与 写通道链接起来,将数据以ok的结构体封装进行传递
+    //     let stdin_to_ws = self.write_rx.map(Ok).forward(write);
+    //     let ws_to_stdout = {
+    //         trace!("---1");
+    //         //读,循环读取,然后拿到 message,,然后开启异步处理 message,
+    //         let result = read.for_each(|message| async {
+    //             let response_data = func(message);
+    //             if response_data.is_some() {
+    //                 let mut data = response_data.unwrap();
+    //                 data.label = lable.clone();
+    //                 let code = data.code.clone();
+    //                 if code.as_str() == "-1" {} else if code.as_str() == "200" {
+    //                     self.read_tx.unbounded_send(data).unwrap();
+    //                 }
+    //             }
+    //         });
+    //         trace!("---3");
+    //         result
+    //     };
+    //
+    //     //必须操作。,因为不同于其他的高级语言,有自动内存管理,所以为了防范地址改变,所以需要做此处理
+    //     pin_mut!(stdin_to_ws, ws_to_stdout,);
+    //     future::select(stdin_to_ws, ws_to_stdout).await;
+    //     trace!("---5");
+    //     trace!("---4");
+    //     Ok(())
+    // }
 
-pub struct AbstractWsMode {}
 
-impl AbstractWsMode {
     //创建链接
     pub async fn ws_connect_async<F>(address_url: String,
-                                     bool_v1: Arc<AtomicBool>,
-                                     write_rx: UnboundedReceiver<Message>,
-                                     read_tx:&UnboundedSender<ResponseData>
-                                     , lable: String, func: F) -> Result<(), Error>
-        where F: Fn(Result<Message, Error>) -> Option<ResponseData>
+                                     lable: String,
+                                     subscribe_array: Vec<String>,
+                                     mut write_rx: UnboundedReceiver<Message>,
+                                     read_tx: UnboundedSender<ResponseData>,
+                                     func: F, ) -> Result<(), Error>
+        where F: Fn(Result<Message, Error>) -> Option<ResponseData>,
     {
         //1.是否走代理
         /*******走代理:根据环境变量配置来决定,如果配置了走代理,没有配置不走*******/
@@ -76,47 +108,143 @@ impl AbstractWsMode {
                 Option::from(proxy)
             }
         };
-        match connect_async(address_url, proxy).await {
-            Ok(( ws_stream, _)) => {
-                trace!("WebSocket 握手完成。");
-                // tokio::task::spawn_local(async move {
-                let (write, read) = ws_stream.split();
-
-                //将socket 的写操作与 写通道链接起来,将数据以ok的结构体封装进行传递
-                let stdin_to_ws = write_rx.map(Ok).forward(write);
-                let ws_to_stdout = {
-                    trace!("---1");
-                    //读,循环读取,然后拿到 message,,然后开启异步处理 message,
-                    let result = read.for_each(|message| async {
-                        let bool_v1_clone = Arc::clone(&bool_v1);
-                        let _bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
-                        let  response_data = func(message);
-                        if response_data.is_some(){
-                           let mut data =  response_data.unwrap();
-                            data.label = lable.clone();
+
+        loop {
+            let (ws_stream, _) = connect_async(address_url.clone(), proxy).await?;
+            trace!("WebSocket 握手完成。");
+            let (mut write, mut read) = ws_stream.split();
+
+            //订阅写入(包括订阅信息 )
+            for s in &subscribe_array {
+                write.send(Message::Text(s.parse().unwrap())).await?;
+            }
+
+
+            //将socket 的写操作与 写通道链接起来,将数据以ok的结构体封装进行传递
+            // let stdin_to_ws = write_rx.map(Ok).forward(write);
+            // Writing task
+            let stdin_to_ws = async {
+                while let Some(message) = write_rx.next().await {
+                    write.send(message).await?;
+                }
+                Ok::<(), tokio_tungstenite::tungstenite::Error>(())
+            };
+            let ws_to_stdout = async {
+                while let Some(message) = read.next().await {
+                    let response_data = func(message);
+                    if response_data.is_some() {
+                        let mut data = response_data.unwrap();
+                        data.label = lable.clone();
+                        let code = data.code.clone();
+                        if code.as_str() == "-1" {} else if code.as_str() == "200" {
                             read_tx.unbounded_send(data).unwrap();
                         }
-                    });
-                    trace!("---3");
-                    result
-                };
-
-                //必须操作。,因为不同于其他的高级语言,有自动内存管理,所以为了防范地址改变,所以需要做此处理
-                pin_mut!(stdin_to_ws, ws_to_stdout,);
-                future::select(stdin_to_ws, ws_to_stdout).await;
-                trace!("---5");
-                trace!("---4");
-
-                Ok(())
-            }
-            Err(_) => {
-                trace!("链接失败");
-                Err(Error::Url(UrlError::UnableToConnect("连接失败".to_string())))
-            }
+                    }
+                }
+                Ok::<(), tokio_tungstenite::tungstenite::Error>(())
+            };
+            // let ws_to_stdout = {
+            //     trace!("---1");
+            //     //读,循环读取,然后拿到 message,,然后开启异步处理 message,
+            //     let result = read.for_each(|message| async {
+            //         let response_data = func(message);
+            //         if response_data.is_some() {
+            //             let mut data = response_data.unwrap();
+            //             data.label = lable.clone();
+            //             let code = data.code.clone();
+            //             if code.as_str() == "-1" {
+            //                 // let close_frame = CloseFrame {
+            //                 //     code: CloseCode::Normal,
+            //                 //     reason: Cow::Borrowed("Bye bye"),
+            //                 // };
+            //                 // let close_message = Message::Close(Some(close_frame));
+            //                 // write.send(close_message);
+            //             } else if code.as_str() == "200" {
+            //                 read_tx.unbounded_send(data).unwrap();
+            //             }
+            //         }
+            //     });
+            //     trace!("---3");
+            //     result
+            // };
+
+            //必须操作。,因为不同于其他的高级语言,有自动内存管理,所以为了防范地址改变,所以需要做此处理
+            pin_mut!(stdin_to_ws, ws_to_stdout,);
+            future::select(stdin_to_ws, ws_to_stdout).await;
+            trace!("---5");
+            trace!("---4");
+            trace!("重启...");
         }
+       return  Ok(())
     }
-}
 
+// match connect_async(address_url, proxy).await {
+//     Ok((ws_stream, _)) => {
+//         trace!("WebSocket 握手完成。");
+//         // tokio::task::spawn_local(async move {
+//         let (write, read) = ws_stream.split();
+//
+//         //将socket 的写操作与 写通道链接起来,将数据以ok的结构体封装进行传递
+//         let stdin_to_ws = write_rx.map(Ok).forward(write);
+//         let ws_to_stdout = {
+//             trace!("---1");
+//             //读,循环读取,然后拿到 message,,然后开启异步处理 message,
+//             let result = read.for_each(|message| async {
+//                 // let bool_v1_clone = Arc::clone(&bool_v1);
+//                 // let _bool_v1_v = bool_v1_clone.load(Ordering::SeqCst);
+//                 let response_data = func(message);
+//                 if response_data.is_some() {
+//                     let mut data = response_data.unwrap();
+//                     data.label = lable.clone();
+//                     read_tx.unbounded_send(data).unwrap();
+//                 }
+//             });
+//             trace!("---3");
+//             result
+//         };
+//
+//         //必须操作。,因为不同于其他的高级语言,有自动内存管理,所以为了防范地址改变,所以需要做此处理
+//         pin_mut!(stdin_to_ws, ws_to_stdout,);
+//         future::select(stdin_to_ws, ws_to_stdout).await;
+//         trace!("---5");
+//         trace!("---4");
+//
+//         Ok(())
+//     }
+//     Err(_) => {
+//         trace!("链接失败");
+//         Err(Error::Url(UrlError::UnableToConnect("连接失败".to_string())))
+//     }
+// }
+
+
+    //心跳包
+    pub async fn ping_or_pong(_bool_v1: Arc<AtomicBool>, write_tx_clone: Arc<Mutex<UnboundedSender<Message>>>, h_type: HeartbeatType, millis: u64) {
+        loop {
+            tokio::time::sleep(Duration::from_millis(millis)).await;
+            let  write_tx_clone = write_tx_clone.lock().unwrap();
+            write_tx_clone.unbounded_send(
+                match h_type {
+                    HeartbeatType::Ping => {
+                        Message::Ping(Vec::from("Ping"))
+                    }
+                    HeartbeatType::Pong => {
+                        Message::Pong(Vec::from("Pong"))
+                    }
+                }
+            ).expect("发送失败");
+            trace!("发起心跳:{:?}",h_type);
+        }
+    }
+
+    //发送数据
+    pub fn send_subscribe(write_tx_clone: Arc<Mutex<UnboundedSender<Message>>>, message: Message) -> bool {
+        let  write_tx_clone = write_tx_clone.lock().unwrap();
+        write_tx_clone.unbounded_send(message.clone()).unwrap();
+        trace!("发送指令:{:?}",message);
+        true
+    }
+}
 
 //创建链接
 pub async fn ws_connect_async(address_url: String) -> (SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>,
@@ -141,7 +269,6 @@ pub async fn ws_connect_async(address_url: String) -> (SplitSink<WebSocketStream
 
 
 pub async fn client(add_url: String) {
-
     let proxy = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(
         127,
         0,
@@ -245,9 +372,9 @@ async fn read_sell(mut rx: futures_channel::mpsc::UnboundedReceiver<Message>) {
 pub fn log_in_to_str() -> String {
     let mut login_json_str = "".to_string();
 
-    let  access_key: String = "b812814f-b792-432c-9c65-44ebe3b8976b".to_string();
-    let  secret_key: String = "D6AF4764DF5FDC74BF2CC88A4A8FD035".to_string();
-    let  passphrase: String = "Astest!@#1".to_string();
+    let access_key: String = "b812814f-b792-432c-9c65-44ebe3b8976b".to_string();
+    let secret_key: String = "D6AF4764DF5FDC74BF2CC88A4A8FD035".to_string();
+    let passphrase: String = "Astest!@#1".to_string();
 
     if access_key.len() > 0 || secret_key.len() > 0 || passphrase.len() > 0 {
         let timestamp = Utc::now().timestamp().to_string();

+ 124 - 62
exchanges/tests/binance_swap_test.rs

@@ -1,17 +1,12 @@
-use std::borrow::Cow;
 use std::collections::BTreeMap;
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
-use futures_util::{SinkExt, StreamExt};
-use futures_util::stream::FusedStream;
-use tokio_tungstenite::tungstenite::Message;
-use tokio_tungstenite::tungstenite::protocol::CloseFrame;
-use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
+use std::sync::{Arc, Mutex};
+use std::sync::atomic::AtomicBool;
+
+use futures_util::StreamExt;
 use tracing::trace;
+
 use exchanges::binance_swap_rest::BinanceSwapRest;
 use exchanges::binance_swap_ws_async::{BinanceSwapLogin, BinanceSwapSubscribeType, BinanceSwapWs, BinanceSwapWsType};
-use exchanges::response_base::ResponseData;
 
 const ACCESS_KEY: &str = "";
 const SECRET_KEY: &str = "";
@@ -22,78 +17,145 @@ const SECRET_KEY: &str = "";
 async fn ws_custom_subscribe() {
     global::log_utils::init_log_with_trace();
 
-    let mut bool_v1 = Arc::new(AtomicBool::new(true));
-    //创建读写通道
+
     let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
     let (read_tx, mut read_rx) = futures_channel::mpsc::unbounded();
 
-    //对象
+    // let (write_tx, write_rx) = tokio::sync::broadcast::channel::<Message>(10);
+    // let (read_tx, mut read_rx) = tokio::sync::broadcast::channel::<ResponseData>(10);
+
+
     let mut ws = get_ws(None);
-    // 币对
     ws.set_symbols(vec!["BTC_USDT".to_string()]);
-    //订阅
     ws.set_subscribe(vec![
-        BinanceSwapSubscribeType::PuBookTicker,
+        // BinanceSwapSubscribeType::PuBookTicker,
         BinanceSwapSubscribeType::PuAggTrade,
-        BinanceSwapSubscribeType::PuDepth20levels100ms,
+        // BinanceSwapSubscribeType::PuDepth20levels100ms,
     ]);
-    //主动发起订阅
-    // tokio::spawn(async move {
-    //     ws.send_subscribe(write_tx);
-    // });
 
+    /*
+    当前问题 卡在,重连机制采用循环的方式,这样会出现通道的引用限制,所以考虑将重连机制的循环拿到最外层,
+        然后现在是的问题是,正常关闭链接,有某个线程没有关闭,导致进程没有结束,无法达成 重连的触发条件
+    */
 
-    //模拟业务场景 一直监听数据
-    let  t1 =   tokio::spawn(async move {
+
+    let write_tx_am = Arc::new(Mutex::new(write_tx));
+    let bool_v1 = Arc::new(AtomicBool::new(true));
+
+    //读取
+    let bool_v1_clone = Arc::clone(&bool_v1);
+    let tr = tokio::spawn(async move {
+        trace!("线程-数据读取-开启");
         loop {
             if let Some(data) = read_rx.next().await {
                 trace!("读取数据data:{:?}",data)
             }
         }
-        trace!("数据读取退出 完成");
+        trace!("线程-数据读取-结束");
     });
 
-    //模拟业务场景 开启链接
-    let bool_v1_clone = Arc::clone(&bool_v1);
-    let t2 = tokio::spawn(async move {
-        //链接
-        ws.ws_connect_async(bool_v1_clone, write_rx, &read_tx).await.unwrap();
-        trace!("ws_connect_async 完成");
-    });
-
-
-    //模拟用户主动写入数据
+    //写数据
     let bool_v2_clone = Arc::clone(&bool_v1);
-    let t3 = tokio::spawn(async move {
-        // loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            let bool_v2_v = bool_v2_clone.load(Ordering::SeqCst);
-            bool_v2_clone.store(!bool_v2_v, Ordering::SeqCst);
-            if bool_v2_v {
-                // let close_frame = CloseFrame {
-                //     code: CloseCode::Normal,
-                //     reason: Cow::Borrowed("Bye bye"),
-                // };
-                // let close_message = Message::Close(Some(close_frame));
-                // write_tx.unbounded_send(close_message).unwrap();
-                // tokio::time::sleep(Duration::from_millis(5000)).await;
-                // //关闭通道
-                // drop(write_tx);
-                // write_tx.close_channel();
-                // break
-            }
+    let write_tx_clone = Arc::clone(&write_tx_am);
+    // let tw = tokio::spawn(async move {
+    //     trace!("线程-数据写入-开始");
+    //     loop {
+    //         tokio::time::sleep(Duration::from_millis(20*1000)).await;
+    //         let close_frame = CloseFrame {
+    //             code: CloseCode::Normal,
+    //             reason: Cow::Borrowed("Bye bye"),
+    //         };
+    //         let close_message = Message::Close(Some(close_frame));
+    //         // AbstractWsMode::send_subscribe(write_tx_clone.clone(), Message::Text("32313221".to_string()));
+    //         AbstractWsMode::send_subscribe(write_tx_clone.clone(), close_message);
+    //         trace!("发送指令成功");
+    //     }
+    //     trace!("线程-数据写入-结束");
+    // });
 
-            //模拟心跳
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            write_tx.unbounded_send(Message::Ping(Vec::from("ping"))).unwrap();
-        }
-        // }
-        trace!("主动推出 完成");
+    // loop {
+    let t1 = tokio::spawn(async move {
+        //链接
+        let bool_v3_clone = Arc::clone(&bool_v1);
+        ws.ws_connect_async(bool_v3_clone, &write_tx_am, write_rx, read_tx).await.expect("链接失败(内部一个心跳线程应该已经关闭了)");
+        trace!("test 唯一线程结束--");
     });
-    // tokio::try_join!(y,y1,y2).unwrap();
-    tokio::try_join!(t2,t3,t1).unwrap();
-    trace!("323123213");
+    tokio::try_join!(t1).unwrap();
+    trace!("当此结束");
+    // }
+    trace!("重启!");
+    trace!("参考交易所关闭");
+    return;
+
+    //************************************
+    //************************************
+    //************************************
+    //************************************
+    //************************************
+    //************************************
+    //************************************
+    //11 点31 分
+
+    // let mut bool_v1 = Arc::new(AtomicBool::new(true));
+    // //创建读写通道
+    // let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
+    // let (read_tx, mut read_rx) = futures_channel::mpsc::unbounded();
+    // // 封装 write_tx 到 Arc 和 Mutex
+    // let write_tx_am = Arc::new(Mutex::new(write_tx));
+    //
+    // //对象
+    // let mut ws = get_ws(None);
+    // // 币对
+    // ws.set_symbols(vec!["BTC_USDT".to_string()]);
+    // //订阅
+    // ws.set_subscribe(vec![
+    //     BinanceSwapSubscribeType::PuBookTicker,
+    //     BinanceSwapSubscribeType::PuAggTrade,
+    //     BinanceSwapSubscribeType::PuDepth20levels100ms,
+    // ]);
+    //
+    //
+    // //模拟业务场景 开启链接
+    // let bool_v1_clone = Arc::clone(&bool_v1);
+    // let write_tx_clone1 = Arc::clone(&write_tx_am);
+    // let t1 = tokio::spawn(async move {
+    //     ws.ws_connect_async(bool_v1_clone, write_tx_clone1, write_rx, &read_tx).await.unwrap();
+    //     trace!("ws_connect_async 完成");
+    // });
+    //
+    // //模拟业务场景 一直监听数据
+    // let t2 = tokio::spawn(async move {
+    //     loop {
+    //         if let Some(data) = read_rx.next().await {
+    //             trace!("读取数据data:{:?}",data)
+    //         }
+    //     }
+    //     trace!("数据读取退出 完成");
+    // });
+    //
+    //
+    // //模拟用户主动写入数据
+    // // let write_tx_clone2 = Arc::clone(&write_tx_am);
+    // // let t3 = tokio::spawn(async move {
+    // //     //模拟心跳
+    // //     loop {
+    // //         tokio::time::sleep(Duration::from_millis(5000)).await;
+    // //         let mut write_tx_clone = write_tx_clone2.lock().unwrap();
+    // //         match write_tx_clone.unbounded_send(Message::Pong(Vec::from("pong"))) {
+    // //             Ok(_) => {
+    // //                 trace!("发送心跳");
+    // //                 continue;
+    // //             }
+    // //             Err(_) => {
+    // //                 break;
+    // //             }
+    // //         }
+    // //     }
+    // //     trace!("主动推出 完成");
+    // // });
+    // // tokio::try_join!(y,y1,y2).unwrap();
+    // tokio::try_join!(t1,t2).unwrap();
+    // trace!("323123213");
 }
 
 //rest-获取服务器时间

+ 98 - 121
exchanges/tests/kucoin_swap_test_async.rs

@@ -1,94 +1,84 @@
-use std::borrow::Cow;
-use std::collections::HashSet;
-use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::Duration;
+use std::sync::{Arc, Mutex};
+use std::sync::atomic::AtomicBool;
 
 use futures_util::StreamExt;
-use tokio_tungstenite::tungstenite::Message;
-use tokio_tungstenite::tungstenite::protocol::CloseFrame;
-use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
 use tracing::trace;
 
 use exchanges::kucoin_swap_ws_async::{KucoinSwapLogin, KucoinSwapSubscribeType, KucoinSwapWs, KucoinSwapWsType};
 
-const ACCESS_KEY: &str = "6393f3565f0d4500011f846b";
-const SECRET_KEY: &str = "9c0df8b7-daaa-493e-a53a-82703067f7dd";
-const PASS_KEY: &str = "b87d055f";
+const ACCESS_KEY: &str = "";
+const SECRET_KEY: &str = "";
+const PASS_KEY: &str = "";
 
 //ws-订阅公共频道信息
 #[tokio::test(flavor = "multi_thread", worker_threads = 5)]
 async fn ws_custom_subscribe_pu() {
     global::log_utils::init_log_with_trace();
 
-    let bool_v1 = Arc::new(AtomicBool::new(true));
-    //创建读写通道
+
     let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
     let (read_tx, mut read_rx) = futures_channel::mpsc::unbounded();
 
+    // let (write_tx, write_rx) = tokio::sync::broadcast::channel::<Message>(10);
+    // let (read_tx, mut read_rx) = tokio::sync::broadcast::channel::<ResponseData>(10);
+
+
     let mut ws = get_ws(None, KucoinSwapWsType::Public).await;
-    // 币对
     ws.set_symbols(vec!["xbt_usdtM".to_string()]);
-    //订阅
     ws.set_subscribe(vec![
         KucoinSwapSubscribeType::PuContractMarketLevel2Depth50,
-        KucoinSwapSubscribeType::PuContractMarkettickerV2,
         KucoinSwapSubscribeType::PuContractMarketExecution,
+        KucoinSwapSubscribeType::PuContractMarkettickerV2,
     ]);
 
-    let subscription = ws.get_subscription();
-    let subscription_v: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
 
+    let write_tx_am = Arc::new(Mutex::new(write_tx));
+    let bool_v1 = Arc::new(AtomicBool::new(true));
 
-    //模拟业务场景 一直监听数据
-    let y2 = tokio::spawn(async move {
+    //读取
+    let bool_v1_clone = Arc::clone(&bool_v1);
+    let tr = tokio::spawn(async move {
+        trace!("线程-数据读取-开启");
         loop {
             if let Some(data) = read_rx.next().await {
                 trace!("读取数据data:{:?}",data)
             }
         }
-        trace!("数据读取退出 完成");
-    });
-
-    //模拟业务场景 开启链接
-    let bool_v1_clone = Arc::clone(&bool_v1);
-    let y = tokio::spawn(async move {
-        //链接
-        ws.ws_connect_async(bool_v1_clone, write_rx, &read_tx).await.unwrap();
-        trace!("ws_connect_async 完成");
+        trace!("线程-数据读取-结束");
     });
 
-
-    //模拟用户主动写入数据
+    //写数据
     let bool_v2_clone = Arc::clone(&bool_v1);
-    let y1 = tokio::spawn(async move {
-        //模拟 链接之后 服务器响应,可以开始订阅
-        tokio::time::sleep(Duration::from_millis(3000)).await;
-        for sub in &subscription_v {
-            trace!("--发起订阅:{:?}", sub);
-            write_tx.unbounded_send(Message::Text(sub.parse().unwrap())).unwrap();
-        }
-
-        //等待15s之后发送关闭指令
-        tokio::time::sleep(Duration::from_millis(15000)).await;
-        let bool_v2_v = bool_v2_clone.load(Ordering::SeqCst);
-        bool_v2_clone.store(!bool_v2_v, Ordering::SeqCst);
-        if bool_v2_v {
-            let close_frame = CloseFrame {
-                code: CloseCode::Normal,
-                reason: Cow::Borrowed("Bye bye"),
-            };
-            let close_message = Message::Close(Some(close_frame));
-            write_tx.unbounded_send(close_message).unwrap();
-
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            //关闭通道
-            drop(write_tx);
-        }
-        trace!("主动推出 完成");
+    let write_tx_clone = Arc::clone(&write_tx_am);
+    // let tw = tokio::spawn(async move {
+    //     trace!("线程-数据写入-开始");
+    //     loop {
+    //         tokio::time::sleep(Duration::from_millis(20*1000)).await;
+    //         let close_frame = CloseFrame {
+    //             code: CloseCode::Normal,
+    //             reason: Cow::Borrowed("Bye bye"),
+    //         };
+    //         let close_message = Message::Close(Some(close_frame));
+    //         // AbstractWsMode::send_subscribe(write_tx_clone.clone(), Message::Text("32313221".to_string()));
+    //         AbstractWsMode::send_subscribe(write_tx_clone.clone(), close_message);
+    //         trace!("发送指令成功");
+    //     }
+    //     trace!("线程-数据写入-结束");
+    // });
+
+    // loop {
+    let t1 = tokio::spawn(async move {
+        //链接
+        let bool_v3_clone = Arc::clone(&bool_v1);
+        ws.ws_connect_async(bool_v3_clone, &write_tx_am, write_rx, read_tx).await.expect("链接失败(内部一个心跳线程应该已经关闭了)");
+        trace!("test 唯一线程结束--");
     });
-    tokio::try_join!(y,y1,y2).unwrap();
-    trace!("323123213");
+    tokio::try_join!(t1).unwrap();
+    trace!("当此结束");
+    // }
+    trace!("重启!");
+    trace!("参考交易所关闭");
+    return;
 }
 
 //ws-订阅私有频道信息
@@ -96,10 +86,6 @@ async fn ws_custom_subscribe_pu() {
 async fn ws_custom_subscribe_pr() {
     global::log_utils::init_log_with_trace();
 
-    let bool_v1 = Arc::new(AtomicBool::new(true));
-    //创建读写通道
-    let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
-    let (read_tx, mut read_rx) = futures_channel::mpsc::unbounded();
 
     //对象
     let btree_map = KucoinSwapLogin {
@@ -107,84 +93,75 @@ async fn ws_custom_subscribe_pr() {
         secret_key: SECRET_KEY.to_string(),
         pass_key: PASS_KEY.to_string(),
     };
+
+    let (write_tx, write_rx) = futures_channel::mpsc::unbounded();
+    let (read_tx, mut read_rx) = futures_channel::mpsc::unbounded();
+
+    // let (write_tx, write_rx) = tokio::sync::broadcast::channel::<Message>(10);
+    // let (read_tx, mut read_rx) = tokio::sync::broadcast::channel::<ResponseData>(10);
+
+
     let mut ws = get_ws(Option::from(btree_map), KucoinSwapWsType::Private).await;
-    // 币对
-    ws.set_symbols(vec!["xbt_usdtM".to_string(),"ACHUSDTM".to_string()]);
-    //订阅
+    ws.set_symbols(vec!["xbt_usdtM".to_string()]);
     ws.set_subscribe(vec![
-        KucoinSwapSubscribeType::PuContractMarketLevel2Depth50,
-        KucoinSwapSubscribeType::PuContractMarketExecution,
+        // KucoinSwapSubscribeType::PuContractMarketLevel2Depth50,
+        // KucoinSwapSubscribeType::PuContractMarketExecution,
         KucoinSwapSubscribeType::PuContractMarkettickerV2,
+
         KucoinSwapSubscribeType::PrContractAccountWallet,
         KucoinSwapSubscribeType::PrContractPosition,
         KucoinSwapSubscribeType::PrContractMarketTradeOrdersSys,
         KucoinSwapSubscribeType::PrContractMarketTradeOrders,
     ]);
 
-    let subscription = ws.get_subscription();
-    let subscription_v: Vec<String> = subscription.into_iter().collect::<HashSet<String>>().into_iter().collect();
 
-    let t1 = tokio::spawn(async move {
+    let write_tx_am = Arc::new(Mutex::new(write_tx));
+    let bool_v1 = Arc::new(AtomicBool::new(true));
+
+    //读取
+    let bool_v1_clone = Arc::clone(&bool_v1);
+    let tr = tokio::spawn(async move {
+        trace!("线程-数据读取-开启");
         loop {
             if let Some(data) = read_rx.next().await {
                 trace!("读取数据data:{:?}",data)
             }
         }
-        trace!("数据读取退出 完成");
+        trace!("线程-数据读取-结束");
     });
 
-
-    //模拟业务场景 开启链接
-    let bool_v1_clone = Arc::clone(&bool_v1);
-    let t2 = tokio::spawn(async move {
-        ws.ws_connect_async(bool_v1_clone, write_rx, &read_tx).await.unwrap();
-        trace!("ws_connect_async 完成");
-    });
-
-    //模拟用户主动写入数据
+    //写数据
     let bool_v2_clone = Arc::clone(&bool_v1);
-    let t3 = tokio::spawn(async move {
-        //模拟 链接之后 服务器响应,可以开始订阅
-        tokio::time::sleep(Duration::from_millis(5000)).await;
-        let bool_v2_v = bool_v2_clone.load(Ordering::SeqCst);
-        bool_v2_clone.store(!bool_v2_v, Ordering::SeqCst);
-        for sub in &subscription_v {
-            trace!("--发起订阅:{:?}", sub);
-            write_tx.unbounded_send(Message::Text(sub.parse().unwrap())).unwrap();
-        }
-        tokio::time::sleep(Duration::from_millis(3000)).await;
-
-
-
-        //
-        // //等待15s之后发送关闭指令
-        // tokio::time::sleep(Duration::from_millis(15000)).await;
-        // let bool_v2_v = bool_v2_clone.load(Ordering::SeqCst);
-        // bool_v2_clone.store(!bool_v2_v, Ordering::SeqCst);
-        // if bool_v2_v {
-        //     // let close_frame = CloseFrame {
-        //     //     code: CloseCode::Normal,
-        //     //     reason: Cow::Borrowed("Bye bye"),
-        //     // };
-        //     // let close_message = Message::Close(Some(close_frame));
-        //     // write_tx.unbounded_send(close_message).unwrap();
-        //
-        //     tokio::time::sleep(Duration::from_millis(5000)).await;
-        //     //关闭通道
-        //     // drop(write_tx);
-        // }
-        //模拟心跳
-        loop {
-            tokio::time::sleep(Duration::from_millis(5000)).await;
-            write_tx.unbounded_send(Message::Ping(Vec::from("ping"))).unwrap();
-        }
-        trace!("主动推出 完成");
+    let write_tx_clone = Arc::clone(&write_tx_am);
+    // let tw = tokio::spawn(async move {
+    //     trace!("线程-数据写入-开始");
+    //     loop {
+    //         tokio::time::sleep(Duration::from_millis(20*1000)).await;
+    //         let close_frame = CloseFrame {
+    //             code: CloseCode::Normal,
+    //             reason: Cow::Borrowed("Bye bye"),
+    //         };
+    //         let close_message = Message::Close(Some(close_frame));
+    //         // AbstractWsMode::send_subscribe(write_tx_clone.clone(), Message::Text("32313221".to_string()));
+    //         AbstractWsMode::send_subscribe(write_tx_clone.clone(), close_message);
+    //         trace!("发送指令成功");
+    //     }
+    //     trace!("线程-数据写入-结束");
+    // });
+
+    // loop {
+    let t1 = tokio::spawn(async move {
+        //链接
+        let bool_v3_clone = Arc::clone(&bool_v1);
+        ws.ws_connect_async(bool_v3_clone, &write_tx_am, write_rx, read_tx).await.expect("链接失败(内部一个心跳线程应该已经关闭了)");
+        trace!("test 唯一线程结束--");
     });
-
-
-    // tokio::try_join!(t1,t2,t3).unwrap();
-    tokio::try_join!(t2,t3,t1).unwrap();
-    trace!("323123213");
+    tokio::try_join!(t1).unwrap();
+    trace!("当此结束");
+    // }
+    trace!("重启!");
+    trace!("参考交易所关闭");
+    return;
 }