fix: #50 新增配置页面
This commit is contained in:
parent
0d2ba60728
commit
9291676543
@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
import traceback
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from flask import Flask, request, send_from_directory
|
from flask import Flask, request, send_from_directory
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
@ -69,6 +70,29 @@ async def do_cmd():
|
|||||||
return {"ret": "OK"}
|
return {"ret": "OK"}
|
||||||
return {"ret": "Unknow cmd"}
|
return {"ret": "Unknow cmd"}
|
||||||
|
|
||||||
|
@app.route("/getsetting", methods=["GET"])
|
||||||
|
async def getsetting():
|
||||||
|
config = xiaomusic.getconfig()
|
||||||
|
log.debug(config)
|
||||||
|
|
||||||
|
alldevices = await xiaomusic.call_main_thread_function(xiaomusic.getalldevices)
|
||||||
|
log.info(alldevices)
|
||||||
|
data = {
|
||||||
|
"mi_did": config.mi_did,
|
||||||
|
"mi_did_list": alldevices["did_list"],
|
||||||
|
"mi_hardware": config.hardware,
|
||||||
|
"mi_hardware_list": alldevices["hardware_list"],
|
||||||
|
"xiaomusic_search": config.search_prefix,
|
||||||
|
"xiaomusic_proxy": config.proxy,
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
|
@app.route("/savesetting", methods=["POST"])
|
||||||
|
async def savesetting():
|
||||||
|
data = request.get_json()
|
||||||
|
log.info(data)
|
||||||
|
await xiaomusic.saveconfig(data)
|
||||||
|
return "save success"
|
||||||
|
|
||||||
def static_path_handler(filename):
|
def static_path_handler(filename):
|
||||||
log.debug(filename)
|
log.debug(filename)
|
||||||
|
@ -5,59 +5,7 @@
|
|||||||
<title>小爱音箱操控面板</title>
|
<title>小爱音箱操控面板</title>
|
||||||
<script src="/static/jquery-3.7.1.min.js"></script>
|
<script src="/static/jquery-3.7.1.min.js"></script>
|
||||||
<script src="/static/app.js"></script>
|
<script src="/static/app.js"></script>
|
||||||
<style>
|
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||||
button {
|
|
||||||
margin: 10px;
|
|
||||||
width: 100px;
|
|
||||||
height: 50px;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 10px;
|
|
||||||
background-color: #008CBA;
|
|
||||||
}
|
|
||||||
button:active {
|
|
||||||
font-weight:bold;
|
|
||||||
background-color: #007CBA;
|
|
||||||
transform: translateY(2px);
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
margin: 10px;
|
|
||||||
width: 300px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container{
|
|
||||||
width: 280px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
@keyframes text-scroll {
|
|
||||||
0% {
|
|
||||||
left: 100%;
|
|
||||||
}
|
|
||||||
25% {
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
left: 0%;
|
|
||||||
}
|
|
||||||
75% {
|
|
||||||
left: -50%;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: -100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.text {
|
|
||||||
white-space: nowrap;
|
|
||||||
font-weight: bold;
|
|
||||||
position: relative;
|
|
||||||
animation: text-scroll 10s linear infinite;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>小爱音箱操控面板<span id="version">(版本未知)</span></h2>
|
<h2>小爱音箱操控面板<span id="version">(版本未知)</span></h2>
|
||||||
@ -65,10 +13,13 @@
|
|||||||
<div id="cmds">
|
<div id="cmds">
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div style="margin-left: 20px;">
|
<div style="margin: 20px;">
|
||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#8e43e7" style="height: 48px; width: 48px;"><path d="M550.826667 154.666667a47.786667 47.786667 0 0 0-19.84 4.48L298.666667 298.666667H186.453333A80 80 0 0 0 106.666667 378.453333v267.093334A80 80 0 0 0 186.453333 725.333333H298.666667l232.32 139.52a47.786667 47.786667 0 0 0 19.84 4.48A46.506667 46.506667 0 0 0 597.333333 822.826667V201.173333a46.506667 46.506667 0 0 0-46.506666-46.506666zM554.666667 822.826667c0 3.413333-3.84 3.84-3.84 3.84L320 688.853333l-9.6-6.186666H186.453333A37.12 37.12 0 0 1 149.333333 645.546667V378.453333A37.12 37.12 0 0 1 186.453333 341.333333h123.946667l10.24-6.186666 229.546667-137.6s3.84 0 3.84 3.84zM667.52 346.026667a21.333333 21.333333 0 0 0 0 30.293333 192 192 0 0 1 0 271.36 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 234.666667 234.666667 0 0 0 0-331.946666 21.333333 21.333333 0 0 0-30.293333 0z"></path><path d="M804.48 219.52a21.333333 21.333333 0 0 0-30.293333 30.293333 370.986667 370.986667 0 0 1 0 524.373334 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 414.08 414.08 0 0 0 0-584.96z"></path></svg>
|
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#8e43e7" style="height: 48px; width: 48px;"><path d="M550.826667 154.666667a47.786667 47.786667 0 0 0-19.84 4.48L298.666667 298.666667H186.453333A80 80 0 0 0 106.666667 378.453333v267.093334A80 80 0 0 0 186.453333 725.333333H298.666667l232.32 139.52a47.786667 47.786667 0 0 0 19.84 4.48A46.506667 46.506667 0 0 0 597.333333 822.826667V201.173333a46.506667 46.506667 0 0 0-46.506666-46.506666zM554.666667 822.826667c0 3.413333-3.84 3.84-3.84 3.84L320 688.853333l-9.6-6.186666H186.453333A37.12 37.12 0 0 1 149.333333 645.546667V378.453333A37.12 37.12 0 0 1 186.453333 341.333333h123.946667l10.24-6.186666 229.546667-137.6s3.84 0 3.84 3.84zM667.52 346.026667a21.333333 21.333333 0 0 0 0 30.293333 192 192 0 0 1 0 271.36 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 234.666667 234.666667 0 0 0 0-331.946666 21.333333 21.333333 0 0 0-30.293333 0z"></path><path d="M804.48 219.52a21.333333 21.333333 0 0 0-30.293333 30.293333 370.986667 370.986667 0 0 1 0 524.373334 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 414.08 414.08 0 0 0 0-584.96z"></path></svg>
|
||||||
<input id="volume" type="range"></input>
|
<input id="volume" type="range"></input>
|
||||||
|
<a href="/static/setting.html">
|
||||||
|
<svg fill="#8e43e7" height="64px" width="64px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-11.88 -11.88 77.76 77.76" xml:space="preserve" stroke="#8e43e7" transform="rotate(0)matrix(1, 0, 0, 1, 0, 0)" stroke-width="0.00054"><g id="SVGRepo_bgCarrier" stroke-width="0" transform="translate(0,0), scale(1)"><rect x="-11.88" y="-11.88" width="77.76" height="77.76" rx="18.6624" fill="#addcff" strokewidth="0"></rect></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round" stroke="#CCCCCC" stroke-width="1.512"></g><g id="SVGRepo_iconCarrier"> <g> <path d="M51.22,21h-5.052c-0.812,0-1.481-0.447-1.792-1.197s-0.153-1.54,0.42-2.114l3.572-3.571 c0.525-0.525,0.814-1.224,0.814-1.966c0-0.743-0.289-1.441-0.814-1.967l-4.553-4.553c-1.05-1.05-2.881-1.052-3.933,0l-3.571,3.571 c-0.574,0.573-1.366,0.733-2.114,0.421C33.447,9.313,33,8.644,33,7.832V2.78C33,1.247,31.753,0,30.22,0H23.78 C22.247,0,21,1.247,21,2.78v5.052c0,0.812-0.447,1.481-1.197,1.792c-0.748,0.313-1.54,0.152-2.114-0.421l-3.571-3.571 c-1.052-1.052-2.883-1.05-3.933,0l-4.553,4.553c-0.525,0.525-0.814,1.224-0.814,1.967c0,0.742,0.289,1.44,0.814,1.966l3.572,3.571 c0.573,0.574,0.73,1.364,0.42,2.114S8.644,21,7.832,21H2.78C1.247,21,0,22.247,0,23.78v6.439C0,31.753,1.247,33,2.78,33h5.052 c0.812,0,1.481,0.447,1.792,1.197s0.153,1.54-0.42,2.114l-3.572,3.571c-0.525,0.525-0.814,1.224-0.814,1.966 c0,0.743,0.289,1.441,0.814,1.967l4.553,4.553c1.051,1.051,2.881,1.053,3.933,0l3.571-3.572c0.574-0.573,1.363-0.731,2.114-0.42 c0.75,0.311,1.197,0.98,1.197,1.792v5.052c0,1.533,1.247,2.78,2.78,2.78h6.439c1.533,0,2.78-1.247,2.78-2.78v-5.052 c0-0.812,0.447-1.481,1.197-1.792c0.751-0.312,1.54-0.153,2.114,0.42l3.571,3.572c1.052,1.052,2.883,1.05,3.933,0l4.553-4.553 c0.525-0.525,0.814-1.224,0.814-1.967c0-0.742-0.289-1.44-0.814-1.966l-3.572-3.571c-0.573-0.574-0.73-1.364-0.42-2.114 S45.356,33,46.168,33h5.052c1.533,0,2.78-1.247,2.78-2.78V23.78C54,22.247,52.753,21,51.22,21z M52,30.22 C52,30.65,51.65,31,51.22,31h-5.052c-1.624,0-3.019,0.932-3.64,2.432c-0.622,1.5-0.295,3.146,0.854,4.294l3.572,3.571 c0.305,0.305,0.305,0.8,0,1.104l-4.553,4.553c-0.304,0.304-0.799,0.306-1.104,0l-3.571-3.572c-1.149-1.149-2.794-1.474-4.294-0.854 c-1.5,0.621-2.432,2.016-2.432,3.64v5.052C31,51.65,30.65,52,30.22,52H23.78C23.35,52,23,51.65,23,51.22v-5.052 c0-1.624-0.932-3.019-2.432-3.64c-0.503-0.209-1.021-0.311-1.533-0.311c-1.014,0-1.997,0.4-2.761,1.164l-3.571,3.572 c-0.306,0.306-0.801,0.304-1.104,0l-4.553-4.553c-0.305-0.305-0.305-0.8,0-1.104l3.572-3.571c1.148-1.148,1.476-2.794,0.854-4.294 C10.851,31.932,9.456,31,7.832,31H2.78C2.35,31,2,30.65,2,30.22V23.78C2,23.35,2.35,23,2.78,23h5.052 c1.624,0,3.019-0.932,3.64-2.432c0.622-1.5,0.295-3.146-0.854-4.294l-3.572-3.571c-0.305-0.305-0.305-0.8,0-1.104l4.553-4.553 c0.304-0.305,0.799-0.305,1.104,0l3.571,3.571c1.147,1.147,2.792,1.476,4.294,0.854C22.068,10.851,23,9.456,23,7.832V2.78 C23,2.35,23.35,2,23.78,2h6.439C30.65,2,31,2.35,31,2.78v5.052c0,1.624,0.932,3.019,2.432,3.64 c1.502,0.622,3.146,0.294,4.294-0.854l3.571-3.571c0.306-0.305,0.801-0.305,1.104,0l4.553,4.553c0.305,0.305,0.305,0.8,0,1.104 l-3.572,3.571c-1.148,1.148-1.476,2.794-0.854,4.294c0.621,1.5,2.016,2.432,3.64,2.432h5.052C51.65,23,52,23.35,52,23.78V30.22z"></path> <path d="M27,18c-4.963,0-9,4.037-9,9s4.037,9,9,9s9-4.037,9-9S31.963,18,27,18z M27,34c-3.859,0-7-3.141-7-7s3.141-7,7-7 s7,3.141,7,7S30.859,34,27,34z"></path> </g> </g></svg>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
30
xiaomusic/static/setting.html
Normal file
30
xiaomusic/static/setting.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<title>小爱音箱操控面板</title>
|
||||||
|
<script src="/static/jquery-3.7.1.min.js"></script>
|
||||||
|
<script src="/static/setting.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>小爱音箱设置面板<span id="version">(版本未知)</span></h2>
|
||||||
|
<hr>
|
||||||
|
<div class="rows">
|
||||||
|
<label for="mi_did">MI_DID:</label>
|
||||||
|
<select id="mi_did"></select>
|
||||||
|
<label for="mi_hardware">MI_HARDWARE:</label>
|
||||||
|
<select id="mi_hardware"></select>
|
||||||
|
<label for="xiaomusic_search">XIAOMUSIC_SEARCH:</label>
|
||||||
|
<select id="xiaomusic_search">
|
||||||
|
<option value="ytsearch:">ytsearch:</option>
|
||||||
|
<option value="bilisearch:">bilisearch:</option>
|
||||||
|
</select>
|
||||||
|
<label for="xiaomusic_proxy">XIAOMUSIC_PROXY(ytsearch需要):</label>
|
||||||
|
<input id="xiaomusic_proxy" type="text" placeholder="http://192.168.2.5:8080"></input>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<button onclick="location.href='/';">返回首页</button>
|
||||||
|
<button id="save">保存</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
67
xiaomusic/static/setting.js
Normal file
67
xiaomusic/static/setting.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
$(function(){
|
||||||
|
// 拉取现有配置
|
||||||
|
$.get("/getsetting", function(data, status) {
|
||||||
|
console.log(data, status);
|
||||||
|
|
||||||
|
var mi_did_div = $("#mi_did")
|
||||||
|
mi_did_div.empty();
|
||||||
|
$.each(data.mi_did_list, function(index, option){
|
||||||
|
mi_did_div.append($('<option>', {
|
||||||
|
value:option,
|
||||||
|
text:option,
|
||||||
|
}));
|
||||||
|
if (data.mi_did == option) {
|
||||||
|
mi_did_div.val(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var mi_hardware_div = $("#mi_hardware")
|
||||||
|
mi_hardware_div.empty();
|
||||||
|
$.each(data.mi_hardware_list, function(index, option){
|
||||||
|
mi_hardware_div.append($('<option>', {
|
||||||
|
value:option,
|
||||||
|
text:option,
|
||||||
|
}));
|
||||||
|
if (data.mi_hardware == option) {
|
||||||
|
mi_hardware_div.val(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.xiaomusic_search != "") {
|
||||||
|
$("#xiaomusic_search").val(data.xiaomusic_search);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.xiaomusic_proxy != "") {
|
||||||
|
$("#xiaomusic_proxy").val(data.xiaomusic_proxy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#save").on("click", () => {
|
||||||
|
var mi_did = $("#mi_did").val();
|
||||||
|
var mi_hardware = $("#mi_hardware").val();
|
||||||
|
var xiaomusic_search = $("#xiaomusic_search").val();
|
||||||
|
var xiaomusic_proxy = $("#xiaomusic_proxy").val();
|
||||||
|
console.log("mi_did", mi_did);
|
||||||
|
console.log("mi_hardware", mi_hardware);
|
||||||
|
console.log("xiaomusic_search", xiaomusic_search);
|
||||||
|
console.log("xiaomusic_proxy", xiaomusic_proxy);
|
||||||
|
var data = {
|
||||||
|
mi_did: mi_did,
|
||||||
|
mi_hardware: mi_hardware,
|
||||||
|
xiaomusic_search: xiaomusic_search,
|
||||||
|
xiaomusic_proxy: xiaomusic_proxy,
|
||||||
|
};
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: "/savesetting",
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
success: (msg) => {
|
||||||
|
alert(msg);
|
||||||
|
},
|
||||||
|
error: (msg) => {
|
||||||
|
alert(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
64
xiaomusic/static/style.css
Normal file
64
xiaomusic/static/style.css
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
button {
|
||||||
|
margin: 10px;
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #008CBA;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
font-weight:bold;
|
||||||
|
background-color: #007CBA;
|
||||||
|
transform: translateY(2px);
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
input,select {
|
||||||
|
margin: 10px;
|
||||||
|
width: 300px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container{
|
||||||
|
width: 280px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
@keyframes text-scroll {
|
||||||
|
0% {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
left: 0%;
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
left: -50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
left: -100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: bold;
|
||||||
|
position: relative;
|
||||||
|
animation: text-scroll 10s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rows {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -9,6 +9,7 @@ import time
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
import traceback
|
import traceback
|
||||||
import mutagen
|
import mutagen
|
||||||
|
import queue
|
||||||
from xiaomusic.httpserver import StartHTTPServer
|
from xiaomusic.httpserver import StartHTTPServer
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -54,6 +55,7 @@ class XiaoMusic:
|
|||||||
self.miio_service = None
|
self.miio_service = None
|
||||||
self.polling_event = asyncio.Event()
|
self.polling_event = asyncio.Event()
|
||||||
self.new_record_event = asyncio.Event()
|
self.new_record_event = asyncio.Event()
|
||||||
|
self.queue = queue.Queue()
|
||||||
|
|
||||||
self.music_path = config.music_path
|
self.music_path = config.music_path
|
||||||
self.hostname = config.hostname
|
self.hostname = config.hostname
|
||||||
@ -88,6 +90,9 @@ class XiaoMusic:
|
|||||||
self.log.setLevel(logging.DEBUG if config.verbose else logging.INFO)
|
self.log.setLevel(logging.DEBUG if config.verbose else logging.INFO)
|
||||||
self.log.debug(config)
|
self.log.debug(config)
|
||||||
|
|
||||||
|
# 尝试从设置里加载配置
|
||||||
|
self.try_init_setting()
|
||||||
|
|
||||||
# 启动时重新生成一次播放列表
|
# 启动时重新生成一次播放列表
|
||||||
self.gen_all_music_list()
|
self.gen_all_music_list()
|
||||||
|
|
||||||
@ -130,10 +135,7 @@ class XiaoMusic:
|
|||||||
self.mina_service = MiNAService(account)
|
self.mina_service = MiNAService(account)
|
||||||
self.miio_service = MiIOService(account)
|
self.miio_service = MiIOService(account)
|
||||||
|
|
||||||
async def _init_data_hardware(self):
|
async def try_update_device_id(self):
|
||||||
if self.config.cookie:
|
|
||||||
# if use cookie do not need init
|
|
||||||
return
|
|
||||||
hardware_data = await self.mina_service.device_list()
|
hardware_data = await self.mina_service.device_list()
|
||||||
# fix multi xiaoai problems we check did first
|
# fix multi xiaoai problems we check did first
|
||||||
# why we use this way to fix?
|
# why we use this way to fix?
|
||||||
@ -155,6 +157,12 @@ class XiaoMusic:
|
|||||||
raise Exception(
|
raise Exception(
|
||||||
f"we have no hardware: {self.config.hardware} please use `micli mina` to check"
|
f"we have no hardware: {self.config.hardware} please use `micli mina` to check"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _init_data_hardware(self):
|
||||||
|
if self.config.cookie:
|
||||||
|
# if use cookie do not need init
|
||||||
|
return
|
||||||
|
await self.try_update_device_id()
|
||||||
if not self.config.mi_did:
|
if not self.config.mi_did:
|
||||||
devices = await self.miio_service.device_list()
|
devices = await self.miio_service.device_list()
|
||||||
try:
|
try:
|
||||||
@ -412,10 +420,10 @@ class XiaoMusic:
|
|||||||
self.log.info(f"{sec}秒后将会播放下一首")
|
self.log.info(f"{sec}秒后将会播放下一首")
|
||||||
|
|
||||||
async def run_forever(self):
|
async def run_forever(self):
|
||||||
|
StartHTTPServer(self.port, self.music_path, self)
|
||||||
async with ClientSession() as session:
|
async with ClientSession() as session:
|
||||||
self.session = session
|
self.session = session
|
||||||
await self.init_all_data(session)
|
await self.init_all_data(session)
|
||||||
StartHTTPServer(self.port, self.music_path, self)
|
|
||||||
task = asyncio.create_task(self.poll_latest_ask())
|
task = asyncio.create_task(self.poll_latest_ask())
|
||||||
assert task is not None # to keep the reference to task, do not remove this
|
assert task is not None # to keep the reference to task, do not remove this
|
||||||
filtered_keywords = [keyword for keyword in KEY_MATCH_ORDER if "#" not in keyword]
|
filtered_keywords = [keyword for keyword in KEY_MATCH_ORDER if "#" not in keyword]
|
||||||
@ -429,6 +437,15 @@ class XiaoMusic:
|
|||||||
await self.new_record_event.wait()
|
await self.new_record_event.wait()
|
||||||
self.new_record_event.clear()
|
self.new_record_event.clear()
|
||||||
new_record = self.last_record
|
new_record = self.last_record
|
||||||
|
if new_record is None:
|
||||||
|
# 其他线程的函数调用
|
||||||
|
try:
|
||||||
|
func, callback, arg1 = self.queue.get(False)
|
||||||
|
ret = await func(arg1=arg1)
|
||||||
|
callback(ret)
|
||||||
|
except queue.Empty:
|
||||||
|
pass
|
||||||
|
continue
|
||||||
self.polling_event.clear() # stop polling when processing the question
|
self.polling_event.clear() # stop polling when processing the question
|
||||||
query = new_record.get("query", "").strip()
|
query = new_record.get("query", "").strip()
|
||||||
ctrl_panel = new_record.get("ctrl_panel", False)
|
ctrl_panel = new_record.get("ctrl_panel", False)
|
||||||
@ -588,3 +605,77 @@ class XiaoMusic:
|
|||||||
def playingmusic(self):
|
def playingmusic(self):
|
||||||
self.log.debug("playingmusic. cur_music:%s", self.cur_music)
|
self.log.debug("playingmusic. cur_music:%s", self.cur_music)
|
||||||
return self.cur_music
|
return self.cur_music
|
||||||
|
|
||||||
|
# 获取当前配置
|
||||||
|
def getconfig(self):
|
||||||
|
return self.config
|
||||||
|
|
||||||
|
def try_init_setting(self):
|
||||||
|
try:
|
||||||
|
filename = os.path.join(self.music_path, "setting.json")
|
||||||
|
with open(filename) as f:
|
||||||
|
data = json.loads(f.read())
|
||||||
|
self.update_config_from_setting(data)
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.log.info(f"The file {filename} does not exist.")
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.log.warning(f"The file {filename} contains invalid JSON.")
|
||||||
|
|
||||||
|
# 保存配置并重新启动
|
||||||
|
async def saveconfig(self, data):
|
||||||
|
# 默认暂时配置保存到 music 目录下
|
||||||
|
filename = os.path.join(self.music_path, "setting.json")
|
||||||
|
with open(filename, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
self.update_config_from_setting(data)
|
||||||
|
await self.call_main_thread_function(self.reinit)
|
||||||
|
|
||||||
|
def update_config_from_setting(self, data):
|
||||||
|
self.config.mi_did = data["mi_did"]
|
||||||
|
self.config.hardware = data["mi_hardware"]
|
||||||
|
self.config.search_prefix = data["xiaomusic_search"]
|
||||||
|
self.config.proxy = data["xiaomusic_proxy"]
|
||||||
|
|
||||||
|
self.search_prefix = self.config.search_prefix
|
||||||
|
self.proxy = self.config.proxy
|
||||||
|
self.log.info("update_config_from_setting ok. data:%s", data)
|
||||||
|
|
||||||
|
# 重新初始化
|
||||||
|
async def reinit(self, **kwargs):
|
||||||
|
await self.try_update_device_id()
|
||||||
|
self.log.info("reinit success")
|
||||||
|
|
||||||
|
# 获取所有设备
|
||||||
|
async def getalldevices(self, **kwargs):
|
||||||
|
arg1 = kwargs["arg1"]
|
||||||
|
self.log.debug("getalldevices. arg1:%s", arg1)
|
||||||
|
did_list = []
|
||||||
|
hardware_list = []
|
||||||
|
hardware_data = await self.mina_service.device_list()
|
||||||
|
for h in hardware_data:
|
||||||
|
did = h.get("miotDID", "")
|
||||||
|
if did != "":
|
||||||
|
did_list.append(did)
|
||||||
|
hardware = h.get("hardware", "")
|
||||||
|
if h.get("hardware", "") != "":
|
||||||
|
hardware_list.append(hardware)
|
||||||
|
alldevices = {
|
||||||
|
"did_list": did_list,
|
||||||
|
"hardware_list": hardware_list,
|
||||||
|
}
|
||||||
|
return alldevices
|
||||||
|
|
||||||
|
# 用于在web线程里调用
|
||||||
|
# 获取所有设备
|
||||||
|
async def call_main_thread_function(self, func, arg1=None):
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
future = loop.create_future()
|
||||||
|
def callback(ret):
|
||||||
|
nonlocal future
|
||||||
|
loop.call_soon_threadsafe(future.set_result, ret)
|
||||||
|
self.queue.put((func, callback, arg1))
|
||||||
|
self.last_record = None
|
||||||
|
self.new_record_event.set()
|
||||||
|
result = await future
|
||||||
|
return result
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user