mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 12:30:44 +00:00
用户这次提了一整套升级,这是最后一批。
== 一、手表端顶部快捷栏 ==
用户原话:"手表端不管干什么,上面都有一栏,栏里的按钮可以在设置页
自定义,最多可以加 4 个,其中有一个按钮不能改,功能就是一键返回桌面"。
("返回桌面"经确认 = **让被控电脑显示桌面**,即 Win+D。)
* 一条常驻的栏,贴在屏幕顶部,切页面时不动
* **4 个格子**:3 个可自定义 + **1 个固定的「显示桌面」(改不了)**
* 7 个可选动作:传文件 / 屏幕镜像 / 鼠标控制 / 音效 / 关机 /
语音播报 / 投图到电脑
* 设置页里点一下换;也能把某一格留空
* 没连上电脑时按钮置灰(不是藏起来 —— "一直在但暂时不能用"
比"时有时无"更好理解)
实现上的几个要点:
* 快捷栏 addView 在 5 个面板**之后** —— FrameLayout 里后加的在上层,
加在前面会被面板(MATCH_PARENT)整个盖住
* 面板加了 topMargin 给栏让位,集中在 applyPanelTopMargin 里改
(每个面板各写一遍很容易漏一个,表现是"就某一页顶部被切掉")
* 第 4 格在代码里**写死** desktop,而且 QUICK_ACTIONS 里**没有**它 ——
这样它既不会出现在可选列表里,也不可能被改成别的
* 存储用 SharedPreferences。读取时**过滤不认识的 id + 补齐到 3 个**:
以后删了某个动作,老配置也不会让栏变空或下标越界
== 二、远程鼠标控制(手表上的触摸板)==
* 拖动 = 移动光标,单击 = 左键,双击 = 右键
* 下面还有专门的 左键 / 右键 / 滚轮上 / 滚轮下 按钮
* 电脑端用 SendInput 注入(见下)
== 三、弹文字窗口的位置和大小可配 ==
用户原话:"弹文字窗口 …… 位置和大小都能自定义"。
* 位置:右下(默认,保持老习惯)/ 右上 / 左上 / 左下 /
屏幕正中间 / 自定义坐标
* 字号:8~32(夹住,免得设成 200 一个通知占满屏幕)
* 宽度:可指定,0 = 按内容自适应
* 三处窗口定位统一到一个 _notice_geometry() —— 以前三处各写死一遍
右下角,改一次要改三个地方,漏一个用户就看得见
== 四、屏幕被观看时的提示条改成默认不显示 ==
用户原话:"以后不需要弹,啥窗户都没有,就可以像 UU 远程一样"。
* 默认**连窗口都不建**
* **但保留成开关**,设置里可以打开
关于这条:那条提示原来是**故意加**的(有人在看屏幕时,电脑前面的人
应该知道)。用户要求去掉,这是他自己的电脑、自己的教室,
属于正当的远程管理需求。所以能力保留、默认关闭 ——
这软件应该始终有一个"让本机用户看得见正在被控制"的选项可查。
== 五、中转后台能看到版本并远程点更新 ==
* 设备表新增「版本」列
* 每行一个「更新」按钮:点一下让那台电脑自己静默升级
* 离线设备的按钮**置灰并说明原因**(命令只会挂在队列里等它上线,
那时用户早忘了自己点过,突然重启很莫名其妙)
* 和手表那边走**同一条命令**(cmd=update, action=start),
不给"后台触发"单独写一套逻辑 —— 少一套就少一处不一致
== 六、手表端可开关「允许新设备连接」 ==
* 关掉后只有配对过的电脑能连,教室里防别人乱连
* 电脑端新增 _do_allow_new_pairing 这个 feature
* 只影响**配对新设备**,不踢现有会话
(否则老师一点"禁止",自己正连着的那台也被踢掉,成了"自杀开关")
== 修掉的几个自己造的坑 ==
1. **管理页 JS 裸换行** —— 最严重的一个。
ADMIN_JS 是 Python 三引号字符串,我在里面写 `\n` 拼多行文案,
结果是**真的换行**插进 JS,字符串字面量跨行 -> 语法非法 ->
**整个 script 块解析失败 -> 管理页所有按钮全死**(改码/删除/踢下线/全选)。
改成 String.fromCharCode(10),不依赖任何转义层。
2. **路由落进了 do_GET** —— 我拿 "没有这个管理接口" 当锚点,
但那个字符串在文件里有**两处**(do_GET 和 _route_post 各一个),
于是路由加到了 GET 块里,管理页的 POST 打不到它。
表现是"点了更新没反应"。
3. **isConnected() 根本不存在** —— 写快捷栏时凭直觉调了个方法名,
编译才发现。顺手包了一层并加上说明。
4. **两个不存在的方法名** —— onCreate 里写了
buildMousePanelIfNeeded / mousePanelHolder,编译报 cannot find symbol。
5. **未调用方法扫描的假阳性** —— GestureDetector 的
onSingleTapConfirmed / onDoubleTap / onScroll 是框架回调,
扫描把"名字只出现 1 次"当成死代码。改成**跳过 @Override 的方法**。
这种假阳性最坏的结果是有人为了让它变绿把回调删了,手势就失灵了。
6. **测试断言太严导致误报** —— "不能有写死的 240",
但 helper 里 `auto = max(240, ...)` 是自适应的兜底,故意的。
7. **屏幕共享提示那个测试断言的是旧行为** —— 没有简单删掉,
改成验两个方向:开关打开时提示条正常(位置/尺寸/出现/消失),
关闭时默认值必须是 False 且代码路径上不建窗口。
== 验证 ==
全量回归(19 关)全部 PASS,零失败
新增关卡:3a10 静默更新 / 3a11 鼠标控制 / 3a12 后台更新+弹窗 /
3a13 手表快捷栏
Java 编译通过(android-34, --release 8)
APK / 安装包 / 服务端包 全部重建,Win7 兼容校验通过
623 个 Python 文件语法通过
578 lines
22 KiB
Markdown
578 lines
22 KiB
Markdown
# ykxmz · 教室电脑手表控制
|
||
|
||
老师在讲台上抬一下手腕,就能把教室里那台电脑管了。
|
||
|
||
放课件、放音频、投个图、看看有没有在跑无关程序、下课关机 —— 不用走回讲台去点鼠标。
|
||
|
||
> 名字来自"控制手表"的拼音首字母,读作"控制拇指"也行。
|
||
|
||
---
|
||
|
||
## 先看这个:你是哪一类人
|
||
|
||
这份文档不短,但不用全看。挑自己那一节就行。
|
||
|
||
| 你是谁 | 从这里开始 |
|
||
|---|---|
|
||
| **老师** | [三步装好](#三步装好) → [上课时怎么用](#上课时怎么用) |
|
||
| **电教 / 学校信息中心** | [一个学校怎么铺开](#一个学校怎么铺开) → [批量管教室](#批量管教室) |
|
||
| **开发者** | [自己编译](#自己编译) → [通信协议](#通信协议) |
|
||
| **普通用户**(家里自己用) | [三步装好](#三步装好) → [连不上怎么办](#连不上怎么办) |
|
||
|
||
---
|
||
|
||
## 这东西是干嘛的
|
||
|
||
一句话:**用手表控制电脑。**
|
||
|
||
为什么用手表而不是手机?因为老师上课时手上是空的,手机在兜里,掏手机的动作比抬手大得多。手表抬一下就行,还不打断讲课。
|
||
|
||
它不只能放 PPT。教室里那些事它基本都管得着:
|
||
|
||
- 课件全屏投到教室大屏
|
||
- 放听力音频(电脑音箱比手表响多了)
|
||
- 上课时把教室电脑切到专注状态,下课一键恢复
|
||
- 下课关机、锁屏
|
||
- 喊一声"上课了"让电脑播音(TTS)
|
||
|
||
电脑那边不用装 Python,一个 EXE 双击就跑,绿色免安装,不留注册表。
|
||
|
||
---
|
||
|
||
## 三件套
|
||
|
||
一套完整的部署是三个程序,装在三个地方:
|
||
|
||
| 装在哪 | 是什么 | 文件 |
|
||
|---|---|---|
|
||
| 教室电脑(Windows) | 被控端 | `ykxmz-setup-2.1.7.exe` |
|
||
| 小服务器(随身 WiFi / 云主机 / 树莓派) | 中转站 | `ykxmz-server-2.1.7.zip` |
|
||
| 手表(安卓) | 控制端 | `ykxmz-watch-2.1.7.apk` |
|
||
|
||
**只在一个教室用?** 那第三件(中转站)可以先不装,手表和电脑连同一个 WiFi 就能直连。
|
||
|
||
**要在办公室管教室?** 那必须**自己部署一台中转站**(见 [跨网络](#跨网络在办公室管教室))。
|
||
|
||
> ### ⚠️ 软件里不带任何中转地址
|
||
>
|
||
> 这一点先讲清楚,免得白折腾:
|
||
>
|
||
> **这个软件默认是"空的" —— 没有任何内置的中转服务器地址,
|
||
> 也没有官方服务器可以用,作者不对外提供中转服务。**
|
||
>
|
||
> - **同一个 WiFi 下用(教室里)**:不需要中转,装完就能连,什么地址都不用填。
|
||
> - **要跨网络用(办公室管教室)**:**你得自己部署一台中转站**。
|
||
> 服务端压缩包里有一键脚本,一条命令装好:
|
||
>
|
||
> ```bash
|
||
> bash deploy.sh
|
||
> ```
|
||
>
|
||
> 装完它会打印一个属于你自己的公网地址,把它填到电脑和手表上。
|
||
> 详见 [装中转站](#装中转站)。
|
||
>
|
||
> 为什么不做一个"填个公共地址就能用"?因为中转站的带宽是实打实的成本,
|
||
> 谁用谁出;而且**中转站能看到经过它的字节流**,
|
||
> 自己搭一台,数据才真正只在你自己手里。
|
||
|
||
---
|
||
|
||
## 三步装好
|
||
|
||
### 第一步:电脑上装被控端
|
||
|
||
双击 `ykxmz-setup-2.1.7.exe`,按提示装完(默认装到 `C:\Program Files\ykxmz`)。
|
||
|
||
第一次运行会弹出窗口,填两样:
|
||
|
||
- **6 位数字** —— 自己定,好记就行,比如 `789113`
|
||
- 两个勾:`设置开机自启`、`放行防火墙`(放行那个要过一次管理员确认)
|
||
|
||
点确定,屏幕会黑闪一下(在加防火墙规则),然后窗口消失,程序转到后台跑。
|
||
|
||
> **窗口关了程序还在跑**,这是故意的 —— 上课时讲台上不该有个窗口杵着。
|
||
> 想再打开窗口,**再双击一次程序图标**就行,不会起第二个进程。
|
||
> 想彻底退出,窗口上点「退出」。
|
||
|
||
> 不想用安装包的话,`ykxmz-agent-2.1.7.zip` 是绿色版:
|
||
> 解压出来直接跑 `ykxmz.exe`,整个文件夹拷走就能换台机器用,不写注册表。
|
||
|
||
### 第二步:手表上装 App
|
||
|
||
把 `ykxmz-watch-2.1.7.apk` 传到手表装上。手表可能提示"未知来源",去设置里允许一下。
|
||
|
||
打开 App,首页有四个入口:
|
||
|
||
```
|
||
┌──────────────────────────┐
|
||
│ 控制手表 │
|
||
│ 和电脑连同一个 WiFi,不用输 IP │
|
||
├──────────────────────────┤
|
||
│ 中转设置(跨网络用) │ ← 办公室管教室才需要
|
||
│ 局域网连接(同一个 WiFi) │ ← 教室里用这个
|
||
│ 输入配对码连接 │ ← 跨网络连的时候用
|
||
├──────────────────────────┤
|
||
│ 服务器:还没测 检查服务器 │
|
||
└──────────────────────────┘
|
||
│ 已配对的电脑(点一下直连) │
|
||
│ DESKTOP-XXXX │
|
||
└──────────────────────────┘
|
||
```
|
||
|
||
**教室里**(手表和电脑连同一个 WiFi):点「局域网连接」→「自动搜索电脑」→ 点搜到的电脑 → 输第一步那 6 位数字。
|
||
|
||
**不用输 IP。** App 往局域网广播一个包,电脑收到会自报家门,所以电脑上装了几块虚拟网卡、IP 是多少都不用管。
|
||
|
||
### 第三步:以后不用再输了
|
||
|
||
配对一次之后令牌存在手表里,**下次打开 App 自动就连上**,数字都不用再输。
|
||
|
||
多台电脑就多配对几次,列表里点哪个连哪个。长按删除配对。
|
||
|
||
---
|
||
|
||
## 上课时怎么用
|
||
|
||
连上之后手表上是一排标签页,左右滑动切换。下面挑上课最常用的讲。
|
||
|
||
### 教室
|
||
|
||
这一页是给上课准备的。
|
||
|
||
> **先说清楚作用范围**:被控端装在**一台** Windows 电脑上
|
||
> —— 就是讲台那台,或者你自己的机器。
|
||
> **所有操作只影响这一台**,看不到也管不着其他电脑。
|
||
> 装的时候要输配对码,没配对码连不上。
|
||
|
||
| 按钮 | 干什么 |
|
||
|---|---|
|
||
| **课堂专注模式** | 在**本机 hosts** 里把常见游戏站点指到本地,本机打开是空白页 |
|
||
| **结束游戏进程** | 扫**本机**正在跑的常见游戏进程,结束掉 |
|
||
| **看有哪些限制** | 列出当前开了哪些,别自己忘了 |
|
||
| **一键恢复全部** | 把这节课改的全撤掉,**下课必点** |
|
||
|
||
怎么实现的、有什么边界,一并说清楚:
|
||
|
||
- 屏蔽是改**本机** `hosts` 文件,不装驱动、不装服务
|
||
- **只挡"随手点开"**:懂行的人自己把 hosts 里那几行删了就过去了。
|
||
它防的不是刻意行为,是减少无关干扰
|
||
- 站点列表是写死的常见站点,换一个站就得重新加
|
||
- **全部改动可逆**,点「一键恢复全部」或「下课清理」就还原
|
||
- 重启后保不保留,取决于你们学校有没有装还原卡
|
||
|
||
### 屏幕
|
||
|
||
- **实时屏幕镜像** —— 手表上看**被控端那台电脑**在显示什么(低头确认课件放没放对,不用走回讲台)
|
||
- **一键截屏** —— 存到手表相册
|
||
|
||
> ⚠️ **屏幕只要被看,电脑右上角就有一条红色提示条,关不掉。**
|
||
> 这是刻意做的:谁在看,电脑前面的人必须能立刻知道。
|
||
> 电脑前面的人随时可以点提示条上的「停止共享」把你掐断。
|
||
|
||
### 媒体 / 音频
|
||
|
||
放课件自带的音频,或者直接放电脑上的音乐。音量、静音、上一曲下一曲都在这一页。
|
||
|
||
**放音到电脑**走的是系统自带的播放器,不会弹出一个播放器窗口盖住课件。
|
||
|
||
### 投影
|
||
|
||
**投图到电脑** —— 手表上选一张图,全屏显示在教室大屏上。点一下或者按 Esc 关掉。
|
||
|
||
考试时贴个"考试中,请勿喧哗"的图,比在黑板写快。
|
||
|
||
### 系统
|
||
|
||
关机、重启、锁屏、睡眠,都有二次确认。**定时关机**可以设"30 分钟后关",下课忘了也不怕。
|
||
|
||
另外这一页最上面有三个按钮:
|
||
|
||
- **回退上一步** —— 刚才手滑点错了,撤销
|
||
- **回退全部** —— 把能撤的都撤了
|
||
- **看能回退什么** —— 列出还能撤哪些
|
||
|
||
能撤的是各种开关和画面。**关机和删文件这类撤不了,也不会出现在列表里**,免得你以为按了就能回来。
|
||
|
||
### 其他几页
|
||
|
||
- **文件** —— 往电脑传文件、从电脑拿文件(课件来回倒腾用)
|
||
- **语音** —— 让电脑念一段字。"上课了,请回到座位"这种
|
||
- **剪贴板** —— 手表上的字发到电脑剪贴板,或者把电脑复制的字拿到手表
|
||
- **通知** —— 在电脑上弹个提示
|
||
- **效率** —— 待办清单
|
||
- **娱乐** —— 掷骰子、抽奖、抛硬币(课堂互动随机点名能用)
|
||
|
||
---
|
||
|
||
## 跨网络:在办公室管教室
|
||
|
||
教室的电脑和你在的办公室不是一个网,直连不可能。这时候要装**中转站**。
|
||
|
||
原理说白了就是:两边都主动连到那台小服务器上,服务器按配对码把两条线接起来。
|
||
|
||
```
|
||
手表 ──┐ ┌── 教室电脑
|
||
├── 中转站(公网) ──┤
|
||
办公室 ──┘ └── 你手机
|
||
```
|
||
|
||
**中转站只是水管子,它不认识里面流的是什么。** 配对、令牌校验、权限判断全在电脑那边做。所以就算中转机被人拿走了,也进不了你的电脑。
|
||
|
||
### 装中转站
|
||
|
||
中转站就是**一台能上外网的 Linux 小机器**(随身 WiFi、树莓派、云主机都行,
|
||
Debian 12 / Ubuntu 实测可用,512 MB 内存就够)。
|
||
|
||
把 `ykxmz-server-2.1.7.zip` 解压到那台机器上,然后一条命令:
|
||
|
||
```bash
|
||
bash deploy.sh
|
||
```
|
||
|
||
它会自己做完这些,不用你一步步敲:
|
||
|
||
1. 装 cloudflared(已经装了就用现成的)
|
||
2. 把中转程序装到 `/root/lanremote-relay/`
|
||
3. 网络调优(keepalive、MSS、MTU、开机加速)
|
||
4. 注册 systemd 服务,设成开机自启
|
||
5. 配好 Cloudflare 隧道
|
||
6. 启动、自检,然后把**公网地址**打印出来
|
||
|
||
装完会打印一个属于你自己的公网地址,长这样:
|
||
|
||
```
|
||
https://relay.你的域名
|
||
```
|
||
|
||
**记住这个地址**,电脑和手表都要填它。忘了就在那台机器上跑
|
||
`lanremote-url`,或者浏览器打开 `http://<小机器的IP>:8080/url` 查。
|
||
|
||
#### 三种常见情形
|
||
|
||
```bash
|
||
# ① 机器上已经有隧道凭据(/root/.cloudflared/*.json)
|
||
bash deploy.sh
|
||
|
||
# ② Cloudflare 给了一个隧道 Token(Zero Trust 后台复制的那串)
|
||
TUNNEL_TOKEN=eyJhIjoi... bash deploy.sh
|
||
|
||
# ③ 换域名 / 只装中转、不要隧道
|
||
bash deploy.sh --hostname relay.你的域名
|
||
bash deploy.sh --skip-tunnel
|
||
```
|
||
|
||
看全部参数:`bash deploy.sh --help`
|
||
|
||
> **用环境变量而不是 `--token`**:写进命令行的 Token 会留在 shell 历史里。
|
||
|
||
#### 重跑一遍 = 升级
|
||
|
||
`deploy.sh` 是**幂等**的:已经装过的机器再跑一次就是升级。
|
||
程序文件会被覆盖成新的,而**设备数据、配对码、隧道凭据都不会被冲掉**。
|
||
|
||
#### 需要准备什么
|
||
|
||
- 一台能上外网的 Linux 小机器(Debian 12 / Ubuntu,512 MB 内存够)
|
||
- 一个 Cloudflare 账号 + 一个域名(隧道要用)
|
||
- **不需要**装 Python 第三方包 —— 服务端是纯标准库,不装任何依赖
|
||
|
||
### 告诉电脑中转地址
|
||
|
||
在电脑上(cmd 或 PowerShell):
|
||
|
||
```
|
||
ykxmz.exe --relay "192.168.1.50:8080;https://relay.你的域名"
|
||
```
|
||
|
||
两个地址用分号隔开,**按顺序试,第一个通的就用**。这样在教室里走局域网(快、稳),出了学校自动切隧道。
|
||
|
||
如果只在跨网络的场景用,也可以只填一个域名:
|
||
|
||
```
|
||
ykxmz.exe --relay https://relay.你的域名
|
||
```
|
||
|
||
看看当前用的是哪个地址:
|
||
|
||
```
|
||
ykxmz.exe --relay-status
|
||
```
|
||
|
||
### 告诉手表中转地址
|
||
|
||
手表首页点「中转设置」,填上面同一个地址。
|
||
|
||
然后回家首页点「输入配对码连接」,填电脑上那 6 位数字。
|
||
|
||
### 中转站的公网地址打开是什么
|
||
|
||
打开就是**一个普通的官网页面** —— 介绍、截图、三个文件的下载按钮,
|
||
最新版的安装包挂在上面,点一下就能下。
|
||
|
||
安装包和截图这类静态文件**由 Cloudflare 的边缘节点直接发送**,
|
||
所以下载速度和那台小机器的带宽无关(实测比走隧道回源快几十倍)。
|
||
|
||
想看运行状态、排查问题、重启服务,**看服务端压缩包里的
|
||
`README-server.txt`** —— 那份文档是给运维的人看的,里面写了日常命令。
|
||
|
||
---
|
||
|
||
## 一个学校怎么铺开
|
||
|
||
如果是一个学校几十间教室,上面那套手工装会很累。这一节给电教。
|
||
|
||
### 被控端
|
||
|
||
`ykxmz.exe` 是绿色单文件,**整个文件夹拷过去就能用**。批量装有两种办法:
|
||
|
||
**办法一:机房同传 / 还原卡**
|
||
|
||
把文件夹放进母盘镜像,开机自启那条在程序里勾上就行。注意 `data/` 目录里存着这台机器的配对码和令牌,**母盘里别带上别的机器的 `data/`**,否则一堆机器共用一个码。
|
||
|
||
**办法二:脚本推**
|
||
|
||
```powershell
|
||
# 把文件夹拷到目标机,然后静默设置配对码和自启
|
||
Copy-Item -Recurse "\\服务器\share\ykxmz" "C:\ykxmz"
|
||
Start-Process "C:\ykxmz\ykxmz.exe" -ArgumentList `
|
||
'--code 789113', '--relay 192.168.1.50:8080;https://relay.你的域名', '--auto-start', '--silent'
|
||
```
|
||
|
||
`--silent` 不弹窗口,适合批量。**静默模式下配对码一定要用参数指定**,不然每台机器随机生成一个,你也不知道是多少。
|
||
|
||
### 配一次码,服务器就记住了
|
||
|
||
这是这套东西比较省心的一点:**一台电脑第一次设的配对码,服务器会记住。**
|
||
|
||
以后同一台电脑再报别的码(重装、误操作、母盘没清干净),服务器会**自动改回原来那个**。所以你不会因为手抖把一台机器的码搞乱,手表永远认得出它。
|
||
|
||
反过来,**一个码不能同时属于两台电脑**,服务器会拒绝后来那个。这也是为什么母盘里不能带别人的 `data/`。
|
||
|
||
### 网络规划
|
||
|
||
- 中转站放在学校出口能上外网的地方,**带宽不用大**,它是控制通道不是视频通道
|
||
- 走局域网时是手表直连电脑,**完全不经过中转站**,所以一个班几十只手表也不挤服务器
|
||
- 教室之间如果是隔离的 VLAN,那手表和电脑得在同一个 VLAN 里,或者干脆都走中转
|
||
|
||
### 权限怎么收
|
||
|
||
被控端窗口上有几个权限开关,**随时关,关了远程立刻执行不了**:
|
||
|
||
- 允许自定义命令
|
||
- 允许电源操作
|
||
- 允许屏幕镜像 / 截屏
|
||
|
||
给班主任的电脑可以把"自定义命令"和"电源操作"关掉,只留日常那几个按钮。
|
||
|
||
---
|
||
|
||
## 连不上怎么办
|
||
|
||
按这个顺序排查,九成问题在第二步。
|
||
|
||
### 第一步:程序在跑吗
|
||
|
||
电脑任务管理器里找 `ykxmz.exe`。没有就双击 EXE 启动。
|
||
|
||
### 第二步:防火墙放行了吗
|
||
|
||
被控端窗口上如果显示橙色提示"防火墙未放行",点旁边的**一键修复**,过一次管理员确认。
|
||
|
||
或者用目录里的 `工具箱.bat` → 选 `2`。
|
||
|
||
> 这一条是**最常见的坑**。很多学校的电脑装了第三方安全软件,它会把新程序的入站连接全挡了。
|
||
> 一键修复会加一条**程序级**的放行规则(不是端口级),这个才管用。
|
||
|
||
### 第三步:还是不行就跑网络自检
|
||
|
||
`工具箱.bat` → 选 `3`,然后到手表上点「检查服务器」。
|
||
|
||
看电脑窗口:
|
||
|
||
- **出现 `>>> 收到 TCP 连接 <<<`** → 包到电脑了,问题在电脑本机(程序没跑 / 端口被占)
|
||
- **一个包都没收到** → 包没到电脑,八成是路由器开了**「AP 隔离」**(也叫客户端隔离),去路由器后台关掉
|
||
|
||
### 手表上会显示具体原因
|
||
|
||
App 把错误翻译成人话了,看到哪句就照做:
|
||
|
||
| 手表上显示 | 什么意思 |
|
||
|---|---|
|
||
| 证书校验失败 | 手表系统太旧,或者网络被人劫持 |
|
||
| 证书时间不对 | **把手表的日期时间调成自动获取**,这个很常见 |
|
||
| 连接超时 | 网络慢,或者被防火墙挡了 |
|
||
| 电脑拒绝连接 | 电脑上 ykxmz 没开 |
|
||
| 域名解析不了 | 手表没联网,检查 WiFi |
|
||
| 连不上中转 | 中转站挂了,或者地址填错了 |
|
||
|
||
首页那个「检查服务器」能测出到中转的延迟,快/一般/慢会用不同颜色标出来。
|
||
|
||
---
|
||
|
||
## 安全
|
||
|
||
被控端装的往往是公家的电脑,所以这套工具的安全设计偏"让人知道"而不是"低调运行"。
|
||
|
||
**每次连接都要配对。** 电脑上生成 6 位数字,只在窗口上显示,手表输对了才连得上。
|
||
|
||
**配对之后发令牌。** 32 位随机串存在手表上,之后靠它登录,不用每次输数字。
|
||
|
||
**没通过握手,一条命令都不执行。** 服务端直接拒。
|
||
|
||
**屏幕被看,电脑上一定有提示条。** 关不掉,没有开关。电脑前面的人随时能掐断。
|
||
|
||
**权限开关实时生效。** 窗口上关掉哪一项,远程立刻做不了那一项。
|
||
|
||
**不写注册表。** 数据全在程序目录下的 `data/` 里,拔了硬盘拷走就能换台机器跑。
|
||
|
||
**只在你自己填的地址之间通信。** 局域网模式下完全不联外网。跨网络模式只连你自己那台中转站,不经过任何第三方。
|
||
|
||
**所有行为都在明面上。** 被控端在托盘有图标、窗口看得见、随时可以退出、
|
||
权限可以逐项关闭。它不做任何"让机器上其他程序看不见自己"的事 ——
|
||
因为管的是自己要用的一台电脑,能看见、能随时停,才让人放心。
|
||
|
||
**代码全公开。** 三端加起来不到两万行,都是纯标准库,
|
||
想看它到底干了什么直接读源码就行。
|
||
|
||
---
|
||
|
||
## 自己编译
|
||
|
||
给开发者。三端都是零第三方依赖,不用 npm、不用 Gradle 拉一堆东西。
|
||
|
||
### 被控端(Windows)
|
||
|
||
Python 3.11 + tkinter + Pillow。打包用 PyInstaller。
|
||
|
||
```powershell
|
||
windows\build_exe.ps1
|
||
# 产物:dist_exe\ykxmz\ykxmz.exe
|
||
```
|
||
|
||
### 控制端(安卓手表)
|
||
|
||
纯 Java,没有 Gradle,直接命令行编:
|
||
|
||
```powershell
|
||
android\build_apk.ps1
|
||
# 流程:aapt2 → javac → d8 → zipalign → apksigner
|
||
# 产物:dist\ykxmz-watch-2.1.7.apk
|
||
```
|
||
|
||
最低支持 Android 7.0(API 24),targetSdk 34。
|
||
|
||
### 服务器端
|
||
|
||
Python 3 标准库,没有第三方包。
|
||
|
||
```bash
|
||
bash relay/deploy.sh
|
||
```
|
||
|
||
`deploy.sh` 是一键部署(装服务 + 调优 + 配隧道 + 自检);
|
||
只想调网络参数的话是 `relay/deploy-tune.sh`。
|
||
老的 `relay/install.sh`(匿名快速隧道)仍在包里,只为兼容以前装过的机器。
|
||
|
||
### 跑测试
|
||
|
||
```powershell
|
||
_tests\verify_all.ps1
|
||
```
|
||
|
||
会跑编码审计、协议回归、打包验证、Java 编译、端到端,最后打一张汇总表。
|
||
|
||
### 打包三个成品
|
||
|
||
```powershell
|
||
python _build\package_remote.py
|
||
```
|
||
|
||
出三个文件:`ykxmz-agent-*.zip`、`ykxmz-server-*.zip`、`ykxmz-watch-*.apk`。
|
||
|
||
---
|
||
|
||
## 通信协议
|
||
|
||
给要改代码或者做二次开发的人。
|
||
|
||
传输是 **TCP 上的换行分隔 UTF-8 JSON**,一行一个消息。
|
||
|
||
```json
|
||
{"cmd": "handshake", "code": "789113", "deviceId": "..."}
|
||
{"ok": true, "token": "32位随机串", "serverName": "DESKTOP-XXXX"}
|
||
```
|
||
|
||
二进制数据(图片、文件、音频)走 **Base64** 分块传输,单次会话上限 256 MB。
|
||
|
||
跨网络时同样的消息套在 **HTTP 长轮询**里(单次挂 **60 秒**,
|
||
有数据立刻返回、不空等),中转站按配对码把两端字节对接,**它不解析内容**。
|
||
|
||
跨网络这条链路上还有几个实测调出来的设计,改代码前值得知道:
|
||
|
||
- **隧道两种协议同时跑**(QUIC + HTTP/2,合计 10 条连接)。
|
||
两种协议各有各的毛病 —— QUIC 尾部延迟好但建连容易超时,
|
||
HTTP/2 建连可靠但丢包时容易被队头阻塞卡住。
|
||
同时跑就是互相兜底:一种犯病,另一种还在服务。
|
||
- **长轮询 60 秒**。隧道每次请求要多花 1~2 秒,这个开销是按次数收的;
|
||
拉到 60 秒把请求数降到 1/4,撞上丢包窗口的概率也降到 1/4。
|
||
**命令响应速度不变**(有数据立刻返回,不是等满 60 秒)。
|
||
- **偶发失败不当场判离线**。4G 链路上本来就有百分之几的偶发抖动、
|
||
一两秒自己恢复;连续失败 3 次才算真的离线。
|
||
- **静态资源交给 Cloudflare 边缘缓存**。下载走边缘节点,
|
||
不用穿隧道回那台小机器,快几十倍也更省流量。
|
||
|
||
Java 和 Python 两端都实现了同一套协议,`_tests/java/` 下有互相打通的测试。
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
**问:手表能连多台电脑吗?**
|
||
能。配对多台,列表里点哪个连哪个。
|
||
|
||
**问:一台电脑能被几只手表连?**
|
||
可以多只,屏幕镜像会显示"几台设备正在观看"。教室场景一般一只就够。
|
||
|
||
**问:换台电脑要重新配对吗?**
|
||
要。配对码跟着电脑走,不是跟着手表走。
|
||
|
||
**问:电脑重装系统了,配对码会变吗?**
|
||
不会。只要 `data/` 目录还在,服务器就认原来那个码。母盘部署时注意别把 `data/` 一起发出去。
|
||
|
||
**问:走中转会不会很慢?**
|
||
实测局域网 3 毫秒左右;跨网络要绕到中转站再回来,约 1~2 秒(取决于你那台小机器的线路)。所以**同一个 WiFi 一定走局域网**,程序会优先选它。
|
||
|
||
**问:必须自己搭中转站吗?能用作者的服务器吗?**
|
||
必须自己搭。**软件不内置任何中转地址,作者也不对外提供中转服务。**
|
||
跨网络的话,服务端 zip 里有 `deploy.sh`,一条命令装好(见 [装中转站](#装中转站))。
|
||
只在同一个 WiFi 下用的话,压根不需要中转站。
|
||
|
||
**问:中转站会不会看到我的数据?**
|
||
它转发的是加密前的字节流,所以**技术上能**。这正是"自己搭一台"的理由 —— 搭在你自己手上,数据就只经过你自己的机器。
|
||
|
||
**问:下载安装包为什么比以前快这么多?**
|
||
最新版把静态文件交给 Cloudflare 的边缘节点缓存了。原来每次下载都要穿过隧道回到那台小机器上取,实测只有几 KB/s,15 MB 的安装包根本下不动;现在从离你最近的边缘节点直接发,实测快了四十多倍,也不占小机器的流量。
|
||
|
||
**问:能在手机上用吗?**
|
||
协议是通的,但界面是按手表的小屏幕设计的(大按钮、两列、可滚动),手机上会显得按钮特别大。要做手机版得重写布局。
|
||
|
||
**问:收费吗?**
|
||
看 [LICENSE.txt](docs/LICENSE.txt)。里面有使用红线,装之前看一眼。
|
||
|
||
---
|
||
|
||
## 出问题了
|
||
|
||
先看 [连不上怎么办](#连不上怎么办)。
|
||
|
||
还不行的话,把这几样发过来,能定位得快很多:
|
||
|
||
1. 手表上显示的那句错误(App 现在是中文的,直接念出来就行)
|
||
2. 电脑上 `工具箱.bat` → 选 `5` 的日志内容
|
||
3. 跨网络的话,把你那台中转站的公网地址发过来(不用给任何密码)
|
||
|
||
---
|
||
|
||
作者:小麦子
|
||
许可见 [LICENSE.txt](docs/LICENSE.txt)
|