Completed documentation for plugins
This commit is contained in:
parent
1cbef67f2c
commit
b876f17f81
23 changed files with 661 additions and 16 deletions
6
docs/source/platypush/plugins/pushbullet.rst
Normal file
6
docs/source/platypush/plugins/pushbullet.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.pushbullet``
|
||||
================================
|
||||
|
||||
.. automodule:: platypush.plugins.pushbullet
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/redis.rst
Normal file
6
docs/source/platypush/plugins/redis.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.redis``
|
||||
===========================
|
||||
|
||||
.. automodule:: platypush.plugins.redis
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/serial.rst
Normal file
6
docs/source/platypush/plugins/serial.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.serial``
|
||||
============================
|
||||
|
||||
.. automodule:: platypush.plugins.serial
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/shell.rst
Normal file
6
docs/source/platypush/plugins/shell.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.shell``
|
||||
===========================
|
||||
|
||||
.. automodule:: platypush.plugins.shell
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/switch.rst
Normal file
6
docs/source/platypush/plugins/switch.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.switch``
|
||||
============================
|
||||
|
||||
.. automodule:: platypush.plugins.switch
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/switch.switchbot.rst
Normal file
6
docs/source/platypush/plugins/switch.switchbot.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.switch.switchbot``
|
||||
======================================
|
||||
|
||||
.. automodule:: platypush.plugins.switch.switchbot
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/switch.wemo.rst
Normal file
6
docs/source/platypush/plugins/switch.wemo.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.switch.wemo``
|
||||
=================================
|
||||
|
||||
.. automodule:: platypush.plugins.switch.wemo
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/tts.rst
Normal file
6
docs/source/platypush/plugins/tts.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.tts``
|
||||
=========================
|
||||
|
||||
.. automodule:: platypush.plugins.tts
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/variable.rst
Normal file
6
docs/source/platypush/plugins/variable.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.variable``
|
||||
==============================
|
||||
|
||||
.. automodule:: platypush.plugins.variable
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/video.omxplayer.rst
Normal file
6
docs/source/platypush/plugins/video.omxplayer.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.video.omxplayer``
|
||||
=====================================
|
||||
|
||||
.. automodule:: platypush.plugins.video.omxplayer
|
||||
:members:
|
||||
|
6
docs/source/platypush/plugins/weather.forecast.rst
Normal file
6
docs/source/platypush/plugins/weather.forecast.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
``platypush.plugins.weather.forecast``
|
||||
======================================
|
||||
|
||||
.. automodule:: platypush.plugins.weather.forecast
|
||||
:members:
|
||||
|
|
@ -26,4 +26,15 @@ Plugins
|
|||
platypush/plugins/midi.rst
|
||||
platypush/plugins/mqtt.rst
|
||||
platypush/plugins/music.mpd.rst
|
||||
platypush/plugins/pushbullet.rst
|
||||
platypush/plugins/redis.rst
|
||||
platypush/plugins/serial.rst
|
||||
platypush/plugins/shell.rst
|
||||
platypush/plugins/switch.rst
|
||||
platypush/plugins/switch.switchbot.rst
|
||||
platypush/plugins/switch.wemo.rst
|
||||
platypush/plugins/tts.rst
|
||||
platypush/plugins/variable.rst
|
||||
platypush/plugins/video.omxplayer.rst
|
||||
platypush/plugins/weather.forecast.rst
|
||||
|
||||
|
|
|
@ -8,7 +8,24 @@ from platypush.plugins import Plugin
|
|||
|
||||
|
||||
class PushbulletPlugin(Plugin):
|
||||
"""
|
||||
This plugin allows you to send pushes and files to your PushBullet account.
|
||||
Note: This plugin will only work if the :mod:`platypush.backend.pushbullet`
|
||||
backend is configured.
|
||||
|
||||
Requires:
|
||||
|
||||
* **requests** (``pip install requests``)
|
||||
"""
|
||||
|
||||
def send_push(self, **kwargs):
|
||||
"""
|
||||
Send a push.
|
||||
|
||||
:param kwargs: Push arguments, see https://docs.pushbullet.com/#create-push
|
||||
:type kwargs: dict
|
||||
"""
|
||||
|
||||
pushbullet = get_backend('pushbullet')
|
||||
resp = requests.post('https://api.pushbullet.com/v2/ephemerals',
|
||||
data=json.dumps({
|
||||
|
@ -27,6 +44,13 @@ class PushbulletPlugin(Plugin):
|
|||
|
||||
|
||||
def send_file(self, filename):
|
||||
"""
|
||||
Send a file.
|
||||
|
||||
:param filename: Path to the local file
|
||||
:type filename: str
|
||||
"""
|
||||
|
||||
pushbullet = get_backend('pushbullet')
|
||||
resp = requests.post('https://api.pushbullet.com/v2/upload-request',
|
||||
data=json.dumps({'file_name': os.path.basename(filename)}),
|
||||
|
|
|
@ -5,7 +5,31 @@ from platypush.plugins import Plugin
|
|||
|
||||
|
||||
class RedisPlugin(Plugin):
|
||||
"""
|
||||
Plugin to send messages on Redis queues.
|
||||
|
||||
Requires:
|
||||
|
||||
* **redis** (``pip install redis``)
|
||||
"""
|
||||
|
||||
def send_message(self, queue, msg, *args, **kwargs):
|
||||
"""
|
||||
Send a message to a Redis queu.
|
||||
|
||||
:param queue: Queue name
|
||||
:type queue: str
|
||||
|
||||
:param msg: Message to be sent
|
||||
:type msg: str, bytes, list, dict, Message object
|
||||
|
||||
:param args: Args passed to the Redis constructor (see https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
||||
:type args: list
|
||||
|
||||
:param kwargs: Kwargs passed to the Redis constructor (see https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
||||
:type kwargs: dict
|
||||
"""
|
||||
|
||||
redis = Redis(*args, **kwargs)
|
||||
redis.rpush(queue, msg)
|
||||
return Response(output={'state': 'ok'})
|
||||
|
|
|
@ -17,6 +17,14 @@ class SerialPlugin(Plugin):
|
|||
"""
|
||||
|
||||
def __init__(self, device, baud_rate=9600, *args, **kwargs):
|
||||
"""
|
||||
:param device: Device path (e.g. ``/dev/ttyUSB0`` or ``/dev/ttyACM0``)
|
||||
:type device: str
|
||||
|
||||
:param baud_rate: Serial baud rate (default: 9600)
|
||||
:type baud_rate: int
|
||||
"""
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.device = device
|
||||
|
@ -53,6 +61,10 @@ class SerialPlugin(Plugin):
|
|||
return output.decode().strip()
|
||||
|
||||
def get_data(self):
|
||||
"""
|
||||
Reads JSON data from the serial device and returns it as a message
|
||||
"""
|
||||
|
||||
ser = serial.Serial(self.device, self.baud_rate)
|
||||
|
||||
try:
|
||||
|
|
|
@ -5,7 +5,20 @@ from platypush.message.response import Response
|
|||
from .. import Plugin
|
||||
|
||||
class ShellPlugin(Plugin):
|
||||
"""
|
||||
Plugin to run custom shell commands.
|
||||
"""
|
||||
|
||||
def exec(self, cmd):
|
||||
"""
|
||||
Execute a command.
|
||||
|
||||
:param cmd: Command to execute
|
||||
:type cmd: str
|
||||
|
||||
:returns: A response object where the ``output`` field will contain the command output as a string, and the ``errors`` field will contain whatever was sent to stderr.
|
||||
"""
|
||||
|
||||
output = None
|
||||
errors = []
|
||||
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
from .. import Plugin
|
||||
|
||||
class SwitchPlugin(Plugin):
|
||||
"""
|
||||
Abstract class for interacting with switch devices
|
||||
"""
|
||||
|
||||
def on(self, args):
|
||||
""" Turn the device on """
|
||||
raise NotImplementedError()
|
||||
|
||||
def off(self, args):
|
||||
""" Turn the device off """
|
||||
raise NotImplementedError()
|
||||
|
||||
def toggle(self, args):
|
||||
""" Toggle the device status (on/off) """
|
||||
raise NotImplementedError()
|
||||
|
||||
def status(self):
|
||||
""" Get the device state """
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
|
|
@ -80,15 +80,38 @@ class Driver(object):
|
|||
|
||||
class SwitchSwitchbotPlugin(SwitchPlugin):
|
||||
"""
|
||||
Plugin to interact with a Switchbot (https://www.switch-bot.com/) device and
|
||||
programmatically control buttons.
|
||||
|
||||
NOTE: since the interaction with the Switchbot requires root privileges
|
||||
(in order to scan on the bluetooth interface or setting gattlib in random),
|
||||
this plugin just wraps the module into a `sudo` flavor, since running
|
||||
Platypush with root privileges should be considered as a very bad idea.
|
||||
Make sure that your user has sudo privileges for running this bit of code.
|
||||
Make sure that your user has sudo privileges for running this plugin.
|
||||
|
||||
Requires:
|
||||
|
||||
* **pybluez** (``pip install pybluez``)
|
||||
* **gattlib** (``pip install gattlib``)
|
||||
* **libboost** (on Debian ```apt-get install libboost-python-dev libboost-thread-dev``)
|
||||
"""
|
||||
|
||||
def __init__(self, bt_interface=None, connect_timeout=None,
|
||||
scan_timeout=None, devices={}, *args, **kwargs):
|
||||
"""
|
||||
:param bt_interface: Bluetooth interface to use (e.g. hci0) default: first available one
|
||||
:type bt_interface: str
|
||||
|
||||
:param connecct_timeout: Timeout for the conncection to the Switchbot device - default: None
|
||||
:type connect_timeout: float
|
||||
|
||||
:param scan_timeout: Timeout for the scan operations - default: None
|
||||
:type scan_timeout: float
|
||||
|
||||
:param devices: Devices to control, as a BMAC address -> name map
|
||||
:type devices: dict
|
||||
"""
|
||||
|
||||
self.bt_interface = bt_interface
|
||||
self.connect_timeout = connect_timeout if connect_timeout else 5
|
||||
self.scan_timeout = scan_timeout if scan_timeout else 2
|
||||
|
@ -118,15 +141,34 @@ class SwitchSwitchbotPlugin(SwitchPlugin):
|
|||
|
||||
|
||||
def press(self, device):
|
||||
"""
|
||||
Send a press button command to a device
|
||||
|
||||
:param device: Device name or address
|
||||
:type device: str
|
||||
"""
|
||||
return self._run(device)
|
||||
|
||||
def on(self, device):
|
||||
"""
|
||||
Send a press-on button command to a device
|
||||
|
||||
:param device: Device name or address
|
||||
:type device: str
|
||||
"""
|
||||
return self._run(device, 'on')
|
||||
|
||||
def off(self, device):
|
||||
"""
|
||||
Send a press-off button command to a device
|
||||
|
||||
:param device: Device name or address
|
||||
:type device: str
|
||||
"""
|
||||
return self._run(device, 'off')
|
||||
|
||||
def scan(self):
|
||||
""" Scan for available Switchbot devices nearby """
|
||||
output = None
|
||||
errors = []
|
||||
|
||||
|
@ -145,5 +187,6 @@ class SwitchSwitchbotPlugin(SwitchPlugin):
|
|||
|
||||
return Response(output=output, errors=errors)
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
||||
|
|
|
@ -6,7 +6,20 @@ from platypush.message.response import Response
|
|||
from .. import SwitchPlugin
|
||||
|
||||
class SwitchWemoPlugin(SwitchPlugin):
|
||||
"""
|
||||
Plugin to control a Belkin WeMo smart switch
|
||||
(https://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/)
|
||||
|
||||
Requires:
|
||||
|
||||
* **ouimeaux** (``pip install ouimeaux``)
|
||||
"""
|
||||
|
||||
def __init__(self, discovery_seconds=3, *args, **kwargs):
|
||||
"""
|
||||
:param discovery_seconds: Discovery time when scanning for devices (default: 3)
|
||||
:type discovery_seconds: int
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.discovery_seconds=discovery_seconds
|
||||
|
@ -15,11 +28,34 @@ class SwitchWemoPlugin(SwitchPlugin):
|
|||
self.refresh_devices()
|
||||
|
||||
def refresh_devices(self):
|
||||
""" Update the list of available devices """
|
||||
self.logger.info('Starting WeMo discovery')
|
||||
self.env.discover(seconds=self.discovery_seconds)
|
||||
self.devices = self.env.devices
|
||||
|
||||
def get_devices(self):
|
||||
"""
|
||||
Get the list of available devices
|
||||
:returns: The list of devices.
|
||||
|
||||
Example output::
|
||||
|
||||
output = {
|
||||
"devices": [
|
||||
{
|
||||
"host": "192.168.1.123",
|
||||
"name": "Switch 1",
|
||||
"state": 1,
|
||||
"model": "Belkin Plugin Socket 1.0",
|
||||
"serialnumber": "123456ABCDEF"
|
||||
},
|
||||
|
||||
{
|
||||
# ...
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
self.refresh_devices()
|
||||
return Response(
|
||||
output = { 'devices': [
|
||||
|
@ -49,12 +85,30 @@ class SwitchWemoPlugin(SwitchPlugin):
|
|||
return Response(output=json.dumps(resp))
|
||||
|
||||
def on(self, device):
|
||||
"""
|
||||
Turn a switch on
|
||||
|
||||
:param device: Device name
|
||||
:type device: str
|
||||
"""
|
||||
return self._exec('on', device)
|
||||
|
||||
def off(self, device):
|
||||
"""
|
||||
Turn a switch off
|
||||
|
||||
:param device: Device name
|
||||
:type device: str
|
||||
"""
|
||||
return self._exec('off', device)
|
||||
|
||||
def toggle(self, device):
|
||||
"""
|
||||
Toggle the state of a switch (on/off)
|
||||
|
||||
:param device: Device name
|
||||
:type device: str
|
||||
"""
|
||||
return self._exec('toggle', device)
|
||||
|
||||
|
||||
|
|
|
@ -6,14 +6,28 @@ from platypush.message.response import Response
|
|||
from .. import Plugin
|
||||
|
||||
class TtsPlugin(Plugin):
|
||||
""" Default Text-to-Speech plugin. It leverages Google Translate and
|
||||
requires mplayer """
|
||||
"""
|
||||
Default Text-to-Speech plugin. It leverages Google Translate.
|
||||
|
||||
Requires:
|
||||
|
||||
* **mplayer** - see your distribution docs on how to install the mplayer package
|
||||
"""
|
||||
|
||||
def __init__(self, lang='en-gb'):
|
||||
super().__init__()
|
||||
self.lang=lang
|
||||
|
||||
def say(self, phrase, lang=None):
|
||||
"""
|
||||
Say a phrase
|
||||
|
||||
:param phrase: Phrase to say
|
||||
:type phrase: str
|
||||
|
||||
:param lang: Language code
|
||||
:type lang: str
|
||||
"""
|
||||
if lang is None: lang=self.lang
|
||||
output = None
|
||||
errors = []
|
||||
|
@ -34,5 +48,6 @@ class TtsPlugin(Plugin):
|
|||
|
||||
return Response(output=output, errors=errors)
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
||||
|
|
|
@ -13,14 +13,37 @@ class VariablePlugin(Plugin):
|
|||
self._variables = {}
|
||||
|
||||
def get(self, name, default_value=None):
|
||||
"""
|
||||
Get the value of a variable by name.
|
||||
|
||||
:param name: Variable name
|
||||
:type name: str
|
||||
|
||||
:param default_value: What will be returned if the variable is not defined (default: None)
|
||||
|
||||
:returns: A map in the format ``{"<name>":"<value>"}``
|
||||
"""
|
||||
|
||||
return Response(output={name: self._variables.get(name, default_value)})
|
||||
|
||||
def set(self, **kwargs):
|
||||
"""
|
||||
Set a variable or a set of variables.
|
||||
|
||||
:param kwargs: Key-value list of variables to set (e.g. ``foo='bar', answer=42``)
|
||||
"""
|
||||
|
||||
for (name, value) in kwargs.items():
|
||||
self._variables[name] = value
|
||||
return Response(output=kwargs)
|
||||
|
||||
def unset(self, name):
|
||||
"""
|
||||
Unset a variable by name if it's set
|
||||
|
||||
:param name: Name of the variable to remove
|
||||
:type name: str
|
||||
"""
|
||||
if name in self._variables:
|
||||
del self._variables[name]
|
||||
return Response(output={'status':'ok'})
|
||||
|
|
|
@ -19,6 +19,22 @@ from platypush.message.event.video import VideoPlayEvent, VideoPauseEvent, \
|
|||
from .. import Plugin
|
||||
|
||||
class VideoOmxplayerPlugin(Plugin):
|
||||
"""
|
||||
Plugin to control video and media playback on your Raspberry Pi or
|
||||
ARM-compatible device using OMXPlayer.
|
||||
|
||||
It can play local files, remote URLs, YouTube URLs and it supports torrents
|
||||
search, download and play.
|
||||
|
||||
Requires:
|
||||
|
||||
* **omxplayer** installed on your system (see your distro instructions)
|
||||
* **omxplayer-wrapper** (``pip install omxplayer-wrapper``)
|
||||
* **python-libtorrent** (``pip install python-libtorrent``), optional for Torrent support
|
||||
* **youtube-dl** installed on your system (see your distro instructions), optional for YouTube support
|
||||
"""
|
||||
|
||||
""" Supported video extensions """
|
||||
video_extensions = {
|
||||
'.avi', '.flv', '.wmv', '.mov', '.mp4', '.m4v', '.mpg', '.mpeg',
|
||||
'.rm', '.swf', '.vob', '.mkv'
|
||||
|
@ -28,6 +44,20 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
torrent_state = {}
|
||||
|
||||
def __init__(self, args=[], media_dirs=[], download_dir=None, torrent_ports=[], *argv, **kwargs):
|
||||
"""
|
||||
:param args: Arguments that will be passed to the OMXPlayer constructor (e.g. subtitles, volume, start position, window size etc.) see https://github.com/popcornmix/omxplayer#synopsis and http://python-omxplayer-wrapper.readthedocs.io/en/latest/omxplayer/#omxplayer.player.OMXPlayer
|
||||
:type args: list
|
||||
|
||||
:param media_dirs: Directories that will be scanned for media files when a search is performed (default: none)
|
||||
:type media_dirs: list
|
||||
|
||||
:param download_dir: Directory where the videos/torrents will be downloaded (default: none)
|
||||
:type download_dir: str
|
||||
|
||||
:param torrent_ports: Torrent ports to listen on (default: 6881 and 6891)
|
||||
:type torrent_ports: list[int]
|
||||
"""
|
||||
|
||||
super().__init__(*argv, **kwargs)
|
||||
|
||||
self.args = args
|
||||
|
@ -54,6 +84,17 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
self.torrent_ports = torrent_ports if torrent_ports else self.default_torrent_ports
|
||||
|
||||
def play(self, resource):
|
||||
"""
|
||||
Play a resource.
|
||||
|
||||
:param resource: Resource to play. Supported types:
|
||||
|
||||
* Local files (format: ``file://<path>/<file>``)
|
||||
* Remote videos (format: ``https://<url>/<resource>``)
|
||||
* YouTube videos (format: ``https://www.youtube.com/watch?v=<id>``)
|
||||
* Torrents (format: ``magnet:?<magnet_uri>``)
|
||||
"""
|
||||
|
||||
if resource.startswith('youtube:') \
|
||||
or resource.startswith('https://www.youtube.com/watch?v='):
|
||||
resource = self._get_youtube_content(resource)
|
||||
|
@ -90,9 +131,11 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
return self.status()
|
||||
|
||||
def pause(self):
|
||||
""" Pause the playback """
|
||||
if self.player: self.player.play_pause()
|
||||
|
||||
def stop(self):
|
||||
""" Stop the playback """
|
||||
if self.player:
|
||||
self.player.stop()
|
||||
self.player.quit()
|
||||
|
@ -101,26 +144,31 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
return self.status()
|
||||
|
||||
def voldown(self):
|
||||
""" Volume down by 10% """
|
||||
if self.player:
|
||||
self.player.set_volume(max(-6000, self.player.volume()-1000))
|
||||
return self.status()
|
||||
|
||||
def volup(self):
|
||||
""" Volume up by 10% """
|
||||
if self.player:
|
||||
self.player.set_volume(min(0, self.player.volume()+1000))
|
||||
return self.status()
|
||||
|
||||
def back(self):
|
||||
""" Back by 30 seconds """
|
||||
if self.player:
|
||||
self.player.seek(-30)
|
||||
return self.status()
|
||||
|
||||
def forward(self):
|
||||
""" Forward by 30 seconds """
|
||||
if self.player:
|
||||
self.player.seek(+30)
|
||||
return self.status()
|
||||
|
||||
def next(self):
|
||||
""" Play the next track/video """
|
||||
if self.player:
|
||||
self.player.stop()
|
||||
|
||||
|
@ -132,48 +180,103 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
|
||||
|
||||
def hide_subtitles(self):
|
||||
""" Hide the subtitles """
|
||||
if self.player: self.player.hide_subtitles()
|
||||
return self.status()
|
||||
|
||||
def hide_video(self):
|
||||
""" Hide the video """
|
||||
if self.player: self.player.hide_video()
|
||||
return self.status()
|
||||
|
||||
def is_playing(self):
|
||||
"""
|
||||
:returns: True if it's playing, False otherwise
|
||||
"""
|
||||
|
||||
if self.player: return self.player.is_playing()
|
||||
else: return False
|
||||
|
||||
def load(self, source, pause=False):
|
||||
if self.player: self.player.load(source, pause)
|
||||
def load(self, resource, pause=False):
|
||||
"""
|
||||
Load a resource/video in the player.
|
||||
|
||||
:param pause: If set, load the video in paused mode (default: False)
|
||||
:type pause: bool
|
||||
"""
|
||||
|
||||
if self.player: self.player.load(resource, pause)
|
||||
return self.status()
|
||||
|
||||
def metadata(self):
|
||||
""" Get the metadata of the current video """
|
||||
if self.player: return Response(output=self.player.metadata())
|
||||
return self.status()
|
||||
|
||||
def mute(self):
|
||||
""" Mute the player """
|
||||
if self.player: self.player.mute()
|
||||
return self.status()
|
||||
|
||||
def unmute(self):
|
||||
""" Unmute the player """
|
||||
if self.player: self.player.unmute()
|
||||
return self.status()
|
||||
|
||||
def seek(self, relative_position):
|
||||
"""
|
||||
Seek backward/forward by the specified number of seconds
|
||||
|
||||
:param relative_position: Number of seconds relative to the current cursor
|
||||
:type relative_position: int
|
||||
"""
|
||||
|
||||
if self.player: self.player.seek(relative_position)
|
||||
return self.status()
|
||||
|
||||
def set_position(self, position):
|
||||
"""
|
||||
Seek backward/forward to the specified absolute position
|
||||
|
||||
:param position: Number of seconds from the start
|
||||
:type position: int
|
||||
"""
|
||||
|
||||
if self.player: self.player.set_seek(position)
|
||||
return self.status()
|
||||
|
||||
def set_volume(self, volume):
|
||||
"""
|
||||
Set the volume
|
||||
|
||||
:param volume: Volume value between 0 and 100
|
||||
:type volume: int
|
||||
"""
|
||||
|
||||
# Transform a [0,100] value to an OMXPlayer volume in [-6000,0]
|
||||
volume = 60.0*volume - 6000
|
||||
if self.player: self.player.set_volume(volume)
|
||||
return self.status()
|
||||
|
||||
def status(self):
|
||||
"""
|
||||
Get the current player state.
|
||||
|
||||
:returns: A dictionary containing the current state.
|
||||
|
||||
Example::
|
||||
|
||||
output = {
|
||||
"source": "https://www.youtube.com/watch?v=7L9KkZoNZkA",
|
||||
"state": "play",
|
||||
"volume": 80,
|
||||
"elapsed": 123,
|
||||
"duration": 300,
|
||||
"width": 800,
|
||||
"height": 600
|
||||
}
|
||||
"""
|
||||
|
||||
state = PlayerState.STOP.value
|
||||
|
||||
if self.player:
|
||||
|
@ -233,6 +336,22 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
self.player.stopEvent += self.on_stop()
|
||||
|
||||
def search(self, query, types=None, queue_results=False, autoplay=False):
|
||||
"""
|
||||
Perform a video search.
|
||||
|
||||
:param query: Query string, video name or partial name
|
||||
:type query: str
|
||||
|
||||
:param types: Video types to search (default: ``["youtube", "file", "torrent"]``)
|
||||
:type types: list
|
||||
|
||||
:param queue_results: Append the results to the current playing queue (default: False)
|
||||
:type queue_results: bool
|
||||
|
||||
:param autoplay: Play the first result of the search (default: False)
|
||||
:type autoplay: bool
|
||||
"""
|
||||
|
||||
results = []
|
||||
if types is None:
|
||||
types = { 'youtube', 'file', 'torrent' }
|
||||
|
@ -360,6 +479,13 @@ class VideoOmxplayerPlugin(Plugin):
|
|||
return Response(output=results)
|
||||
|
||||
def download_torrent(self, magnet):
|
||||
"""
|
||||
Download a torrent to ``download_dir`` by Magnet URI
|
||||
|
||||
:param magnet: Magnet URI
|
||||
:type magnet: str
|
||||
"""
|
||||
|
||||
import libtorrent as lt
|
||||
|
||||
if not self.download_dir:
|
||||
|
|
|
@ -3,27 +3,253 @@ from platypush.plugins.http.request import HttpRequestPlugin
|
|||
|
||||
|
||||
class WeatherForecastPlugin(HttpRequestPlugin):
|
||||
""" Plugin for getting weather updates through Darksky API """
|
||||
"""
|
||||
Plugin for getting weather updates through Darksky API
|
||||
|
||||
Requires:
|
||||
|
||||
* **requests** (``pip install requests``)
|
||||
"""
|
||||
|
||||
def __init__(self, darksky_token, lat, long, units='si', **kwargs):
|
||||
""" Supported unit types: ca, uk2, us, si """
|
||||
"""
|
||||
:param darksky_token: Your token for using the darksky API, see https://darksky.net/dev
|
||||
:type darksky_token: str
|
||||
|
||||
:param lat: Default forecast latitude
|
||||
:type lat: float
|
||||
|
||||
:param long: Default forecast longitude
|
||||
:type long: float
|
||||
|
||||
:param units: Weather units (default: "si").
|
||||
|
||||
Supported units:
|
||||
|
||||
* **si** (international system)
|
||||
* **us** (US imperial units)
|
||||
* **uk** (UK imperial units)
|
||||
* **ca** (Canada imperial units)
|
||||
|
||||
:type units: str
|
||||
"""
|
||||
|
||||
super().__init__(method='get', output='json')
|
||||
self.darksky_token = darksky_token
|
||||
self.units = units
|
||||
self.lat = lat
|
||||
self.long = long
|
||||
self.latest_bulletin = {}
|
||||
self.url = 'https://api.darksky.net/forecast/{}/{},{}?units={}'. \
|
||||
format(darksky_token, lat, long, units)
|
||||
|
||||
def get_current_weather(self, **kwargs):
|
||||
response = self.get(self.url)
|
||||
print(response)
|
||||
def _get_url(self, lat=None, long=None):
|
||||
return 'https://api.darksky.net/forecast/{}/{},{}?units={}'. \
|
||||
format(self.darksky_token, (lat or self.lat), (long or self.long),
|
||||
self.units)
|
||||
|
||||
def get_current_weather(self, lat=None, long=None, **kwargs):
|
||||
"""
|
||||
Get the current weather.
|
||||
|
||||
:param lat: Weather latitude (default: configured latitude)
|
||||
:type lat: float
|
||||
|
||||
:param long: Weather longitude (default: configured longitude)
|
||||
:type long: float
|
||||
|
||||
:returns: A dictionary containing the current weather object.
|
||||
|
||||
Example output::
|
||||
|
||||
output = {
|
||||
"time": 1529947892,
|
||||
"summary": "Mostly Cloudy",
|
||||
"icon": "partly-cloudy-day",
|
||||
"precipIntensity": 0.0483,
|
||||
"precipProbability": 0.04,
|
||||
"precipType": "rain",
|
||||
"temperature": 27.94,
|
||||
"apparentTemperature": 29.6,
|
||||
"dewPoint": 20.01,
|
||||
"humidity": 0.62,
|
||||
"pressure": 1009.34,
|
||||
"windSpeed": 1.83,
|
||||
"windGust": 5.49,
|
||||
"windBearing": 192,
|
||||
"cloudCover": 0.66,
|
||||
"uvIndex": 0,
|
||||
"visibility": 16.09,
|
||||
"ozone": 273.74
|
||||
}
|
||||
"""
|
||||
|
||||
response = self.get(self._get_url(lat, long))
|
||||
return Response(output=response.output['currently'])
|
||||
|
||||
def get_hourly_forecast(self, **kwargs):
|
||||
response = self.get(self.url)
|
||||
def get_hourly_forecast(self, lat=None, long=None, **kwargs):
|
||||
"""
|
||||
Get the hourly forecast.
|
||||
|
||||
:param lat: Weather latitude (default: configured latitude)
|
||||
:type lat: float
|
||||
|
||||
:param long: Weather longitude (default: configured longitude)
|
||||
:type long: float
|
||||
|
||||
:returns: A forecast object.
|
||||
|
||||
Example output::
|
||||
|
||||
output = {
|
||||
"summary": "Partly cloudy starting tomorrow morning, continuing until tomorrow evening.",
|
||||
"icon": "partly-cloudy-day",
|
||||
"data": [
|
||||
{
|
||||
"time": 1529946000,
|
||||
"summary": "Clear",
|
||||
"icon": "clear-day",
|
||||
"precipIntensity": 0,
|
||||
"precipProbability": 0,
|
||||
"temperature": 18.94,
|
||||
"apparentTemperature": 18.94,
|
||||
"dewPoint": 11.99,
|
||||
"humidity": 0.64,
|
||||
"pressure": 1025.53,
|
||||
"windSpeed": 5.1,
|
||||
"windGust": 6.22,
|
||||
"windBearing": 329,
|
||||
"cloudCover": 0.14,
|
||||
"uvIndex": 1,
|
||||
"visibility": 14.19,
|
||||
"ozone": 334.3
|
||||
},
|
||||
{
|
||||
"time": 1529949600,
|
||||
"summary": "Clear",
|
||||
"icon": "clear-day",
|
||||
"precipIntensity": 0,
|
||||
"precipProbability": 0,
|
||||
"temperature": 18.41,
|
||||
"apparentTemperature": 18.41,
|
||||
"dewPoint": 11.12,
|
||||
"humidity": 0.63,
|
||||
"pressure": 1025.54,
|
||||
"windSpeed": 4.6,
|
||||
"windGust": 6.18,
|
||||
"windBearing": 340,
|
||||
"cloudCover": 0.07,
|
||||
"uvIndex": 1,
|
||||
"visibility": 16.09,
|
||||
"ozone": 333.53
|
||||
},
|
||||
# ...
|
||||
}
|
||||
"""
|
||||
|
||||
response = self.get(self._get_url(lat, long))
|
||||
return Response(output=response.output['hourly'])
|
||||
|
||||
def get_daily_forecast(self, **kwargs):
|
||||
response = self.get(self.url)
|
||||
def get_daily_forecast(self, lat=None, long=None, **kwargs):
|
||||
"""
|
||||
Get the daily forecast.
|
||||
|
||||
:param lat: Weather latitude (default: configured latitude)
|
||||
:type lat: float
|
||||
|
||||
:param long: Weather longitude (default: configured longitude)
|
||||
:type long: float
|
||||
|
||||
:returns: A forecast object.
|
||||
|
||||
Example output::
|
||||
|
||||
"output": {
|
||||
"summary": "Light rain on Sunday, with high temperatures rising to 28°C on Sunday.",
|
||||
"icon": "rain",
|
||||
"data": [
|
||||
{
|
||||
"time": 1529877600,
|
||||
"summary": "Mostly cloudy until afternoon.",
|
||||
"icon": "partly-cloudy-day",
|
||||
"sunriseTime": 1529896835,
|
||||
"sunsetTime": 1529957280,
|
||||
"moonPhase": 0.42,
|
||||
"precipIntensity": 0,
|
||||
"precipIntensityMax": 0.0051,
|
||||
"precipIntensityMaxTime": 1529888400,
|
||||
"precipProbability": 0,
|
||||
"temperatureHigh": 20.04,
|
||||
"temperatureHighTime": 1529931600,
|
||||
"temperatureLow": 10.68,
|
||||
"temperatureLowTime": 1529982000,
|
||||
"apparentTemperatureHigh": 20.04,
|
||||
"apparentTemperatureHighTime": 1529931600,
|
||||
"apparentTemperatureLow": 10.68,
|
||||
"apparentTemperatureLowTime": 1529982000,
|
||||
"dewPoint": 12.18,
|
||||
"humidity": 0.77,
|
||||
"pressure": 1025.16,
|
||||
"windSpeed": 3.84,
|
||||
"windGust": 6.51,
|
||||
"windGustTime": 1529881200,
|
||||
"windBearing": 336,
|
||||
"cloudCover": 0.5,
|
||||
"uvIndex": 6,
|
||||
"uvIndexTime": 1529928000,
|
||||
"visibility": 14.08,
|
||||
"ozone": 331.24,
|
||||
"temperatureMin": 13.89,
|
||||
"temperatureMinTime": 1529960400,
|
||||
"temperatureMax": 20.04,
|
||||
"temperatureMaxTime": 1529931600,
|
||||
"apparentTemperatureMin": 13.89,
|
||||
"apparentTemperatureMinTime": 1529960400,
|
||||
"apparentTemperatureMax": 20.04,
|
||||
"apparentTemperatureMaxTime": 1529931600
|
||||
},
|
||||
{
|
||||
"time": 1529964000,
|
||||
"summary": "Partly cloudy throughout the day.",
|
||||
"icon": "partly-cloudy-day",
|
||||
"sunriseTime": 1529983261,
|
||||
"sunsetTime": 1530043677,
|
||||
"moonPhase": 0.45,
|
||||
"precipIntensity": 0,
|
||||
"precipIntensityMax": 0,
|
||||
"precipProbability": 0,
|
||||
"temperatureHigh": 20.95,
|
||||
"temperatureHighTime": 1530018000,
|
||||
"temperatureLow": 11.47,
|
||||
"temperatureLowTime": 1530064800,
|
||||
"apparentTemperatureHigh": 20.95,
|
||||
"apparentTemperatureHighTime": 1530018000,
|
||||
"apparentTemperatureLow": 11.47,
|
||||
"apparentTemperatureLowTime": 1530064800,
|
||||
"dewPoint": 10.19,
|
||||
"humidity": 0.69,
|
||||
"pressure": 1026.14,
|
||||
"windSpeed": 3.67,
|
||||
"windGust": 7.13,
|
||||
"windGustTime": 1530036000,
|
||||
"windBearing": 4,
|
||||
"cloudCover": 0.3,
|
||||
"uvIndex": 5,
|
||||
"uvIndexTime": 1530010800,
|
||||
"visibility": 16.09,
|
||||
"ozone": 328.59,
|
||||
"temperatureMin": 10.68,
|
||||
"temperatureMinTime": 1529982000,
|
||||
"temperatureMax": 20.95,
|
||||
"temperatureMaxTime": 1530018000,
|
||||
"apparentTemperatureMin": 10.68,
|
||||
"apparentTemperatureMinTime": 1529982000,
|
||||
"apparentTemperatureMax": 20.95,
|
||||
"apparentTemperatureMaxTime": 1530018000
|
||||
},
|
||||
# ...
|
||||
}
|
||||
"""
|
||||
|
||||
response = self.get(self._get_url(lat, long))
|
||||
return Response(output=response.output['daily'])
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue