Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
066fddbb68 | ||
|
|
b5d00db7ca | ||
|
|
1405eca23f | ||
|
|
43e6739726 | ||
|
|
affd94d1cf | ||
|
|
53f8ab31ee | ||
|
|
c5edea969c | ||
|
|
e4dc39ef39 |
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
exec > /dev/null 2>&1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
cat << 'EOF'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
cat << 'EOF'
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ PS:如果还是不行,建议更换其他更易识别的唤醒词。
|
||||
|
||||
由于 ASR 相关模型文件体积较大,并未直接提交在 git 仓库中,你可以在 release 中下载 [VAD + KWS 相关模型](https://github.com/idootop/open-xiaoai/releases/tag/vad-kws-models),然后解压到 `xiaozhi/models` 路径下即可。
|
||||
|
||||
## 相关项目
|
||||
|
||||
- [oxa-server](https://github.com/pu-007/oxa-server): 提供了更强大易用的 config.py 的配置方式
|
||||
|
||||
## 鸣谢
|
||||
|
||||
该演示使用的 Python 版小智 AI 客户端基于 [py-xiaozhi](https://github.com/Huang-junsen/py-xiaozhi) 项目,特此鸣谢。
|
||||
|
||||
@@ -65,8 +65,8 @@ APP_CONFIG = {
|
||||
"xiaozhi": {
|
||||
"OTA_URL": "https://api.tenclass.net/xiaozhi/ota/",
|
||||
"WEBSOCKET_URL": "wss://api.tenclass.net/xiaozhi/v1/",
|
||||
"WEBSOCKET_ACCESS_TOKEN": "(可选)一般用不到这个值",
|
||||
"DEVICE_ID": "(可选)默认自动生成",
|
||||
"VERIFICATION_CODE": "首次登陆时,验证码会在这里更新",
|
||||
"WEBSOCKET_ACCESS_TOKEN": "", #(可选)一般用不到这个值
|
||||
"DEVICE_ID": "", #(可选)默认自动生成
|
||||
"VERIFICATION_CODE": "", # 首次登陆时,验证码会在这里更新
|
||||
},
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ class WebsocketProtocol(Protocol):
|
||||
if self.websocket and get_xiaozhi().device_state == DeviceState.IDLE:
|
||||
try:
|
||||
await self.send_text(
|
||||
json.dumps({"session_id": "", "type": "abort"})
|
||||
json.dumps({"session_id": "", "type": "ping"})
|
||||
)
|
||||
except Exception:
|
||||
# 发送心跳失败,重新连接
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
# 你的小米账号/密码
|
||||
#你的小米账号/密码
|
||||
MI_USER=23333333
|
||||
MI_PASS=xxxxxxxxx
|
||||
|
||||
# 你的小爱音箱名称/DID
|
||||
#你的小爱音箱名称/DID
|
||||
MI_DID=小爱音箱Pro
|
||||
|
||||
# 你的 SSH 登录密码(默认为 open-xiaoai)
|
||||
#你的 SSH 登录密码,默认为 open-xiaoai
|
||||
SSH_PASSWORD=open-xiaoai
|
||||
|
||||
#账号登录异常时,请取消下面的注释,使用 MI_TOKEN 登录
|
||||
#MI_TOKEN=你的 passToken 获取教程 👉 https://github.com/idootop/migpt-next/issues/4
|
||||
|
||||
# 获取设备异常时,请取消下面的注释,查看设备列表详情
|
||||
#MI_DEBUG=true
|
||||
|
||||
@@ -6,6 +6,7 @@ ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
|
||||
&& echo $TZ > /etc/timezone \
|
||||
&& apk add --no-cache \
|
||||
bash \
|
||||
file \
|
||||
patch \
|
||||
python3 \
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
> 刷机有风险,操作需谨慎。请勿下载使用不明来历的固件!
|
||||
|
||||
小爱音箱 Pro 补丁固件制作流程:
|
||||
|
||||
- 固件提取(登录小米账号获取 OTA 链接)
|
||||
- 开启固化 SSH(支持自定义登录密码)
|
||||
- 禁用系统自动更新(系统更新后需要重新刷机打补丁)
|
||||
@@ -12,31 +13,31 @@
|
||||
## 下载固件
|
||||
|
||||
你可以直接在 [Github Releases](https://github.com/idootop/open-xiaoai/releases) 页面下载打包好的固件:
|
||||
- [Xiaomi 智能音箱 Pro v1.56.19](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.19)
|
||||
- [小爱音箱 Pro v1.88.206](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.206)
|
||||
|
||||
- [Xiaomi 智能音箱 Pro v1.56.31](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.31)
|
||||
- [小爱音箱 Pro v1.88.221](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.221)
|
||||
|
||||
> [!TIP]
|
||||
> 里面有两个文件,下载 `patched` 那个:
|
||||
>
|
||||
> - `xxx_patched.squashfs` 打补丁后的固件
|
||||
> - `xxx.squashfs` 原版固件(可用来刷回原系统)
|
||||
|
||||
> [!NOTE]
|
||||
> 默认 SSH 登录密码为 `open-xiaoai`,如需修改请自行制作固件。
|
||||
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 请下载和你当前小爱音箱版本一致的固件,跨版本刷机可能会出现未知错误,导致设备变砖。
|
||||
> 如果上面没有你的版本,请升级设备固件到最新版本,或者按照下面的教程自行制作固件。
|
||||
|
||||
> [!CAUTION]
|
||||
> 当前支持的最新固件版本为:
|
||||
> - Xiaomi 智能音箱 Pro 👉 [v1.56.19](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.19)
|
||||
> - 小爱音箱 Pro 👉 [v1.88.206](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.206)
|
||||
>
|
||||
> - Xiaomi 智能音箱 Pro 👉 [v1.56.31](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.31)
|
||||
> - 小爱音箱 Pro 👉 [v1.88.221](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.221)
|
||||
>
|
||||
> 更新版本的固件可能存在变化,导致刷机失败,设备变砖,请自行评估风险。
|
||||
|
||||
|
||||
|
||||
## 制作固件
|
||||
|
||||
你可以按照下面的 2 种方法,制作自定义固件。
|
||||
@@ -66,13 +67,25 @@ SSH_PASSWORD=open-xiaoai
|
||||
- Docker:https://www.docker.com/get-started/
|
||||
|
||||
> [!NOTE]
|
||||
> Windows 系统推荐使用 [Git Bash](https://git-scm.com/downloads) 终端运行。
|
||||
>
|
||||
> CMD 和 PowerShell 终端需要调整下面命令中文件(夹)的实际路径。
|
||||
> Windows 系统请在 [Git Bash](https://git-scm.com/downloads) 终端中运行以下命令。
|
||||
|
||||
> [!TIP]
|
||||
> 如果你是 Apple Silicon 芯片,请先在 Docker Desktop - Settings - General - Virtual Machine Options 中打开 Apple Virtual framework 选项,然后开启 `Use Rosetta for x86_64/amd64 emulation on Apple Silicon`
|
||||
|
||||
```shell
|
||||
# 克隆代码
|
||||
git clone https://github.com/idootop/open-xiaoai.git
|
||||
|
||||
# 进入当前项目根目录
|
||||
cd packages/client-patch
|
||||
|
||||
# 使用 Docker 进行构建
|
||||
docker run -it --rm --env-file $(pwd)/.env -v $(pwd)/assets:/app/assets -v $(pwd)/patches:/app/patches idootop/open-xiaoai:latest
|
||||
docker run -it --rm \
|
||||
--platform linux/amd64 \
|
||||
--env-file $(pwd)/.env \
|
||||
-v $(pwd)/assets:/app/assets \
|
||||
-v $(pwd)/patches:/app/patches \
|
||||
idootop/open-xiaoai:latest
|
||||
|
||||
# ✅ 打包完成,固件文件已复制到 assets 目录...
|
||||
# /app/assets/mico_all_92db90ed6_1.88.197/root-patched.squashfs
|
||||
@@ -113,7 +126,7 @@ npm run build
|
||||
示例:
|
||||
|
||||
```bash
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
/usr/sbin/tts_play.sh '初始化成功'
|
||||
```
|
||||
```
|
||||
|
||||
Generated
+20
-20
@@ -8,11 +8,11 @@
|
||||
"name": "open-xiaoai-patch",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@mi-gpt/miot": "^1.0.0"
|
||||
"@mi-gpt/miot": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mi-gpt/config": "1.0.0",
|
||||
"@types/node": "^22.13.11",
|
||||
"@mi-gpt/config": "1.1.0",
|
||||
"@types/node": "^24.2.1",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
@@ -443,9 +443,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mi-gpt/config": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/config/-/config-1.0.0.tgz",
|
||||
"integrity": "sha512-oo/roYiRcGiHsZESjukwPTsRFqddShTJ8gkccR5ZMYn8SySj07A0nCsEsLEfB9mLkvNY8D6PCO1NxbRDDRBBlA==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/config/-/config-1.1.0.tgz",
|
||||
"integrity": "sha512-o24iFINsoDuvInnMpfBQ4zCuTObbdodjXyizXmxl3yyYOMjmIAXizO/1UZ9/dv3UVTov3sjL09aCGuBeIVhvtA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -453,12 +453,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mi-gpt/miot": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/miot/-/miot-1.0.0.tgz",
|
||||
"integrity": "sha512-smWhddHzK1du3/LW2FifBrIIyeZNx/RvTSe0Zi4v3lYZwK8NeEwomg1jBjktQCCV4Fh8OuqNbCdNbmiVXmr5kw==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/miot/-/miot-1.2.1.tgz",
|
||||
"integrity": "sha512-DAFNUsLPepXSqJk/b+zfct8NCQHZzcl7f1t4X2WPKzxmDNagkawYlb96uPbk4syvn+DSg6vqle0Wm+gjmJ4kUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mi-gpt/utils": "1.0.0",
|
||||
"@mi-gpt/utils": "1.1.1",
|
||||
"axios": "^1.8.4",
|
||||
"pako": "^2.1.0"
|
||||
},
|
||||
@@ -467,22 +467,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mi-gpt/utils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/utils/-/utils-1.0.0.tgz",
|
||||
"integrity": "sha512-hAU/uYPNiNJgXWkQrVqRLe/9Uz8AgtoiNwcbbwQs8iXJcyq3NjcSHkkwUseJAnaQFE9iv/kvHZZsx3r2HhlKjw==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@mi-gpt/utils/-/utils-1.1.1.tgz",
|
||||
"integrity": "sha512-FiGHV2RDBRGE/Xb9Q5H757t3ZqOpo6gL+44VXiRxQb3fQiapOpn038RAWErHJYZajYzkxP2jl8Wggsb+wp77Zg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
|
||||
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
|
||||
"version": "24.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz",
|
||||
"integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
"undici-types": "~7.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
@@ -883,9 +883,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
||||
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"ota": "tsx --env-file=.env src/ota.ts",
|
||||
"extract": "sh src/extract.sh",
|
||||
"patch": "sh src/patch.sh",
|
||||
"squashfs": "sh src/squashfs.sh",
|
||||
"build": "sh src/build.sh"
|
||||
"extract": "bash src/extract.sh",
|
||||
"patch": "bash src/patch.sh",
|
||||
"squashfs": "bash src/squashfs.sh",
|
||||
"build": "bash src/build.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mi-gpt/miot": "^1.0.0"
|
||||
"@mi-gpt/miot": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mi-gpt/config": "1.0.0",
|
||||
"@types/node": "^22.13.11",
|
||||
"@mi-gpt/config": "1.1.0",
|
||||
"@types/node": "^24.2.1",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -13,36 +13,18 @@ const kSupportedDevices = [
|
||||
// 获取 OTA 信息
|
||||
async function getOTA(channel: "release" | "current" | "stable" = "release") {
|
||||
const MiNA = await getMiNA({
|
||||
did: process.env.MI_DID!,
|
||||
userId: process.env.MI_USER!,
|
||||
password: process.env.MI_PASS!,
|
||||
passToken: process.env.MI_TOKEN,
|
||||
debug: !!process.env.MI_DEBUG,
|
||||
});
|
||||
if (!MiNA) {
|
||||
console.log(`❌ 登录失败,请检查小米账号密码是否正确:`);
|
||||
console.log(`当前账号:${process.env.MI_USER}`);
|
||||
console.log(`当前密码:${process.env.MI_PASS}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const devices = await MiNA.getDevices();
|
||||
const speaker = devices?.find(
|
||||
(e: any) =>
|
||||
e.name === process.env.MI_DID || e.miotDID === process.env.MI_DID
|
||||
);
|
||||
if (!speaker) {
|
||||
console.log(`❌ 找不到设备: ${process.env.MI_DID}`);
|
||||
console.log(`可用设备列表:`);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
devices.map((e: any) => ({
|
||||
name: e.name,
|
||||
did: e.miotDID,
|
||||
})),
|
||||
null,
|
||||
4
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
const speaker = MiNA.account.device as any;
|
||||
|
||||
if (!kSupportedDevices.includes(speaker.hardware)) {
|
||||
console.log(
|
||||
@@ -65,7 +47,7 @@ async function getOTA(channel: "release" | "current" | "stable" = "release") {
|
||||
}
|
||||
|
||||
const model = speaker.hardware;
|
||||
const time = new Date().getTime();
|
||||
const time = Date.now();
|
||||
const sn = process.env.DEBUG_VERSION ? "" : speaker.serialNumber;
|
||||
const version = process.env.DEBUG_VERSION ?? speaker.romVersion;
|
||||
const otaInfo = `channel=${channel}&filterID=${sn}&locale=zh_CN&model=${model}&time=${time}&version=${version}&8007236f-a2d6-4847-ac83-c49395ad6d65`;
|
||||
@@ -88,7 +70,7 @@ async function main() {
|
||||
} else {
|
||||
ota = await getOTA();
|
||||
}
|
||||
if (!ota.url) {
|
||||
if (!ota?.url) {
|
||||
console.log(`❌ 获取设备信息失败`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
@@ -28,7 +28,7 @@ apply_patches() {
|
||||
# 清理临时文件
|
||||
rm "$temp_patch"
|
||||
elif [[ "$file" == *.sh ]]; then
|
||||
sh "$file"
|
||||
bash "$file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
@@ -40,14 +40,20 @@ elif [ "$MODEL" = "LX06" ]; then
|
||||
IMAGE_MAX_SIZE=$((0x02800000))
|
||||
fi
|
||||
|
||||
SIZE=`stat -L -c %s $FIRMWARE/root-patched.squashfs`
|
||||
echo "📊 当前固件大小: $SIZE 字节"
|
||||
SIZE=$(stat -L -c %s "$FIRMWARE/root-patched.squashfs")
|
||||
SIZE_MB=$((SIZE / 1024 / 1024))
|
||||
IMAGE_MAX_SIZE_MB=$((IMAGE_MAX_SIZE / 1024 / 1024))
|
||||
|
||||
echo "📊 当前固件大小: $SIZE 字节 ($SIZE_MB MB)"
|
||||
|
||||
if [ "$SIZE" -ge "$IMAGE_MAX_SIZE" ]; then
|
||||
echo "❌ 固件大小超过允许的最大值:$IMAGE_MAX_SIZE 字节"
|
||||
echo "❌ 固件大小超过允许的最大值:$IMAGE_MAX_SIZE 字节 ($IMAGE_MAX_SIZE_MB MB)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 固件大小检查通过,剩余空间: $((IMAGE_MAX_SIZE - SIZE)) 字节"
|
||||
REMAINING_BYTES=$((IMAGE_MAX_SIZE - SIZE))
|
||||
REMAINING_MB=$((REMAINING_BYTES / 1024 / 1024))
|
||||
echo "✅ 固件大小检查通过,剩余可用空间: $REMAINING_BYTES 字节 ($REMAINING_MB MB)"
|
||||
|
||||
cp -rf $FIRMWARE $BASE_DIR/assets/$FIRMWARE
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ cross build --release --target armv7-unknown-linux-gnueabihf
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> 如果你是 Apple silicon 芯片,为了能够正常使用 cross 交叉编译镜像,请先在 Docker Desktop - Settings - General - Virtual Machine Options 中打开 Apple Virtual framework 选项,然后开启 `Use Rosetta for x86_64/amd64 emulation on Apple Silicon`
|
||||
> 如果你是 Apple Silicon 芯片,为了能够正常使用 cross 交叉编译镜像,请先在 Docker Desktop - Settings - General - Virtual Machine Options 中打开 Apple Virtual framework 选项,然后开启 `Use Rosetta for x86_64/amd64 emulation on Apple Silicon`
|
||||
|
||||
编译成功后,将构建好的补丁程序 `client` 复制到小爱音箱上
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
exec > /dev/null 2>&1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
cat << 'EOF'
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ chmod +x ./flash
|
||||
# 执行命令后拔掉小爱音箱的电源线,重新插上电源,等待设备连接
|
||||
./flash connect
|
||||
|
||||
# 第 2 步:设置启动延时(5 秒)
|
||||
./flash delay 5
|
||||
# 第 2 步:设置启动延时(15 秒)
|
||||
./flash delay 15
|
||||
|
||||
# 第 3 步:切换启动分区
|
||||
./flash switch boot0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
RED='\033[0;31m'
|
||||
|
||||
Reference in New Issue
Block a user