发帖
3 0 0

【电子DIY作品】小安打卡签到搭档+Ai-WV01-32S+BW2/Android

WT_0213
论坛元老

134

主题

1995

回帖

2万

积分

论坛元老

勤劳的打工人

积分
21987
电子DIY 75 3 昨天 23:45
[i=s] 本帖最后由 WT_0213 于 2026-7-31 14:21 编辑 [/i]

上视频

改了好多版本,这个算是比较完善的。还在继续优化中。模型都是用的免费的感觉也可以了。手机搭档这个版本我比较喜欢。也可以换成平板。想的是做个小镜子放到平板摄像头位置,类似学习机那种效果。时间不太够用,只能慢慢来了。初版就这样了。给娃娃定好任务。签到打卡兑奖。一句话搞定学习问题。养成良好习惯。

内容有些乱。边做边写。

这个项目有服务+Android

通过小安Ai-WV01-32S作为主控。直接问答。或者连接Android机,直接进行APP的操控。想着用磁吸了。因为手机不支持,没办法体现了。

Android 端可以调用相机,拍照直接给结果,比RTSP方案快很多。
更直观一些。

然后就是服务+BW21

RTSP 摄像头 BW21

cgi-bin_mmwebwx-bin_webwxgetmsgimg_&MsgID=8670630262432788832&skey=@crypt_3423.jpg

之前做的 【电子DIY作品】基于BW21-CBV-Kit火灾隐患警报器

拍照识别作业是否正确给出建议。

想着 Ai-WV01-32S+BW21 + 小安派 R1/R2
结果发现,服务端配合AI就写了快二十天了,就晚上回来都睡下了,起来写一写,服务完善了以后,发现BW21 , RTSP流延迟非常高,调整服务和RTSP代码,后来限制清晰度,终于到了能用的状态。

Ai-WV01-32S 代码微调了一下,总体还是基于源代码做了一点点改动主要是串口数据部分,准备对接小安派R1的。站在前人的肩膀上了属于是。

做这个主要是想为家里宝贝规划任务,让宝贝能够清晰看到当天任务完成情况。兑换奖励激励更好的完成每日任务。服务端做的相对丰富一些。硬件部分有些着急感觉还能 做的更完善。

硬件一直想着能够模块化。想了好到方案,怎么组合这些硬件。
目前想到的 pogopin 、弹片连接器 这两种连接器不用插拔。

第一种比较占地方,第二种不好固定。想要做好东西还是比较难呀。

后来再试放弃了,直接插拔了,先设计外壳。下面是AI-WV01-32S的外壳示例图。

Snipaste_2026-07-29_00-20-40.png
Snipaste_2026-07-29_00-15-24.png

核心模块 AI-WV01-32S

cgi-bin_mmwebwx-bin_webwxgetmsgimg_&MsgID=4158771104537382882&skey=@crypt_3423.jpg

cgi-bin_mmwebwx-bin_webwxgetmsgimg_&MsgID=8523606119229451504&skey=@crypt_3423.jpg

可以复用。

硬件

AI-WV01-32S

Ai-WV01-32S 如果出厂固件是商用版,一定要先联网授权以后再,烧录开源版。不然商用版授权好像就没了。

仓库地址 : https://gitee.com/Ai-Thinker-Open/aipi-palchatv1

Ai-WV01-32S模组的使用可以参考

【小安AI】Ai-WV01-32S模组使用体验

参考电路:

SCH.CAkYfepZ.png

也可以看下

【体验】Ai-WV02-32S 这不就跑起来了么

配网参考

安信可AiPi-PalChatV1 + 开箱 + 配网

配网逻辑都一样

Ai-WV01-32S 与 Ai-WV02-32S 对比

cgi-bin_mmwebwx-bin_webwxgetmsgimg_&MsgID=8844355450940890958&skey=@crypt_3423.jpeg

Ai-WV02-32S可用gpio更多一些

固件

有固件号的为官方正式固件,无固件号的为测试版固件。

适用型号 固件号 固件描述 版本 是否支持 UART-MCP 下载链接 提示音
AiPi-PalChatV1 X020 AiPi-PalChatV1 初版出厂固件 V1.9 点击下载 /
AiPi-PalChatV1 X020 AiPi-PalChatV1 兼容商用版 V2.1 点击下载 /
AiPi-PalChatV1 X020 AiPi-PalChatV1 支持MCP控制(⭐Ai-WV01 同款固件) V2.3 点击下载 /
AiPi-PalChatV1 离线语音芯片 X020 AiPi-PalChatV1 离线语音固件(适用于V1.9版本) V1.0 点击下载 /
AiPi-PalChatV1 UART-MCP / AiPi-PalChatV1 串口MCP交互固件 V2.8 点击下载 /
AiPi-PalChatV1 / 角色“湾湾小何”提示音测试固件 V2.9 点击下载
AiPi-PalChatV1 / 角色“天才童声”提示音测试固件 V2.9 点击下载
AiPi-PalChatV1 / 角色“佩奇猪”提示音测试固件 V2.9 点击下载
AiPi-PalChatV1 / 角色“湾湾小何”提示音测试固件 V3.0 点击下载
AiPi-PalChatV1 / 英文版固件 V2.9 点击下载 /
AiPi-PalChatV1 / 角色“湾湾小何”提示音测试固件 V3.2 点击下载

烧录固件

接线

USB转TTL Ai-WV01-32S
5V(可选) 5V (功放)
3V3 3V3
GND GND
TXD RXD
RXD TXD
DTR IO8
RTS EN

这里如果打印了PCB就不用看这个了,直接插Type-c口就可以了

烧录

烧录方式直接照搬官方烧录方式即可。使用上面推荐的串口工具可以自动下载程序。

  • 1.打开正确的 COM 口
  • 2.勾选 enable,选择合并好的固件
  • 3.点击烧录
  • 4.烧录完成

接口图

BW21

BW21源码

#include "WiFi.h"

#include "StreamIO.h"
#include "VideoStream.h"
#include "RTSP.h"

#define CHANNEL 0

// Default preset configurations for each video channel:
// Channel 0 : 1920 x 1080 30FPS H264
// Channel 1 : 1280 x 720  30FPS H264
// Channel 2 : 1280 x 720  30FPS MJPEG

// ========== 视频编码核心配置 ==========
// 参数顺序:分辨率、帧率、编码格式、快照模式
// 错题识别推荐 720P,编码和带宽延迟更低;需1080P改回 VIDEO_FHD 即可
VideoSetting config(VIDEO_D1, CAM_FPS, VIDEO_H264, 0);
RTSP rtsp;
StreamIO videoStreamer(1, 1);    // 1 Input Video -> 1 Output RTSP

char ssid[] = "WIFI";    //  SSID (name) BW21可以连5GWIFI
char pass[] = "密码";        // password 密码
int status = WL_IDLE_STATUS;

void setup()
{
Serial.begin(115200);

// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);

// wait 2 seconds for connection:
delay(2000);

}

// ========== 优化2:编码侧核心低延迟参数 ==========
// 必须在 configVideoChannel 之前设置完成
config._gop = CAM_NN_GOP;                // GOP=12,30fps下每0.4秒一个I帧,抓拍等待时间缩短60%+
config.setBitrate(1600000);      // 1.6Mbps,720P文字识别完全足够
config._rc_mode = 1;             // 强制 CBR 恒定码率,避免VBR波动导致接收端缓冲堆积

// 关闭B帧:设置H.264为 Baseline profile(天然无B帧,消除编码帧缓存)
// 参数:level=31(Level3.1), profile=66(Baseline), entropy_mode=0(CAVLC)
config.setH264EncParams(31, 66, 0);

// 配置视频通道 + 初始化视频系统
Camera.configVideoChannel(CHANNEL, config);
Camera.videoInit();  // 内部自动完成摄像头初始化,禁止手动调用camInit

// ========== 优化3:缩小编码输出队列,减少内部帧堆积 ==========
// 队列长度设为2,仅保留最少缓冲,避免已编码帧在板端堆积延迟
Camera.setQLen(CHANNEL, 2);

// 配置并启动 RTSP 服务
rtsp.configVideo(config);
rtsp.begin();

// 绑定视频流到 RTSP 输出
videoStreamer.registerInput(Camera.getStream(CHANNEL));
videoStreamer.registerOutput(rtsp);
if (videoStreamer.begin() != 0) {
Serial.println("StreamIO link start failed");
}

// 启动视频通道输出
Camera.channelBegin(CHANNEL);

delay(1000);
printInfo();

}

void loop()
{
// Do nothing
}

void printInfo(void)
{
Serial.println(" ");
Serial.println("------------------------------");
Serial.println("- Summary of Streaming -");
Serial.println("------------------------------");
Camera.printInfo();

IPAddress ip = WiFi.localIP();

Serial.println("- RTSP -");
rtsp.printInfo(ip.get_address());

}

服务端

部署:

1、Windows系统

在Windwos系统下找个地方创建个文件夹将manager_windows_amd64.exe放进去,例如

image.png
直接运行 kids-task-manager_windows_amd64.exe 文件
文件会同步生成kids-task-data.db数据库文件就可以直接使用了。

这里增加了 小智mcp服务

image.png

2、Linux 系统
这里手上有个arm小板子,debian系统的高通410的WIFI棒子,高功耗低跑小小服务也够用了。

使用lucky反向代理可以用域名访问
https://mp.weixin.qq.com/s/-flZPg7SDjpZheZ-m6P1UA

免费域名
dnshe.com

加了这种扩展板 https://oshwhub.com/zy143l/ufi_hub_rj45_share

image.png

目前内存占用极低

image.png

创建项目存放目录

mkdir /opt/kids-task-manager/
user@WiFi-Debian:~$ ll /opt/kids-task-manager/
总用量 9120
drwxr-xr-x 1 user user      92  7月 16 11:13 .
drwxr-xr-x 1 root root      34  7月 14 22:46 ..
-rw-r--r-- 1 user user   94208  7月 16 11:13 kids-task-data.db
-rwxrwxrwx 1 user user 9240728  7月 16 10:55 kids-task-manager_linux_arm64

这里增加了 小智mcp服务

image.png

调整用户所属用户组

sudo chown -R $USER:$USER /opt/kids-task-manager

拉取文件

wget https://gitee.com/lazy-ai/kids-task-manager/raw/master/dist/kids-task-manager_linux_arm64

可执行

chmod 777 kids-task-manager_linux_arm64

创建服务

sudo nano /etc/systemd/system/kids-task.service
[Unit]
Description=Kids Task Manager Service
After=network.target

[Service]
User=user
Group=user
WorkingDirectory=/opt/kids-task-manager
ExecStart=/opt/kids-task-manager/kids-task-manager_linux_arm64
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target
#重载服务
sudo systemctl daemon-reload

#设置开机自启
sudo systemctl enable kids-task.service

#立即启动服务
sudo systemctl start kids-task.service

这样服务就启动了

user@WiFi-Debian:~$ systemctl status kids-task
● kids-task.service - Kids Task Manager Service
     Loaded: loaded (/etc/systemd/system/kids-task.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2026-07-16 10:56:07 CST; 3h 40min ago
   Main PID: 413582 (kids-task-manag)
      Tasks: 7 (limit: 511)
     Memory: 8.1M
        CPU: 3.371s
     CGroup: /system.slice/kids-task.service
             └─413582 /opt/kids-task-manager/kids-task-manager_linux_arm64

7月 16 10:56:07 WiFi-Debian kids-task-manager_linux_arm64[413582]: 🚀 宝贝任务管理服务已启动
7月 16 10:56:07 WiFi-Debian kids-task-manager_linux_arm64[413582]:    本机访问:   http://localhost:8080
7月 16 10:56:07 WiFi-Debian kids-task-manager_linux_arm64[413582]:    局域网访问: (同一 WiFi / 网段下的手机、其他电脑可直接打开)
7月 16 10:56:07 WiFi-Debian kids-task-manager_linux_arm64[413582]:                http://192.168.50.137:8080
7月 16 10:56:07 WiFi-Debian kids-task-manager_linux_arm64[413582]: 📁 数据库文件: kids-task-data.db

可以看到设备地址和端口

如果想使用文件url进行视觉识别,则需要创建一个静态文件的服务
这里将文件存到内存卡中了。

检查当前用户

id $user

user@WiFi-Debian:~$id $user
用户id=1000(user) 组id=1000(user) 组=1000(user),20(dialout),27(sudo),29(audio),44(video),46(plugdev)

调整挂载sdcard的用户uid=1000,gid=1000

sudo nano /etc/fstab

user@WiFi-Debian:~$ cat /etc/fstab
LABEL=arch64 / btrfs defaults,noatime,compress=zstd,commit=120 0 0
debugfs /sys/kernel/debug debugfs defaults 0 0
UUID=7DFE-5FCD /mnt/sdcard exfat defaults,uid=1000,gid=1000,nofail,x-systemd.device-timeout=30,x-systemd.requires=/dev/disk/by-uuid/7DFE-5FCD 0 0

这里使用的是 busybox
命令

busybox httpd -h /mnt/sdcard/images -p 0.0.0.0:8081

终端执行只是前台 / 临时后台进程,一旦断开 SSH、设备重启,服务直接消失。

一、做成 systemd 开机自启(推荐,Debian 标准方案)

1. 创建服务文件
sudo nano /etc/systemd/system/img-httpd.service

粘贴下面内容

[Unit]
Description=Busybox image static server
After=local-fs.target network.target

[Service]
Type=forking
# 如果你只给穿透调用,强烈建议 127.0.0.1:8081,不要0.0.0.0
ExecStart=/usr/bin/busybox httpd -h /mnt/sdcard/images -p 0.0.0.0:8081
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
2. 生效并设置开机启动
sudo systemctl daemon-reload 

# 设置开机自启 
sudo systemctl enable img-httpd 

# 立即启动服务 
sudo systemctl start img-httpd

使用 url/图片名称就可以访问了

演示:

Snipaste_2026-07-16_13-50-23.png

Snipaste_2026-07-16_13-50-40.png

Snipaste_2026-07-16_13-50-45.png

Snipaste_2026-07-16_13-50-51.png

Snipaste_2026-07-16_13-50-57.png

Snipaste_2026-07-21_08-36-21.png

Snipaste_2026-07-21_08-36-38.png

Snipaste_2026-07-21_08-36-49.png

Snipaste_2026-07-16_13-51-11.png

宝贝任务管理服务 (Kids Task Manager)

用 Go 写的家庭任务与积分小系统,带一个网页管理界面。给孩子派任务、攒积分、换奖励,家长在后台统一管理。

数据用 SQLite 存(纯 Go 驱动 modernc.org/sqlite,不依赖 CGO),所以整个程序就是一个二进制文件,Windows / macOS / Linux(含 ARM64,树莓派之类)都能直接跑。

能做什么

  • 家庭成员:加家长和小孩。家长把任务派给某个孩子,每个孩子的任务和积分是分开的。
  • 任务排期:支持单次某天、日期区间、每天、每周、每月这几种方式。
  • 积分与奖励:完成任务实时加分,顶栏显示当前成员余额。家长设奖励(可限制库存,库存填 -1 表示不限量),孩子用自己的积分兑换。兑换后支持「取消兑换」,积分和库存会退回去。
  • 奖励定向:奖励可以设为所有人可兑换,也可以只给某个孩子(专属奖励只有本人能看到、能兑换)。
  • 日历视图:月历按完成度上色,点某天能勾当天的任务;也支持按周、按月的概览。
  • 作业检查:给每个孩子留一条作业检查记录,含检查内容/评语、附件图片、以及错题(题目/答案/备注)。也能直接调接口录入。
  • AI 检查:在作业检查里上传作业图片或填图片地址,自动调用配置好的大模型识别,生成一条检查记录(科目/内容/附件/错题)。提示词可以在系统配置里改,也能一键恢复默认;模型繁忙(1305/429/503)会按设置的次数自动重试。
  • 登录保护:首页要输密码才能进(默认 123456),局域网里别人也看不到数据。

搭建 Go 环境

项目用 Go 1.22+,标准库加纯 Go 的 SQLite 驱动,不需要 GCC,交叉编译开箱即用。

1. 装 Go

https://go.dev/dl/ 下载(国内用 https://golang.google.cn/dl/ 更快),选对应系统的包:

  • Windows:下 go1.22.x.windows-amd64.msi 双击装。

  • macOS:Intel 选 darwin-amd64.pkg,Apple Silicon 选 darwin-arm64.pkg

  • Linux:下 linux-amd64.tar.gz 解到 /usr/local
    bash

    wget https://go.dev/dl/go1.22.x.linux-amd64.tar.gz
    sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.22.x.linux-amd64.tar.gz
    

装完把 Go 的 bin 目录加进 PATH(Windows/macOS 安装包一般自动加;Linux 要自己加,比如往 ~/.bashrc 里写 export PATH=$PATH:/usr/local/go/bin)。

2. 验证

bash

go version     # 能看到版本号就行,比如 go version go1.22.5 linux/amd64
go env GOPATH

3. 配代理(国内网络)

依赖 modernc.org/sqlite,国内直连可能超时:

bash

go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=off

如果公司网络要走 HTTP 代理,再设 HTTP_PROXY / HTTPS_PROXY(不需要就跳过)。

本项目锁了 modernc.org/sqlite 的兼容版本。如果 go build 提示要自动升级工具链,执行 go env -w GOTOOLCHAIN=local 用本地 Go 版本即可。

4. 拉代码、构建

bash

git clone https://gitee.com/lazy-ai/kids-task-manager.git
cd kids-task-manager
go mod download
go run .          # 直接跑,浏览器开 http://localhost:8080
go build -o app . # 编译当前平台

快速开始

用预编译二进制

dist/ 里已经是各平台的成品:

bash

dist/kids-task-manager_windows_amd64.exe   # Windows
dist/kids-task-manager_darwin_amd64        # macOS Intel
dist/kids-task-manager_darwin_arm64        # macOS Apple Silicon
dist/kids-task-manager_linux_amd64         # Linux x86_64
dist/kids-task-manager_linux_arm64         # Linux ARM64 / aarch64(树莓派、高通 Snapdragon 410 等)

跑起来后浏览器打开 http://localhost:8080

自己用 Go 跑 / 编译

bash

cd kids-task-manager
go run .
go build -o app .

交叉编译

bash

bash build.sh              # macOS / Linux / Git Bash
powershell -File build.ps1 # Windows PowerShell

因为 SQLite 驱动是纯 Go 的,交叉编译不用 gcc。

自定义启动参数

bash

./kids-task-manager -addr :9000 -data mydata.db
  • -addr:监听地址,默认 :8080
  • -data:SQLite 文件路径,默认 kids-task-data.db

Linux 部署脚本

deploy.sh 会自动识别架构(x86_64 → linux_amd64,aarch64/arm64 → linux_arm64),挑 dist/ 里对应的二进制以守护进程方式跑起来:

bash

chmod +x deploy.sh
./deploy.sh start     # 后台启动,默认 :8080
./deploy.sh status    # 看运行状态
./deploy.sh restart   # 重启
./deploy.sh stop      # 停
./deploy.sh logs      # 实时看日志

KTM_ADDR=:9000 KTM_DATA=/var/lib/ktm.db ./deploy.sh start  # 自定义端口/数据文件
./deploy.sh build     # dist/ 里没有对应二进制时,本机现场编译

脚本会把 PID 写进 kids-task-manager.pid,日志写进 kids-task-manager.log。优先用 dist/ 里的预编译文件,没有才 go build。远程访问记得开防火墙端口,用服务器 IP 代替 localhost

怎么用

  1. 第一次启动会自动建好「家长」和「宝贝」两个成员。
  2. 点右上角 👪 成员 加孩子(也能加多个家长)。
  3. 切到某个成员视角,在 📋 任务 页点 + 添加任务:填标题、积分、指派给谁、排期方式。
  4. 在 🎁 奖励 页加可兑换的奖励;切到孩子视角点「兑换」就扣他的积分。
  5. 📊 统计 页看日历、完成度、积分汇总和最近动态。
  6. 📝 作业检查 页给某个孩子加一条检查记录:填科目、检查内容/评语,可传附件(作业照片),逐条登错题(题目/答案/备注)。也可以直接 POST /api/checks 批量写。

顶部的成员切换器决定当前视角:家长能看到所有孩子的任务并管理一切;孩子只看到自己的任务、奖励和积分。

登录

服务默认要登录:首页先弹登录框,输对密码才能看数据,避免局域网里别人随便访问。

  • 默认密码 123456(没单独改过时生效)。
  • 登录后令牌存在浏览器本地,刷新页面不用重登;重启服务后令牌作废,要再登一次。
  • 改密码:进 ⚙️ 系统配置 最下面的 🔐 访问控制,填新密码点「保存密码」。留空会恢复成默认 123456

AI 检查提示词

⚙️ 系统配置 的「大模型配置」里有一个提示词文本框:

  • AI 检查时会把这段提示词连同作业图片一起发给大模型,让它识别并生成检查记录。
  • 默认是一段内置提示词(要求模型只返回可解析的 JSON)。如果识别效果不理想,可以在这里改——比如强调科目顺序、错题格式、评语详略等。
  • 点「恢复默认提示词」就还原成内置的那版。

目录结构

kids-task-manager/
├── go.mod          # 模块定义(依赖 modernc.org/sqlite,纯 Go)
├── main.go         # 服务入口、路由、内嵌前端
├── store.go        # 数据模型 + SQLite 持久化
├── handlers.go     # REST API 与业务逻辑
├── calendar.go     # 日历/排期计算
├── api_test.go     # 单元测试(内存路由,不需要端口)
├── build.sh        # 跨平台构建脚本(bash)
├── build.ps1       # 跨平台构建脚本(PowerShell)
├── web/
│   ├── index.html  # 管理页面
│   ├── style.css   # 样式
│   └── app.js      # 前端逻辑
└── kids-task-data.db  # 运行时生成的 SQLite 数据库

API 一览

方法 路径 说明
GET /api/members 家庭成员列表
POST /api/members 新增成员 {name,role,emoji,color}
PUT /api/members/{id} 编辑成员
DELETE /api/members/{id} 删除成员(级联删其任务/积分)
GET /api/tasks?member={id} 任务列表(按成员隔离)
GET /api/tasks/range?start=&end=&member= 按日期区间展开任务(缺省查当天)
POST /api/tasks 新建任务 {title,points,member_id,mode,date,start_date,end_date,weekdays,monthdays,color}
PUT /api/tasks/{id} 编辑任务
DELETE /api/tasks/{id} 删除任务
POST /api/instances/toggle 切换某次任务完成 {task_id,key}
GET /api/rewards 奖励列表
POST /api/rewards 新建奖励
PUT /api/rewards/{id} 编辑奖励
DELETE /api/rewards/{id} 删除奖励
POST /api/rewards/{id}/redeem 兑换 {member_id};专属奖励非本人会被拒
POST /api/redemptions/{id}/cancel 取消兑换(仅本人、每笔一次,退积分/回补库存){member_id}
GET /api/redemptions?member= 兑换记录列表(按成员过滤,含奖励标题)
DELETE /api/redemptions/{id} 删除兑换记录并退积分 {member_id}
GET /api/calendar?member=&year=&month= 月历数据
GET /api/summary?member= 积分汇总
GET /api/history?member= 最近动态(含 earn/redeem/refund
GET /api/checks?member= 作业检查记录列表(按成员过滤)
POST /api/checks 新增检查记录(见下方「作业检查接口」)
PUT /api/checks/{id} 编辑检查记录 {member_id,subject,content,attachments,wrong_questions}
DELETE /api/checks/{id} 删除检查记录
POST /api/login 登录校验 {password},成功返回 {token}(公开接口)
POST /api/logout 退出登录(使当前令牌失效)
GET /api/settings/access 读取当前登录密码(需登录)
PUT /api/settings/access 修改登录密码 {password},留空恢复默认 123456(需登录)
GET /api/settings/ai 读取大模型配置(含 enabled/api_key/model/base_url/retry/prompt/default_promptdefault_prompt 是内置默认提示词,供「恢复默认」用)(需登录)
PUT /api/settings/ai 保存大模型配置(同上字段,留空字段不覆盖已有值)(需登录)
POST /api/checks/ai AI 检查:传作业图片(attachments,data URL 数组)或图片 url,调大模型识别并自动建一条检查记录;需带 member(归属成员 id)和可选 subject(需登录)

所有 /api/** 接口都开了 CORS(Access-Control-Allow-Origin: *),外部网页/小程序能直接调;跨域请求浏览器会先发 OPTIONS 预检,服务端已处理。

POST /api/loginGET /api/health 外,其余接口都要带登录后的会话令牌(请求头 Authorization: Bearer <token>X-Auth-Token),否则返回 401。令牌存在浏览器 localStorage,重启服务后失效。

数据模型

  • 成员 (members)id, name, role(家长/孩子), color, emoji, balance
  • 任务 (tasks)id, member_id, title, points, mode(once/range/daily/weekly/monthly), date, start_date, end_date, weekdays, monthdays, color, active
    • weeklyweekdays 是逗号分隔的星期几(0=周日..6=周六,如 "1,3,5" 表示周一三五);为空时回退周日
    • monthlymonthdays 是逗号分隔的号(1..31,如 "1,15,20");为空回退每月 1 号;某月没有这个号(如 2 月 30 号)自动跳过
  • 任务实例 (instances):某次出现(按 key,具体日期)的完成状态。每周/每月一个周期可能多天,所以每天独立记完成
  • 奖励 (rewards)id, title, cost, stock(-1 不限量), emoji, member_id(空=所有人可兑换;填某成员 id=仅其可见可兑换)
  • 兑换记录 (redemptions)id, reward_id, member_id, points, at, cancelled, cancelled_at
  • 检查记录 (checks)id, member_id, subject, content, attachments(JSON), wrong_questions(JSON), created_at
  • 流水 (ledger):每次积分变动记录,类型 earn(获得) / redeem(兑换) / refund(取消或删除兑换后归还),用于历史和余额对账
  • 系统设置 (settings):键值表,存 ai_config(大模型配置 JSON:enabled/api_key/model/base_url/retry/prompt)和 admin_password(登录密码,空或未设置时回退默认 123456

删除成员会级联删其任务、实例、兑换和流水;删除任务模板会一并删完成记录。

接口调用示例

后端对所有 /api/** 开了 CORS,任意前端、脚本或小程序都能直接调。下面用 curl 演示「查奖励 → 兑换 → 删兑换记录退积分」:

bash

# 1) 查某成员的可用奖励(专属奖励已按 member 过滤)
curl "http://localhost:8080/api/rewards?member=m_child_001"

# 2) 用该成员身份兑换某个奖励
curl -X POST "http://localhost:8080/api/rewards/r_xxx/redeem" \
     -H "Content-Type: application/json" \
     -d '{"member_id":"m_child_001"}'
# => {"balance":50,"redemption_id":"rd_xxx"}

# 3) 查该成员的兑换记录
curl "http://localhost:8080/api/redemptions?member=m_child_001"

# 4) 删该兑换记录(退积分)
curl -X DELETE "http://localhost:8080/api/redemptions/rd_xxx" \
     -H "Content-Type: application/json" \
     -d '{"member_id":"m_child_001"}'
# => {"balance":100}

按日期区间查任务

GET /api/tasks/range 把各类重复任务(每天/每周/每月/指定日/区间)按天展开到给定区间,每天返回当天该做的任务、完成状态和可得积分。适合外部系统拉「今日待办」或「某段时间的计划」。

查询参数(都可省略):

参数 说明 缺省
start 区间起始 YYYY-MM-DD 今天
end 区间结束 YYYY-MM-DD(含当天) 等于 start(即查单天)
member 只查该成员 全部成员

bash

# 查某成员 2026/07/09 ~ 2026/07/10 的任务
curl "http://localhost:8080/api/tasks/range?member=m_child_001&start=2026-07-09&end=2026-07-10"

# 不传 start/end,默认查今天
curl "http://localhost:8080/api/tasks/range?member=m_child_001"

返回结构:

json

{
  "start": "2026-07-09",
  "end": "2026-07-10",
  "member": "m_child_001",
  "days": [
    {
      "date": "2026-07-09",
      "weekday": 4,
      "tasks": [
        {"id": "i_xxx", "template_id": "t_xxx", "title": "刷牙", "points": 5, "done": true}
      ],
      "done": 1,
      "total": 2,
      "points": 15
    }
  ],
  "summary": {"days": 2, "total_tasks": 4, "done_tasks": 1, "pending": 3}
}

days[].tasks[].id 是任务实例 id(没完成过就是空字符串),配合 template_id 和日期 date 就能调 POST /api/instances/toggle 勾选完成。

作业检查接口

「作业检查」的数据能直接通过 /api/checks 读写,适合家长用脚本、小程序或外部系统批量录入某次作业的检查结果(含图片附件和错题)。

字段说明

字段 类型 说明
member_id string 必填,记录归属的孩子成员 id(对应的成员不存在会报 400)
subject string 科目,如「数学」「语文」(可选)
content string 检查内容 / 评语(可选,但 content / attachments / wrong_questions 至少填一个)
attachments array 附件列表,每项 {name, type, data}datadata:;base64,xxxx 形式的 data URL(比如作业照片)
wrong_questions array 错题列表,每项 {title, answer, note},对应题目 / 正确答案或解析 / 备注

新增一条检查记录

bash

# 给 m_child_001 加一条数学作业检查:评语 + 一张图片附件 + 一道错题
curl -X POST "http://localhost:8080/api/checks" \
     -H "Content-Type: application/json" \
     -d '{
       "member_id": "m_child_001",
       "subject": "数学",
       "content": "竖式计算粗心,已订正",
       "attachments": [
         {
           "name": "homework.jpg",
           "type": "image/jpeg",
           "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDA...(省略 base64 内容)"
         }
       ],
       "wrong_questions": [
         {"title": "23 + 19 = ?", "answer": "42", "note": "个位 3+9=12 进位漏写"},
         {"title": "100 - 56 = ?", "answer": "44", "note": "退位错误"}
       ]
     }'
# => {"id":"c_xxx","member_id":"m_child_001","subject":"数学","content":"竖式计算粗心,已订正",
#     "attachments":[...],"wrong_questions":[...],"created_at":1752547200}

查询 / 编辑 / 删除

bash

# 查某成员的全部检查记录(不传 member 就查全部)
curl "http://localhost:8080/api/checks?member=m_child_001"

# 编辑某条记录(要带 member_id 做归属校验)
curl -X PUT "http://localhost:8080/api/checks/c_xxx" \
     -H "Content-Type: application/json" \
     -d '{"member_id":"m_child_001","subject":"数学","content":"已重新检查,全部正确"}'

# 删除某条记录
curl -X DELETE "http://localhost:8080/api/checks/c_xxx"
# => {"ok":true}

业务规则:

  • 取消兑换(POST /api/redemptions/{id}/cancel)和删除记录(DELETE /api/redemptions/{id})都会退积分;前者留着记录标「已取消」,后者直接删掉。两者都限本人操作,已取消的记录不再重复退。
  • 只有限量奖励(stock ≥ 0)且仍上架时,取消/删除才会回补库存。
  • 专属奖励(有 member_id)对别人不可见也不可兑换,归属校验在服务端强制做。
  • 检查记录创建时服务端会校验 member_id 对应的成员是否存在;contentattachmentswrong_questions 至少填一个,否则返回 400。

AI 检查与大模型配置接口

「作业检查 → 🤖 AI 检查」也能直接调接口。服务有登录保护,调用前先 POST /api/login 拿令牌,放到请求头 Authorization: Bearer <token>

1) 配置大模型(以智谱 GLM 视觉模型为例)

bash

# 先登录拿令牌(默认密码 123456)
TOKEN=$(curl -s -X POST "http://localhost:8080/api/login" \
  -H "Content-Type: application/json" -d '{"password":"123456"}' | sed -n 's/.*"token":"$[^"]*$".*/\1/p')

# 保存大模型配置:启用、API Key、模型、接口地址、重试次数、提示词(可选,留空用默认)
curl -X PUT "http://localhost:8080/api/settings/ai" \
  -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -d '{
    "ai": {
      "enabled": true,
      "api_key": "你的_API_Key",
      "model": "glm-4.6v-flash",
      "base_url": "https://open.bigmodel.cn/api/paas/v4/chat/completions",
      "retry": 2
    }
  }'
# => {"ok":true}

# 读当前配置(default_prompt 是内置默认提示词,可用来「恢复默认」)
curl "http://localhost:8080/api/settings/ai" -H "Authorization: Bearer $TOKEN"

2) 调用 AI 检查(上传图片)

bash

# 传一张作业图片(data URL),让大模型识别并自动建一条检查记录
curl -X POST "http://localhost:8080/api/checks/ai" \
  -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -d '{
    "member": "m_child_001",
    "subject": "数学",
    "attachments": [
      {"name":"homework.jpg","type":"image/jpeg","data":"data:image/jpeg;base64,/9j/4AAQ...(省略)"}
    ]
  }'
# => {"id":"c_xxx","member_id":"m_child_001","subject":"数学",
#     "content":"...","attachments":[...],"wrong_questions":[...],"created_at":...}

# 也可以只传图片 URL(不传 attachments,改用 url 字段):
# -d '{"member":"m_child_001","url":"https://example.com/homework.jpg"}'

大模型返回的内容要能解析成 JSON(含 subject/content/wrong_questions 等字段),解析失败会返回具体错误。遇到模型繁忙(如 1305 访问量过大/429/503)会按设置里的重试次数自动重试,全失败则返回最后一条错误。

注册智谱

并创建API_KEY。

通过我的专属邀请链接注册即可获得额外GLM-4-Air 2000万Tokens好友专属福利,期待和你一起在BigModel上探索AGI时代的应用;链接:
注册连接

注册过程就不多说了。注册成功后,登录就行了。

1、登录智谱

Snipaste_2025-07-17_08-57-15.png

2、控制台

Snipaste_2025-07-17_08-58-08.png

3、创建KEY

Snipaste_2025-07-17_08-58-27.png

点击 添加新的API Key

Snipaste_2025-07-17_08-58-51.png

填写 API key 名称,确定后创建

Snipaste_2025-07-17_08-59-25.png

创建成功后会在列表中展示出来,点击 复制

附加(非必要,但建议)

实名认证,赠送免费资源包。

Snipaste_2025-07-17_08-48-36.png

进入个人中心,点击 认证

Snipaste_2025-07-17_08-49-01.png

个人实名认证

Snipaste_2025-07-17_08-49-19.png
填写实名信息

支付宝扫码,进行人脸认证。

认证完成后,点击 已完成刷脸认证

Snipaste_2025-07-17_08-54-38.png
点击 查看资源包

Snipaste_2025-07-17_08-55-35.png

还有免费模型

Snipaste_2026-07-16_13-58-39.png

免费模型唯一不足的地方就是容易提示访问量过大,服务中加了重试机制可以重试。

有条件的话可以买一些更好的模型,效果会更好一些。这里就先使用免费的。

目前服务端只支持智普模型,其他模型没有做适配。

增加了小智MCP功能

源码地址

https://gitee.com/lazy-ai/go-mcp-task.git

go-mcp-task(MCP 任务服务 / Sidecar)

一个用 Go 写的 MCP(Model Context Protocol)服务,作为 kids-task-manager 的伴随进程(sidecar)运行。它把 kids-task-manager 的本地能力——摄像头抓拍、作业识别、成员/检查记录查询、计算器——包装成 MCP 工具,既能通过 stdio 被本地 MCP 客户端调用,也能通过 WebSocket 连上小智(云端 MCP 接入点),让云端 AI 直接调用这些工具。

本项目是 kids-task-manager 的「MCP 桥」:kids-task-manager 负责数据、Web UI、RTSP 摄像头、大模型识别;go-mcp-task 只负责把这些能力暴露给 MCP 客户端 / 云端 AI。两个仓库互相独立,部署时二进制放在同一目录即可。

它是怎么工作的

  • 作为 kids-task-manager 的子进程自动拉起(系统配置里「自动启动任务服务」默认开启),运行同目录下的 go-mcp-task_<goos>_<goarch>[.exe]
  • 启动时从命令行参数(或环境变量)读取 kids-task-manager 的基址、登录密码 / 会话令牌。
  • 两条通信链路并存
    • stdio:本地 MCP 客户端按行读写 JSON-RPC 2.0(initialize / tools/list / tools/call / ping)。
    • WebSocket(可选):配置了 -mcp-endpoint(小智接入点 wss://...?token=...)后,作为 WebSocket client 连上该接入点,在连接内充当 MCP server,云端 AI 即可调用本地工具;连接断开后自动指数退避重连。

暴露的工具

工具 说明
calculator 安全数学求值,支持 sin/cos/sqrt/log/pow/abs/floor/ceil/round/factorial 等函数与 pi/e/tau/phi 常量,以及 rand() 系列。
get_config 回显运行期配置(含 -mcp-endpoint 注入的接入点地址与 base_url)。验证「改了接入点是否生效」时调用(改 endpoint 会触发 sidecar 重启)。
list_cameras 列出 kids-task-manager 已配置的摄像头,返回 [{id,name,url,enabled,...}]capture_frame / check_homework 需要先拿 device_id
list_members 列出家庭成员,check_homework 需要其中的 member_id
capture_frame 调用「摄像头识别 → 获取视频帧」接口抓一帧,返回 base64 图片与元数据。参数 device_id
check_homework 抓帧 + 大模型作业识别,返回识别结果(科目 / 内容 / 错题等)。参数 device_id + member_id,可选 subject(覆盖模型推断的科目)。
list_checks 列出最近作业检查记录(科目 / 内容 / 错题 / 时间等)。

工具级业务错误(success=false)会映射为 MCP 的 isError=true;工具内部 panic 会被兜底为错误响应,不会拖垮整个 stdio 服务。

命令行参数

参数 说明 默认
-base-url kids-task-manager 基址,如 http://127.0.0.1:8080 http://127.0.0.1:8080
-password 登录密码(也可设环境变量 KTM_PASSWORD);未配置则尝试匿名,但受保护接口需鉴权
-token 会话令牌,直接指定可跳过登录(也可设 KTM_TOKEN
-timeout HTTP 请求总超时,含摄像头抓拍 + 大模型作业识别耗时,建议 ≥60s 120s
-mcp-endpoint 小智 MCP 接入点地址(wss://api.xiaozhi.me/mcp/?token=...);配置后作为 WebSocket client 连上云端,本地工具即被云端 AI 调用
-status-addr 本地状态端点监听地址(如 127.0.0.1:8123);非空时暴露 GET /status,供 kids-task-manager 代理展示。为空则不启动

所有参数都有对应的环境变量(KTM_ 前缀),命令行参数优先于环境变量默认值。

环境变量

变量 对应参数
KTM_BASE_URL -base-url
KTM_PASSWORD -password
KTM_TOKEN -token
KTM_MCP_ENDPOINT -mcp-endpoint
KTM_STATUS_ADDR -status-addr

身份鉴权

  • 未传 -token 且有 -password 时,首次访问受保护接口会自动 POST /api/login 换取令牌并缓存于进程内存。
  • 缓存的令牌随进程重启失效;kids-task-manager 重启 sidecar 时会用最新配置重新拉起。

本地状态端点(调试用)

配置了 -status-addr(kids-task-manager 默认注入 127.0.0.1:8123)时暴露:

  • GET /status:JSON 状态快照,包含
    • cloud:小智连接状态(configured / connected / state / endpoint / last_error);
    • log:接收输入日志(in 请求 / out 响应,stdiocloud 来源);
    • responses:写回的响应(排查「工具到底返回了什么 / 为何报错」);
    • calls:🔧 工具内部调用日志(check_homework / capture_frame 对 kids-task-manager 的 HTTP 请求、SSE 事件、耗时、报错)。这是定位 check_homework 卡死/超时的关键——MCP 响应只有在工具函数返回后才记录,而内部调用日志能在「请求发出 → 收到 HTTP 状态 → 收到各 SSE 事件 → 完成/报错」各阶段即时留痕,即便最终响应因连接断开丢失,也能看出卡在哪一步。
  • GET /healthz:简易存活探针。

kids-task-manager 的「📜 通信日志」面板会代理展示上述数据,并单独呈现「🔧 工具内部调用」区块。

连接保护(防重连风暴)

  • 云端 MCP 连接:每收到一帧 JSON-RPC 消息都在独立 goroutine 中处理并写回(写锁保护并发响应帧),读循环始终空闲、ping 即时被应答。避免 check_homework 这类耗时数十秒的长任务阻塞读循环、导致云端心跳超时而反复重连(表现为日志里反复出现 initialize #0)。
  • 断线重连:指数退避(1s → 封顶 600s),接入点地址已自带 token,无需额外 header;连接失败会记录次数与错误并自动重试。

构建

纯 Go + gorilla/websocket,无 CGO 依赖,交叉编译开箱即用:

# 构建当前平台
go build -o go-mcp-task .

# 交叉编译(示例:树莓派 / 高通 Snapdragon 410 = linux/arm64)
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o go-mcp-task_linux_arm64 .

# Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o go-mcp-task_windows_amd64.exe .

通常由 kids-task-manager 的 build.sh 一并把本项目构建到其 dist/(命名规则 go-mcp-task_<goos>_<goarch>[.exe]),与 kids-task-manager 二进制同目录打包。

日志约定

  • 所有诊断日志写 stderr,绝不污染 stdout 的 JSON-RPC 流,保证本地 MCP 客户端能可靠按行解析。

目录结构

go-mcp-task/
├── go.mod          # 模块定义(依赖 gorilla/websocket)
├── main.go         # 入口:解析参数、启动 cloud/status、stdio 读写循环
├── server.go       # MCP stdio 服务端(JSON-RPC 分发、工具清单与调度)
├── ktm.go          # ktmClient:调用 kids-task-manager REST API(鉴权 / SSE 解析 / 各工具实现 / 内部调用日志)
├── cloud.go        # 小智 WebSocket 连接 + 自动重连 + 每消息并发处理
├── status.go       # 本地状态端点(/status / /healthz)+ 连接状态与日志环形缓冲
├── eval.go         # calculator 安全求值实现
├── *_test.go       # 单元测试
└── dist/           # (可选)本地构建产物

与 kids-task-manager 的对接

  • kids-task-manager 在「🧮 MCP 任务服务」设置里保存 autostartendpoint;开启自动启动且未运行则立即拉起 go-mcp-task,关闭则停止;改 endpoint 会触发 sidecar 重启使之生效。
  • 部署时把 kids-task-managergo-mcp-task 两个二进制放到同一目录,前者即可自动发现并管理后者。详见 kids-task-manager/README.md

附件

upload 附件:外壳文件.zip

upload 附件:AiPi-WV01-32s.zip

──── 0人觉得很赞 ────

使用道具 举报

太强了,值得点赞
太强了,给幸福哥点个赞
太强了,给幸福哥点赞~
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 31223 个
  • 话题数: 42319 篇