Extended and updated pieces of documentation on the HTTP server, Zigbee2mqtt and mpd. Also added example dashboard template and event hook script.

This commit is contained in:
Fabio Manganiello 2021-02-22 01:20:01 +01:00
parent 151d0008ee
commit ffb7a3e5a3
6 changed files with 272 additions and 119 deletions

View file

@ -16,21 +16,21 @@
# Using multiple files is encouraged in the case of large configurations # Using multiple files is encouraged in the case of large configurations
# that can easily end up in a messy config.yaml file, as they help you # that can easily end up in a messy config.yaml file, as they help you
# keep your configuration more organized. # keep your configuration more organized.
include: #include:
- include/logging.yaml # - include/logging.yaml
- include/media.yaml # - include/media.yaml
- include/sensors.yaml # - include/sensors.yaml
# platypush logs on stdout by default. You can use the logging section to specify # platypush logs on stdout by default. You can use the logging section to specify
# an alternative file or change the logging level. # an alternative file or change the logging level.
logging: #logging:
filename: ~/.local/log/platypush/platypush.log # filename: ~/.local/log/platypush/platypush.log
level: INFO # level: INFO
# The device_id is used by many components of platypush and it should uniquely # The device_id is used by many components of platypush and it should uniquely
# identify a device in your network. If nothing is specified then the hostname # identify a device in your network. If nothing is specified then the hostname
# will be used. # will be used.
device_id: myname #device_id: my_device
## -- ## --
## Plugin configuration examples ## Plugin configuration examples
@ -46,31 +46,31 @@ device_id: myname
# https://docs.platypush.tech/en/latest/platypush/plugins/light.hue.html # https://docs.platypush.tech/en/latest/platypush/plugins/light.hue.html
# for reference. You can easily install the required dependencies for the plugin through # for reference. You can easily install the required dependencies for the plugin through
# pip install 'platypush[hue]' # pip install 'platypush[hue]'
light.hue: #light.hue:
# IP address or hostname of the Hue bridge # # IP address or hostname of the Hue bridge
bridge: 192.168.1.10 # bridge: 192.168.1.10
# Groups that will be handled by default if nothing is specified on the request # # Groups that will be handled by default if nothing is specified on the request
groups: # groups:
- Living Room # - Living Room
# Example configuration of music.mpd plugin, see # Example configuration of music.mpd plugin, see
# https://docs.platypush.tech/en/latest/platypush/plugins/music.mpd.html # https://docs.platypush.tech/en/latest/platypush/plugins/music.mpd.html
# You can easily install the dependencies through pip install 'platypush[mpd]' # You can easily install the dependencies through pip install 'platypush[mpd]'
music.mpd: #music.mpd:
host: localhost # host: localhost
port: 6600 # port: 6600
# Example configuration of media.chromecast plugin, see # Example configuration of media.chromecast plugin, see
# https://docs.platypush.tech/en/latest/platypush/plugins/media.chromecast.html # https://docs.platypush.tech/en/latest/platypush/plugins/media.chromecast.html
# You can easily install the dependencies through pip install 'platypush[chromecast]' # You can easily install the dependencies through pip install 'platypush[chromecast]'
media.chromecast: #media.chromecast:
chromecast: Living Room TV # chromecast: Living Room TV
# Plugins with empty configuration can also be explicitly enabled by specifying # Plugins with empty configuration can also be explicitly enabled by specifying
# enabled=True or disabled=False (it's a good practice if you want the # enabled=True or disabled=False (it's a good practice if you want the
# corresponding web panel to be enabled, if available) # corresponding web panel to be enabled, if available)
camera: #camera:
enabled: True # enabled: True
# Support for last.fm scrobbling. Install dependencies with 'pip install "platypush[lastfm]" # Support for last.fm scrobbling. Install dependencies with 'pip install "platypush[lastfm]"
lastfm: lastfm:
@ -81,13 +81,11 @@ lastfm:
# Support for calendars - in this case Google and Facebook calendars # Support for calendars - in this case Google and Facebook calendars
# Installing the dependencies: pip install 'platypush[ical,google]' # Installing the dependencies: pip install 'platypush[ical,google]'
calendar: #calendar:
calendars: # calendars:
- # - type: platypush.plugins.google.calendar.GoogleCalendarPlugin
type: platypush.plugins.google.calendar.GoogleCalendarPlugin # - type: platypush.plugins.calendar.ical.CalendarIcalPlugin
- # url: https://www.facebook.com/events/ical/upcoming/?uid=your_user_id&key=your_key
type: platypush.plugins.calendar.ical.CalendarIcalPlugin
url: https://www.facebook.com/events/ical/upcoming/?uid=your_user_id&key=your_key
## -- ## --
## Backends configuration examples ## Backends configuration examples
@ -118,77 +116,49 @@ calendar:
backend.http: backend.http:
# Listening port # Listening port
port: 8008 port: 8008
# Websocket port
websocket_port: 8009
# Through resource_dirs you can specify external folders whose content can be accessed on # Through resource_dirs you can specify external folders whose content can be accessed on
# the web server through a custom URL. In the case below we have a Dropbox folder containing # the web server through a custom URL. In the case below we have a Dropbox folder containing
# our pictures and we mount it to the '/carousel' endpoint. # our pictures and we mount it to the '/carousel' endpoint.
resource_dirs: resource_dirs:
carousel: ~/Dropbox/Photos/carousel carousel: /mnt/hd/photos/carousel
# Dashboard configuration. The dashboard is a collection of widgets and it's organized in
# multiple rows. Each rows can be split in 12 columns. Therefore 'columns: 12' will make
# a widget span over the whole row, while 'columns: 6' will make a widget take half the
# horizontal space of a column.
dashboard:
widgets:
-
widget: calendar
columns: 6
-
widget: music
columns: 3
-
widget: date-time-weather
columns: 3
-
widget: image-carousel
columns: 6
images_path: ~/Dropbox/Photos/carousel
refresh_seconds: 15
-
widget: rss-news
# Requires backend.http.poll to be enabled with some
# RSS sources and write them to sqlite db
columns: 6
limit: 25
db: "sqlite:////home/user/.local/share/platypush/feeds/rss.db"
# The HTTP poll backend is a versatile backend that can monitor for HTTP-based resources and # The HTTP poll backend is a versatile backend that can monitor for HTTP-based resources and
# trigger events whenever new entries are available. In the example below we show how to use # trigger events whenever new entries are available. In the example below we show how to use
# the backend to listen for changes on a set of RSS feeds. New content will be stored by default # the backend to listen for changes on a set of RSS feeds. New content will be stored by default
# on a SQLite database under ~/.local/share/platypush/feeds/rss.db. # on a SQLite database under ~/.local/share/platypush/feeds/rss.db.
# Install the required dependencies through 'pip install "platypush[rss,db]"' # Install the required dependencies through 'pip install "platypush[rss,db]"'
backend.http.poll: #backend.http.poll:
requests: # requests:
- # - type: platypush.backend.http.request.rss.RssUpdates # HTTP poll type (RSS)
# HTTP poll type (RSS) # # Remote URL
type: platypush.backend.http.request.rss.RssUpdates # url: http://www.theguardian.com/rss/world
# Remote URL # # Custom title
url: http://www.theguardian.com/rss/world # title: The Guardian - World News
# Custom title # # How often we should check for changes
title: The Guardian - World News # poll_seconds: 600
# How often we should check for changes # # Maximum number of new entries to be processed
poll_seconds: 600 # max_entries: 10
# Maximum number of new entries to be processed #
max_entries: 10 # - type: platypush.backend.http.request.rss.RssUpdates
- # url: http://www.physorg.com/rss-feed
type: platypush.backend.http.request.rss.RssUpdates # title: Phys.org
url: http://www.physorg.com/rss-feed # poll_seconds: 600
title: Phys.org # max_entries: 10
poll_seconds: 600 #
max_entries: 10 # - type: platypush.backend.http.request.rss.RssUpdates
- # url: http://feeds.feedburner.com/Techcrunch
type: platypush.backend.http.request.rss.RssUpdates # title: Tech Crunch
url: http://feeds.feedburner.com/Techcrunch # poll_seconds: 600
title: Tech Crunch # max_entries: 10
poll_seconds: 600 #
max_entries: 10 # - type: platypush.backend.http.request.rss.RssUpdates
- # url: http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml
type: platypush.backend.http.request.rss.RssUpdates # title: The New York Times
url: http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml # poll_seconds: 300
title: The New York Times # max_entries: 10
poll_seconds: 300
max_entries: 10
# MQTT backend. Installed required dependencies through 'pip install "platypush[mqtt]"' # MQTT backend. Installed required dependencies through 'pip install "platypush[mqtt]"'
backend.mqtt: backend.mqtt:
@ -196,15 +166,15 @@ backend.mqtt:
host: mqtt-server host: mqtt-server
# By default the backend will listen for messages on the platypush_bus_mq/device_id # By default the backend will listen for messages on the platypush_bus_mq/device_id
# topic, but you can change the prefix using the topic attribute # topic, but you can change the prefix using the topic attribute
topic: my_platypush_bus # topic: MyBus
# Raw TCP socket backend. It can run commands sent as JSON over telnet or netcat # Raw TCP socket backend. It can run commands sent as JSON over telnet or netcat
backend.tcp: #backend.tcp:
port: 3333 # port: 3333
# Websocket backend. Install required dependencies through 'pip install "platypush[http]"' # Websocket backend. Install required dependencies through 'pip install "platypush[http]"'
backend.websocket: #backend.websocket:
port: 8765 # port: 8765
## -- ## --
## Assistant configuration examples ## Assistant configuration examples
@ -254,9 +224,12 @@ backend.assistant.snowboy:
assistant.echo: assistant.echo:
audio_player: mplayer audio_player: mplayer
# Install Google Assistant dependencies with 'pip install "platypush[google-assistant]"' # Install Google Assistant dependencies with 'pip install "platypush[google-assistant-legacy]"'
assistant.google.pushtotalk: assistant.google:
language: en-US enabled: True
backend.assistant.google:
enabled: True
## -- ## --
## Procedure examples ## Procedure examples
@ -327,14 +300,14 @@ procedure.outside_home:
procedure.send_request(target, action, args): procedure.send_request(target, action, args):
- action: mqtt.send_message - action: mqtt.send_message
args: args:
topic: my_platypush_bus/${target} topic: platypush_bus_mq/${target}
host: mqtt-server host: mqtt-server
port: 1883 port: 1883
msg: msg:
type: request type: request
target: ${target} target: ${target}
action: ${action} action: ${action}
args: "${context.get('args', {}}" args: ${args}
## -- ## --
## Event hook examples ## Event hook examples
@ -418,4 +391,3 @@ cron.TestCron:
- action: shell.exec - action: shell.exec
args: args:
cmd: ~/bin/myscript.sh cmd: ~/bin/myscript.sh

View file

@ -0,0 +1,33 @@
<!-- Dashboard templates are stored as ~/.config/platypush/dashboards/<name>.xml and can be accessed on
http://<host>:8008/dashboard/<name>. A dashboard can show a custom set of widgets on a screen - e.g. calendar
events, media information, photo carousels, sensors data, weather forecast and news headlines. The available
widgets are stored as Vue.js templates under `platypush/backend/http/webapp/src/components/widgets`. -->
<Dashboard>
<!-- Display the following widgets on the same row. Each row consists of 12 columns.
You can specify the width of each widget either through class name (e.g. col-6 means
6 columns out of 12, e.g. half the size of the row) or inline style
(e.g. `style="width: 50%"`). -->
<Row>
<!-- Show a calendar widget with the upcoming events. It requires the `calendar` plugin to
be enabled and configured. -->
<Calendar class="col-6" />
<!-- Show the current track and other playback info. It requires `music.mpd` plugin or any
other music plugin enabled. -->
<Music class="col-3" />
<!-- Show current date, time and weather. It requires a `weather` plugin or backend enabled -->
<DateTimeWeather class="col-3" />
</Row>
<!-- Display the following widgets on a second row -->
<Row>
<!-- Show a carousel of images from a local folder. For security reasons, the folder must be
explicitly exposed as an HTTP resource through the backend `resource_dirs` attribute. -->
<ImageCarousel class="col-6" img-dir="/mnt/hd/photos/carousel" />
<!-- Show the news headlines parsed from a list of RSS feed and stored locally through the
`http.poll` backend -->
<RssNews class="col-6" db="sqlite:////path/to/your/rss.db" />
</Row>
</Dashboard>

43
examples/conf/hook.py Normal file
View file

@ -0,0 +1,43 @@
# A more versatile way to define event hooks than the YAML format of `config.yaml` is through native Python scripts.
# You can define hooks as simple Python functions that use the `platypush.event.hook.hook` decorator to specify on
# which event type they should be called, and optionally on which event attribute values.
#
# Event hooks should be stored in Python files under `~/.config/platypush/scripts`. All the functions that use the
# @hook decorator will automatically be discovered and imported as event hooks into the platform at runtime.
# `run` is a utility function that runs a request by name (e.g. `light.hue.on`).
from platypush.utils import run
# @hook decorator
from platypush.event.hook import hook
# Event types that you want to react to
from platypush.message.event.assistant import ConversationStartEvent, SpeechRecognizedEvent
@hook(SpeechRecognizedEvent, phrase='play ${title} by ${artist}')
def on_music_play_command(event, title=None, artist=None, **context):
"""
This function will be executed when a SpeechRecognizedEvent with `phrase="play the music"` is triggered.
`event` contains the event object and `context` any key-value info from the running context.
Note that in this specific case we can leverage the token-extraction feature of SpeechRecognizedEvent through
${} that operates on regex-like principles to extract any text that matches the pattern into context variables.
"""
results = run('music.mpd.search', filter={
'artist': artist,
'title': title,
})
if results:
run('music.mpd.play', results[0]['file'])
else:
run('tts.say', "I can't find any music matching your query")
@hook(ConversationStartEvent)
def on_conversation_start(event, **context):
"""
A simple hook that gets invoked when a new conversation starts with a voice assistant and simply pauses the music
to make sure that your speech is properly detected.
"""
run('music.mpd.pause_if_playing')

View file

@ -12,36 +12,137 @@ from platypush.utils import get_ssl_server_context, set_thread_name
class HttpBackend(Backend): class HttpBackend(Backend):
""" """
The HTTP backend is a general-purpose web server that you can leverage: The HTTP backend is a general-purpose web server.
* To execute Platypush commands via HTTP calls. Example:: Example configuration:
curl -XPOST -H 'Content-Type: application/json' -H "X-Token: your_token" \\ .. code-block:: yaml
-d '{
"type":"request", backend.http:
"target":"nodename", # Default HTTP listen port
"action":"tts.say", port: 8008
"args": {"phrase":"This is a test"} # Default websocket port
}' \\ websocket_port: 8009
http://localhost:8008/execute # External folders that will be exposed over `/resources/<name>`
resource_dirs:
photos: /mnt/hd/photos
videos: /mnt/hd/videos
music: /mnt/hd/music
You can leverage this backend:
* To execute Platypush commands via HTTP calls. In order to do so:
** Register a user to Platypush through the web panel (usually served on ``http://host:8008/``).
** Generate a token for your user, either through the web panel (Settings -> Generate Token) or via API:
.. code-block:: shell
curl -XPOST -H 'Content-Type: application/json' -d '
{
"username": "$YOUR_USER",
"password": "$YOUR_PASSWORD"
}' http://host:8008/auth
** Execute actions through the ``/execute`` endpoint:
.. code-block:: shell
curl -XPOST -H 'Content-Type: application/json' -H "Authorization: Bearer $YOUR_TOKEN" -d '
{
"type": "request",
"action": "tts.say",
"args": {
"text": "This is a test"
}
}' http://localhost:8008/execute
* To interact with your system (and control plugins and backends) through the Platypush web panel, * To interact with your system (and control plugins and backends) through the Platypush web panel,
by default available on your web root document. Any plugin that you have configured and available as a panel by default available on ``http://host:8008/``. Any configured plugin that has an available panel
plugin will appear on the web panel as well as a tab. plugin will be automatically added to the web panel.
* To display a fullscreen dashboard with your configured widgets, by default available under ``/dashboard/<dashboard_name>`` * To display a fullscreen dashboard with custom widgets.
* To stream media over HTTP through the ``/media`` endpoint ** Widgets are available as Vue.js components under
``platypush/backend/http/webapp/src/components/widgets``.
** Explore their options (some may require some plugins or backends to be configured in order to work) and
create a new dashboard template under ``~/.config/platypush/dashboards``- e.g. ``main.xml``:
.. code-block:: xml
<Dashboard>
<!-- Display the following widgets on the same row. Each row consists of 12 columns.
You can specify the width of each widget either through class name (e.g. col-6 means
6 columns out of 12, e.g. half the size of the row) or inline style
(e.g. `style="width: 50%"`). -->
<Row>
<!-- Show a calendar widget with the upcoming events. It requires the `calendar` plugin to
be enabled and configured. -->
<Calendar class="col-6" />
<!-- Show the current track and other playback info. It requires `music.mpd` plugin or any
other music plugin enabled. -->
<Music class="col-3" />
<!-- Show current date, time and weather. It requires a `weather` plugin or backend enabled -->
<DateTimeWeather class="col-3" />
</Row>
<!-- Display the following widgets on a second row -->
<Row>
<!-- Show a carousel of images from a local folder. For security reasons, the folder must be
explicitly exposed as an HTTP resource through the backend `resource_dirs` attribute. -->
<ImageCarousel class="col-6" img-dir="/mnt/hd/photos/carousel" />
<!-- Show the news headlines parsed from a list of RSS feed and stored locally through the
`http.poll` backend -->
<RssNews class="col-6" db="sqlite:////path/to/your/rss.db" />
</Row>
</Dashboard>
** The dashboard will be accessible under ``http://host:8008/dashboard/<name>``, where ``name=main`` if for
example you stored your template under ``~/.config/platypush/dashboards/main.xml``.
* To expose custom endpoints that can be called as web hooks by other applications and run some custom logic.
All you have to do in this case is to create a hook on a
:class:`platypush.message.event.http.hook.WebhookEvent` with the endpoint that you want to expose and store
it under e.g. ``~/.config/platypush/scripts/hooks.py``:
.. code-block:: python
from platypush.context import get_plugin
from platypush.event.hook import hook
from platypush.message.event.http.hook import WebhookEvent
hook_token = 'abcdefabcdef'
# Expose the hook under the /hook/lights_toggle endpoint
@hook(WebhookEvent, hook='lights_toggle')
def lights_toggle(event, **context):
# Do any checks on the request
assert event.headers.get('X-Token') == hook_token, 'Unauthorized'
# Run some actions
lights = get_plugin('light.hue')
lights.toggle()
Any plugin can register custom routes under ``platypush/backend/http/app/routes/plugins``. Any plugin can register custom routes under ``platypush/backend/http/app/routes/plugins``.
Any additional route is managed as a Flask blueprint template and the `.py` Any additional route is managed as a Flask blueprint template and the `.py`
module can expose lists of routes to the main webapp through the module can expose lists of routes to the main webapp through the
``__routes__`` object (a list of Flask blueprints). ``__routes__`` object (a list of Flask blueprints).
Note that if you set up a main token, it will be required for any HTTP Security: Access to the endpoints requires at least one user to be registered. Access to the endpoints is regulated
interaction - either as ``X-Token`` HTTP header, on the query string in the following ways (with the exception of event hooks, whose logic is up to the user):
(attribute name: ``token``), as part of the JSON payload root (attribute
name: ``token``), or via HTTP basic auth (any username works). * **Simple authentication** - i.e. registered username and password.
* **JWT token** provided either over as ``Authorization: Bearer`` header or ``GET`` ``?token=<TOKEN>``
parameter. A JWT token can be generated either through the web panel or over the ``/auth`` endpoint.
* **Global platform token**, usually configured on the root of the ``config.yaml`` as ``token: <VALUE>``.
It can provided either over on the ``X-Token`` header or as a ``GET`` ``?token=<TOKEN>`` parameter.
* **Session token**, generated upon login, it can be used to authenticate requests through the ``Cookie`` header
(cookie name: ``session_token``).
Requires: Requires:

View file

@ -16,9 +16,13 @@ class MusicMpdPlugin(MusicPlugin):
sources through plugins (e.g. Spotify, TuneIn, Soundcloud, local files sources through plugins (e.g. Spotify, TuneIn, Soundcloud, local files
etc.). etc.).
**NOTE**: As of Mopidy 3.0 MPD is an optional interface provided by the ``mopidy-mpd`` extension. Make sure that you
have the extension installed and enabled on your instance to use this plugin with your server.
Requires: Requires:
* **python-mpd2** (``pip install python-mpd2``) * **python-mpd2** (``pip install python-mpd2``)
""" """
_client_lock = threading.RLock() _client_lock = threading.RLock()

View file

@ -33,8 +33,8 @@ class ZigbeeMqttPlugin(MqttPlugin, SwitchPlugin):
.. code-block:: shell .. code-block:: shell
wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/coordinator/Z-Stack_Home_1.2/bin/default/CC2531_DEFAULT_20190608.zip wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/coordinator/Z-Stack_Home_1.2/bin/default/CC2531_DEFAULT_20201127.zip
unzip CC2531_DEFAULT_20190608.zip unzip CC2531_DEFAULT_20201127.zip
[sudo] cc-tool -e -w CC2531ZNP-Prod.hex [sudo] cc-tool -e -w CC2531ZNP-Prod.hex
- You can disconnect your debugger and downloader cable once the firmware is flashed. - You can disconnect your debugger and downloader cable once the firmware is flashed.