JZClientForNode 项目图标 JZClientForNode 小天才手表家长端 · Node 版
项目文档

部署与使用文档

从零把 JZClientForNode 跑起来:环境、登录、WebUI、绑定手表、OneBot 接入与常见问题。全程不需要 npm install。

快速开始

自己部署只需要三步:装 Node、clone 代码、启动。没有构建步骤,没有第三方依赖,也不会往系统里装任何全局包。

不会部署?那就用云端托管

注册账号后云端会自动开一台独立实例,浏览器打开就能用,关掉网页也继续在线收消息。

直接用云端托管

环境要求

项目要求
Node.js≥ 18(推荐 20 / 22 LTS)
操作系统macOS / Linux / Windows
ffmpeg + ffprobe可选。非 AMR 语音转码、长语音 / 长视频自动切段需要
npm 依赖无。不需要执行 npm install
i 没有 ffmpeg 也能正常收发文本、图片和短视频。只有超过 58 秒的语音、超过 28 秒的视频会明确报错「需要 ffmpeg」,不会把超长的东西硬发出去。

下载代码

bash
git clone https://github.com/laolibuhuifei/JZclient-for-node.git JZClientForNode
cd JZClientForNode
i 仓库名是小写 c 的 JZclient-for-node,后面那个参数是把目录改名成 JZClientForNode,纯属好看,不影响运行。

启动

bash
npm start
# 或者
node bin/jzclient.js

首次运行直接进入登录流程,输入小天才账号密码即可。登录票据和设备标识缓存在本地,之后每次启动会自动把 WebUI 拉起来。

  1. 输入账号密码:账号就是在小天才 App 里用的那个手机号和密码。
  2. 新设备验证:新设备首次登录会返回 010410,程序会拉出该账号的密保问题,默认选中包含「天才号」的那条,填 10 位手表天才号即可。
  3. 自动拉起 WebUI:终端会打印本机地址、局域网地址和访问令牌。
  4. 浏览器打开:点终端里的「快捷链接」,或者打开首页粘贴令牌。
! 密保答案校验通过后,换票偶尔会返回 000002 出现未知异常——服务端把「这台设备已通过验证」落库是异步的。程序会间隔 0.9s / 1.8s 自动重试最多 3 次,仍失败就用刚才的密码重新登录一次,不需要你手动处理。

运行期数据放在哪

登录票据、设备标识、手表状态、AI 配置、OneBot 令牌全部在 ~/.watch-parent-cli/config.json。这个文件基本等于账号密码,别提交到仓库、别发给别人、别贴到群里。

json
"webui": { "port": 8787, "host": "0.0.0.0", "token": "jz_..." }
! 删掉 ~/.watch-parent-cli 目录等于退出登录 + 丢掉设备标识,下次启动会被当成新设备,重新走一遍密保验证。

常用环境变量

变量作用
WP_LOG=debug输出请求体、IM 原始帧等细节,排查问题用
WP_LOG=warn只看告警和错误
WP_LOG=silent完全静默
WP_LOG_COLOR=0关闭 ANSI 颜色(NO_COLOR=1 同效),适合重定向到文件

WebUI 使用

命令行只负责账号,所有功能都在 WebUI 里操作。登录成功后自动启动,终端会打印地址、局域网地址和访问令牌:

text
WebUI 已启动  http://127.0.0.1:8787
  局域网  http://192.168.1.20:8787

  访问令牌  jz_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  快捷链接  http://127.0.0.1:8787/?token=jz_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

两种进入方式

  • 点「快捷链接」——URL 里的 ?token= 会自动种 Cookie 再跳回干净的地址
  • 直接打开首页,在登录页粘贴令牌
i 默认监听 0.0.0.0(局域网能访问),但所有 /api 接口都要求访问令牌,没有令牌只能看到登录页。只想本机用就把 host 改成 "127.0.0.1"。连续输错 8 次会锁定该 IP 10 分钟;着急就在命令行按 t new 重新生成(会踢掉已登录的浏览器)。

页面一览

页面能做什么
主页账号概览、CPU / 内存实时磁贴、系统信息、手表列表、每日一言、公告
概览头像、型号、电量、在线状态、快捷状态
定位实时位置、历史轨迹、安全区域、丢表模式
聊天会话列表、消息收发、图片 / 语音 / 视频 / 位置 / 链接 / 表情
功能宝贝资料、通讯录、好友、健康、应用、WiFi、闹钟、设置、隐藏功能、绑定
我的账号信息、OneBot 接入、对外 API、外观背景、退出登录

多块手表时,左上角的表名胶囊是切换器——点一下换表,当前页所有卡片跟着切过去。功能入口会按型号能力自动裁剪,不会给你一堆点不动的按钮。

深浅色主题

顶栏右上角的图标循环切换三种状态:跟随系统 → 浅色 → 深色。选择存在 localStorage 的 jz_theme 键里,刷新后保留。

改端口 / 换令牌

json
"webui": { "port": 8787, "host": "0.0.0.0", "token": "jz_..." }

改完重启进程生效。把 token 清空后会重新生成一个,旧的浏览器会话随之失效。

绑定手表

支持两种绑定方式,都在 WebUI 的「功能 → 绑定手表」页操作。

没绑定过的手表

  1. 输入 16 位手表绑定号
  2. 若服务端返回 010014,输入手表屏幕上显示的验证码
  3. 选择手表端登录的账号:0 创建新账号(绑定后你是管理员,新账号由手表端注册生成);1..n 迁移已有账号(可选是否保留旧手表上的数据)
  4. 提交后当前账号成为该手表管理员

已有管理员的手表

  1. 查询会显示管理员信息,绑定方式只能选「申请加入」
  2. 如服务端要求校验管理员手机号,输入管理员完整手机号(最多 5 次)
  3. 提交后由管理员在手表上同意,申请期间可随时撤回

验证码错误码

错误码含义
010015验证码错误
010016验证码已失效
010017错误次数已达上限
010018当日次数已达上限

微聊与消息

登录成功后(以及 WebUI 服务启动时)会自动建立 IM 长连接,不用手动打开聊天页;断线后 5 秒自动重连。

支持的消息类型

文本、表情、颜文字、位置、链接、图片、语音、视频。微聊对语音和视频有单条时长上限,超了手表端放不出来,所以程序会自动切段发送:

类型单条上限切段阈值段数上限段间隔
语音60 秒58 秒20 段350 ms
视频30 秒28 秒30 段500 ms

每段在日志里标成 [语音 2/3]、[视频 2/7],发的顺序就是播放顺序。网页录音、拖拽上传、OneBot 的 record 段、B 站点播走的是同一套切段逻辑。

收不到消息怎么排查

先看聊天页顶部的状态条,它会实时告诉你链路到底通不通:

状态文案含义
IM 已连接 · 12 秒前收到数据链路正常
IM 连接异常,正在重连…连接断了,5 秒后自动重连
IM 已连接 · 已 N 分钟没有收到数据(变红)连接半死,程序会在心跳连续 3 次失败且 120 秒无入帧后主动销毁重连
i 只看「已连接」标志是不够的——NAT 超时导致的 TCP 半开状态下它永远是 true。所以程序内部用心跳和入帧时间双重判定,不会出现「显示已连接但一条消息都收不到」。

状态正常但依然没消息时,按顺序排查:

  1. 手表端聊天记录里有没有这条消息(确认手表真的发出去了)
  2. 该会话是否在范围内——OneBot 和 B 站点播的「只收这些会话」是按手表分开勾的,单聊和家庭群是两个会话
  3. 用 WP_LOG=debug npm start 重启,看日志里有没有对应的 recv 行

OneBot v11 接入

WebUI 起来后会为每块手表各拉起一套 OneBot v11 服务,可以把微聊接进 AstrBot、NoneBot 这类机器人框架。没有「全局一套收所有表」的模式——每块表的端口、令牌、会话范围都是分开的,机器人只会看到它那块表的会话。

传输地址令牌
HTTP APIhttp://0.0.0.0:<该表端口>(第一块表默认 5700)onebotWatches[watchId].http.token
正向 WebSocketws://0.0.0.0:<该表端口>(第一块表默认 5701)onebotWatches[watchId].ws.token
反向 WebSocket由 onebotWatches[watchId].wsClient.url 指定(默认关闭)onebotWatches[watchId].wsClient.token
i 端口留空自动分配,从 5700 起按 10 递增(5700/5701、5710/5711…),会和其他手表的端口一起避让。令牌首次启用时自动生成并写回配置。

在哪配置

WebUI →「我的」→「OneBot v11 接入」卡片 → 右上角「设置」。卡片只显示当前手表(左上角切换条选中的那块),切到别的表它就跟着切过去。

  1. 本表设置:启用开关、HTTP 端口、WS 端口、反向 WS(地址 / 令牌 / 重连间隔)、「只收这些会话」勾选、两个令牌的重置按钮
  2. 通用设置:所有手表共用 —— QQ 兼容模式、心跳间隔
  3. 保存:只重启这块表的实例,别的表不受影响。端口被占用时会保存成功但状态显示「未运行」

正向还是反向?

场景用哪种说明
AstrBot 和本程序在同一台机器 / 同一局域网正向 WSAstrBot 主动连 ws://<本机 IP>:5701,本程序不用开端口映射
AstrBot 在公网服务器,本程序在家庭网络内反向 WS本程序主动连 AstrBot 的 WS 端点,穿透 NAT 不用做端口映射
只需要偶尔调一下接口HTTP APIPOST http://<IP>:5700/<action>?access_token=...

AstrBot 配置:正向 WS

  1. 平台选 OneBot v11 (aiocqhttp)
  2. WS 地址填 ws://<电脑局域网 IP>:<那块表的端口>(第一块表默认 5701)
  3. access_token 填那块表自己的 WS 令牌

多块手表就建多个 OneBot v11 平台,各自填对应表的地址和令牌。

AstrBot 配置:反向 WS

  1. AstrBot 里新建一个 OneBot v11 平台,连接方式选反向 WebSocket,记下它监听的端口(默认 6199,路径固定 /ws)和 access_token
  2. WebUI 里那块表的「本表设置 → 反向 WS」打开开关,填地址和令牌;或者直接改配置
  3. 保存后热重启。日志出现 [onebot] 反向 WS 已连接 即成功;断线会按 reconnect 秒数自动重连
json
"wsClient": { "enabled": true, "url": "ws://1.2.3.4:6199/ws", "token": "对方设置的令牌", "reconnect": 5 }
i 握手时会带 X-Self-ID(这块表的 IM 账号标识)和 X-Client-Role: Universal,aiocqhttp 依赖这两个头识别连接,缺了会被直接拒绝。路径要写全:AstrBot 固定 /ws,部分框架用 /onebot/v11/ws,只写到端口会被拒。令牌会同时以 Authorization: Bearer 和 ?access_token= 两种形式发送。

支持的 action

分类action
基础get_login_info get_status get_version_info can_send_image can_send_record clean_cache
查询get_friend_list get_group_list get_group_info get_group_member_list get_stranger_info get_recent_contact
发送send_private_msg send_group_msg send_msg send_group_forward_msg send_private_forward_msg
消息get_msg get_forward_msg get_group_msg_history get_friend_msg_history get_image get_record

消息段支持 text face image record video at reply location share file forward;媒体段认 http(s)、base64://、data URL 和本地绝对路径四种写法。

QQ 兼容模式

按 QQ 写的插件会调一堆 QQ 专有动作,只要有一个返回 1404,很多插件整条链路就崩了。所以按三档处理(开关 onebot.qqCompat,默认开):

  • 静默成功:delete_msg / set_group_ban / set_group_card / send_like … 微聊物理上做不到,返回 {} 让插件继续往下跑。注意这些动作不会真的发生
  • 返回空值:get_group_honor_info / get_cookies / get_csrf_token … 结构对得上 QQ、内容是空的
  • 明确拒绝:set_group_leave / set_group_kick / delete_friend / ocr_image … 危险或确实做不到,直接报错
! 关掉 qqCompat 后「静默成功」那一档会改成明确报错,方便排查「插件为什么没反应」。delete_friend 会破坏手表绑定关系,永远拒绝。

暂不支持:HTTP 上报(webhook)、真正的撤回、禁言、戳一戳、群文件、好友 / 入群申请审批。

B 站点播

让手表在微聊里自己点视频看:孩子发一句 /搜索 小猪佩奇,机器人回 10 条带序号的视频;再发 /播放 3,程序就把第 3 条下载下来用微聊视频发过去,手表端直接能播。

命令作用
/搜索 关键词搜 B 站视频,回前 10 条并标上序号(标题 · UP主 · 时长)
/播放 序号下载上一条搜索结果里的第 N 条并发过来
/b站看用法

命令写法很宽松,不用记:

  • 斜杠可有可无:/搜索 小猪佩奇 和 搜索 小猪佩奇 一样,点歌 是 搜索 的别名
  • 裸词必须带参数:搜索 两个字单独发出去不算命令,不然正常聊天里说「搜索不到」也会被抢走
  • 单聊里可以直接回数字:搜完列表后回一个 1 就等于 /播放 1(只在单聊生效,群里说数字太容易误触)
  • 发在没勾选的会话里会收到提示,不会静默丢弃

配置

WebUI →「我的」→「B 站点播」,每块手表单独一套:

  • 开关:只对启用的手表生效
  • 会话范围:勾选在哪些会话里响应(不勾 = 按手表名自动匹配单聊 + 家庭群,和 OneBot 一致)
  • 时长 / 大小上限:单条视频的闸门,默认 10 分钟 / 100MB
  • 每天上限:防小孩一口气刷十几条,默认 20 条,0 表示不限
! 单聊和家庭群是两个会话,要各勾一次。只勾了单聊,在家庭群里发命令不会有反应(会收到范围提示)。
i 只依赖 Node 内置 fetch 和 ffmpeg,没有 yt-dlp 之类的第三方工具。搜索结果按「手表 + 会话」隔离保留 30 分钟,群里搜的序号不会串到单聊。超过 30 秒的视频自动切段发送。仅用于个人学习与家庭自用,视频版权归原作者与 B 站所有。

日志与排查

日志有两个出口:终端(带颜色,适合 > webui.log)和 WebUI 日志页(网页实时滚动,适合远程看)。两边内容一致,都经过同一套脱敏。

text
[18:00:56.062] INFO  webui   服务已启动 http://127.0.0.1:8787
[18:00:57.301] INFO  im      长连接已建立
[18:01:12.884] INFO  chat    recv  msgType=1  dialogId=...

出问题先看这三处

  1. 终端 / 日志页有没有 ERROR:绝大多数问题这里已经有原文,比猜快得多
  2. 聊天页顶部的 IM 状态条:判断是「没连上」还是「连上了但对方没发」
  3. 「我的」里 OneBot 卡片的状态:显示「未运行」通常是端口被占用或启动失败,日志里有原因
i 排查时用 WP_LOG=debug npm start,会把请求体、IM 原始帧都打出来。注意 debug 日志里可能含手机号等敏感信息,贴出来前先脱敏。

常见问题

需要先 npm install 吗?

不需要。项目零第三方依赖,clone 下来直接 npm start。

WebUI 页面打不开

先确认端口没被占用:lsof -nP -iTCP:8787。默认监听 0.0.0.0,本机和局域网都能连;连不上就看系统防火墙有没有拦这个端口。

一直停在令牌输入页

令牌在启动终端里打印,也可以在命令行里按 t 再看一次。输错 8 次会被锁 10 分钟,着急就按 t new 重新生成一个(会踢掉已登录的浏览器)。

登录失败 / 接口返回参数错误

检查 src/site.config.js 里的 ssoHost、ssoSalt、checksum、brand、apkType 是否与客户端版本匹配。官方客户端升级后接口路径和签名会变,需要同步调整。

新设备验证过不去,一直报 000002

010410 是正常的「新设备」提示,按提示答密保问题(默认选「手表天才号」)。换票返回 000002 是服务端异步落库造成的竞态,程序会自动重试 3 次,仍失败就用密码重新登录一次,不需要你操作。

反向 WS 一直重连 / 日志报「连接被拒绝」

ws:// 和 wss:// 要跟对方一致(对方开了 TLS 就得用 wss://)。url 要写全路径:AstrBot 固定 /ws,部分框架用 /onebot/v11/ws,只写到端口会被拒。令牌要和对方设置的一致。日志里出现 反向 WS 已连接 才算成功,之后每隔 reconnect 秒重试一次是正常行为。

语音发送失败

非 AMR 格式需要本机安装 ffmpeg 做转码。

报「音频切分失败(需要 ffmpeg)」

单条语音上限 60 秒,超过 58 秒会走自动切段,这一步依赖 ffmpeg(切分)和 ffprobe(量时长),两个都在 ffmpeg 发行包里。装完确认 ffmpeg -version 和 ffprobe -version 都能跑。

会不会封号?

型号能力门控是为了降低异常请求被风控的概率,但不保证不封号。请只对自己拥有或已获得明确授权的账号和手表使用,风险自行评估。

我的数据会被上传到哪?

登录票据、设备标识、手表状态都只存在本机 ~/.watch-parent-cli/config.json。项目作者的服务器只提供两件事:主页公告、以及可选的云端托管平台。用自托管时数据不会离开你的机器。

文档没解决?进群问

QQ 群 1129480840 · 部署、插件、协议相关的问题都可以直接问,群里也会同步版本更新。

点击加入群聊
JZClientForNode QQ 群二维码

已知限制

项目按「能跑通、能日常用」的标准在做,下面这些是明确还没搞定的部分,欢迎提 PR。

功能缺口

  • 短信验证码登录:SSO 路径已确认,尚未接入,目前只能账号密码登录
  • 摄像头管控、应用白名单:未实现
  • 隐私相关开关:各网关写接口都返回 000007,目前只能查看不能修改
  • 单应用使用时长:接口还没定位到
  • OneBot v11 缺 HTTP 上报(webhook);撤回 / 禁言 / 戳一戳 / 群文件只是「静默成功」的兼容实现

需要真机验证

  • 全新手表的管理员绑定:代码已实现,缺真表端到端验证
  • 非管理员迁移:未实测

协议风险

  • 接口路径、参数和签名会随官方客户端版本变化,升级后可能需要同步调整 src/site.config.js
  • 型号能力门控不保证不封号,请自行评估风险

不想自己维护?

云端托管帮你搞定 Node 环境、端口、证书和在线保活,你只管用。

去托管平台