阶段3+4+5:管理页白色化 + 局域网诊断 + 全量验收

阶段3 管理页
- 清掉全部深色主题残留(地址框 #0b1220、按钮悬停 #262c36、
  删除按钮 #2d1214 等 11 处),现在 0 处深色
- 接口全部正常:health / downloads / netcheck

阶段4 局域网诊断
- 查清楚"电脑不在同一网络"是怎么回事:被控端是**对的**
  (lan_ips() 报 ['192.168.2.64', '169.254.83.107'],真实地址排第一),
  是手表当时真不在 192.168.2.x —— 可能连了 5G 频段的另一个路由器,或开着移动数据
- 所以改了手表的提示:不再只说"不在同一网络",
  而是把**双方地址都打出来**,用户一眼能看出是网段不同还是连错 WiFi
- 端到端验证局域网路径:认证 1 ms,功能列表 207 项

阶段1 结论修正(一天内推翻自己两次,如实记录)
- 第一次判断"优选 IP 无用":错。半小时内确实能避开超时 IP
- 第二次固定优选 IP:也错。那些实测 138ms 的 IP 半小时后全不通了
  —— Cloudflare anycast 可达性随运营商路由变化,固定 IP 等于钉死到会失效的地址
- 最终:不固定,靠 GeoDNS + cloudflared 重试 + ha-connections 2 冗余
- 撤销后立即变好:连接稳定 2 条、超时告警 0 次、设备侧延迟 4.40s -> 1.66s
- **真正的瓶颈**:分段实测发现本机到 Cloudflare 的**裸 RTT 就 1439 ms**,
  比经隧道的请求(1215 ms)还慢。说明瓶颈是这条网络的 4G 上行本身,
  不是设备的隧道。公网侧已无优化空间。
- 局域网 118 ms vs 公网 1215 ms,快 10 倍 —— 这才是该走的路

阶段5 验收
- 全量回归 29 项全通过
- 设备侧验收 38 项全通过
- 成品:setup exe 14.37 MB / server zip / watch apk,已同步到设备下载区
This commit is contained in:
xmz7891
2026-10-07 00:13:10 +08:00
parent 566d9e384f
commit 7b7830d8c5
80 changed files with 1890 additions and 39 deletions
+98
View File
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
r'''阶段4:诊断局域网直连为什么没生效。
现象(手表日志):
已更新电脑地址为 192.168.2.64:8765
电脑不在同一网络,继续用中转
判断逻辑在手表端 MainActivity:
pickSameSubnet(client.relayLanIps()) <- 拿电脑报上来的 lanIps
localIpv4List() <- 拿手表自己的网卡 IP
sameSubnet(a, b) <- 比前 3 段(/24)
可能出问题的地方:
1. 被控端报的 lanIps 里全是虚拟网卡(VMware/VirtualBox/Hyper-V)
—— 真实的 192.168.2.64 反而不在里面
2. 手表自己的 localIpv4List() 拿到的是运营商 IP(移动数据)
3. 手表和电脑真的不在一个网段
这个脚本查第 1 条:本机被控端实际会报哪些 IP。
第 2、3 条要手表端日志,我先把能查的查清。
'''
from __future__ import annotations
import json
import socket
import subprocess
import sys
import time
from pathlib import Path
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
sys.path.insert(0, str(ROOT / "windows"))
def main() -> int:
print(" 一、被控端会报哪些 lanIps(这才是关键)")
try:
from lanremote.discovery import local_ipv4_list
ips = local_ipv4_list()
print(" local_ipv4_list() -> %s" % (ips,))
except Exception as exc: # noqa: BLE001
print(" 拿不到(%s),换个方式" % exc)
ips = []
# 直接列出所有网卡地址,对照着看
print()
print(" 二、本机所有 IPv4 地址(含虚拟网卡)")
try:
result = subprocess.run(
["powershell", "-NoProfile", "-Command",
"Get-NetIPAddress -AddressFamily IPv4 | "
"Where-Object { $_.IPAddress -notlike '127.*' } | "
"ForEach-Object { $_.IPAddress + ' ' + $_.InterfaceAlias }"],
capture_output=True, text=True, timeout=60,
encoding="utf-8", errors="replace")
for line in (result.stdout or "").splitlines():
if line.strip():
print(" " + line.strip())
except Exception as exc: # noqa: BLE001
print(" 失败: %s" % exc)
print()
print(" 三、判断:报出去的 IP 里有没有真实局域网地址")
real = [ip for ip in ips
if ip.startswith(("192.168.", "10.", "172.16.", "172.17.",
"172.18.", "172.19.", "172.2", "172.30.",
"172.31.")) and not ip.startswith("169.254.")]
virtual_hint = [ip for ip in ips if ip.startswith(("192.168.56.",
"192.168.99.",
"172.17.", "172.18.",
"172.19."))]
print(" 报出去的: %s" % (ips or "(空)"))
print(" 像真实局域网的: %s" % (real or "(没有!)"))
print(" 像虚拟网卡的: %s" % (virtual_hint or "(没有)"))
if not ips:
print()
print(" ⚠ 一个都没报 —— 手表当然匹配不上。")
elif not real:
print()
print(" ⚠ 报的全是虚拟网卡地址,手表连不到这些。")
else:
print()
print(" OK 至少有一个真实局域网地址,手表应该能匹配到 %s" % real[0])
print()
print(" 四、手表端要看的日志关键字")
print(" 手表连上后,日志区会打:")
print(" 「已更新电脑地址为 x.x.x.x:8765」—— 这是被控端报的地址")
print(" 「电脑不在同一网络,继续用中转」—— 说明 sameSubnet 没匹配上")
print(" 要确认两件事:")
print(" 1. 那个 x.x.x.x 是不是电脑真实的局域网地址")
print(" 2. 手表自己的 WiFi 地址是不是同一个 /24")
return 0
if __name__ == "__main__":
sys.exit(main())