Changed nav bar text to icons
This commit is contained in:
parent
277d6ec271
commit
26ee3fc75c
8 changed files with 91 additions and 30 deletions
|
@ -1,9 +1,27 @@
|
||||||
|
{%
|
||||||
|
with pluginIcons = {
|
||||||
|
'light.hue': 'fa fa-lightbulb',
|
||||||
|
'media.mplayer': 'fa fa-film',
|
||||||
|
'media.mpv': 'fa fa-film',
|
||||||
|
'media.omxplayer': 'fa fa-film',
|
||||||
|
'media.vlc': 'fa fa-film',
|
||||||
|
'music.mpd': 'fa fa-music',
|
||||||
|
'music.snapcast': 'fa fa-volume-up',
|
||||||
|
'tts': 'fa fa-comment',
|
||||||
|
'tts.google': 'fa fa-comment',
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
{% for plugin in plugins|sort %}
|
{% for plugin in plugins|sort %}
|
||||||
<li :class="{selected: '{{ plugin }}' == selectedPlugin}">
|
<li :class="{selected: '{{ plugin }}' == selectedPlugin}" title="{{ plugin }}">
|
||||||
<a href="#{{ plugin }}" @click="selectedPlugin = '{{ plugin }}'">
|
<a href="#{{ plugin }}" @click="selectedPlugin = '{{ plugin }}'">
|
||||||
{{ plugin }}
|
{% if plugin in pluginIcons %}
|
||||||
|
<i class="{{ pluginIcons[plugin] }}"></i>
|
||||||
|
{% else %}
|
||||||
|
{% raw %}{{ plugin }}{{% endraw %}
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -14,3 +32,5 @@
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@ class Plugin(EventGenerator):
|
||||||
.get('action', [])
|
.get('action', [])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run(self, method, *args, **kwargs):
|
def run(self, method, *args, **kwargs):
|
||||||
if method not in self.registered_actions:
|
if method not in self.registered_actions:
|
||||||
raise RuntimeError('{} is not a registered action on {}'.format(
|
raise RuntimeError('{} is not a registered action on {}'.format(
|
||||||
|
|
|
@ -8,10 +8,10 @@ from Adafruit_IO import Client
|
||||||
from Adafruit_IO.errors import ThrottlingError
|
from Adafruit_IO.errors import ThrottlingError
|
||||||
|
|
||||||
from platypush.context import get_backend
|
from platypush.context import get_backend
|
||||||
from platypush.message import Message
|
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
|
||||||
data_throttler_lock = Lock()
|
data_throttler_lock = None
|
||||||
|
|
||||||
|
|
||||||
class AdafruitIoPlugin(Plugin):
|
class AdafruitIoPlugin(Plugin):
|
||||||
"""
|
"""
|
||||||
|
@ -49,7 +49,7 @@ class AdafruitIoPlugin(Plugin):
|
||||||
|
|
||||||
_DATA_THROTTLER_QUEUE = 'platypush/adafruit.io'
|
_DATA_THROTTLER_QUEUE = 'platypush/adafruit.io'
|
||||||
|
|
||||||
def __init__(self, username, key, throttle_seconds=None, *args, **kwargs):
|
def __init__(self, username, key, throttle_seconds=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
:param username: Your Adafruit username
|
:param username: Your Adafruit username
|
||||||
:type username: str
|
:type username: str
|
||||||
|
@ -57,33 +57,39 @@ class AdafruitIoPlugin(Plugin):
|
||||||
:param key: Your Adafruit IO key
|
:param key: Your Adafruit IO key
|
||||||
:type key: str
|
:type key: str
|
||||||
|
|
||||||
:param throttle_seconds: If set, then instead of sending the values directly over ``send`` the plugin will first collect all the samples within the specified period and then dispatch them to Adafruit IO. You may want to set it if you have data sources providing a lot of data points and you don't want to hit the throttling limitations of Adafruit.
|
:param throttle_seconds: If set, then instead of sending the values directly over ``send`` the plugin will
|
||||||
|
first collect all the samples within the specified period and then dispatch them to Adafruit IO.
|
||||||
|
You may want to set it if you have data sources providing a lot of data points and you don't want to hit
|
||||||
|
the throttling limitations of Adafruit.
|
||||||
:type throttle_seconds: float
|
:type throttle_seconds: float
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
global data_throttler_lock
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self._username = username
|
self._username = username
|
||||||
self._key = key
|
self._key = key
|
||||||
self.aio = Client(username=username, key=key)
|
self.aio = Client(username=username, key=key)
|
||||||
self.throttle_seconds = throttle_seconds
|
self.throttle_seconds = throttle_seconds
|
||||||
|
|
||||||
|
if not data_throttler_lock:
|
||||||
|
data_throttler_lock = Lock()
|
||||||
|
|
||||||
if self.throttle_seconds and not data_throttler_lock.locked():
|
if self.throttle_seconds and not data_throttler_lock.locked():
|
||||||
redis = self._get_redis()
|
self._get_redis()
|
||||||
self.logger.info('Starting Adafruit IO throttler thread')
|
self.logger.info('Starting Adafruit IO throttler thread')
|
||||||
data_throttler_lock.acquire(False)
|
data_throttler_lock.acquire(False)
|
||||||
self.data_throttler = Thread(target=self._data_throttler())
|
self.data_throttler = Thread(target=self._data_throttler())
|
||||||
self.data_throttler.start()
|
self.data_throttler.start()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def _get_redis(self):
|
def _get_redis():
|
||||||
from redis import Redis
|
from redis import Redis
|
||||||
|
|
||||||
redis_args = get_backend('redis').redis_args
|
redis_args = get_backend('redis').redis_args
|
||||||
redis_args['socket_timeout'] = 1
|
redis_args['socket_timeout'] = 1
|
||||||
return Redis(**redis_args)
|
return Redis(**redis_args)
|
||||||
|
|
||||||
|
|
||||||
def _data_throttler(self):
|
def _data_throttler(self):
|
||||||
from redis.exceptions import TimeoutError as QueueTimeoutError
|
from redis.exceptions import TimeoutError as QueueTimeoutError
|
||||||
|
|
||||||
|
@ -115,7 +121,8 @@ class AdafruitIoPlugin(Plugin):
|
||||||
try:
|
try:
|
||||||
self.send(feed, value, enqueue=False)
|
self.send(feed, value, enqueue=False)
|
||||||
except ThrottlingError:
|
except ThrottlingError:
|
||||||
self.logger.warning('Adafruit IO throttling threshold hit, taking a nap before retrying')
|
self.logger.warning('Adafruit IO throttling threshold hit, taking a nap ' +
|
||||||
|
'before retrying')
|
||||||
time.sleep(self.throttle_seconds)
|
time.sleep(self.throttle_seconds)
|
||||||
|
|
||||||
data = {}
|
data = {}
|
||||||
|
@ -135,7 +142,9 @@ class AdafruitIoPlugin(Plugin):
|
||||||
:param value: Value to send
|
:param value: Value to send
|
||||||
:type value: Numeric or string
|
:type value: Numeric or string
|
||||||
|
|
||||||
:param enqueue: If throttle_seconds is set, this method by default will append values to the throttling queue to be periodically flushed instead of sending the message directly. In such case, pass enqueue=False to override the behaviour and send the message directly instead.
|
:param enqueue: If throttle_seconds is set, this method by default will append values to the throttling queue
|
||||||
|
to be periodically flushed instead of sending the message directly. In such case, pass enqueue=False to
|
||||||
|
override the behaviour and send the message directly instead.
|
||||||
:type enqueue: bool
|
:type enqueue: bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -145,8 +154,7 @@ class AdafruitIoPlugin(Plugin):
|
||||||
else:
|
else:
|
||||||
# Otherwise send it to the Redis queue to be picked up by the throttler thread
|
# Otherwise send it to the Redis queue to be picked up by the throttler thread
|
||||||
redis = self._get_redis()
|
redis = self._get_redis()
|
||||||
redis.rpush(self._DATA_THROTTLER_QUEUE, json.dumps({feed:value}))
|
redis.rpush(self._DATA_THROTTLER_QUEUE, json.dumps({feed: value}))
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def send_location_data(self, feed, lat, lon, ele, value):
|
def send_location_data(self, feed, lat, lon, ele, value):
|
||||||
|
@ -169,12 +177,19 @@ class AdafruitIoPlugin(Plugin):
|
||||||
:type value: Numeric or string
|
:type value: Numeric or string
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.aio.send_location_data(feed=feed, value=value, lat=lat, lon=lon, ele=ele)
|
self.aio.send_data(feed=feed, value=value, metadata={
|
||||||
|
'lat': lat,
|
||||||
|
'lon': lon,
|
||||||
|
'ele': ele,
|
||||||
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _cast_value(cls, value):
|
def _cast_value(cls, value):
|
||||||
try: value = float(value)
|
try:
|
||||||
except: pass
|
value = float(value)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _convert_data_to_dict(self, *data):
|
def _convert_data_to_dict(self, *data):
|
||||||
|
@ -188,7 +203,6 @@ class AdafruitIoPlugin(Plugin):
|
||||||
} for i in data
|
} for i in data
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def receive(self, feed, limit=1):
|
def receive(self, feed, limit=1):
|
||||||
"""
|
"""
|
||||||
|
@ -243,7 +257,7 @@ class AdafruitIoPlugin(Plugin):
|
||||||
:type feed: str
|
:type feed: str
|
||||||
|
|
||||||
:param data_id: Data point ID to remove
|
:param data_id: Data point ID to remove
|
||||||
:type data_id: int
|
:type data_id: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.aio.delete(feed, data_id)
|
self.aio.delete(feed, data_id)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import time
|
||||||
from platypush.plugins import action
|
from platypush.plugins import action
|
||||||
from platypush.plugins.music import MusicPlugin
|
from platypush.plugins.music import MusicPlugin
|
||||||
|
|
||||||
|
|
||||||
class MusicMpdPlugin(MusicPlugin):
|
class MusicMpdPlugin(MusicPlugin):
|
||||||
"""
|
"""
|
||||||
This plugin allows you to interact with an MPD/Mopidy music server. MPD
|
This plugin allows you to interact with an MPD/Mopidy music server. MPD
|
||||||
|
|
|
@ -29,7 +29,7 @@ class MusicSnapcastPlugin(Plugin):
|
||||||
:type port: int
|
:type port: int
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
|
@ -3,6 +3,7 @@ import urllib.parse
|
||||||
|
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
|
||||||
|
|
||||||
class TtsPlugin(Plugin):
|
class TtsPlugin(Plugin):
|
||||||
"""
|
"""
|
||||||
Default Text-to-Speech plugin. It leverages Google Translate.
|
Default Text-to-Speech plugin. It leverages Google Translate.
|
||||||
|
@ -28,15 +29,13 @@ class TtsPlugin(Plugin):
|
||||||
:type language: str
|
:type language: str
|
||||||
"""
|
"""
|
||||||
if language is None: language=self.lang
|
if language is None: language=self.lang
|
||||||
output = None
|
|
||||||
errors = []
|
|
||||||
cmd = ['mplayer -ao alsa -really-quiet -noconsolecontrols ' +
|
cmd = ['mplayer -ao alsa -really-quiet -noconsolecontrols ' +
|
||||||
'"http://translate.google.com/translate_tts?{}"'
|
'"http://translate.google.com/translate_tts?{}"'
|
||||||
.format(urllib.parse.urlencode({
|
.format(urllib.parse.urlencode({
|
||||||
'ie' : 'UTF-8',
|
'ie': 'UTF-8',
|
||||||
'client' : 'tw-ob',
|
'client': 'tw-ob',
|
||||||
'tl' : language,
|
'tl': language,
|
||||||
'q' : text,
|
'q': text,
|
||||||
}))]
|
}))]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -6,6 +6,7 @@ from google.cloud import texttospeech
|
||||||
|
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
|
||||||
|
|
||||||
class TtsGooglePlugin(Plugin):
|
class TtsGooglePlugin(Plugin):
|
||||||
"""
|
"""
|
||||||
Advanced text-to-speech engine that leverages the Google Cloud TTS API.
|
Advanced text-to-speech engine that leverages the Google Cloud TTS API.
|
||||||
|
|
|
@ -12,6 +12,7 @@ import urllib.request
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_module_and_method_from_action(action):
|
def get_module_and_method_from_action(action):
|
||||||
""" Input : action=music.mpd.play
|
""" Input : action=music.mpd.play
|
||||||
Output : ('music.mpd', 'play') """
|
Output : ('music.mpd', 'play') """
|
||||||
|
@ -19,7 +20,7 @@ def get_module_and_method_from_action(action):
|
||||||
tokens = action.split('.')
|
tokens = action.split('.')
|
||||||
module_name = str.join('.', tokens[:-1])
|
module_name = str.join('.', tokens[:-1])
|
||||||
method_name = tokens[-1:][0]
|
method_name = tokens[-1:][0]
|
||||||
return (module_name, method_name)
|
return module_name, method_name
|
||||||
|
|
||||||
|
|
||||||
def get_message_class_by_type(msgtype):
|
def get_message_class_by_type(msgtype):
|
||||||
|
@ -49,6 +50,32 @@ def get_event_class_by_type(type):
|
||||||
return getattr(event_module, type.split('.')[-1])
|
return getattr(event_module, type.split('.')[-1])
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_module_by_name(plugin_name):
|
||||||
|
""" Gets the module of a plugin by name (e.g. "music.mpd" or "media.vlc") """
|
||||||
|
|
||||||
|
module_name = 'platypush.plugins.' + plugin_name
|
||||||
|
try:
|
||||||
|
return importlib.import_module('platypush.plugins.' + plugin_name)
|
||||||
|
except ImportError as e:
|
||||||
|
logger.error('Cannot import {}: {}'.format(module_name, str(e)))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_class_by_name(plugin_name):
|
||||||
|
""" Gets the class of a plugin by name (e.g. "music.mpd" or "media.vlc") """
|
||||||
|
|
||||||
|
module = get_plugin_module_by_name(plugin_name)
|
||||||
|
if not module:
|
||||||
|
return
|
||||||
|
|
||||||
|
class_name = getattr(module, ''.join([_.capitalize() for _ in plugin_name.split('.')]) + 'Plugin')
|
||||||
|
try:
|
||||||
|
return getattr(module, ''.join([_.capitalize() for _ in plugin_name.split('.')]) + 'Plugin')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error('Cannot import class {}: {}'.format(class_name, str(e)))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def set_timeout(seconds, on_timeout):
|
def set_timeout(seconds, on_timeout):
|
||||||
"""
|
"""
|
||||||
Set a function to be called if timeout expires without being cleared.
|
Set a function to be called if timeout expires without being cleared.
|
||||||
|
|
Loading…
Reference in a new issue