17 from threading
import Event
20 from .threaded_event_emitter
import ThreadedEventEmitter
21 from websocket
import (WebSocketApp, WebSocketConnectionClosedException,
26 from mycroft.util import validate_param, create_echo_function
31 def __init__(self, host=None, port=None, route=None, ssl=None):
33 config = Configuration.get().
get(
"websocket")
34 host = host
or config.get(
"host")
35 port = port
or config.get(
"port")
36 route = route
or config.get(
"route")
37 ssl = ssl
or config.get(
"ssl")
42 self.
url = WebsocketClient.build_url(host, port, route, ssl)
51 scheme =
"wss" if ssl
else "ws" 52 return scheme +
"://" + host +
":" + str(port) + route
55 return WebSocketApp(self.
url,
61 self.connected_event.set()
62 self.emitter.emit(
"open")
67 self.emitter.emit(
"close")
70 """ On error start trying to reconnect to the websocket. """ 71 if isinstance(error, WebSocketConnectionClosedException):
72 LOG.warning(
'Could not send message because connection has closed')
74 LOG.exception(
'=== ' + repr(error) +
' ===')
77 self.emitter.emit(
'error', error)
78 if self.client.keep_running:
80 except Exception
as e:
81 LOG.error(
'Exception closing websocket: ' + repr(e))
83 LOG.warning(
"WS Client will reconnect in %d seconds." % self.
retry)
84 time.sleep(self.
retry)
87 self.emitter.emit(
'reconnecting')
90 except WebSocketException:
94 parsed_message = Message.deserialize(message)
95 self.emitter.emit(
'message', message)
96 self.emitter.emit(parsed_message.type, parsed_message)
99 if not self.connected_event.wait(10):
101 raise ValueError(
'You must execute run_forever() ' 102 'before emitting messages')
103 self.connected_event.wait()
106 if hasattr(message,
'serialize'):
107 self.client.send(message.serialize())
109 self.client.send(json.dumps(message.__dict__))
110 except WebSocketConnectionClosedException:
111 LOG.warning(
'Could not send {} message because connection ' 112 'has been closed'.format(message.type))
115 """Send a message and wait for a response. 118 message (Message): message to send 119 reply_type (str): the message type of the expected reply. 120 Defaults to "<message.type>.response". 121 timeout: seconds to wait before timeout, defaults to 3 123 The received message or None if the response timed out 127 def handler(message):
128 """Receive response data.""" 129 response.append(message)
132 self.
once(reply_type
or message.type +
'.response', handler)
136 start_time = time.monotonic()
137 while len(response) == 0:
139 if time.monotonic() - start_time > (timeout
or 3.0):
141 self.
remove(reply_type, handler)
142 except (ValueError, KeyError):
151 def on(self, event_name, func):
152 self.emitter.on(event_name, func)
154 def once(self, event_name, func):
155 self.emitter.once(event_name, func)
159 if event_name
in self.emitter._events:
160 LOG.debug(
"Removing found '"+str(event_name)+
"'")
162 LOG.debug(
"Not able to find '"+str(event_name)+
"'")
163 self.emitter.remove_listener(event_name, func)
165 LOG.warning(
'Failed to remove event {}: {}'.format(event_name,
167 for line
in traceback.format_stack():
168 LOG.warning(line.strip())
170 if event_name
in self.emitter._events:
171 LOG.debug(
"Removing found '"+str(event_name)+
"'")
173 LOG.debug(
"Not able to find '"+str(event_name)+
"'")
174 LOG.warning(
"Existing events: " + str(self.emitter._events))
175 for evt
in self.emitter._events:
176 LOG.warning(
" "+str(evt))
177 LOG.warning(
" "+str(self.emitter._events[evt]))
178 if event_name
in self.emitter._events:
179 LOG.debug(
"Removing found '"+str(event_name)+
"'")
181 LOG.debug(
"Not able to find '"+str(event_name)+
"'")
182 LOG.warning(
'----- End dump -----')
186 Remove all listeners connected to event_name. 189 event_name: event from which to remove listeners 191 if event_name
is None:
193 self.emitter.remove_all_listeners(event_name)
197 self.client.run_forever()
201 self.connected_event.clear()
207 def repeat_utterance(message):
208 message.type =
'speak' 212 ws.on(
'recognizer_loop:utterance', repeat_utterance)
216 if __name__ ==
"__main__":
def wait_for_response(self, message, reply_type=None, timeout=None)
def once(self, event_name, func)
def remove(self, event_name, func)
def validate_param(value, name)
def remove_all_listeners(self, event_name)
def build_url(host, port, route, ssl)
def create_echo_function(name, whitelist=None)
def on_message(self, message)
def on(self, event_name, func)
def __init__(self, host=None, port=None, route=None, ssl=None)
def on_error(self, error)
def get(phrase, lang=None, context=None)