mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 17:10:43 +00:00
ykxmz 1.5.0:修复手表端 TLS 证书校验 + MTU 修复网络稳定性
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""手表端接上电脑功能注册表。
|
||||
|
||||
新增「功能」分页:显示 / 音量 / 系统 / 查看 / 效率 / 文件 六个分组,
|
||||
点进去是这一组的功能列表,按 kind 决定怎么执行:
|
||||
toggle 直接切换
|
||||
value 弹档位选择(亮度 10~100 分 5 档)
|
||||
input 弹输入框(有的要两个字段)
|
||||
action 直接执行;删除类先确认
|
||||
"""
|
||||
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")
|
||||
|
||||
# ---- 1. 加一个「功能」分页 ----
|
||||
TAB_OLD = ''' new TabDef("系统", new Act[]{'''
|
||||
|
||||
TAB_NEW = ''' new TabDef("功能", new Act[]{
|
||||
act("显示", new Runnable() {
|
||||
public void run() { pickFeatureGroup("显示"); }
|
||||
}),
|
||||
act("音量", new Runnable() {
|
||||
public void run() { pickFeatureGroup("音量"); }
|
||||
}),
|
||||
act("系统", new Runnable() {
|
||||
public void run() { pickFeatureGroup("系统"); }
|
||||
}),
|
||||
act("查看", new Runnable() {
|
||||
public void run() { pickFeatureGroup("查看"); }
|
||||
}),
|
||||
act("效率", new Runnable() {
|
||||
public void run() { pickFeatureGroup("效率"); }
|
||||
}),
|
||||
act("文件", new Runnable() {
|
||||
public void run() { pickFeatureGroup("文件"); }
|
||||
}),
|
||||
}),
|
||||
new TabDef("系统", new Act[]{'''
|
||||
|
||||
# ---- 2. 方法 ----
|
||||
ANCHOR = " private Button bigButton(String text, int color, float sizeSp) {"
|
||||
|
||||
METHODS = ''' // ==================================================================
|
||||
// 电脑功能(由电脑端声明,这里只负责拉列表和调用)
|
||||
// ==================================================================
|
||||
|
||||
private List<Map<String, Object>> featureCache = null;
|
||||
|
||||
/** 按分组列出电脑端的功能。 */
|
||||
private void pickFeatureGroup(final String group) {
|
||||
appendLog("正在获取「" + group + "」功能…");
|
||||
io.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (featureCache == null) {
|
||||
Map<String, Object> reply =
|
||||
client.call(Json.obj("cmd", "feature_list"), 20000);
|
||||
featureCache = mapList(reply, "features");
|
||||
}
|
||||
final List<Map<String, Object>> items =
|
||||
new ArrayList<Map<String, Object>>();
|
||||
List<String> labels = new ArrayList<String>();
|
||||
for (Map<String, Object> item : featureCache) {
|
||||
if (!group.equals(Json.str(item, "group", ""))) {
|
||||
continue;
|
||||
}
|
||||
items.add(item);
|
||||
labels.add(Json.str(item, "label", "?"));
|
||||
}
|
||||
final List<String> finalLabels = labels;
|
||||
ui.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (finalLabels.isEmpty()) {
|
||||
toast("这一组暂时没有功能");
|
||||
return;
|
||||
}
|
||||
showChooser("电脑功能 · " + group, finalLabels, new Chooser() {
|
||||
@Override
|
||||
public void onPick(int index) {
|
||||
dispatchFeature(items.get(index));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
featureCache = null;
|
||||
postError("获取功能列表", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 按功能类型决定怎么执行。 */
|
||||
private void dispatchFeature(final Map<String, Object> feature) {
|
||||
final String name = Json.str(feature, "name", "");
|
||||
final String label = Json.str(feature, "label", name);
|
||||
final String kind = Json.str(feature, "kind", "action");
|
||||
if (name.isEmpty()) {
|
||||
toast("功能名不对");
|
||||
return;
|
||||
}
|
||||
|
||||
if ("toggle".equals(kind)) {
|
||||
boolean on = Json.bool(feature, "on", false);
|
||||
runFeature(name, Json.obj("on", !on), (on ? "关闭 " : "开启 ") + label);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("value".equals(kind)) {
|
||||
int min = Json.integer(feature, "min", 0);
|
||||
int max = Json.integer(feature, "max", 100);
|
||||
final List<String> labels = new ArrayList<String>();
|
||||
final List<Integer> values = new ArrayList<Integer>();
|
||||
for (int step = 1; step <= 5; step++) {
|
||||
int value = min + (max - min) * step / 5;
|
||||
values.add(value);
|
||||
labels.add(String.valueOf(value));
|
||||
}
|
||||
showChooser(label, labels, new Chooser() {
|
||||
@Override
|
||||
public void onPick(int index) {
|
||||
runFeature(name, Json.obj("value", values.get(index)),
|
||||
label + " = " + values.get(index));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if ("input".equals(kind)) {
|
||||
String hint = Json.str(feature, "hint", "输入");
|
||||
final String key = Json.str(feature, "key", "text");
|
||||
String hint2 = Json.str(feature, "hint2", "");
|
||||
final String key2 = Json.str(feature, "key2", "");
|
||||
if (!key2.isEmpty() && !hint2.isEmpty()) {
|
||||
promptTwo(label, hint, hint2, new TwoHandler() {
|
||||
@Override
|
||||
public void onInput(String first, String second) {
|
||||
Map<String, Object> params = Json.obj(key, first);
|
||||
params.put(key2, second);
|
||||
runFeature(name, params, label);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
promptInput(label, hint, "", new InputHandler() {
|
||||
@Override
|
||||
public void onInput(String text) {
|
||||
if (!text.isEmpty()) {
|
||||
runFeature(name, Json.obj(key, text), label);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// action:删除类的先确认
|
||||
if (name.startsWith("delete_") || name.equals("empty_recycle")
|
||||
|| name.equals("clear_clip") || name.equals("restart_explorer")) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(label)
|
||||
.setMessage("确定要执行「" + label + "」吗?")
|
||||
.setPositiveButton("执行", new android.content.DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(android.content.DialogInterface d, int w) {
|
||||
runFeature(name, Json.obj(), label);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("取消", null)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
runFeature(name, Json.obj(), label);
|
||||
}
|
||||
|
||||
private void runFeature(final String name, final Map<String, Object> params,
|
||||
final String label) {
|
||||
appendLog("执行:" + label);
|
||||
io.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Map<String, Object> request = Json.obj("cmd", "feature_run",
|
||||
"name", name);
|
||||
request.put("params", params);
|
||||
final Map<String, Object> reply = client.call(request, 30000);
|
||||
final boolean ok = Json.bool(reply, "ok", false);
|
||||
final String note = ok
|
||||
? Json.str(reply, "note", "已执行")
|
||||
: Json.str(reply, "error", "执行失败");
|
||||
ui.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
appendLog(label + ":" + firstLine(note));
|
||||
// 查看类的结果比较长,用对话框显示
|
||||
if (note.length() > 40 || note.contains("\\n")) {
|
||||
new AlertDialog.Builder(MainActivity.this)
|
||||
.setTitle(label)
|
||||
.setMessage(note)
|
||||
.setPositiveButton("知道了", null)
|
||||
.show();
|
||||
} else {
|
||||
toast(note);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (final IOException e) {
|
||||
postError(label, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String firstLine(String text) {
|
||||
int cut = text.indexOf('\\n');
|
||||
return cut > 0 ? text.substring(0, cut) : text;
|
||||
}
|
||||
|
||||
/** 两个输入框的对话框。 */
|
||||
private interface TwoHandler {
|
||||
void onInput(String first, String second);
|
||||
}
|
||||
|
||||
private void promptTwo(String title, String hint1, String hint2,
|
||||
final TwoHandler handler) {
|
||||
LinearLayout box = new LinearLayout(this);
|
||||
box.setOrientation(LinearLayout.VERTICAL);
|
||||
box.setPadding(dp(14), dp(8), dp(14), 0);
|
||||
|
||||
final EditText first = new EditText(this);
|
||||
first.setHint(hint1);
|
||||
first.setSingleLine(true);
|
||||
box.addView(first);
|
||||
|
||||
final EditText second = new EditText(this);
|
||||
second.setHint(hint2);
|
||||
second.setSingleLine(true);
|
||||
box.addView(second);
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(title)
|
||||
.setView(box)
|
||||
.setPositiveButton("确定", new android.content.DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(android.content.DialogInterface d, int w) {
|
||||
handler.onInput(first.getText().toString().trim(),
|
||||
second.getText().toString().trim());
|
||||
}
|
||||
})
|
||||
.setNegativeButton("取消", null)
|
||||
.show();
|
||||
}
|
||||
|
||||
/** 把回复里的对象数组取出来。 */
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<Map<String, Object>> mapList(Map<String, Object> reply, String key) {
|
||||
List<Map<String, Object>> out = new ArrayList<Map<String, Object>>();
|
||||
try {
|
||||
Object raw = reply == null ? null : reply.get(key);
|
||||
if (raw instanceof List) {
|
||||
for (Object item : (List<Object>) raw) {
|
||||
if (item instanceof Map) {
|
||||
out.add((Map<String, Object>) item);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// 结构不对就返回空
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private Button bigButton(String text, int color, float sizeSp) {'''
|
||||
|
||||
|
||||
def main() -> int:
|
||||
text = MAIN.read_text(encoding="utf-8")
|
||||
ok = True
|
||||
for old, new, tag in ((TAB_OLD, TAB_NEW, "功能分页"),
|
||||
(ANCHOR, METHODS, "功能方法")):
|
||||
if old not in text:
|
||||
print(f" [失败] {tag} 锚点未匹配")
|
||||
ok = False
|
||||
else:
|
||||
text = text.replace(old, new, 1)
|
||||
print(f" {tag}: OK")
|
||||
if ok:
|
||||
MAIN.write_text(text, encoding="utf-8")
|
||||
return 0 if ok else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user