diff --git a/Cargo.toml b/Cargo.toml index 7498940..603d96f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,10 +67,13 @@ tokio-websockets = { version = "0.8", features = [ "client", "fastrand", "sha1_smol", + "rustls-webpki-roots", ] } bytes = "1.10.0" qrcode = { version = "0.14.1", default-features = false, features = [] } +rustls-rustcrypto = "0.0.2-alpha" +chrono = { version = "0.4.41", default-features = false, features = ["now", "pure-rust-locales", "clock"] } [build-dependencies] embuild = "0.33" diff --git a/sdkconfig.defaults b/sdkconfig.defaults index f6e4d34..5f43c98 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,5 +1,5 @@ # Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) -CONFIG_ESP_MAIN_TASK_STACK_SIZE=30720 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=65536 # Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). # This allows to use 1 ms granularity for thread sleeps (10 ms by default). diff --git a/src/main.rs b/src/main.rs index 0e547e5..ea7d629 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod network; mod protocol; mod ui; mod ws; +mod sntp; #[derive(Debug, Clone)] struct Setting { @@ -184,6 +185,13 @@ fn main() -> anyhow::Result<()> { let wifi = _wifi.unwrap(); log_heap(); + let now_time = sntp::sync_time(); + gui.state = "SNTP sync".to_string(); + gui.text = format!("{}", now_time); + gui.display_flush().unwrap(); + + log_heap(); + let mac = wifi.ap_netif().get_mac().unwrap(); let mac_str = format!( "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", diff --git a/src/sntp.rs b/src/sntp.rs new file mode 100644 index 0000000..13920de --- /dev/null +++ b/src/sntp.rs @@ -0,0 +1,31 @@ +use chrono::{DateTime, FixedOffset, TimeZone, Utc}; +use esp_idf_svc::sntp::{EspSntp, SyncStatus::Completed}; +use std::{thread::sleep, time::Duration}; + +pub fn sync_time() -> String { + log::info!("SNTP sync time"); + show_now(); + let ntp_client = EspSntp::new_default().unwrap(); + loop { + let status = ntp_client.get_sync_status(); + log::debug!("sntp sync status {:?}", status); + if status == Completed { + break; + } + sleep(Duration::from_secs(1)); + } + log::info!("SNTP synchronized!"); + show_now() +} + +fn show_now() -> String { + let cst = FixedOffset::east_opt(8 * 3600).unwrap(); // 安全的偏移量创建 + + let utc_now = Utc::now(); + let local_now: DateTime = cst.from_utc_datetime(&utc_now.naive_utc()); + let now_str = local_now.format("%Y-%m-%dT%H:%M:%S%:z").to_string(); + + log::info!("now time: {}", now_str); + + now_str.to_string() +} diff --git a/src/ws.rs b/src/ws.rs index 1b6e0f8..6b13c27 100644 --- a/src/ws.rs +++ b/src/ws.rs @@ -7,24 +7,61 @@ fn print_stack_high() { use crate::{app::Event, protocol::ServerEvent}; use futures_util::{SinkExt, StreamExt, TryFutureExt}; -use tokio_websockets::Message; +use std::sync::Arc; +use tokio::net::TcpStream; +use tokio_websockets::{Connector, Message}; pub struct Server { - pub uri: String, timeout: std::time::Duration, ws: tokio_websockets::WebSocketStream>, } impl Server { pub async fn new(uri: String) -> anyhow::Result { - let (ws, _resp) = tokio_websockets::ClientBuilder::new() + log::info!("uri: {}", uri); + + let (scheme, rest) = uri.split_once("://").unwrap(); + let default_port = match scheme { + "wss" => 443, + _ => 80, + }; + + // 提取 host[:port] 部分 + let host_port = rest.split('/').next().unwrap(); + let (host, port) = if let Some((h, p)) = host_port.split_once(':') { + (h, p.parse::().unwrap_or(default_port)) + } else { + (host_port, default_port) + }; + log::info!("connecting to {}:{}", host, port); + + log::info!("establish tcp connection"); + let tcp_stream = TcpStream::connect(format!("{host}:{port}")).await?; + let stream = match scheme { + "ws" => Connector::Plain.wrap(host, tcp_stream).await?, + _ => { + log::info!("init tls provider"); + let provider = Arc::new(rustls_rustcrypto::provider()); + log::info!("init tls connector"); + let connector = Connector::new_rustls_with_crypto_provider(provider)?; + log::info!("warp tls connection"); + connector.wrap(host, tcp_stream).await? + } + }; + let (ws, resp) = tokio_websockets::ClientBuilder::new() .uri(&uri)? - .connect() + .connect_on(stream) .await?; + log::info!( + "ws resp status: {:?}, headers: {:?} ", + resp.status(), + resp.headers() + ); + let timeout = std::time::Duration::from_secs(30); - Ok(Self { uri, timeout, ws }) + Ok(Self { timeout, ws }) } pub fn set_timeout(&mut self, timeout: std::time::Duration) {