Add voice buttons, Wi-Fi netconfig, and demo STT server
This commit is contained in:
+47
-1
@@ -116,11 +116,55 @@ def _apply_button_latch_reset(btn, data):
|
||||
return btn
|
||||
|
||||
|
||||
def _apply_button_voice(btn, data):
|
||||
"""Apply kind + voice block. Voice buttons disable latch."""
|
||||
kind = (data.get("kind") or btn.get("kind") or "press").strip().lower()
|
||||
if kind not in ("press", "voice"):
|
||||
abort(400, "kind must be press or voice")
|
||||
btn["kind"] = kind
|
||||
if kind != "voice":
|
||||
btn.pop("voice", None)
|
||||
return btn
|
||||
|
||||
voice_in = data.get("voice") if isinstance(data.get("voice"), dict) else {}
|
||||
cancel_url = (voice_in.get("cancelUrl") or data.get("cancelUrl") or "").strip()
|
||||
source_id = (voice_in.get("sourceId") or data.get("sourceId") or "").strip()
|
||||
try:
|
||||
max_record_ms = int(voice_in.get("maxRecordMs", data.get("maxRecordMs", 30000)))
|
||||
except (TypeError, ValueError):
|
||||
abort(400, "maxRecordMs must be an integer")
|
||||
if max_record_ms < 1000 or max_record_ms > 120000:
|
||||
abort(400, "maxRecordMs must be 1000..120000")
|
||||
|
||||
btn["voice"] = {
|
||||
"cancelUrl": cancel_url,
|
||||
"sourceId": source_id or btn.get("id") or "panel-01",
|
||||
"maxRecordMs": max_record_ms,
|
||||
}
|
||||
# Voice uses its own cancel flow — disable latch.
|
||||
btn["latchReset"] = {"enabled": False}
|
||||
action = btn.setdefault("action", {})
|
||||
action["type"] = "http_post"
|
||||
if "timeoutMs" not in action:
|
||||
action["timeoutMs"] = 60000
|
||||
return btn
|
||||
|
||||
|
||||
def _apply_button_action(action, data):
|
||||
action["type"] = data.get("actionType", action.get("type", "http_get"))
|
||||
action["url"] = data.get("url", action.get("url", ""))
|
||||
if "headers" in data:
|
||||
action["headers"] = data["headers"]
|
||||
action["headers"] = data["headers"] if isinstance(data["headers"], dict) else {}
|
||||
if "apiKey" in data:
|
||||
headers = action.setdefault("headers", {})
|
||||
if not isinstance(headers, dict):
|
||||
headers = {}
|
||||
action["headers"] = headers
|
||||
key = (data.get("apiKey") or "").strip()
|
||||
if key:
|
||||
headers["X-API-Key"] = key
|
||||
else:
|
||||
headers.pop("X-API-Key", None)
|
||||
if "body" in data:
|
||||
action["body"] = data["body"]
|
||||
if "timeoutMs" in data:
|
||||
@@ -195,6 +239,7 @@ def api_add_button():
|
||||
"color": data.get("color", "#7b007b"),
|
||||
}
|
||||
_apply_button_latch_reset(btn, data)
|
||||
_apply_button_voice(btn, data)
|
||||
cfg.setdefault("buttons", []).append(btn)
|
||||
save_config(cfg)
|
||||
return jsonify(btn)
|
||||
@@ -228,6 +273,7 @@ def api_update_button(bid):
|
||||
if "color" in data:
|
||||
b["color"] = data["color"]
|
||||
_apply_button_latch_reset(b, data)
|
||||
_apply_button_voice(b, data)
|
||||
save_config(cfg)
|
||||
return jsonify(b)
|
||||
abort(404)
|
||||
|
||||
Reference in New Issue
Block a user