Working on wake websocket
This commit is contained in:
+3
-1
@@ -172,4 +172,6 @@
|
||||
!rhasspy/train/*.py
|
||||
!rhasspy/train/jsgf2fst/*.py
|
||||
!*.py
|
||||
!VERSION
|
||||
!VERSION
|
||||
|
||||
!pip
|
||||
|
||||
@@ -30,7 +30,7 @@ from swagger_ui import quart_api_doc
|
||||
|
||||
from rhasspy.actor import ActorSystem, ConfigureEvent, RhasspyActor
|
||||
from rhasspy.core import RhasspyCore
|
||||
from rhasspy.events import IntentRecognized, ProfileTrainingFailed
|
||||
from rhasspy.events import IntentRecognized, ProfileTrainingFailed, WakeWordDetected
|
||||
from rhasspy.utils import (
|
||||
FunctionLoggingHandler,
|
||||
buffer_to_wav,
|
||||
@@ -698,7 +698,7 @@ async def api_text_to_intent():
|
||||
|
||||
intent_json = json.dumps(intent)
|
||||
logger.debug(intent_json)
|
||||
await add_ws_event(WS_EVENT_INTENT, intent_json)
|
||||
await add_ws_event(WS_EVENT_USER, "intent", intent_json)
|
||||
|
||||
if not no_hass:
|
||||
# Send intent to Home Assistant
|
||||
@@ -734,7 +734,7 @@ async def api_speech_to_intent() -> Response:
|
||||
|
||||
intent_json = json.dumps(intent)
|
||||
logger.debug(intent_json)
|
||||
await add_ws_event(WS_EVENT_INTENT, intent_json)
|
||||
await add_ws_event(WS_EVENT_USER, "intent", intent_json)
|
||||
|
||||
if not no_hass:
|
||||
# Send intent to Home Assistant
|
||||
@@ -780,7 +780,7 @@ async def api_stop_recording() -> Response:
|
||||
|
||||
intent_json = json.dumps(intent)
|
||||
logger.debug(intent_json)
|
||||
await add_ws_event(WS_EVENT_INTENT, intent_json)
|
||||
await add_ws_event(WS_EVENT_USER, "intent", intent_json)
|
||||
|
||||
if not no_hass:
|
||||
# Send intent to Home Assistant
|
||||
@@ -1115,25 +1115,25 @@ async def swagger_yaml() -> Response:
|
||||
# WebSocket API
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
WS_EVENT_INTENT = 0
|
||||
WS_EVENT_USER = 0
|
||||
WS_EVENT_LOG = 1
|
||||
|
||||
ws_queues: List[List[asyncio.Queue]] = [[], []]
|
||||
ws_locks: List[asyncio.Lock] = [asyncio.Lock(), asyncio.Lock()]
|
||||
|
||||
|
||||
async def add_ws_event(event_type: int, text: str):
|
||||
async def add_ws_event(event_type: int, message_type: str, text: str):
|
||||
"""Send text out to all websockets for a specific event."""
|
||||
async with ws_locks[event_type]:
|
||||
for q in ws_queues[event_type]:
|
||||
await q.put(text)
|
||||
await q.put((message_type, text))
|
||||
|
||||
|
||||
# Send logging messages out to websocket
|
||||
logging.root.addHandler(
|
||||
FunctionLoggingHandler(
|
||||
lambda msg: asyncio.run_coroutine_threadsafe(
|
||||
add_ws_event(WS_EVENT_LOG, msg), loop
|
||||
add_ws_event(WS_EVENT_LOG, "log", msg), loop
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -1156,7 +1156,13 @@ class WebSocketObserver(RhasspyActor):
|
||||
intent_json = json.dumps(message.intent)
|
||||
self._logger.debug(intent_json)
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
add_ws_event(WS_EVENT_INTENT, intent_json), loop
|
||||
add_ws_event(WS_EVENT_USER, "intent", intent_json), loop
|
||||
)
|
||||
elif isinstance(message, WakeWordDetected):
|
||||
assert core is not None
|
||||
wake_json = json.dumps({"wakewordId": message.name, "siteId": core.siteId})
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
add_ws_event(WS_EVENT_USER, "wake", wake_json), loop
|
||||
)
|
||||
|
||||
|
||||
@@ -1165,19 +1171,41 @@ async def api_events_intent() -> None:
|
||||
"""Websocket endpoint to receive intents as JSON."""
|
||||
# Add new queue for websocket
|
||||
q: asyncio.Queue = asyncio.Queue()
|
||||
async with ws_locks[WS_EVENT_INTENT]:
|
||||
ws_queues[WS_EVENT_INTENT].append(q)
|
||||
async with ws_locks[WS_EVENT_USER]:
|
||||
ws_queues[WS_EVENT_USER].append(q)
|
||||
|
||||
try:
|
||||
while True:
|
||||
text = await q.get()
|
||||
await websocket.send(text)
|
||||
message_type, text = await q.get()
|
||||
if message_type == "intent":
|
||||
await websocket.send(text)
|
||||
except Exception:
|
||||
logger.exception("api_events_intent")
|
||||
|
||||
# Remove queue
|
||||
async with ws_locks[WS_EVENT_INTENT]:
|
||||
ws_queues[WS_EVENT_INTENT].remove(q)
|
||||
async with ws_locks[WS_EVENT_USER]:
|
||||
ws_queues[WS_EVENT_USER].remove(q)
|
||||
|
||||
|
||||
@app.websocket("/api/events/wake")
|
||||
async def api_events_wake() -> None:
|
||||
"""Websocket endpoint to report wake up."""
|
||||
# Add new queue for websocket
|
||||
q: asyncio.Queue = asyncio.Queue()
|
||||
async with ws_locks[WS_EVENT_USER]:
|
||||
ws_queues[WS_EVENT_USER].append(q)
|
||||
|
||||
try:
|
||||
while True:
|
||||
message_type, text = await q.get()
|
||||
if message_type == "wake":
|
||||
await websocket.send(text)
|
||||
except Exception:
|
||||
logger.exception("api_events_wake")
|
||||
|
||||
# Remove queue
|
||||
async with ws_locks[WS_EVENT_USER]:
|
||||
ws_queues[WS_EVENT_USER].remove(q)
|
||||
|
||||
|
||||
@app.websocket("/api/events/log")
|
||||
@@ -1190,7 +1218,7 @@ async def api_events_log() -> None:
|
||||
|
||||
try:
|
||||
while True:
|
||||
text = await q.get()
|
||||
_, text = await q.get()
|
||||
await websocket.send(text)
|
||||
except concurrent.futures.CancelledError:
|
||||
pass
|
||||
|
||||
@@ -13,6 +13,11 @@ body {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#logo {
|
||||
border-color: red;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.response {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ doit==0.31.1
|
||||
fuzzywuzzy[speedup]==0.17.0
|
||||
google-cloud-texttospeech==0.5.0
|
||||
html5lib==1.0.1
|
||||
json5==0.8.5
|
||||
json5==0.7.0
|
||||
multidict==4.6.1
|
||||
networkx>=2.0
|
||||
num2words==0.5.10
|
||||
@@ -15,6 +15,6 @@ pydash==4.7.6
|
||||
quart==0.6.15
|
||||
quart-cors==0.1.3
|
||||
requests==2.22.0
|
||||
rhasspy-nlu==0.1.4.1
|
||||
rhasspy-nlu==0.1.6
|
||||
swagger-ui-py==0.1.7
|
||||
webrtcvad==2.0.10
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ class RhasspyCore:
|
||||
self._session: Optional[aiohttp.ClientSession] = aiohttp.ClientSession()
|
||||
self.dialogue_manager: Optional[RhasspyActor] = None
|
||||
|
||||
self.download_status: typing.List[str] = []
|
||||
self.download_status: List[str] = []
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
+23
-2
@@ -3,7 +3,7 @@
|
||||
<!-- Top Bar -->
|
||||
<nav class="navbar navbar-expand-sm navbar-dark bg-dark fixed-top">
|
||||
<a href="/">
|
||||
<img class="navbar-brand" v-bind:class="spinnerClass" src="/img/logo.png">
|
||||
<img id="logo" class="navbar-brand" v-bind:class="spinnerClass" src="/img/logo.png">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
@@ -191,7 +191,9 @@
|
||||
|
||||
version: '',
|
||||
|
||||
downloadStatus: ''
|
||||
downloadStatus: '',
|
||||
|
||||
wakeSocket: null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -365,6 +367,24 @@
|
||||
if (this.downloading) {
|
||||
setTimeout(this.updateDownloadStatus, 1000)
|
||||
}
|
||||
},
|
||||
|
||||
connectWakeSocket: function() {
|
||||
// Connect to /api/events/intent websocket
|
||||
var wsProtocol = 'ws://'
|
||||
if (window.location.protocol == 'https:') {
|
||||
wsProtocol = 'wss://'
|
||||
}
|
||||
|
||||
var wsURL = wsProtocol + window.location.host + '/api/events/wake'
|
||||
this.wakeSocket = new WebSocket(wsURL)
|
||||
this.wakeSocket.onmessage = (evt) => {
|
||||
$('#logo').css('border-width', '5px')
|
||||
}
|
||||
this.wakeSocket.onclose = () => {
|
||||
// Try to reconnect
|
||||
setTimeout(this.connectWakeSocket, 1000)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -376,6 +396,7 @@
|
||||
this.getCustomWords()
|
||||
this.getUnknownWords()
|
||||
this.getProblems()
|
||||
/* this.connectWakeSocket() */
|
||||
this.$options.sockets.onmessage = function(event) {
|
||||
this.rhasspyLog = event.data + '\n' + this.rhasspyLog
|
||||
}
|
||||
|
||||
@@ -136,7 +136,9 @@
|
||||
audioContext: null,
|
||||
recorder: null,
|
||||
|
||||
sendHass: true
|
||||
sendHass: true,
|
||||
|
||||
intentSocket: null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -276,7 +278,30 @@
|
||||
playLastVoiceCommand: function(event) {
|
||||
TranscribeService.playRecording()
|
||||
.catch(err => this.$parent.error(err))
|
||||
},
|
||||
|
||||
connectIntentSocket: function() {
|
||||
// Connect to /api/events/intent websocket
|
||||
var wsProtocol = 'ws://'
|
||||
if (window.location.protocol == 'https:') {
|
||||
wsProtocol = 'wss://'
|
||||
}
|
||||
|
||||
var wsURL = wsProtocol + window.location.host + '/api/events/intent'
|
||||
this.intentSocket = new WebSocket(wsURL)
|
||||
this.intentSocket.onmessage = (evt) => {
|
||||
this.jsonSource = JSON.parse(evt.data)
|
||||
this.sentence = this.jsonSource.raw_text
|
||||
}
|
||||
this.intentSocket.onclose = () => {
|
||||
// Try to reconnect
|
||||
setTimeout(this.connectIntentSocket, 1000)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
this.connectIntentSocket()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user