Removed deprecated integrations and added new web dashboard documentation

Fabio Manganiello 2021-03-28 16:55:24 +02:00
parent 0156ead85f
commit 28757cc1f8
3 changed files with 397 additions and 76 deletions

@ -21,18 +21,24 @@
* [Smart cards backend](#smart-cards-backend)
* [Weather forecast backend](#weather-forecast-backend)
Platypush backends are components that can listen for event on any source that generates events or messages. Platypush can support through backends things like message queues, HTTP requests, voice assistant interactions, music player events, MIDI events, button events, measurements from sensors, events from smart cards and more. You can see a backend as a component that runs in its own thread or process and posts messages, action requests or events to the main bus when something happens.
Platypush backends are components that can listen for events on any source that generates events or messages. Platypush
can support through backends things like message queues, HTTP requests, voice assistant interactions, music player
events, MIDI events, button events, measurements from sensors, events from smart cards and more. You can see a backend
as a component that runs in its own thread or process and posts messages, action requests or events to the main bus when
something happens.
# HTTP server
[Backend reference](https://docs.platypush.tech/en/latest/platypush/backend/http.html)
The HTTP server is a powerful feature of Platypush and one of the main ways to interact with the application and its components. If configured, the HTTP backend will run a Flask server (default port: 8008) that you can use to interact with Platypush in several ways:
The HTTP server is a powerful feature of Platypush and one of the main ways to interact with the application and its
components. If configured, the HTTP backend will run a Flask server (default port: 8008) that you can use to interact
with Platypush in several ways:
1. To send action requests as JSON messages through the web API
2. To control the configured plugins (lights, switches, music, sensors etc.) through the web panel
3. As a dashboard to show on a monitor or a tv with your favourite widgets (calendar, music player, weather, sensors state, news etc.)
3. As a dashboard to show on a monitor or a tv with your favourite widgets (calendar, music player, weather, sensors
state, news etc.)
## Configuration
@ -46,12 +52,36 @@ backend.http:
Websockets are used both in the web panel and dashboard interfaces to deliver real-time messages to the plugins and widgets.
**NOTE**: If you configured a security `token` on your Platypush instance (warmly recommended), then all the HTTP calls need to bear that token either:
## Authentication
- On the `X-Token` header
- On the query string (`?token=...`)
- At the top level of the JSON request (`{"type":"request", ..., "token":"..."}`)
- Through interactive basic HTTP authentication in case of browser-based interaction
The HTTP backend acts also as a user registration and authentication gateway. After configuring it in your
`config.yaml`, start Platypush and head to `http://host:8008/`. If no users have yet been created, you should see a
user registration panel, otherwise a login interface will be prompted.
Upon registration, you can generate an API token that can be used in your calls either:
- Through the web panel. Create a user/login to the web panel, head to the Settings (gear icon in the menu), select
_Generate Token_, enter your username and password and its expiry date, and a new JWT token will be generated.
- Through the API, using the `/auth` endpoint:
```shell
$ curl -XPOST -H "Content-Type: application/json" --data '{
"username":"user",
"password":"pass"
}' http://host:8008/auth
{
"token": "..."
}
```
Once you have a JWT token, you can use it on your API calls either:
- On the `Authorization` header (format: `Authorization: Bearer <TOKEN>`) [advised].
- On the `X-Token` header.
- On the query string (`?token=...`).
- At the top level of the JSON request (`{"type":"request", ..., "token":"..."}`).
## cURL commands
@ -61,7 +91,8 @@ Example 1: play music through the [MPD plugin](plugins#mpd-mopidy-support):
```shell
curl -XPOST -H 'Content-Type: application/json' \
-d '{"type":"request", "target":"hostname", "action":"music.mpd.play"}' \
-H "Authorization: Bearer $TOKEN" \
-d '{"type":"request", "action":"music.mpd.play"}' \
http://hostname:8008/execute
```
@ -69,7 +100,8 @@ Example 2: turn on your lights through the [Philips Hue plugin](plugins#philips-
```shell
curl -XPOST -H 'Content-Type: application/json' \
-d '{"type":"request", "target":"hostname", "action":"lights.hue.on", "args": {"groups": ["Living Room"]}}' \
-H "Authorization: Bearer $TOKEN" \
-d '{"type":"request", "action":"lights.hue.on", "args": {"groups": ["Living Room"]}}' \
http://hostname:8008/execute
```
@ -77,7 +109,8 @@ Example 3: run a configured procedure:
```shell
curl -XPOST -H 'Content-Type: application/json' \
-d '{"type":"request", "target":"hostname", "action":"procedure.at_home"}' \
-H "Authorization: Bearer $TOKEN" \
-d '{"type":"request", "action":"procedure.at_home"}' \
http://hostname:8008/execute
```
@ -96,49 +129,354 @@ tts:
You can use the web panel to control your lights, music, video, sensors, motors, switches, and whatever is provided by the plugins.
## Dashboard
## Dashboards
You can use Platypush to power a fullscreen dashboard with your calendar, music state, photos, weather forecast, news, sensors state etc. to show on a computer, tv or laptop screen.
You can use Platypush to power a fullscreen dashboard with your calendar, music state, photos, weather forecast, news,
sensors state etc. to show on a computer, tv or laptop screen.
Change your `backend.http` configuration to also include the widgets that you want to include on the dashboard.
The configuration for dashboards has changed since Platypush 0.20.0 - while only one dashboard per service was
previously supported, and configured directly inside of the `backend.http` configuration, it's now possible to configure
multiple dashboards and do it directly in an HTML-like format that allows much more flexibility.
Dashboards consist of *widgets*, which are customizable components that can be freely arranged on the dashboard canvas.
Widgets are Vue components stored under
[`backend/http/webapp/src/components/widgets`](https://git.platypush.tech/platypush/platypush/-/tree/master/platypush/backend/http/webapp/src/components/widgets).
Widgets are available for most of a common dashboard's components - such as calendar, music status, time and weather,
image and news carousels. You can easily grab the configuration of each widget by looking at the `props` defined on the
associated Vue component (*TODO: manage self-generated documentation for widgets*), and some widgets may require some
other plugin or backend to be enabled in order to work - for example, `Calendar` requires the `calendar` plugin,
`Weather` requires the `weather.openweathermap` plugin, and so on.
Dashboard configurations are stored by default under the `~/.config/platypush/dashboards` folder. Each dashboard should
be an XML file.
Let's take a look at a simple dashboard configuration that includes the following widgets:
- A calendar
- A music status widget
- A date/time/weather widget
- An image carousel
- A news carousel
### Calendar
- Dependencies installation:
```shell
# Support for Google Calendar and ICal calendar URLs
$ [sudo] pip install 'platypush[ical,google]'
```
- Grant app access to the calendar API, if you are using a Google Calendar:
```shell
python -m platypush.plugins.google.credentials \
"https://www.googleapis.com/auth/calendar.readonly" \
/path/to/your/google/api/client_secret.json
```
- `config.yaml` configuration:
```yaml
calendar:
# Monitor your Google Calendar and an ICal calendar (e.g. your Facebook events calendar)
calendars:
- type: platypush.plugins.google.calendar.GoogleCalendarPlugin
- type: platypush.plugins.calendar.ical.CalendarIcalPlugin
url: https://www.facebook.com/events/ical/upcoming/?uid=YOUR_UID&key=YOUR_KEY
```
### Music state and current track
This is currently only supported for MPD/Mopidy integrations - but, given the amount of music service plugins available
for Mopidy, this should easily cover most of the use cases out there.
Also, note that since the version 3.0 Mopidy no longer exposes the MPD interface by default - you'll have to install the
`mopidy-mpd` package separately.
- Install the MPD dependencies:
```shell
$ [sudo] pip install 'platypush[mpd]'
```
- Configure the MPD plugin and, if you are using Mopidy, the Mopidy backend (for real-time monitoring):
```yaml
music.mpd:
host: localhost
port: 6600
backend.music.mopidy:
enabled: True
```
### Date/time/weather widget
Get an OpenWeatherMap API token and configure the associated Platypush plugin:
```yaml
weather.openweathermap:
token: YOUR_TOKEN
lat: YOUR_LAT
long: YOUR_LONG
# Otherwise, you can also configure the default location by
# city ID or free search
```
### Image carousel
You can configure one or more directories on the system to be exposed over the web server as *resources*. This enables
you to easily expose images stored on your drive as HTTP URLs. For example:
```yaml
backend.http:
port: 8008
websocket_port: 8009
# resource_dirs allows you to expose the content of some absolute directories on your
# filesystem as static elements through the webserver under the <BASE_URL>/resources URL.
# In the example below, the files under ~/Dropbox/Photos/carousel will be accessible through
# http://localhost:8008/resources/carousel
resource_dirs:
carousel: ~/Dropbox/Photos/carousel
dashboard: # Your dashboard configuration
background_image: https://some/background.png # Background image
widgets: # Widgets configuration
calendar: # Calendar widget. It requires the calendar plugin to be configured
columns: 6 # 6 columns on the first row
music: # Music playback state. It requires the music.mpd plugin to be configured
columns: 3 # 3 columns on the first row
date-time-weather: # Date, weather and sensors plugin
columns: 3 # 3 columns on the first row
image-carousel: # Photo carousel
columns: 6 # 6 columns on the second row
images_path: ~/Dropbox/Photos/carousel # Path to scan for carousel pictures.
# It must be a subdirectory of at least
# one item of resource_dirs.
refresh_seconds: 15 # Time between two pictures
rss-news: # News from your RSS feeds
# Requires backend.http.poll to be enabled with some
# RSS sources, and configured to write items to sqlite db
columns: 6 # 6 columns on the second row
limit: 25 # Maximum number of items to show in a carousel news iteration
db: "sqlite:////home/blacklight/.local/share/platypush/feeds/rss.db" # Database where the HTTP poll backend
# stores the RSS items
# ...
resource_dirs:
photos: /mnt/hd/Photos
```
Note that you can design the layout of the dashboard by specifying how many columns a widget should take. Each row contains 12 columns. In the example above, for example, we placed the calendar widget to occupy half of the first row while the music and weather widgets take one quarter each, and the second row is split between the image carousel and the news carousel.
You can now access your photos over `http://host:8008/resources/photos/PHOTO.jpg` - we'll see soon how to import this
folder into a carousel widget.
### News carousel
- Install the dependencies:
```shell
$ [sudo] pip install 'platypush[rss]'
```
- Configure the RSS feeds you want to scan:
```yaml
backend.http.poll:
requests:
- type: platypush.backend.http.request.rss.RssUpdates
url: http://site1.com/rss
title: Site 1
poll_seconds: 600
max_entries: 10
- type: platypush.backend.http.request.rss.RssUpdates
url: http://site2.com/rss
title: Site 2
poll_seconds: 600
max_entries: 10
```
Feed updates by default will be stored in `~/.local/share/platypush/feeds/rss.db` - we'll use that in a moment.
### Adding the widgets
Once all the dependencies are installed and configured, you can add the widgets to the dashboard.
Dashboard templates are stored as XML files under `~/.config/platypush/dashboards`. Create a new file under this folder
(e.g. `main.xml`) with the following content:
```xml
<Dashboard>
<Row>
<Calendar class="col-6" />
<Music class="col-3" />
<DateTimeWeather class="col-3" />
</Row>
<Row>
<!-- Note: the folder must have been exposed through the resource_dirs attribute of backend.http -->
<ImageCarousel class="col-6" img-dir="/mnt/hd/Photos" />
<RssNews class="col-6" db="sqlite:////home/user/.local/share/platypush/feeds/rss.db" />
</Row>
</Dashboard>
```
A few observations:
- `<Dashboard>` is the root element of a dashboard template.
- A dashboard is organized in rows, so all the widgets belonging to the same `<Row>` element will be displayed on the
same row.
- Each row is divided into 12 columns, and you can specify the width of a widget through the `col-n` class, where `n` is
the width of the widget in column - for example, `col-6` means that the widget takes half of the row.
- Column width can be made reactive through the `-s-`, `-m-`, `-l-` and `-xl-` modifiers. The following statement, for
example, means that the width of the `<Music>` widget will be 100% of the row on a small screen, 50% on a medium
screen (usually tablet-sized screens) and 25% on a large screen (usually desktop-sized screens or larger):
```xml
<Music class="col-s-12 col-m-6 col-l-3" />
```
- You can also specify custom classes on a widget definition or custom a custom CSS style through the `class` and
`style` attributes.
Once configured, you can access your dashboard on `http://host:8008/dashboard/main` - assuming that the template you
just created was stored in a file named `main.xml`:
![Dashboard screenshot](https://blog.platypush.tech/img/dashboard-1.png)
### Creating custom widgets
In some cases you may want to have a UI that shows specific information from plugins (for example, sensor data, or
toggles/sliders for some specific devices or services), but that information isn't provided by the default widgets that
come with Platypush. Alternatively, the application's main web panel exposes lots of information and features from
plugins, but it requires some clicking around to get it, while you may want a simple dashboard that shows all the
information you need on a single view.
Platypush provides a way for you to define custom widgets through the `<Component>` widget. You can use `<Component>` to
define reactive widgets with custom HTML and JavaScript and using a few base ingredients to build complex interfaces.
The following elements can be used inside of a `<Component>` widget:
- `<Run>`: a basic element that shows some text and an optional icon and performs one or more specified actions when
clicked.
- `<Switch>`: an element used to interact with devices or services with an on/off binary state and toggle their state
upon user interaction.
- `<Slider>`: an element used to interact with devices or services with a numeric value included in a specified range.
- `<Sensor>`: an element used to display read-only values from custom devices, services or endpoints.
Let's take an example where we want to build a widget to show and manage in one single component the devices and
controls in a living room. These include:
- A TV connected to a Tp-Link Wi-Fi smart switch.
- A Zigbee temperature sensor.
- A Z-Wave dimmer.
- Music playback control.
A widget that displays and controls these features can be written as it follows:
```xml
<Dashboard>
<Row>
<Component>
<!-- You can insert custom HTML tags in a <Component> -->
<h1 style="font-size: 1.5em">Living Room</h1>
<!-- Element to play/pause the music playback -->
<Run name="Music pause" icon-class="fa fa-pause">
<actions>
<action name="music.mpd.pause" />
</actions>
</Run>
<!-- Element to control a Tp-Link smart plug -->
<Switch name="TV Switch" icon-class="fa fa-tv">
<actions>
<action name="switch.tplink.toggle">
<device>TV Switch</device>
</action>
<after>
self.refresh()
</after>
</actions>
<handlers>
<refresh interval="10">
self.value = Object.values(await self.request('switch.tplink.status'))
.filter((dev) => dev.name === 'TV Switch')[0].on
</refresh>
</handlers>
</Switch>
<!-- Element to control a Z-Wave dimmer -->
<Slider name="Lights dimmer" icon-class="fa fa-lightbulb">
<actions>
<action name="zwave.set_value">
<id_on_network>VALUE_ID_ON_NET</id_on_network>
<data>{{ self.value }}</data>
</action>
</actions>
<handlers>
<refresh interval="10">
self.value = await self.request('zwave.get_value',
{id_on_network: 'VALUE_ID_ON_NET'}).data
</refresh>
<event type="platypush.message.event.zwave.ZwaveValueChangedEvent">
if (event.value.id_on_network === 'VALUE_ID_ON_NET')
self.value = event.value.data
</event>
</handlers>
</Slider>
<!-- Element to display data from a Zigbee sensor -->
<Sensor name="Temperature" icon-class="fa fa-thermometer-half">
<handlers>
<refresh interval="10">
self.value = await self.request('zigbee.mqtt.device_get',
{'device': 'Temperature Sensor', 'property': 'temperature'}).temperature
</refresh>
<event type="platypush.message.event.zigbee.mqtt.ZigbeeMqttDevicePropertySetEvent">
if (event.device === 'Temperature Sensor' &amp;&amp; event.properties.temperature != null)
self.value = event.properties.temperature
</event>
</handlers>
</Sensor>
</Component>
</Row>
</Dashboard>
```
A few words on what's happening here:
- The `<Component>` widget, under the hood, is a Vue template. This means that you can easily embed your custom HTML
into it.
- Each element should have a `name` (displayed on the UI) and can optionally have either an `icon-class` or an
`icon-url` - the former would select a FontAwesome icon class for the element, the latter an icon URL. You can also
use `icon-color` when using `icon-class` to change the icon's color.
- Elements usually have an `<actions>` tag, which can contain one or more `<action>` tags representing the actions to
execute upon user interaction.
- Each `<action>` tag can also have one or more child tags, each representing an argument
to be passed to the action.
- An `<actions>` tag can optionally have a `<before>` or an `<after>` tag, containing a JavaScript routine to be
executed respectively before or after the actions are run. In the example above, `<after>` runs `self.refresh()` on
the `<Switch>` tag so that the value is updated after user interaction.
- You can access the reference to the element in your JavaScript code through the `self` object. Each element usually
has a `value` property (binary state in the case of a switch, numeric value in the case of a slider or sensor, etc.)
that can be read and modified by your snippets.
- You can also embed the current `value` property (or any other variable or property) in an action argument through the
following syntax: `<arg>{{ self.value }}</arg>`.
- The `self` object also has a `.request()` method that runs an action through `backend.http`. It takes two arguments:
the action name and an optional object with its arguments.
- All the custom JS snippets are automatically wrapped inside of an `async` function, so you can use `await` inside of
them.
- An element can also have one or more `<handlers>` defined as JavaScript snippets to run when a particular event
occurs. Available handler tags:
- `<refresh>`: Handler to be called when the element is mounted and at regular intervals, specified by the `interval`
parameter (in seconds). This handler can also be programmatically called from other snippets through
`self.refresh()`.
- `<mounted>`: Handler called when the element is first mounted.
- `<event>`: Handler called when a specific platform event is received - the type of the event can be specified with
the `type` parameter. In the example above, we have defined an event handler on `ZwaveValueChangedEvent` events, so
that the element will be updated when the Z-Wave dimmer value gets updated, and one on
`ZigbeeMqttDevicePropertySetEvent` events to update the widget when a new temperature value is received.
- An `event` object is passed to the event handlers and it can be accessed from your snippets.
This is all you need to know to create your custom dashboards - feel free to look in the documented properties of the
widgets for more advanced use cases.
# RSS feeds backend
@ -438,14 +776,14 @@ socket.onmessage = (msg) => {
console.log(msg);
};
var msg = {"type":"request", "target":"hostname", "action":"plugin.action"};
var msg = {"type":"request", "action":"plugin.action"};
socket.send(JSON.stringify(msg));
```
Or through command-line tools like [wscat](https://www.npmjs.com/package/wscat):
```shell
wscat -w 0 -c 'ws://turing:8765' -x '{"type":"request", "target":"hostname", "action":"light.batsignal.on"}'
wscat -w 0 -c 'ws://turing:8765' -x '{"type":"request", "action":"light.batsignal.on"}'
```
# TCP backend
@ -464,7 +802,7 @@ backend.tcp:
After enabling and restarting Platypush you can easily test this backend with tools like telnet or netcat:
```shell
echo -n '{"type":"request", "target":"hostname", "action":"plugin.action"}' | nc hostname 5555
echo -n '{"type":"request", "action":"plugin.action"}' | nc hostname 5555
```
# Pushbullet backend
@ -651,7 +989,7 @@ You can also communicate the other way around: you can programmatically send pus
You can also connect [IFTTT](https://ifttt.com) to Platypush actions by leveraging Pushbullet. For example, you can create an applet triggered on sunset (date/time channel) to turn on the lights by sending a push like this to your Platypush device:
```json
{"type":"request", "target":"hostname", "action":"light.hue.on"}
{"type":"request", "action":"light.hue.on"}
```
# Kafka backend
@ -830,8 +1168,13 @@ If you want to take a picture through the cURL interface:
```bash
curl -XPOST -H 'Content-Type: application/json' \
-d '{"type":"request", "target":"hostname", "action":"camera.pi.take_picture", "args": {"image_file":"/tmp/my_picture.jpg"}}' \
http://hostname:8008/execute
-H "Authorization: Bearer $TOKEN" -d '{
"type":"request",
"action":"camera.pi.take_picture",
"args": {
"image_file":"/tmp/my_picture.jpg"
}
}' http://hostname:8008/execute
```
# Sensor backends

@ -361,16 +361,6 @@ curl -XPOST -H 'Content-Type: application/json' \
http://hostname:8008/execute
```
# Shell plugin
[Plugin reference](https://docs.platypush.tech/en/latest/platypush/plugins/shell.html)
You can also run custom shell commands on the target machine through the `shell` plugin, that requires no configuration. Example of remote execution through the `pusher` script:
```shell
pusher --target hostname --action shell.exec --cmd "uname -a"
```
# HTTP requests plugin
[Plugin reference](https://docs.platypush.tech/en/latest/platypush/plugins/http.request.html)

@ -369,21 +369,10 @@ This would be a sample snippet for an Apache Kafka configuration:
```yaml
backend.kafka:
pusher: True # Default pusher backend
server: server:9092 # Kafka server and port
topic: platypush # Topic prefix. Note: platypush will create a topic for each device named <topic>.<device_id>
```
Note: specifying `pusher: True` on a backend configuration means that that backend will be the default one used to deliver requests or events to other nodes through the `pusher` script, if no `--backend` option is passed.
## Local backend configuration
```yaml
backend.local:
request_fifo: /tmp/platypush-requests.fifo
response_fifo: /tmp/platypush-responses.fifo
```
## Google Assistant configuration
Follow the steps on the [Google Assistant SDK](https://github.com/googlesamples/assistant-sdk-python/tree/master/google-assistant-sdk) page and get the assistant sample running on your machine.
@ -456,4 +445,3 @@ Now you can take a more in-depth to look to the available:
- [Plugins](plugins)
- [Backends](backends)