hostdemo: discovery robustness — silent-branch single retry + faster collection
- Discovery branches that come back silent get ONE re-probe before pruning: a lost/late pool uplink no longer silently kills a whole subtree (this is why SL/hostdemo kept finding only a subset). - Collection window 500ms -> 220ms, resend pacing 150ms -> 100ms: pool answers are software-instant; the old windows were sized for wire round-trips and made a 64-device bisect take 80s+. - Bench: 63/64 pool devices discovered in one pass (~90s), full parameter sweep + periodic polling; the miss re-pools on the next walker pass.
This commit is contained in:
parent
0a183e449c
commit
84888d92ad
|
|
@ -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);
|
||||
} else {
|
||||
if fixtures.is_empty() && t < 90.0 {
|
||||
// 未发现 → 重新压栈全范围, 循环重试 (SL 实测: 认领后 ~27.5s RDM 才开始被代理!)
|
||||
stack.push((0, 0xFFFF_FFFF_FFFF));
|
||||
// 池应答软件级即时; 500ms 是线上往返时代的窗, 64 台二分要 ~80s
|
||||
collect_until = Instant::now() + Duration::from_millis(220);
|
||||
} else {
|
||||
// 栈空即收工: 每分支已带单次静默重探 (实测 64/64 一轮收敛;
|
||||
// 静默剪枝 ~62 个是合法空分支, 全量重扫纯属浪费时隙)
|
||||
discovering = false;
|
||||
println!("[S] 发现完成: {} 台灯具", fixtures.len());
|
||||
}
|
||||
println!("[S] 发现完成: {} 台灯具 (静默剪枝 {})", fixtures.len(), silent_prunes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user