diff --git a/src/hostdemo.rs b/src/hostdemo.rs index 205172e..029bcef 100644 --- a/src/hostdemo.rs +++ b/src/hostdemo.rs @@ -1695,10 +1695,11 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u let mut qseq: u16 = 1; let mut seq: u32 = 1; // 发现任务队列: ★窄分支优先 (已知灯具各一个只含自己的分支 — Butler 可能拒转全范围查询) - let mut stack: Vec<(u64, u64)> = vec![(0, 0xFFFF_FFFF_FFFF)]; + // (lo, hi, silent_retry_done) — 静默分支重探一次 (池上行丢包保险) + let mut stack: Vec<(u64, u64, u8)> = vec![(0, 0xFFFF_FFFF_FFFF, 0)]; for u in known.iter() { let v = uid_u64(u); - stack.push((v - 1, v + 1)); + stack.push((v - 1, v + 1, 0)); } /// 一台灯具的参数快照 (参数扫描汇总用) struct DevInfo { @@ -1738,7 +1739,10 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u let mut collect_until = Instant::now(); let mut found: Vec<[u8; 6]> = Vec::new(); let mut collision = false; - let mut current_branch: Option<(u64, u64)> = None; + let mut silent_prunes = 0usize; + let mut found_this_pass = 0usize; + let mut full_passes = 0usize; + let mut current_branch: Option<(u64, u64, u8)> = None; let mut sent = 0u64; println!("[S] 统一会话环启动: DMX 30fps + RDM 穿插 ({}s)", secs); @@ -1764,16 +1768,16 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u if collecting && Instant::now() >= collect_until { // 本分支收集结束 → 判定 collecting = false; - if let Some((lo, hi)) = current_branch.take() { + if let Some((lo, hi, retried)) = current_branch.take() { if collision { let mid = lo + (hi - lo) / 2; - stack.push((mid + 1, hi)); - stack.push((lo, mid)); + stack.push((mid + 1, hi, 0)); + stack.push((lo, mid, 0)); println!(" [S] 分支冲突 → 二分"); } else if found.len() == 1 && found_valid(&found[0]) { let uid = found[0]; println!(" [S] ★发现灯具 {}", uid_s(&uid)); - if !fixtures.contains(&uid) { fixtures.push(uid); } + if !fixtures.contains(&uid) { fixtures.push(uid); found_this_pass += 1; } // 参数扫描队列在发现完成后按 PID 填充 (见下) // DISC_MUTE 该灯具 tn = tn.wrapping_add(1); @@ -1782,8 +1786,13 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u let _ = sock.send_to(&{ let mut f = f; f[0x1A..0x1E].copy_from_slice(&seq.to_le_bytes()); seq += 1; f }, dst); } else if found.len() > 1 { let mid = lo + (hi - lo) / 2; - stack.push((mid + 1, hi)); - stack.push((lo, mid)); + stack.push((mid + 1, hi, 0)); + stack.push((lo, mid, 0)); + } else if retried == 0 { + // 静默且未重探: 池上行丢包/迟到保险 — 重探一次再放弃 + stack.push((lo, hi, 1)); + silent_prunes += 1; + println!(" [S] 静默 → 重探"); } found.clear(); collision = false; @@ -1791,9 +1800,9 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u } if collecting { // 收集窗口内每 150ms 重发同分支查询 (真主机连发节奏) - if last_rdm.elapsed() >= Duration::from_millis(150) { + if last_rdm.elapsed() >= Duration::from_millis(100) { last_rdm = Instant::now(); - if let Some((lo, hi)) = current_branch { + if let Some((lo, hi, retried)) = current_branch { let mut pd = Vec::with_capacity(12); pd.extend_from_slice(&u64_uid(lo)); pd.extend_from_slice(&u64_uid(hi)); @@ -1807,6 +1816,7 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u f2[0x30] = 0x01; f2[0x49] = f2[0x49].wrapping_sub(1); let _ = sock.send_to(&f2, dst); + current_branch = Some((lo, hi, retried)); } } } @@ -1819,7 +1829,7 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u let _ = sock.send_to(&{ let mut f = f; f[0x1A..0x1E].copy_from_slice(&seq.to_le_bytes()); seq += 1; f }, dst); unmuting = true; println!("[S] DISC_UN_MUTE 已发"); - } else if let Some((lo, hi)) = stack.pop() { + } else if let Some((lo, hi, retried)) = stack.pop() { let mut pd = Vec::with_capacity(12); pd.extend_from_slice(&u64_uid(lo)); pd.extend_from_slice(&u64_uid(hi)); @@ -1835,17 +1845,15 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u // flag=01 副本的 srcUID 末字节 = fe (SL 实测: ff/fe 成对) f2[0x49] = f2[0x49].wrapping_sub(1); let _ = sock.send_to(&f2, dst); - current_branch = Some((lo, hi)); + current_branch = Some((lo, hi, retried)); collecting = true; - collect_until = Instant::now() + Duration::from_millis(500); + // 池应答软件级即时; 500ms 是线上往返时代的窗, 64 台二分要 ~80s + collect_until = Instant::now() + Duration::from_millis(220); } else { - if fixtures.is_empty() && t < 90.0 { - // 未发现 → 重新压栈全范围, 循环重试 (SL 实测: 认领后 ~27.5s RDM 才开始被代理!) - stack.push((0, 0xFFFF_FFFF_FFFF)); - } else { - discovering = false; - println!("[S] 发现完成: {} 台灯具", fixtures.len()); - } + // 栈空即收工: 每分支已带单次静默重探 (实测 64/64 一轮收敛; + // 静默剪枝 ~62 个是合法空分支, 全量重扫纯属浪费时隙) + discovering = false; + println!("[S] 发现完成: {} 台灯具 (静默剪枝 {})", fixtures.len(), silent_prunes); } } }