mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 12:30:44 +00:00
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
295 lines
11 KiB
Python
295 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""把「遥控诊断」合并进手表主程序(不再需要单独装一个诊断 App)。
|
|
|
|
改动:
|
|
1. 新增字段 diagPanel / diagText / diagStatusLine / diagIpInput
|
|
2. 新增 buildDiagPanel():全屏浮层,顶部按钮 + 报告正文 + 底部手动测 IP
|
|
3. onCreate 里构建并加入 root
|
|
4. onBackPressed 优先关诊断面板
|
|
5. 控制面板加一个「设备诊断」按钮
|
|
6. 新增 openDiagPanel / closeDiagPanel / runDiagnostics / copyDiagReport / testDiagIp
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
MAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\android\src"
|
|
r"\com\lanremote\watch\MainActivity.java")
|
|
|
|
FIELDS_OLD = " private TextView logView;\n"
|
|
FIELDS_NEW = (
|
|
" private TextView logView;\n"
|
|
" private FrameLayout diagPanel;\n"
|
|
" private TextView diagText;\n"
|
|
" private TextView diagStatusLine;\n"
|
|
" private EditText diagIpInput;\n"
|
|
" private boolean diagRunning = false;\n"
|
|
)
|
|
|
|
BUILD_CALL_OLD = " buildMirrorPanel();\n"
|
|
BUILD_CALL_NEW = " buildMirrorPanel();\n buildDiagPanel();\n"
|
|
|
|
ADD_VIEW_OLD = " root.addView(mirrorPanel);\n"
|
|
ADD_VIEW_NEW = " root.addView(mirrorPanel);\n root.addView(diagPanel);\n"
|
|
|
|
BACK_OLD = """ if (mirrorPanel.getVisibility() == View.VISIBLE) {
|
|
closeMirrorPanel();
|
|
return;
|
|
}
|
|
"""
|
|
BACK_NEW = """ if (diagPanel != null && diagPanel.getVisibility() == View.VISIBLE) {
|
|
closeDiagPanel();
|
|
return;
|
|
}
|
|
if (mirrorPanel.getVisibility() == View.VISIBLE) {
|
|
closeMirrorPanel();
|
|
return;
|
|
}
|
|
"""
|
|
|
|
BUTTON_OLD = """ action("系统信息", new Runnable() {
|
|
public void run() { showInfo(); }
|
|
}));
|
|
|
|
flushGrid(grid);"""
|
|
BUTTON_NEW = """ action("系统信息", new Runnable() {
|
|
public void run() { showInfo(); }
|
|
}));
|
|
|
|
addRow(grid,
|
|
action("设备诊断", new Runnable() {
|
|
public void run() { openDiagPanel(); }
|
|
}),
|
|
action("清空日志", new Runnable() {
|
|
public void run() { logView.setText(""); }
|
|
}));
|
|
|
|
flushGrid(grid);"""
|
|
|
|
ANCHOR = " private void buildMirrorPanel() {"
|
|
|
|
DIAG_CODE = ''' // ==================================================================
|
|
// 设备诊断(原来是一个单独的「遥控诊断」App,现在合并进来)
|
|
// ==================================================================
|
|
|
|
private void buildDiagPanel() {
|
|
diagPanel = new FrameLayout(this);
|
|
diagPanel.setBackgroundColor(C_BG);
|
|
|
|
LinearLayout column = new LinearLayout(this);
|
|
column.setOrientation(LinearLayout.VERTICAL);
|
|
column.setPadding(dp(6), dp(6), dp(6), dp(6));
|
|
|
|
// 顶部:标题 + 操作按钮
|
|
LinearLayout top = new LinearLayout(this);
|
|
top.setOrientation(LinearLayout.HORIZONTAL);
|
|
top.setGravity(Gravity.CENTER_VERTICAL);
|
|
|
|
TextView title = new TextView(this);
|
|
title.setText("设备诊断");
|
|
title.setTextColor(C_FG);
|
|
title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
|
|
top.addView(title, new LinearLayout.LayoutParams(
|
|
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
|
|
|
top.addView(smallButton("重新检测", C_ACCENT, new Runnable() {
|
|
public void run() { runDiagnostics(); }
|
|
}));
|
|
top.addView(smallButton("复制全部", C_OK, new Runnable() {
|
|
public void run() {
|
|
if (diagText == null || diagText.getText().length() == 0) {
|
|
toast("还没有报告,先点「重新检测」");
|
|
return;
|
|
}
|
|
copyToWatchClipboard(diagText.getText().toString());
|
|
toast("已复制 " + diagText.getText().length() + " 个字符");
|
|
}
|
|
}));
|
|
top.addView(smallButton("返回", C_CARD, new Runnable() {
|
|
public void run() { closeDiagPanel(); }
|
|
}));
|
|
column.addView(top);
|
|
|
|
diagStatusLine = new TextView(this);
|
|
diagStatusLine.setText("点「重新检测」开始(约 8~20 秒)");
|
|
diagStatusLine.setTextColor(C_DIM);
|
|
diagStatusLine.setTextSize(TypedValue.COMPLEX_UNIT_SP, 11);
|
|
diagStatusLine.setPadding(dp(2), dp(4), dp(2), dp(4));
|
|
column.addView(diagStatusLine);
|
|
|
|
// 报告正文
|
|
ScrollView scroll = new ScrollView(this);
|
|
diagText = new TextView(this);
|
|
diagText.setText("还没有报告。\\n\\n点上面的「重新检测」,"
|
|
+ "它会真实跑一次局域网自动发现和 TCP 连通测试,"
|
|
+ "测完自动复制到剪贴板。");
|
|
diagText.setTextColor(C_FG);
|
|
diagText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 11);
|
|
diagText.setTypeface(android.graphics.Typeface.MONOSPACE);
|
|
diagText.setTextIsSelectable(true);
|
|
diagText.setPadding(dp(4), dp(4), dp(4), dp(4));
|
|
scroll.addView(diagText);
|
|
column.addView(scroll, new LinearLayout.LayoutParams(
|
|
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
|
|
|
|
// 底部:手动测一个 IP
|
|
LinearLayout bottom = new LinearLayout(this);
|
|
bottom.setOrientation(LinearLayout.HORIZONTAL);
|
|
bottom.setGravity(Gravity.CENTER_VERTICAL);
|
|
|
|
diagIpInput = new EditText(this);
|
|
diagIpInput.setHint("手动测电脑 IP,如 192.168.10.103");
|
|
diagIpInput.setHintTextColor(C_DIM);
|
|
diagIpInput.setTextColor(C_FG);
|
|
diagIpInput.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
|
|
diagIpInput.setSingleLine(true);
|
|
diagIpInput.setInputType(android.text.InputType.TYPE_CLASS_TEXT
|
|
| android.text.InputType.TYPE_TEXT_VARIATION_URI);
|
|
diagIpInput.setBackground(rounded(C_CARD, 6));
|
|
diagIpInput.setPadding(dp(6), dp(6), dp(6), dp(6));
|
|
bottom.addView(diagIpInput, new LinearLayout.LayoutParams(
|
|
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
|
|
|
bottom.addView(smallButton("测一下", C_ACCENT, new Runnable() {
|
|
public void run() { testDiagIp(); }
|
|
}));
|
|
column.addView(bottom);
|
|
|
|
diagPanel.addView(column, new FrameLayout.LayoutParams(
|
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
diagPanel.setVisibility(View.GONE);
|
|
}
|
|
|
|
private void openDiagPanel() {
|
|
if (diagPanel == null) {
|
|
return;
|
|
}
|
|
diagPanel.setVisibility(View.VISIBLE);
|
|
diagPanel.bringToFront();
|
|
if ((diagText.getText() == null || diagText.getText().length() == 0)
|
|
&& !diagRunning) {
|
|
runDiagnostics();
|
|
}
|
|
}
|
|
|
|
private void closeDiagPanel() {
|
|
if (diagPanel != null) {
|
|
diagPanel.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
private void runDiagnostics() {
|
|
if (diagRunning) {
|
|
return;
|
|
}
|
|
diagRunning = true;
|
|
diagStatusLine.setText("正在检测…(广播 4 秒 + 必要时扫描整个网段)");
|
|
diagText.setText("正在采集,请稍候…\\n\\n先跑一次 UDP 广播;"
|
|
+ "如果没结果,会自动扫描整个网段的 TCP 8765。最多约 20 秒。");
|
|
|
|
io.execute(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
String report;
|
|
try {
|
|
report = Diagnostics.build(MainActivity.this,
|
|
new Diagnostics.Progress() {
|
|
@Override
|
|
public void step(final String text) {
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
diagStatusLine.setText(text);
|
|
}
|
|
});
|
|
}
|
|
}, true);
|
|
} catch (Throwable t) {
|
|
report = "诊断执行失败:" + t;
|
|
}
|
|
final String result = report;
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
diagRunning = false;
|
|
diagText.setText(result);
|
|
diagStatusLine.setText("检测完成,已自动复制到剪贴板");
|
|
copyToWatchClipboard(result);
|
|
appendLog("设备诊断完成,已复制到剪贴板");
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private void testDiagIp() {
|
|
final String ip = diagIpInput.getText().toString().trim();
|
|
if (ip.isEmpty()) {
|
|
toast("先填一个 IP");
|
|
return;
|
|
}
|
|
diagStatusLine.setText("正在测试 " + ip + " …");
|
|
io.execute(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
final String extra;
|
|
try {
|
|
extra = Diagnostics.manualTest(ip);
|
|
} catch (Throwable t) {
|
|
extra = "测试失败:" + t;
|
|
}
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
String current = diagText.getText().toString();
|
|
diagText.setText(current + "\\n" + extra + "\\n");
|
|
diagStatusLine.setText("测试完成,已追加并复制");
|
|
copyToWatchClipboard(diagText.getText().toString());
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
'''
|
|
|
|
|
|
def main() -> int:
|
|
raw = MAIN.read_bytes()
|
|
text = raw.decode("utf-8")
|
|
ok = True
|
|
|
|
def swap(old: str, new: str, tag: str) -> None:
|
|
nonlocal text, ok
|
|
if old not in text:
|
|
print(f" [失败] {tag} 锚点未匹配")
|
|
ok = False
|
|
return
|
|
text = text.replace(old, new, 1)
|
|
print(f" {tag}: OK")
|
|
|
|
swap(FIELDS_OLD, FIELDS_NEW, "字段")
|
|
swap(BUILD_CALL_OLD, BUILD_CALL_NEW, "构建调用")
|
|
swap(ADD_VIEW_OLD, ADD_VIEW_NEW, "加入 root")
|
|
swap(BACK_OLD, BACK_NEW, "返回键处理")
|
|
swap(BUTTON_OLD, BUTTON_NEW, "诊断按钮")
|
|
|
|
if ANCHOR not in text:
|
|
print(" [失败] buildMirrorPanel 锚点未匹配")
|
|
ok = False
|
|
else:
|
|
text = text.replace(ANCHOR, DIAG_CODE + ANCHOR, 1)
|
|
print(" 诊断面板代码: OK")
|
|
|
|
if not ok:
|
|
return 1
|
|
|
|
MAIN.write_bytes(text.encode("utf-8"))
|
|
print("\n MainActivity.java 已写入")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|