fix: 修复型号M01无法获取到对话记录的问题

This commit is contained in:
涵曦 2024-10-13 01:06:14 +08:00
parent f249edbd6a
commit 2e864eed7c
9 changed files with 89 additions and 24 deletions

View File

@ -182,6 +182,7 @@ docker build -t xiaomusic .
| L05C | [小米小爱音箱Play 增强版](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l05c) |
| L09A | [小米音箱Art](https://home.mi.com/webapp/content/baike/product/index.html?model=xiaomi.wifispeaker.l09a) |
| LX04 X10A X08A | 已经支持的触屏版 |
| M01/XMYX01JY | 小米小爱音箱HD (获取对话记录的接口比较特殊) |
型号与产品名称对照可以在这里查询 <https://home.miot-spec.com/s/xiaomi.wifispeaker>

View File

@ -158,6 +158,9 @@ class Config:
enable_yt_dlp_cookies: bool = (
os.getenv("XIAOMUSIC_ENABLE_YT_DLP_COOKIES", "false").lower() == "true"
)
get_ask_by_mina: bool = (
os.getenv("XIAOMUSIC_GET_ASK_BY_MINA", "false").lower() == "true"
)
def append_keyword(self, keys, action):
for key in keys.split(","):

View File

@ -19,3 +19,8 @@ PLAY_TYPE_TTS = {
PLAY_TYPE_ALL: "已经设置为全部循环",
PLAY_TYPE_RND: "已经设置为随机播放",
}
# 需要采用 mina 获取对话记录的设备型号
GET_ASK_BY_MINA = {
"M01",
}

View File

@ -6,9 +6,9 @@
<meta name="viewport" content="width=device-width">
<title>Debug For XiaoMusic</title>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728246380">
<link rel="stylesheet" type="text/css" href="./style.css?version=1728752616">
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script src="./jquery-3.7.1.min.js?version=1728246380"></script>
<script src="./jquery-3.7.1.min.js?version=1728752616"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>歌曲下载工具</title>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728246380">
<script src="./jquery-3.7.1.min.js?version=1728246380"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728752616">
<script src="./jquery-3.7.1.min.js?version=1728752616"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

@ -4,9 +4,9 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<script src="./jquery-3.7.1.min.js?version=1728246380"></script>
<script src="./app.js?version=1728246380"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728246380">
<script src="./jquery-3.7.1.min.js?version=1728752616"></script>
<script src="./app.js?version=1728752616"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728752616">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

@ -5,7 +5,7 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>M3U to JSON Converter</title>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728246380">
<link rel="stylesheet" type="text/css" href="./style.css?version=1728752616">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

@ -4,9 +4,9 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<script src="./jquery-3.7.1.min.js?version=1728246380"></script>
<script src="./setting.js?version=1728246380"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728246380">
<script src="./jquery-3.7.1.min.js?version=1728752616"></script>
<script src="./setting.js?version=1728752616"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1728752616">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@ -183,6 +183,12 @@ var vConsole = new window.VConsole();
<option value="false" selected>false</option>
</select>
<label for="get_ask_by_mina">特殊型号获取对话记录:</label>
<select id="get_ask_by_mina">
<option value="true">true</option>
<option value="false" selected>false</option>
</select>
<label for="music_list_url">歌单地址:</label>
<input id="music_list_url" type="text" value="https://gist.githubusercontent.com/hanxi/dda82d964a28f8110f8fba81c3ff8314/raw/example.json"></input>

View File

@ -26,6 +26,7 @@ from xiaomusic.config import (
)
from xiaomusic.const import (
COOKIE_TEMPLATE,
GET_ASK_BY_MINA,
LATEST_ASK_API,
PLAY_TYPE_ALL,
PLAY_TYPE_ONE,
@ -175,10 +176,15 @@ class XiaoMusic:
session._cookie_jar = self.cookie_jar
# 拉取所有音箱的对话记录
tasks = [
self.get_latest_ask_from_xiaoai(session, device_id)
for device_id in self.device_id_did
]
tasks = []
for device_id in self.device_id_did:
hardware = self.get_hardward(device_id)
if hardware in GET_ASK_BY_MINA or self.config.get_ask_by_mina:
tasks.append(self.get_latest_ask_by_mina(device_id))
else:
tasks.append(
self.get_latest_ask_from_xiaoai(session, device_id)
)
await asyncio.gather(*tasks)
start = time.perf_counter()
@ -315,6 +321,38 @@ class XiaoMusic:
else:
return self._get_last_query(device_id, data)
async def get_latest_ask_by_mina(self, device_id):
try:
did = self.get_did(device_id)
response = await self.mina_service.ubus_request(
device_id, "nlp_result_get", "mibrain", {}
)
self.log.debug(
f"get_latest_ask_by_mina device_id:{device_id} did:{did} response:{response}"
)
if d := response.get("data", {}).get("info", {}):
result = json.loads(d).get("result", [])
if result and len(result) > 0:
answers = (
json.loads(result[0]["nlp"])
.get("response", {})
.get("answer", [{}])
)
if answers:
query = answers[0].get("intention", {}).get("query", "").strip()
timestamp = result[0]["timestamp"]
answer = answers[0].get("content", {}).get("to_speak")
last_record = {
"time": timestamp,
"did": did,
"query": query,
"answer": answer,
}
self._check_last_query(last_record)
except Exception as e:
self.log.exception(f"get_latest_ask_by_mina {e}")
return
def _get_last_query(self, device_id, data):
did = self.get_did(device_id)
self.log.debug(f"_get_last_query device_id:{device_id} did:{did} data:{data}")
@ -323,15 +361,26 @@ class XiaoMusic:
if not records:
return
last_record = records[0]
timestamp = last_record.get("time")
# 首次用当前时间初始化
if did not in self.last_timestamp:
self.last_timestamp[did] = int(time.time() * 1000)
if timestamp > self.last_timestamp[did]:
self.last_timestamp[did] = timestamp
last_record["did"] = did
self.last_record = last_record
self.new_record_event.set()
last_record["did"] = did
answers = last_record.get("answers", [{}])
if answers:
answer = answers[0].get("tts", {}).get("text", "").strip()
last_record["answer"] = answer
self._check_last_query(last_record)
def _check_last_query(self, last_record):
did = last_record["did"]
timestamp = last_record.get("time")
query = last_record.get("query", "").strip()
self.log.debug(f"获取到最后一条对话记录:{query} {timestamp}")
# 首次用当前时间初始化
if did not in self.last_timestamp:
self.last_timestamp[did] = int(time.time() * 1000)
if timestamp > self.last_timestamp[did]:
self.last_timestamp[did] = timestamp
self.last_record = last_record
self.new_record_event.set()
def get_filename(self, name):
if name not in self.all_music:
@ -662,6 +711,7 @@ class XiaoMusic:
query = new_record.get("query", "").strip()
did = new_record.get("did", "").strip()
await self.do_check_cmd(did, query, False)
answer = new_record.get("answer")
answers = new_record.get("answers", [{}])
if answers:
answer = answers[0].get("tts", {}).get("text", "").strip()