@yee94/qk80mk2 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — 2026-10-18
4
+
5
+ - Direct USB CDC static theme (`ABKT`) and custom image (`ABKG`) uploads.
6
+ - 320×172 RGB565 encoding, verified against the bundled official WASM.
7
+ - Device detection, response validation, fragmented-read buffering and exclusive port access.
8
+ - No-flow pacing (6 ms), drain and settle (2 s), timeout and cancellation handling.
9
+ - JSON CLI output and ESM API for image encoding and upload.
10
+ - Complete official WASM/JS/config snapshot with source URLs and checksums.
11
+ - Physical theme upload verified by the user on macOS, Node.js 24, firmware v1.1.1.
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ MIT License — original project code only
2
+
3
+ Copyright (c) 2026 yee.wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ Third-party material in reference/official-assets/ is excluded from this MIT
24
+ grant. Its rights remain with its respective owners. See THIRD_PARTY_NOTICES.md
25
+ and reference/LICENSE.via-app for upstream provenance and licensing information.
package/README.md CHANGED
@@ -1,3 +1,281 @@
1
- # Temporary Holding Version
1
+ # @yee94/qk80mk2 — QK80 MK2 Node.js 图片替换工具
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 直接通过 USB CDC 上传主题图片,无浏览器、HTTP 服务、Python或 WASM 运行依赖。
4
+ WASM 只用于开发阶段的离线一致性校验。
5
+
6
+ - GitHub:https://github.com/yee94/qk80mk2-node
7
+ - npm:https://www.npmjs.com/package/@yee94/qk80mk2
8
+ - CLI:`qk80-screen`;版本:`0.1.0`
9
+ - 完整官方 WASM、JS 与设备配置随 Git 仓库及 npm 包分发,无需额外下载。
10
+
11
+ ## 快速开始:直接使用 npx(推荐)
12
+
13
+ **无需克隆仓库或全局安装。**准备 Node.js 22+,USB 数据线连接键盘,
14
+ 关闭占用串口的官网配置器,即可执行:
15
+
16
+ ```sh
17
+ # 查看连接的键盘
18
+ npx --yes @yee94/qk80mk2 devices
19
+
20
+ # 将图片替换为键盘主题(默认 ABKT)
21
+ npx --yes @yee94/qk80mk2 upload ./photo.png
22
+
23
+ # 上传到 Custom Animation 页面(ABKG)
24
+ npx --yes @yee94/qk80mk2 upload ./photo.png --target custom
25
+
26
+ # 只编码,不访问键盘
27
+ npx --yes @yee94/qk80mk2 encode ./photo.png --out ./theme.abkt
28
+
29
+ # 帮助与版本
30
+ npx --yes @yee94/qk80mk2 --help
31
+ npx --yes @yee94/qk80mk2 --version
32
+ ```
33
+
34
+ 图片路径相对**当前工作目录**,包含空格时请加引号。
35
+ 包只有一个可执行入口 `qk80-screen`,npx 会自动选择,不需要额外写命令名。
36
+ 首次运行会下载并缓存 npm 包及原生依赖;无需浏览器或本地 HTTP 服务。
37
+
38
+ 如果机器默认使用内网镜像,请显式指定外网源:
39
+
40
+ ```sh
41
+ npx --yes --registry=https://registry.npmjs.org/ @yee94/qk80mk2 upload "./my photo.png"
42
+ ```
43
+
44
+ 自动化建议锁定版本并读取 JSON 输出:
45
+
46
+ ```sh
47
+ npx --yes --registry=https://registry.npmjs.org/ @yee94/qk80mk2@0.1.0 upload ./photo.png --json
48
+ ```
49
+
50
+ `--yes`、`--registry` 属于 npx 参数,写在包名前;`--target`、`--json` 等工具参数写在包名后。
51
+ 以上外网命令需 npm 发布完成后才可使用;源码仓库可直接运行 `node src/cli.js`。
52
+
53
+ ## 能力列表
54
+
55
+ | 能力 | 支持情况 |
56
+ | --- | --- |
57
+ | 320×172 静态主题图片替换 | 支持,ABKT,实机确认 |
58
+ | Custom Animation 页面静态图片 | 支持编码/CDC 上传,ABKG;不是动态 GIF |
59
+ | 图片方向、缩放、居中裁剪、透明背景 | 支持,输出 RGB565 |
60
+ | PNG/JPEG 等静态图片输入 | 支持 sharp 可解码的静态格式 |
61
+ | 离线编码 / 已编码文件上传 | 支持,不依赖外部 API 服务 |
62
+ | USB 设备发现 / 指定端口 | 支持,VID 514b / PID 4d02 |
63
+ | 流控、回包检查、限速、超时、取消 | 支持 |
64
+ | JS ESM API / JSON CLI 输出 | 支持,适合脚本及外部定时调度 |
65
+ | 官方 WASM 一致性校验 | 支持,完整资源已包含 |
66
+ | 蓝牙 / 2.4GHz 图片上传 | 未实现、未验证 |
67
+ | 动画/GIF、灯光、按键、固件升级 | 本项目不提供 |
68
+ | 屏幕实时视频流 / 渲染成功回读 | 不支持;这是静态文件上传 |
69
+
70
+ ## 固件与兼容性
71
+
72
+ | 项目 | 已验证 / 要求 |
73
+ | --- | --- |
74
+ | 键盘 | Qwertykeys QK80 MK2,LCD 320×172 |
75
+ | 主板 Master 固件 | v1.1.1(2025-03-21),此前读取版本字段为 `0x0111` |
76
+ | 屏幕 PLC 固件 | 用户安装配套 v1.1.1 后完成实机验证;未单独回读 PLC 版本 |
77
+ | 老版本 | v1.0.3 的早期尝试曾被拒绝;本项目不保证兼容 |
78
+ | 系统与运行时 | macOS + Node.js 24 实机通过;声明 Node.js ≥22 |
79
+ | Linux / Windows / Bun | 尚未实机验证;建议使用 Node.js |
80
+ | 连接 | USB 有线;自动更新期间需保持 USB 连接 |
81
+
82
+ 官方固件入口:[Firmware and Software](https://www.qwertykeys.com/pages/fw),选择 **QK80 MK2**。
83
+ 已验证配套文件为 `qk80mk2_master_v1.1.1_20250321_*.uf2` 与
84
+ `qk80mk2_plc_v1.1.1_20250321_*.uf2`。本项目包含的是编码 WASM,不包含或刷写固件。
85
+
86
+ ## 实机验证
87
+
88
+ 2026-10-18,macOS / Node.js 24 / QK80 MK2 v1.1.1:
89
+
90
+ - Node 将静态 PNG 编码为主题 `ABKT`。
91
+ - `ABKT` 和 `ABKG` 都与官网 WASM **110,100 字节完全一致**。
92
+ - USB 串口上传,设备返回 `flowControl=false`。
93
+ - 默认每包间隔 6 ms,发送排空后保持连接 2 秒。
94
+ - **用户确认主题正确显示,并且没有卡在 loading。**
95
+
96
+ 这是静态图片替换,不是视频流。传输时可能短暂出现 loading。
97
+
98
+ ## 其他安装方式
99
+
100
+ 需要 Node.js 22+,已验证 Node.js 24。使用 Node 而非 Bun 执行原生串口依赖。
101
+
102
+ ```sh
103
+ npm install -g @yee94/qk80mk2 --registry=https://registry.npmjs.org/
104
+ qk80-screen --version
105
+ qk80-screen devices
106
+ qk80-screen upload /absolute/path/photo.png
107
+ ```
108
+
109
+ 从源码安装(以下开发命令在仓库根目录运行):
110
+
111
+ ```sh
112
+ git clone https://github.com/yee94/qk80mk2-node.git
113
+ cd qk80mk2-node
114
+ npm ci
115
+ node src/cli.js devices
116
+ ```
117
+
118
+ 已安装的 CLI 与 `node src/cli.js` 接收相同参数。
119
+
120
+ USB 数据线连接键盘,关闭官网配置器对串口的连接。
121
+ 根据 VID `514b` / PID `4d02` 自动检测;找到多台时必须传入 `--port`。
122
+ 系统串口排他锁避免同时上传。
123
+
124
+ ## 常用命令
125
+
126
+ ### 替换主题图片(默认)
127
+
128
+ ```sh
129
+ npx --yes @yee94/qk80mk2 upload /absolute/path/photo.png
130
+ ```
131
+
132
+ 图片自动按 EXIF 方向旋转,居中 cover 裁剪到 320×172,透明区域按黑色合成。
133
+ 支持 sharp 能读取的静态图片;动画、固件、按键映射不在本工具范围。
134
+
135
+ ### 替换 Custom Animation 图片
136
+
137
+ ```sh
138
+ npx --yes @yee94/qk80mk2 upload photo.png --target custom
139
+ ```
140
+
141
+ `theme` = ABKT,`custom` = ABKG;不会自动切换键盘当前菜单。
142
+
143
+ ### 只编码,不访问键盘
144
+
145
+ ```sh
146
+ npx --yes @yee94/qk80mk2 encode photo.png --out output/theme.abkt
147
+ npx --yes @yee94/qk80mk2 upload output/theme.abkt
148
+ ```
149
+
150
+ ## 自动化
151
+
152
+ ```sh
153
+ npx --yes @yee94/qk80mk2@0.1.0 upload /absolute/path/photo.png --json
154
+ ```
155
+
156
+ stdout 为 JSON,进度写 stderr。失败退出码 1,SIGINT/SIGTERM 取消退出码 130。
157
+ Ctrl+C 或传输异常会尽力发送 `0xE2` 取消并关闭串口,不会自动换 HID 或反复重试。
158
+
159
+ 成功结果例:
160
+
161
+ ```json
162
+ {
163
+ "status": "sent",
164
+ "bytes": 110100,
165
+ "target": "ABKT",
166
+ "flowControl": false,
167
+ "packetDelayMs": 6,
168
+ "settleMs": 2000,
169
+ "displayVerified": false,
170
+ "port": "/dev/tty.usbmodem0000000000004"
171
+ }
172
+ ```
173
+
174
+ 协议没有“屏幕渲染成功”确认,因此每次运行仍返回 `displayVerified:false`。
175
+ 实机验证记录与每次传输状态分开,不能用 `sent` 推断物理屏幕状态。
176
+ 定时调度请等上一次进程结束;建议分钟级而非每秒重复刷屏。
177
+
178
+ ### JS API
179
+
180
+ ```js
181
+ import {encodeImage, upload, devices} from '@yee94/qk80mk2';
182
+
183
+ console.log(await devices());
184
+ const image = await encodeImage('/absolute/path/photo.png', {target:'theme'});
185
+ const result = await upload(image, {
186
+ signal: AbortSignal.timeout(60_000),
187
+ onProgress: ({stage,sent,total}) => console.error(stage,sent,total),
188
+ });
189
+ console.log(result);
190
+ ```
191
+
192
+ `upload()` 负责打开、传输、排空、等待和关闭。文件格式错误、设备错误、回包错误会抛异常。
193
+
194
+ 调试参数(保留默认值可复用已验证路径):
195
+
196
+ ```sh
197
+ node src/cli.js upload photo.png --packet-delay-ms 6 --settle-ms 2000 --timeout-ms 5000
198
+ ```
199
+
200
+ ## 与原 Python 实现的区别
201
+
202
+ 编码本身通过了官方比对;此前“主题不受支持”“HID 写入成功”的推断没有充分证据。
203
+
204
+ | 原实现问题/不足 | 本项目处理 |
205
+ | --- | --- |
206
+ | 文件头仅检查错误字节,未验证完整回显 | 校验命令、回显和完整 64 字节包 |
207
+ | HID 将 `0xFF` 回包视为成功,缺乏实际显示保证 | 不使用这条有争议的 fallback,固定 USB CDC |
208
+ | 无逐包应答时连续写入 | 每个 64 字节包间隔 6 ms,接近 115200 baud / 8N1 的线速预算 |
209
+ | 发送后立即关闭 | drain 后保持连接 2 秒,让设备处理尾部数据 |
210
+ | `image uploaded` 容易被误解为显示成功 | 明确 `sent` 与实机显示验证的区别 |
211
+ | 交互中断与异步串口事件处理不足 | 超时、取消、断连、分片/合并回包及排他锁 |
212
+
213
+ 限速和收尾等待这组设置已实机通过;尚未单独隔离哪一个因素导致旧版本 loading。
214
+ 不会将经验性延时描述为官网的隐藏指令,也不改写固件。
215
+
216
+ ## 测试与官方核验
217
+
218
+ ```sh
219
+ npm test
220
+ node scripts/verify-assets.js
221
+ npm run verify:official -- /absolute/path/photo.png
222
+ ```
223
+
224
+ 测试覆盖流控开/关完整重组、文件头拒绝、回显损坏、用户取消、无效文件/参数、串口分片/合包、超时和断连。
225
+
226
+ 完整官方校验资源位于 `reference/official-assets/`,已纳入 Git 与 npm 包
227
+ (开发校验资料,不是日常上传运行依赖):
228
+
229
+ - https://cfg.qwertykeys.com/assets/index-e0db734e.js → `index.js`
230
+ - https://cfg.qwertykeys.com/tabkb/configs.json → `configs.json`
231
+ - https://cfg.qwertykeys.com/assets/kbres-20adae5e.wasm → `kbres.wasm`
232
+
233
+ WASM SHA-256:`20adae5e429f0aea9c788ea928756f9c3a884f9e2e581c70bc4dfbe345a8fd04`。
234
+ 校验程序先将输入规范化到 320×172,再运行同一份 PNG 的官方及本地编码。
235
+ Node VM 仅用于执行可信的官方模块,不是安全沙箱。
236
+
237
+ `reference/manifest.json` 记录来源、大小及 SHA-256。WASM 是 **6,810,636 字节的完整二进制**,
238
+ 不是 Git LFS 指针,也不会在安装时额外下载。
239
+
240
+ ## 项目结构
241
+
242
+ ```text
243
+ src/
244
+ cli.js 命令行、JSON 输出、退出码
245
+ image.js sharp 图像规范化、RGB565 与 ABKT/ABKG 编码
246
+ protocol.js 文件头握手、分包、应答与取消
247
+ serial.js 串口发现、读取缓冲、排他连接和资源释放
248
+ index.js 公共 ESM API
249
+ scripts/
250
+ verify-official.js 运行官方 WASM,与本项目编码逐字节比对
251
+ verify-assets.js 检查随包资源 SHA-256
252
+ reference/
253
+ official-assets/ 完整官方 WASM / JS / 设备配置
254
+ manifest.json 资源清单
255
+ LICENSE.via-app 上游项目许可
256
+ test/ 串口协议与资源生命周期测试
257
+ ```
258
+
259
+ ## 常见问题
260
+
261
+ - **找不到设备**:检查 USB 数据线与有线模式,运行 `qk80-screen devices`。蓝牙打字连接不等于 CDC 上传连接。
262
+ - **串口被占用**:断开官网配置器及其他串口程序后再试,同一时刻只运行一个上传进程。
263
+ - **文件头 `0xEE`**:设备拒绝当前文件;先核对型号、固件和编码,不要切换到未经确认的 HID fallback。
264
+ - **loading**:传输期间短暂 loading 可能正常。默认限速和收尾等待已实机通过;如果持续卡住,保留报错和设备信息,不要循环盲传。
265
+ - **图片不是当前页面**:`theme` 与 `custom` 是不同目标,此工具不会自动导航键盘菜单。
266
+ - **自动化更新**:由外部程序生成图片,再调用 `upload` 替换;本项目只负责图片编码与设备传输。
267
+
268
+ ## 发布与许可
269
+
270
+ ```sh
271
+ npm ci
272
+ npm test
273
+ node scripts/verify-assets.js
274
+ npm pack --dry-run
275
+ npm publish --access public --registry=https://registry.npmjs.org/
276
+ ```
277
+
278
+ 发布包名固定为 `@yee94/qk80mk2`,项目 `.npmrc` 与 `publishConfig` 指向外网 npm。
279
+ 运行日志、个人数据快照及生成图片位于 `output/`,不提交、不打入 npm 包。
280
+ 原创代码使用 MIT;随附官方资源保留上游权利及许可说明,详见
281
+ [LICENSE](LICENSE)、[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
@@ -0,0 +1,36 @@
1
+ # Third-party material
2
+
3
+ ## Official Qwertykeys configurator snapshots
4
+
5
+ `reference/official-assets/` contains unmodified resources downloaded from
6
+ https://cfg.qwertykeys.com/ on 2026-10-18:
7
+
8
+ | Local file | Upstream resource |
9
+ | --- | --- |
10
+ | `index.js` | `/assets/index-e0db734e.js` |
11
+ | `configs.json` | `/tabkb/configs.json` |
12
+ | `kbres.wasm` | `/assets/kbres-20adae5e.wasm` |
13
+
14
+ These resources are bundled for reproducible, offline interoperability tests.
15
+ They are not used during normal image encoding or USB upload. Copyright and
16
+ third-party component notices inside these artifacts remain intact.
17
+ Exact sizes and SHA-256 digests are recorded in `reference/manifest.json`.
18
+
19
+ The deployed configurator links to https://github.com/tabkb/via-app as its source
20
+ repository. That repository publishes a GPL-3.0 license, reproduced at
21
+ `reference/LICENSE.via-app`. The deployment's exact source commit and the
22
+ component-level license inventory of its compiled WASM have not been identified;
23
+ the repository license is not asserted to be a complete WASM license inventory.
24
+ No MIT relicensing of these third-party artifacts is intended.
25
+
26
+ ## Protocol reference
27
+
28
+ The wire-format investigation was informed by
29
+ https://github.com/Zephyr73/qk80mk2 (MIT) and the deployed official configurator.
30
+ This project independently implements the static-image encoding and CDC uploader
31
+ in JavaScript; it is not affiliated with Qwertykeys.
32
+
33
+ ## Runtime dependencies
34
+
35
+ `serialport` and `sharp` are installed via npm; their own licenses and the licenses
36
+ of their native/transitive dependencies apply. See their installed LICENSE files.
package/package.json CHANGED
@@ -1,6 +1,24 @@
1
1
  {
2
2
  "name": "@yee94/qk80mk2",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "QK80 MK2 static theme uploader over USB CDC",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "author": "yee.wang <wyy.xb@qq.com>",
8
+ "repository": { "type": "git", "url": "git+https://github.com/yee94/qk80mk2-node.git" },
9
+ "homepage": "https://github.com/yee94/qk80mk2-node#readme",
10
+ "bugs": { "url": "https://github.com/yee94/qk80mk2-node/issues" },
11
+ "keywords": ["qk80", "qk80mk2", "keyboard", "serialport", "lcd"],
12
+ "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
13
+ "files": ["src/", "scripts/", "reference/", "README.md", "LICENSE", "THIRD_PARTY_NOTICES.md", "CHANGELOG.md"],
14
+ "engines": { "node": ">=22" },
15
+ "bin": { "qk80-screen": "./src/cli.js" },
16
+ "exports": "./src/index.js",
17
+ "scripts": {
18
+ "test": "node --test",
19
+ "devices": "node src/cli.js devices",
20
+ "verify:official": "node scripts/verify-official.js reference/official-assets reference/official-assets/kbres.wasm",
21
+ "prepublishOnly": "npm test"
22
+ },
23
+ "dependencies": { "serialport": "^13.0.0", "sharp": "^0.34.0" }
24
+ }