21 changed files with 98 additions and 87 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
#! /bin/sh
#!/bin/sh
exec > /dev/null 2>&1
+1 -1
View File
@@ -1,4 +1,4 @@
#! /bin/sh
#!/bin/sh
cat << 'EOF'
+1 -1
View File
@@ -1,4 +1,4 @@
#! /bin/sh
#!/bin/sh
cat << 'EOF'
+4
View File
@@ -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) 项目,特此鸣谢。
+3 -3
View File
@@ -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:
# 发送心跳失败,重新连接
+9 -4
View File
@@ -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
+1
View File
@@ -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 \
+24 -11
View File
@@ -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)
- [Xiaomi 智能音箱 Pro v1.56.31](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.31)
- [小爱音箱 Pro v1.88.206](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.206)
> [!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)
>
> - Xiaomi 智能音箱 Pro 👉 [v1.56.31](https://github.com/idootop/open-xiaoai/releases/tag/OH2P_1.56.31)
> - 小爱音箱 Pro 👉 [v1.88.206](https://github.com/idootop/open-xiaoai/releases/tag/LX06_1.88.206)
>
> 更新版本的固件可能存在变化,导致刷机失败,设备变砖,请自行评估风险。
## 制作固件
你可以按照下面的 2 种方法,制作自定义固件。
@@ -66,13 +67,25 @@ SSH_PASSWORD=open-xiaoai
- Dockerhttps://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 '初始化成功'
```
```
+20 -20
View File
@@ -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"
}
+7 -7
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e
+6 -24
View File
@@ -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);
}
+2 -2
View File
@@ -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
+11 -5
View File
@@ -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
+1 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
#! /bin/sh
#!/bin/sh
exec > /dev/null 2>&1
+1 -1
View File
@@ -1,4 +1,4 @@
#! /bin/sh
#!/bin/sh
cat << 'EOF'
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
RED='\033[0;31m'