Don't trigger the default Assistant response if the phrase matched an internal rule. Also, backends should be easily accessible through a context module (more context variables will be added there)

This commit is contained in:
Fabio Manganiello 2017-12-24 02:35:45 +01:00
parent 939744314e
commit 18830232a4
6 changed files with 67 additions and 37 deletions

View file

@ -7,8 +7,9 @@ from threading import Thread
from .bus import Bus from .bus import Bus
from .config import Config from .config import Config
from .context import register_backends
from .event.processor import EventProcessor from .event.processor import EventProcessor
from .utils import get_or_load_plugin, init_backends, get_module_and_name_from_action from .utils import get_or_load_plugin, get_module_and_name_from_action
from .message.event import Event, StopEvent from .message.event import Event, StopEvent
from .message.request import Request from .message.request import Request
from .message.response import Response from .message.response import Response
@ -105,7 +106,7 @@ class Daemon(object):
self.bus = Bus(on_message=self.on_message()) self.bus = Bus(on_message=self.on_message())
# Initialize the backends and link them to the bus # Initialize the backends and link them to the bus
self.backends = init_backends(bus=self.bus) self.backends = register_backends(bus=self.bus)
# Start the backend threads # Start the backend threads
for backend in self.backends.values(): for backend in self.backends.values():

View file

@ -47,6 +47,10 @@ class AssistantGoogleBackend(Backend):
self.bus.post(SpeechRecognizedEvent(phrase=phrase)) self.bus.post(SpeechRecognizedEvent(phrase=phrase))
def stop_conversation(self):
if self.assistant: self.assistant.stop_conversation()
def send_message(self, msg): def send_message(self, msg):
# Can't send a message on an event source, ignoring # Can't send a message on an event source, ignoring
# TODO Make a class for event sources like these. Event sources # TODO Make a class for event sources like these. Event sources
@ -58,6 +62,7 @@ class AssistantGoogleBackend(Backend):
super().run() super().run()
with Assistant(self.credentials) as assistant: with Assistant(self.credentials) as assistant:
self.assistant = assistant
for event in assistant.start(): for event in assistant.start():
self._process_event(event) self._process_event(event)

View file

@ -0,0 +1,51 @@
import importlib
import functools
from ..config import Config
# Map: backend_name -> backend_instance
backends = {}
# Map: plugin_name -> plugin_instance
plugins = {}
def register_backends(bus=None, **kwargs):
""" Initialize the backend objects based on the configuration and returns
a name -> backend_instance map.
Params:
bus -- If specific (it usually should), the messages processed by the
backends will be posted on this bus.
kwargs -- Any additional key-value parameters required to initialize the backends
"""
global backends
for (name, cfg) in Config.get_backends().items():
module = importlib.import_module('platypush.backend.' + name)
# e.g. backend.pushbullet main class: PushbulletBackend
cls_name = functools.reduce(
lambda a,b: a.title() + b.title(),
(module.__name__.title().split('.')[2:])
) + 'Backend'
try:
b = getattr(module, cls_name)(bus=bus, **cfg, **kwargs)
backends[name] = b
except AttributeError as e:
logging.warning('No such class in {}: {}'.format(
module.__name__, cls_name))
raise RuntimeError(e)
return backends
def get_backend(name):
""" Returns the backend instance identified by name if it exists """
global backends
return backends[name]
# vim:sw=4:ts=4:et:

View file

@ -1,5 +1,6 @@
import re import re
from platypush.context import get_backend
from platypush.message.event import Event from platypush.message.event import Event
class AssistantEvent(Event): class AssistantEvent(Event):
@ -7,6 +8,7 @@ class AssistantEvent(Event):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._assistant = get_backend('assistant.google')
class ConversationStartEvent(AssistantEvent): class ConversationStartEvent(AssistantEvent):
@ -49,7 +51,10 @@ class SpeechRecognizedEvent(AssistantEvent):
else: else:
recognized_tokens.pop(0) recognized_tokens.pop(0)
return [len(condition_tokens) == 0, parsed_args] is_match = len(condition_tokens) == 0
if is_match and self._assistant: self._assistant.stop_conversation()
return [is_match, parsed_args]
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et:

View file

@ -5,8 +5,8 @@ import sys
from platypush.bus import Bus from platypush.bus import Bus
from platypush.config import Config from platypush.config import Config
from platypush.context import register_backends
from platypush.message.request import Request from platypush.message.request import Request
from platypush.utils import init_backends
class Pusher(object): class Pusher(object):
@ -97,7 +97,7 @@ class Pusher(object):
def get_backend(self, name): def get_backend(self, name):
# Lazy init # Lazy init
if not self.backends: if not self.backends:
self.backends = init_backends(bus=self.bus) self.backends = register_backends(bus=self.bus)
if name not in self.backends: if name not in self.backends:
raise RuntimeError('No such backend configured: {}'.format(name)) raise RuntimeError('No such backend configured: {}'.format(name))

View file

@ -42,38 +42,6 @@ def get_or_load_plugin(plugin_name, reload=False):
return plugin return plugin
def init_backends(bus=None, **kwargs):
""" Initialize the backend objects based on the configuration and returns
a name -> backend_instance map.
Params:
bus -- If specific (it usually should), the messages processed by the
backends will be posted on this bus.
kwargs -- Any additional key-value parameters required to initialize the backends
"""
backends = {}
for k in Config.get_backends().keys():
module = importlib.import_module('platypush.backend.' + k)
cfg = Config.get_backends()[k]
# e.g. backend.pushbullet main class: PushbulletBackend
cls_name = functools.reduce(
lambda a,b: a.title() + b.title(),
(module.__name__.title().split('.')[2:])
) + 'Backend'
try:
b = getattr(module, cls_name)(bus=bus, **cfg, **kwargs)
backends[k] = b
except AttributeError as e:
logging.warning('No such class in {}: {}'.format(
module.__name__, cls_name))
raise RuntimeError(e)
return backends
def get_module_and_name_from_action(action): def get_module_and_name_from_action(action):
""" Input : action=music.mpd.play """ Input : action=music.mpd.play
Output : ('music.mpd', 'play') """ Output : ('music.mpd', 'play') """