forked from platypush/platypush
Updated README
This commit is contained in:
parent
ab2425ebd0
commit
5415f0ccf3
1 changed files with 372 additions and 355 deletions
727
README.md
727
README.md
|
@ -4,22 +4,16 @@ Platypush
|
||||||
[![Build Status](https://ci.platypush.tech/status.svg)](https://ci.platypush.tech/latest.log)
|
[![Build Status](https://ci.platypush.tech/status.svg)](https://ci.platypush.tech/latest.log)
|
||||||
[![Documentation Status](https://ci.platypush.tech/docs/status.svg)](https://ci.platypush.tech/docs/latest.log)
|
[![Documentation Status](https://ci.platypush.tech/docs/status.svg)](https://ci.platypush.tech/docs/latest.log)
|
||||||
[![pip version](https://img.shields.io/pypi/v/platypush.svg?style=flat)](https://pypi.python.org/pypi/platypush/)
|
[![pip version](https://img.shields.io/pypi/v/platypush.svg?style=flat)](https://pypi.python.org/pypi/platypush/)
|
||||||
[![License](https://img.shields.io/github/license/BlackLight/platypush.svg)](https://git.platypush.tech/platypush/platypush/-/blob/master/LICENSE.txt)
|
[![License](https://img.shields.io/github/license/BlackLight/platypush.svg)](https://git.platypush.tech/platypush/platypush/src/branch/master/LICENSE.txt)
|
||||||
[![Last Commit](https://img.shields.io/github/last-commit/BlackLight/platypush.svg)](https://git.platypush.tech/platypush/platypush/-/commits/master/)
|
[![Last Commit](https://img.shields.io/github/last-commit/BlackLight/platypush.svg)](https://git.platypush.tech/platypush/platypush/commits/branch/master)
|
||||||
[![Join chat on Matrix](https://img.shields.io/matrix/:platypush?server_fqdn=matrix.platypush.tech)](https://matrix.to/#/#platypush:matrix.platypush.tech)
|
[![Join chat on Matrix](https://img.shields.io/matrix/:platypush?server_fqdn=matrix.platypush.tech)](https://matrix.to/#/#platypush:matrix.platypush.tech)
|
||||||
[![Contributions](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://git.platypush.tech/platypush/platypush/-/blob/master/CONTRIBUTING.md)
|
[![Contributions](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://git.platypush.tech/platypush/platypush/src/branch/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
<!-- toc -->
|
<!-- toc -->
|
||||||
|
|
||||||
- [Architecture](#architecture)
|
+ [Useful links](#useful-links)
|
||||||
* [Plugins](#plugins)
|
- [Introduction](#introduction)
|
||||||
* [Actions](#actions)
|
+ [What it can do](#what-it-can-do)
|
||||||
* [Backends](#backends)
|
|
||||||
* [Events](#events)
|
|
||||||
* [Hooks](#hooks)
|
|
||||||
* [Procedures](#procedures)
|
|
||||||
* [Cronjobs](#cronjobs)
|
|
||||||
* [The web interface](#the-web-interface)
|
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
* [System installation](#system-installation)
|
* [System installation](#system-installation)
|
||||||
+ [Install through `pip`](#install-through-pip)
|
+ [Install through `pip`](#install-through-pip)
|
||||||
|
@ -31,17 +25,27 @@ Platypush
|
||||||
+ [Check the instructions reported in the documentation](#check-the-instructions-reported-in-the-documentation)
|
+ [Check the instructions reported in the documentation](#check-the-instructions-reported-in-the-documentation)
|
||||||
* [Virtual environment installation](#virtual-environment-installation)
|
* [Virtual environment installation](#virtual-environment-installation)
|
||||||
* [Docker installation](#docker-installation)
|
* [Docker installation](#docker-installation)
|
||||||
|
- [Architecture](#architecture)
|
||||||
|
* [Plugins](#plugins)
|
||||||
|
* [Actions](#actions)
|
||||||
|
* [Backends](#backends)
|
||||||
|
* [Events](#events)
|
||||||
|
* [Hooks](#hooks)
|
||||||
|
* [Procedures](#procedures)
|
||||||
|
* [Cronjobs](#cronjobs)
|
||||||
|
* [Entities](#entities)
|
||||||
|
* [The web interface](#the-web-interface)
|
||||||
- [Mobile app](#mobile-app)
|
- [Mobile app](#mobile-app)
|
||||||
- [Tests](#tests)
|
- [Tests](#tests)
|
||||||
- [Funding](#funding)
|
- [Funding](#funding)
|
||||||
|
|
||||||
<!-- tocstop -->
|
<!-- tocstop -->
|
||||||
|
|
||||||
|
#### Useful links
|
||||||
- Recommended read: [**Getting started with Platypush**](https://blog.platypush.tech/article/Ultimate-self-hosted-automation-with-Platypush).
|
- Recommended read: [**Getting started with Platypush**](https://blog.platypush.tech/article/Ultimate-self-hosted-automation-with-Platypush).
|
||||||
|
|
||||||
- The [blog](https://blog.platypush.tech) is in general a good place to get
|
- The [blog](https://blog.platypush.tech) is a good place to get more insights
|
||||||
more insights on what you can build with it and inspiration about possible
|
and inspiration on what you can build.
|
||||||
usages.
|
|
||||||
|
|
||||||
- The [wiki](https://git.platypush.tech/platypush/platypush/wiki) also
|
- The [wiki](https://git.platypush.tech/platypush/platypush/wiki) also
|
||||||
contains many resources on getting started.
|
contains many resources on getting started.
|
||||||
|
@ -49,19 +53,19 @@ Platypush
|
||||||
- Extensive documentation for all the available integrations and messages [is
|
- Extensive documentation for all the available integrations and messages [is
|
||||||
available](https://docs.platypush.tech/).
|
available](https://docs.platypush.tech/).
|
||||||
|
|
||||||
- If you have issues/feature requests/enhancement ideas please [create an
|
- If you have issues/feature requests/enhancements please [create an
|
||||||
issue](https://git.platypush.tech/platypush/platypush/-/issues).
|
issue](https://git.platypush.tech/platypush/platypush/issues).
|
||||||
|
|
||||||
- A [Reddit channel](https://www.reddit.com/r/platypush) is also available for
|
|
||||||
more general questions.
|
|
||||||
|
|
||||||
- A [Matrix instance](https://matrix.to/#/#platypush:matrix.platypush.tech) is
|
- A [Matrix instance](https://matrix.to/#/#platypush:matrix.platypush.tech) is
|
||||||
also available if you are looking for more interactive support.
|
available if you are looking for interactive support.
|
||||||
|
|
||||||
---
|
- A [Reddit channel](https://www.reddit.com/r/platypush) is available for
|
||||||
|
general questions.
|
||||||
|
|
||||||
Platypush is a general-purpose extensible platform for automation and
|
## Introduction
|
||||||
integration across multiple services and devices.
|
|
||||||
|
Platypush is a general-purpose extensible platform for automation across
|
||||||
|
multiple services and devices.
|
||||||
|
|
||||||
It enables users to create their own self-hosted pieces of automation based on
|
It enables users to create their own self-hosted pieces of automation based on
|
||||||
events (*if this happens then do that*)
|
events (*if this happens then do that*)
|
||||||
|
@ -70,16 +74,15 @@ everything you need to visualize and control under one roof.
|
||||||
|
|
||||||
It takes some concepts from [IFTTT](https://ifttt.com),
|
It takes some concepts from [IFTTT](https://ifttt.com),
|
||||||
[Tasker](https://tasker.joaoapps.com/), [Microsoft
|
[Tasker](https://tasker.joaoapps.com/), [Microsoft
|
||||||
Flow](https://flow.microsoft.com), [PushBullet](https://pushbullet.com) and
|
Flow](https://flow.microsoft.com) and [Home
|
||||||
[Home Assistant](https://www.home-assistant.io/) to provide an environment
|
Assistant](https://www.home-assistant.io/) to provide an environment where the
|
||||||
where the user can easily connect things together.
|
user can easily connect things together.
|
||||||
|
|
||||||
Its ideal home is a single-board computer like a RaspberryPi that you can
|
It's built with compatibility and flexibility in mind, and it can easily run on
|
||||||
configure to orchestrate any home automation and cloud automation in your own
|
any device that can run a Python interpreter - from a Raspberry Pi zero, to an
|
||||||
living room or garage, but it can easily run on any device that can run a
|
old smartphone, to a beefy server.
|
||||||
Python interpreter, and the bar for the hardware requirements is very low as
|
|
||||||
well - I use it to run pieces of automation on devices as powerful as a
|
#### What it can do
|
||||||
RaspberryPi Zero or an old Nokia N900 with Linux.
|
|
||||||
|
|
||||||
You can use Platypush to do things like:
|
You can use Platypush to do things like:
|
||||||
|
|
||||||
|
@ -110,323 +113,7 @@ You can use Platypush to do things like:
|
||||||
- [Create a custom single hub for Zigbee and Z-Wave smart devices](https://blog.platypush.tech/article/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge)
|
- [Create a custom single hub for Zigbee and Z-Wave smart devices](https://blog.platypush.tech/article/Transform-a-RaspberryPi-into-a-universal-Zigbee-and-Z-Wave-bridge)
|
||||||
- Build your own web dashboard with calendar, weather, news and music controls
|
- Build your own web dashboard with calendar, weather, news and music controls
|
||||||
(basically, anything that has a Platypush web widget)
|
(basically, anything that has a Platypush web widget)
|
||||||
- ...and much more (basically, anything that comes with a [Platypush plugin](https://docs.platypush.tech/en/latest/plugins.html))
|
- ...and much more (basically, anything that comes with a [Platypush plugin](https://docs.platypush.tech))
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
The architecture of Platypush consists of a few simple pieces, orchestrated by
|
|
||||||
a configuration file stored by default under
|
|
||||||
[`~/.config/platypush/config.yaml`](https://git.platypush.tech/platypush/platypush/-/blob/master/examples/conf/config.yaml):
|
|
||||||
|
|
||||||
### Plugins
|
|
||||||
|
|
||||||
[Full list](https://docs.platypush.tech/en/latest/plugins.html)
|
|
||||||
|
|
||||||
Plugins are integrations that do things - like [modify
|
|
||||||
files](https://docs.platypush.tech/en/latest/platypush/plugins/file.html),
|
|
||||||
[train and evaluate machine learning
|
|
||||||
models](https://docs.platypush.tech/en/latest/platypush/plugins/tensorflow.html),
|
|
||||||
[control
|
|
||||||
cameras](https://docs.platypush.tech/en/latest/platypush/plugins/camera.pi.html),
|
|
||||||
[read
|
|
||||||
sensors](https://docs.platypush.tech/en/latest/platypush/plugins/gpio.sensor.dht.html),
|
|
||||||
[parse a web
|
|
||||||
page](https://docs.platypush.tech/en/latest/platypush/plugins/http.webpage.html),
|
|
||||||
[control
|
|
||||||
lights](https://docs.platypush.tech/en/latest/platypush/plugins/light.hue.html),
|
|
||||||
[send
|
|
||||||
emails](https://docs.platypush.tech/en/latest/platypush/plugins/mail.smtp.html),
|
|
||||||
[control
|
|
||||||
Chromecasts](https://docs.platypush.tech/en/latest/platypush/plugins/media.chromecast.html),
|
|
||||||
[run voice
|
|
||||||
queries](https://docs.platypush.tech/en/latest/platypush/plugins/assistant.google.html),
|
|
||||||
[handle torrent
|
|
||||||
transfers](https://docs.platypush.tech/en/latest/platypush/plugins/torrent.html)
|
|
||||||
or control
|
|
||||||
[Zigbee](https://docs.platypush.tech/en/latest/platypush/plugins/zigbee.mqtt.html)
|
|
||||||
or [Z-Wave](https://docs.platypush.tech/en/latest/platypush/plugins/zwave.html)
|
|
||||||
devices.
|
|
||||||
|
|
||||||
The configuration of a plugin matches one-on-one that of its documented class
|
|
||||||
constructor, so it's very straightforward to write a configuration for a plugin
|
|
||||||
by reading its documentation:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
light.hue:
|
|
||||||
# Groups that will be controlled by default
|
|
||||||
groups:
|
|
||||||
- Living Room
|
|
||||||
- Hall
|
|
||||||
```
|
|
||||||
|
|
||||||
### Actions
|
|
||||||
|
|
||||||
Plugins expose *actions*, that match one-on-one the plugin class methods
|
|
||||||
denoted by `@action`, so it's very straightforward to invoke plugin actions by
|
|
||||||
just reading the plugin documentation. They can be invoked directly from your
|
|
||||||
own scripts or they can be sent to the platform through any supported channel
|
|
||||||
as simple JSON messages:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "request",
|
|
||||||
"action": "light.hue.on",
|
|
||||||
"args": {
|
|
||||||
"lights": ["Entrance Bulb"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Backends
|
|
||||||
|
|
||||||
[Full list](https://docs.platypush.tech/en/latest/backends.html)
|
|
||||||
|
|
||||||
They are background services that either listen for messages on channels (like
|
|
||||||
an [HTTP
|
|
||||||
backend](https://docs.platypush.tech/en/latest/platypush/backend/http.html), an
|
|
||||||
[MQTT
|
|
||||||
instance](https://docs.platypush.tech/en/latest/platypush/backend/mqtt.html), a
|
|
||||||
[Kafka
|
|
||||||
instance](https://docs.platypush.tech/en/latest/platypush/backend/kafka.html),
|
|
||||||
[Pushbullet](https://docs.platypush.tech/en/latest/platypush/backend/pushbullet.html)
|
|
||||||
etc.) or monitor a device or a service for events (like a
|
|
||||||
[sensor](https://docs.platypush.tech/en/latest/platypush/backend/sensor.html),
|
|
||||||
a custom [voice
|
|
||||||
assistant](https://docs.platypush.tech/en/latest/platypush/backend/assistant.google.html),
|
|
||||||
a bridge running on a
|
|
||||||
[Zigbee](https://docs.platypush.tech/en/latest/platypush/backend/zigbee.mqtt.html)
|
|
||||||
or
|
|
||||||
[Z-Wave](https://docs.platypush.tech/en/latest/platypush/backend/zwave.html),
|
|
||||||
an [NFC card
|
|
||||||
reader](https://docs.platypush.tech/en/latest/platypush/backend/nfc.html), a
|
|
||||||
[MIDI
|
|
||||||
device](https://docs.platypush.tech/en/latest/platypush/backend/midi.html), a
|
|
||||||
[Telegram
|
|
||||||
channel](https://docs.platypush.tech/en/latest/platypush/backend/chat.telegram.html),
|
|
||||||
a [Bluetooth
|
|
||||||
scanner](https://docs.platypush.tech/en/latest/platypush/backend/bluetooth.scanner.ble.html)
|
|
||||||
etc.).
|
|
||||||
|
|
||||||
If a backend supports the execution of requests (e.g. HTTP, MQTT, Kafka,
|
|
||||||
Websocket and TCP) then you can send requests to these services in JSON format.
|
|
||||||
For example, in the case of the HTTP backend:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# Get a token
|
|
||||||
curl -XPOST -H 'Content-Type: application/json' -d '
|
|
||||||
{
|
|
||||||
"username": "$YOUR_USER",
|
|
||||||
"password": "$YOUR_PASSWORD"
|
|
||||||
}' http://host:8008/auth
|
|
||||||
|
|
||||||
# Execute a request
|
|
||||||
|
|
||||||
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://host:8008/execute
|
|
||||||
```
|
|
||||||
|
|
||||||
### Events
|
|
||||||
|
|
||||||
[Full list](https://docs.platypush.tech/en/latest/events.html)
|
|
||||||
|
|
||||||
When a certain event occurs (e.g. a JSON request is received, or a [Bluetooth
|
|
||||||
device is
|
|
||||||
connected](https://docs.platypush.tech/en/latest/platypush/events/bluetooth.html#platypush.message.event.bluetooth.BluetoothDeviceConnectedEvent),
|
|
||||||
or a [Flic button is
|
|
||||||
pressed](https://docs.platypush.tech/en/latest/platypush/events/button.flic.html#platypush.message.event.button.flic.FlicButtonEvent),
|
|
||||||
or some [speech is detected on the voice assistant
|
|
||||||
service](https://docs.platypush.tech/en/latest/platypush/events/assistant.html#platypush.message.event.assistant.SpeechRecognizedEvent),
|
|
||||||
or an [RSS feed has new
|
|
||||||
items](https://docs.platypush.tech/en/latest/platypush/events/http.rss.html#platypush.message.event.http.rss.NewFeedEvent),
|
|
||||||
or a [new email is
|
|
||||||
received](https://docs.platypush.tech/en/latest/platypush/events/mail.html#platypush.message.event.mail.MailReceivedEvent),
|
|
||||||
or a [new track is
|
|
||||||
played](https://docs.platypush.tech/en/latest/platypush/events/music.html#platypush.message.event.music.NewPlayingTrackEvent),
|
|
||||||
or an [NFC tag is
|
|
||||||
detected](https://docs.platypush.tech/en/latest/platypush/events/nfc.html#platypush.message.event.nfc.NFCTagDetectedEvent),
|
|
||||||
or [new sensor data is
|
|
||||||
available](https://docs.platypush.tech/en/latest/platypush/events/sensor.html#platypush.message.event.sensor.SensorDataChangeEvent),
|
|
||||||
or [a value of a Zigbee device
|
|
||||||
changes](https://docs.platypush.tech/en/latest/platypush/events/zigbee.mqtt.html#platypush.message.event.zigbee.mqtt.ZigbeeMqttDevicePropertySetEvent),
|
|
||||||
etc.), the associated backend will trigger an
|
|
||||||
[event](https://docs.platypush.tech/en/latest/events.html).
|
|
||||||
|
|
||||||
### Hooks
|
|
||||||
|
|
||||||
Event hooks are custom pieces of logic that will be run when a certain event is
|
|
||||||
triggered. Hooks are the glue that connects events to actions, exposing a
|
|
||||||
paradigm similar to IFTTT (_if a certain event happens then run these
|
|
||||||
actions_). They can declared as:
|
|
||||||
|
|
||||||
- Sections of the [`config.yaml`](https://git.platypush.tech/platypush/platypush/-/blob/master/examples/conf/config.yaml).
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
event.hook.SearchSongVoiceCommand:
|
|
||||||
if:
|
|
||||||
type: platypush.message.event.assistant.SpeechRecognizedEvent
|
|
||||||
phrase: "play ${title} by ${artist}"
|
|
||||||
then:
|
|
||||||
- action: music.mpd.clear
|
|
||||||
- action: music.mpd.search
|
|
||||||
args:
|
|
||||||
filter:
|
|
||||||
artist: ${artist}
|
|
||||||
title: ${title}
|
|
||||||
|
|
||||||
- if ${len(output)}:
|
|
||||||
- action: music.mpd.play
|
|
||||||
args:
|
|
||||||
resource: ${output[0]['file']}
|
|
||||||
```
|
|
||||||
|
|
||||||
- Stand-alone Python scripts stored under `~/.config/platypush/scripts` and
|
|
||||||
will be dynamically imported at start time.
|
|
||||||
[Example](https://git.platypush.tech/platypush/platypush/-/blob/master/examples/conf/hook.py):
|
|
||||||
|
|
||||||
```python
|
|
||||||
from platypush.event.hook import hook
|
|
||||||
from platypush.utils import run
|
|
||||||
from platypush.message.event.assistant import SpeechRecognizedEvent
|
|
||||||
|
|
||||||
@hook(SpeechRecognizedEvent, phrase='play ${title} by ${artist}')
|
|
||||||
def on_music_play_command(event, title=None, artist=None, **context):
|
|
||||||
results = run('music.mpd.search', filter={
|
|
||||||
'artist': artist,
|
|
||||||
'title': title,
|
|
||||||
})
|
|
||||||
|
|
||||||
if results:
|
|
||||||
run('music.mpd.play', results[0]['file'])
|
|
||||||
```
|
|
||||||
|
|
||||||
### Procedures
|
|
||||||
|
|
||||||
Procedures are pieces of custom logic that can be executed as atomic actions
|
|
||||||
using `procedure.<name>` as an action name.
|
|
||||||
|
|
||||||
They can be defined either in the `config.yaml` or as Python scripts stored
|
|
||||||
under `~/.config/platypush/scripts` - provided that the procedure is also
|
|
||||||
imported in `~/.config/platypush/scripts/__init__.py` so it can be discovered
|
|
||||||
by the service.
|
|
||||||
|
|
||||||
YAML example for a procedure that can be executed when we arrive home and turns
|
|
||||||
on the lights if the luminosity is lower that a certain thresholds, says a
|
|
||||||
welcome home message using the TTS engine and starts playing the music:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
procedure.at_home:
|
|
||||||
# Get luminosity data from a sensor - e.g. LTR559
|
|
||||||
- action: gpio.sensor.ltr559.get_data
|
|
||||||
|
|
||||||
# If it's lower than a certain threshold, turn on the lights
|
|
||||||
- if ${int(light or 0) < 110}:
|
|
||||||
- action: light.hue.on
|
|
||||||
|
|
||||||
# Say a welcome home message
|
|
||||||
- action: tts.google.say
|
|
||||||
args:
|
|
||||||
text: Welcome home
|
|
||||||
|
|
||||||
# Play the music
|
|
||||||
- action: music.mpd.play
|
|
||||||
```
|
|
||||||
|
|
||||||
Python example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Content of ~/.config/platypush/scripts/home.py
|
|
||||||
from platypush.procedure import procedure
|
|
||||||
from platypush.utils import run
|
|
||||||
|
|
||||||
@procedure
|
|
||||||
def at_home(**context):
|
|
||||||
sensor_data = run('gpio.sensor.ltr559.get_data')
|
|
||||||
if sensor_data['light'] < 110:
|
|
||||||
run('light.hue.on')
|
|
||||||
|
|
||||||
run('tts.google.say', text='Welcome home')
|
|
||||||
run('music.mpd.play')
|
|
||||||
```
|
|
||||||
|
|
||||||
In either case, you can easily trigger the at-home procedure by sending an
|
|
||||||
action request message to a backend - for example, over the HTTP backend:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
curl -XPOST -H 'Content-Type: application/json' \
|
|
||||||
-H "Authorization: Bearer $YOUR_TOKEN" -d '
|
|
||||||
{
|
|
||||||
"type": "request",
|
|
||||||
"action": "procedure.at_home"
|
|
||||||
}' http://host:8008/execute
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cronjobs
|
|
||||||
|
|
||||||
Cronjobs are pieces of logic that will be run at regular intervals, expressed
|
|
||||||
in crontab-compatible syntax. They can be defined either in the `config.yaml`
|
|
||||||
or as Python scripts stored under `~/.config/platypush/scripts` as functions
|
|
||||||
labelled by the `@cron` decorator.
|
|
||||||
|
|
||||||
Note that seconds are also supported (unlike the standard crontab definition),
|
|
||||||
but, for back-compatibility with the standard crontab format, they are at the
|
|
||||||
end of the cron expression, so the expression is actually in the format
|
|
||||||
`<minute> <hour> <day_of_month> <month> <day_of_week> <second>`.
|
|
||||||
|
|
||||||
YAML example for a cronjob that is executed every 30 seconds and checks if a
|
|
||||||
Bluetooth device is nearby:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
cron.check_bt_device:
|
|
||||||
cron_expression: '* * * * * */30'
|
|
||||||
actions:
|
|
||||||
- action: bluetooth.lookup_name
|
|
||||||
args:
|
|
||||||
addr: XX:XX:XX:XX:XX:XX
|
|
||||||
|
|
||||||
- if ${name}:
|
|
||||||
- action: procedure.on_device_on
|
|
||||||
- else:
|
|
||||||
- action: procedure.on_device_off
|
|
||||||
```
|
|
||||||
|
|
||||||
Python example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Content of ~/.config/platypush/scripts/bt_cron.py
|
|
||||||
from platypush.cron import cron
|
|
||||||
from platypush.utils import run
|
|
||||||
|
|
||||||
@cron('* * * * * */30')
|
|
||||||
def check_bt_device(**context):
|
|
||||||
name = run('bluetooth.lookup_name').get('name')
|
|
||||||
if name:
|
|
||||||
# on_device_on logic here
|
|
||||||
else:
|
|
||||||
# on_device_off logic here
|
|
||||||
```
|
|
||||||
|
|
||||||
### The web interface
|
|
||||||
|
|
||||||
If
|
|
||||||
[`backend.http`](https://docs.platypush.tech/en/latest/platypush/backend/http.html)
|
|
||||||
is enabled then a web interface will be provided by default on
|
|
||||||
`http://host:8008/`. Besides using the `/execute` endpoint for running
|
|
||||||
requests, the built-in web server also provides a full-featured interface that
|
|
||||||
groups together the controls for most of the plugins - e.g. sensors, switches,
|
|
||||||
music controls and search, media library and torrent management, lights,
|
|
||||||
Zigbee/Z-Wave devices and so on. The UI is responsive and mobile-friendly.
|
|
||||||
|
|
||||||
The web service also provides means for the user to create [custom
|
|
||||||
dashboards](https://git.platypush.tech/platypush/platypush/-/blob/master/examples/conf/dashboard.xml)
|
|
||||||
that can be used to show information from multiple sources on a large screen.
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -435,10 +122,10 @@ that can be used to show information from multiple sources on a large screen.
|
||||||
Platypush uses Redis to deliver and store requests and temporary messages:
|
Platypush uses Redis to deliver and store requests and temporary messages:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Example for Debian-based distributions
|
# Example for Debian-based distributions
|
||||||
[sudo] apt-get install redis-server
|
[sudo] apt-get install redis-server
|
||||||
|
|
||||||
# Enable and start the service
|
# Enable and start the service
|
||||||
[sudo] systemctl enable redis
|
[sudo] systemctl enable redis
|
||||||
[sudo] systemctl start redis
|
[sudo] systemctl start redis
|
||||||
```
|
```
|
||||||
|
@ -475,7 +162,7 @@ or tags.
|
||||||
git clone https://git.platypush.tech/platypush/platypush.git
|
git clone https://git.platypush.tech/platypush/platypush.git
|
||||||
cd platypush
|
cd platypush
|
||||||
[sudo] pip install .
|
[sudo] pip install .
|
||||||
# Or
|
# Or
|
||||||
[sudo] python3 setup.py install
|
[sudo] python3 setup.py install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -489,7 +176,7 @@ ways to check the dependencies required by an extension:
|
||||||
|
|
||||||
All the extensions that require extra dependencies are listed in the
|
All the extensions that require extra dependencies are listed in the
|
||||||
[`extras_require` section under
|
[`extras_require` section under
|
||||||
`setup.py`](https://git.platypush.tech/platypush/platypush/-/blob/master/setup.py#L72).
|
`setup.py`](https://git.platypush.tech/platypush/platypush/src/branch/master/setup.py#L84).
|
||||||
|
|
||||||
#### Install via `manifest.yaml`
|
#### Install via `manifest.yaml`
|
||||||
|
|
||||||
|
@ -532,7 +219,7 @@ platypush
|
||||||
|
|
||||||
It's advised to run it as a systemd service though - simply copy the provided
|
It's advised to run it as a systemd service though - simply copy the provided
|
||||||
[`.service`
|
[`.service`
|
||||||
file](https://git.platypush.tech/platypush/platypush/-/blob/master/examples/systemd/platypush.service)
|
file](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/systemd/platypush.service)
|
||||||
to `~/.config/systemd/user`, check if the path of `platypush` matches the path
|
to `~/.config/systemd/user`, check if the path of `platypush` matches the path
|
||||||
where it's installed on your system, and start the service via `systemctl`:
|
where it's installed on your system, and start the service via `systemctl`:
|
||||||
|
|
||||||
|
@ -613,6 +300,336 @@ directory in the same folder as the `config.yaml`.
|
||||||
|
|
||||||
[Wiki instructions](https://git.platypush.tech/platypush/platypush/wiki/Run-platypush-in-a-container)
|
[Wiki instructions](https://git.platypush.tech/platypush/platypush/wiki/Run-platypush-in-a-container)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The architecture of Platypush consists of a few simple pieces, orchestrated by
|
||||||
|
a configuration file stored by default under
|
||||||
|
[`~/.config/platypush/config.yaml`](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/conf/config.yaml):
|
||||||
|
|
||||||
|
### Plugins
|
||||||
|
|
||||||
|
[Full list](https://docs.platypush.tech/en/latest/plugins.html)
|
||||||
|
|
||||||
|
Plugins are integrations that do things - like [modify
|
||||||
|
files](https://docs.platypush.tech/en/latest/platypush/plugins/file.html),
|
||||||
|
[train and evaluate machine learning
|
||||||
|
models](https://docs.platypush.tech/en/latest/platypush/plugins/tensorflow.html),
|
||||||
|
[control
|
||||||
|
cameras](https://docs.platypush.tech/en/latest/platypush/plugins/camera.pi.html),
|
||||||
|
[read
|
||||||
|
sensors](https://docs.platypush.tech/en/latest/platypush/plugins/gpio.sensor.dht.html),
|
||||||
|
[parse a web
|
||||||
|
page](https://docs.platypush.tech/en/latest/platypush/plugins/http.webpage.html),
|
||||||
|
[control
|
||||||
|
lights](https://docs.platypush.tech/en/latest/platypush/plugins/light.hue.html),
|
||||||
|
[send
|
||||||
|
emails](https://docs.platypush.tech/en/latest/platypush/plugins/mail.smtp.html),
|
||||||
|
[control
|
||||||
|
Chromecasts](https://docs.platypush.tech/en/latest/platypush/plugins/media.chromecast.html),
|
||||||
|
[run voice
|
||||||
|
queries](https://docs.platypush.tech/en/latest/platypush/plugins/assistant.google.html),
|
||||||
|
[handle torrent
|
||||||
|
transfers](https://docs.platypush.tech/en/latest/platypush/plugins/torrent.html)
|
||||||
|
or control
|
||||||
|
[Zigbee](https://docs.platypush.tech/en/latest/platypush/plugins/zigbee.mqtt.html)
|
||||||
|
or [Z-Wave](https://docs.platypush.tech/en/latest/platypush/plugins/zwave.html)
|
||||||
|
devices.
|
||||||
|
|
||||||
|
The configuration of a plugin matches one-on-one that of its documented class
|
||||||
|
constructor, so it's very straightforward to write a configuration for a plugin
|
||||||
|
by reading its documentation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
light.hue:
|
||||||
|
# Groups that will be controlled by default
|
||||||
|
groups:
|
||||||
|
- Living Room
|
||||||
|
- Hall
|
||||||
|
```
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
Plugins expose *actions*, that match one-on-one the plugin class methods
|
||||||
|
denoted by `@action`, so it's very straightforward to invoke plugin actions by
|
||||||
|
just reading the plugin documentation. They can be invoked directly from your
|
||||||
|
own scripts or they can be sent to the platform through any supported channel
|
||||||
|
as simple JSON messages:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "request",
|
||||||
|
"action": "light.hue.on",
|
||||||
|
"args": {
|
||||||
|
"lights": ["Entrance Bulb"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backends
|
||||||
|
|
||||||
|
[Full list](https://docs.platypush.tech/en/latest/backends.html)
|
||||||
|
|
||||||
|
They are background services that listen for messages on channels (like
|
||||||
|
an [HTTP
|
||||||
|
backend](https://docs.platypush.tech/en/latest/platypush/backend/http.html), an
|
||||||
|
[MQTT
|
||||||
|
instance](https://docs.platypush.tech/en/latest/platypush/backend/mqtt.html), a
|
||||||
|
[Kafka
|
||||||
|
instance](https://docs.platypush.tech/en/latest/platypush/backend/kafka.html),
|
||||||
|
[Pushbullet](https://docs.platypush.tech/en/latest/platypush/backend/pushbullet.html)
|
||||||
|
etc.).
|
||||||
|
|
||||||
|
If a backend supports the execution of requests (e.g. HTTP, MQTT, Kafka,
|
||||||
|
Websocket and TCP) then you can send requests to these services in JSON format.
|
||||||
|
For example, in the case of the HTTP backend:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Get a token
|
||||||
|
curl -XPOST -H 'Content-Type: application/json' -d '
|
||||||
|
{
|
||||||
|
"username": "$YOUR_USER",
|
||||||
|
"password": "$YOUR_PASSWORD"
|
||||||
|
}' http://host:8008/auth
|
||||||
|
|
||||||
|
# Execute a request
|
||||||
|
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://host:8008/execute
|
||||||
|
```
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
[Full list](https://docs.platypush.tech/en/latest/events.html)
|
||||||
|
|
||||||
|
When a certain event occurs (e.g. a JSON request is received, or a [Bluetooth
|
||||||
|
device is
|
||||||
|
connected](https://docs.platypush.tech/en/latest/platypush/events/bluetooth.html#platypush.message.event.bluetooth.BluetoothDeviceConnectedEvent),
|
||||||
|
or a [Flic button is
|
||||||
|
pressed](https://docs.platypush.tech/en/latest/platypush/events/button.flic.html#platypush.message.event.button.flic.FlicButtonEvent),
|
||||||
|
or some [speech is detected on the voice assistant
|
||||||
|
service](https://docs.platypush.tech/en/latest/platypush/events/assistant.html#platypush.message.event.assistant.SpeechRecognizedEvent),
|
||||||
|
or an [RSS feed has new
|
||||||
|
items](https://docs.platypush.tech/en/latest/platypush/events/http.rss.html#platypush.message.event.http.rss.NewFeedEvent),
|
||||||
|
or a [new email is
|
||||||
|
received](https://docs.platypush.tech/en/latest/platypush/events/mail.html#platypush.message.event.mail.MailReceivedEvent),
|
||||||
|
or a [new track is
|
||||||
|
played](https://docs.platypush.tech/en/latest/platypush/events/music.html#platypush.message.event.music.NewPlayingTrackEvent),
|
||||||
|
or an [NFC tag is
|
||||||
|
detected](https://docs.platypush.tech/en/latest/platypush/events/nfc.html#platypush.message.event.nfc.NFCTagDetectedEvent),
|
||||||
|
or [new sensor data is
|
||||||
|
available](https://docs.platypush.tech/en/latest/platypush/events/sensor.html#platypush.message.event.sensor.SensorDataChangeEvent),
|
||||||
|
or [a value of a Zigbee device
|
||||||
|
changes](https://docs.platypush.tech/en/latest/platypush/events/zigbee.mqtt.html#platypush.message.event.zigbee.mqtt.ZigbeeMqttDevicePropertySetEvent),
|
||||||
|
etc.), the associated backend will trigger an
|
||||||
|
[event](https://docs.platypush.tech/en/latest/events.html).
|
||||||
|
|
||||||
|
### Hooks
|
||||||
|
|
||||||
|
Event hooks are custom pieces of logic that will be run when a certain event is
|
||||||
|
triggered. Hooks are the glue that connects events to actions, exposing a
|
||||||
|
paradigm similar to IFTTT (_if a certain event happens then run these
|
||||||
|
actions_). They can declared as:
|
||||||
|
|
||||||
|
- Sections of the [`config.yaml`](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/conf/config.yaml).
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
event.hook.SearchSongVoiceCommand:
|
||||||
|
if:
|
||||||
|
type: platypush.message.event.assistant.SpeechRecognizedEvent
|
||||||
|
phrase: "play ${title} by ${artist}"
|
||||||
|
then:
|
||||||
|
- action: music.mpd.clear
|
||||||
|
- action: music.mpd.search
|
||||||
|
args:
|
||||||
|
filter:
|
||||||
|
artist: ${artist}
|
||||||
|
title: ${title}
|
||||||
|
|
||||||
|
- if ${len(output)}:
|
||||||
|
- action: music.mpd.play
|
||||||
|
args:
|
||||||
|
resource: ${output[0]['file']}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Stand-alone Python scripts stored under `~/.config/platypush/scripts` and
|
||||||
|
will be dynamically imported at start time.
|
||||||
|
[Example](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/conf/hook.py):
|
||||||
|
|
||||||
|
```python
|
||||||
|
from platypush.event.hook import hook
|
||||||
|
from platypush.utils import run
|
||||||
|
from platypush.message.event.assistant import SpeechRecognizedEvent
|
||||||
|
|
||||||
|
@hook(SpeechRecognizedEvent, phrase='play ${title} by ${artist}')
|
||||||
|
def on_music_play_command(event, title=None, artist=None, **context):
|
||||||
|
results = run('music.mpd.search', filter={
|
||||||
|
'artist': artist,
|
||||||
|
'title': title,
|
||||||
|
})
|
||||||
|
|
||||||
|
if results:
|
||||||
|
run('music.mpd.play', results[0]['file'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Procedures
|
||||||
|
|
||||||
|
Procedures are pieces of custom logic that can be executed as atomic actions
|
||||||
|
using `procedure.<name>` as an action name.
|
||||||
|
|
||||||
|
They can be defined either in the `config.yaml` or as Python scripts stored
|
||||||
|
under `~/.config/platypush/scripts` - provided that the procedure is also
|
||||||
|
imported in `~/.config/platypush/scripts/__init__.py` so it can be discovered
|
||||||
|
by the service.
|
||||||
|
|
||||||
|
YAML example for a procedure that can be executed when we arrive home and turns
|
||||||
|
on the lights if the luminosity is lower that a certain thresholds, says a
|
||||||
|
welcome home message using the TTS engine and starts playing the music:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
procedure.at_home:
|
||||||
|
# Get luminosity data from a sensor - e.g. LTR559
|
||||||
|
- action: gpio.sensor.ltr559.get_data
|
||||||
|
|
||||||
|
# If it's lower than a certain threshold, turn on the lights
|
||||||
|
- if ${int(light or 0) < 110}:
|
||||||
|
- action: light.hue.on
|
||||||
|
|
||||||
|
# Say a welcome home message
|
||||||
|
- action: tts.google.say
|
||||||
|
args:
|
||||||
|
text: Welcome home
|
||||||
|
|
||||||
|
# Play the music
|
||||||
|
- action: music.mpd.play
|
||||||
|
```
|
||||||
|
|
||||||
|
Python example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Content of ~/.config/platypush/scripts/home.py
|
||||||
|
from platypush.procedure import procedure
|
||||||
|
from platypush.utils import run
|
||||||
|
|
||||||
|
@procedure
|
||||||
|
def at_home(**context):
|
||||||
|
sensor_data = run('gpio.sensor.ltr559.get_data')
|
||||||
|
if sensor_data['light'] < 110:
|
||||||
|
run('light.hue.on')
|
||||||
|
|
||||||
|
run('tts.google.say', text='Welcome home')
|
||||||
|
run('music.mpd.play')
|
||||||
|
```
|
||||||
|
|
||||||
|
In either case, you can easily trigger the at-home procedure by sending an
|
||||||
|
action request message to a backend - for example, over the HTTP backend:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -XPOST -H 'Content-Type: application/json' \
|
||||||
|
-H "Authorization: Bearer $YOUR_TOKEN" -d '
|
||||||
|
{
|
||||||
|
"type": "request",
|
||||||
|
"action": "procedure.at_home"
|
||||||
|
}' http://host:8008/execute
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cronjobs
|
||||||
|
|
||||||
|
Cronjobs are pieces of logic that will be run at regular intervals, expressed
|
||||||
|
in crontab-compatible syntax. They can be defined either in the `config.yaml`
|
||||||
|
or as Python scripts stored under `~/.config/platypush/scripts` as functions
|
||||||
|
labelled by the `@cron` decorator.
|
||||||
|
|
||||||
|
Note that seconds are also supported (unlike the standard crontab definition),
|
||||||
|
but, for back-compatibility with the standard crontab format, they are at the
|
||||||
|
end of the cron expression, so the expression is actually in the format
|
||||||
|
`<minute> <hour> <day_of_month> <month> <day_of_week> <second>`.
|
||||||
|
|
||||||
|
YAML example for a cronjob that is executed every 30 seconds and checks if a
|
||||||
|
Bluetooth device is nearby:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
cron.check_bt_device:
|
||||||
|
cron_expression: '* * * * * */30'
|
||||||
|
actions:
|
||||||
|
- action: bluetooth.lookup_name
|
||||||
|
args:
|
||||||
|
addr: XX:XX:XX:XX:XX:XX
|
||||||
|
|
||||||
|
- if ${name}:
|
||||||
|
- action: procedure.on_device_on
|
||||||
|
- else:
|
||||||
|
- action: procedure.on_device_off
|
||||||
|
```
|
||||||
|
|
||||||
|
Python example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Content of ~/.config/platypush/scripts/bt_cron.py
|
||||||
|
from platypush.cron import cron
|
||||||
|
from platypush.utils import run
|
||||||
|
|
||||||
|
@cron('* * * * * */30')
|
||||||
|
def check_bt_device(**context):
|
||||||
|
name = run('bluetooth.lookup_name').get('name')
|
||||||
|
if name:
|
||||||
|
# on_device_on logic here
|
||||||
|
else:
|
||||||
|
# on_device_off logic here
|
||||||
|
```
|
||||||
|
|
||||||
|
### Entities
|
||||||
|
|
||||||
|
Entities are a fundamental building block of Platypush. Most of the
|
||||||
|
integrations will store their state or connected devices in the form of
|
||||||
|
entities - e.g. the sensors detected by the Z-Wave/Zigbee/Bluetooth
|
||||||
|
integration, or the lights connected to a Hue bridge, or your cloud nodes, or
|
||||||
|
your custom Arduino/ESP machinery, and so on.
|
||||||
|
|
||||||
|
Entities provide a consistent interface to interact with your integrations
|
||||||
|
regardless of their type and the plugin that handles them. For instance, all
|
||||||
|
temperature sensors will expose the same interface, regardless if they are
|
||||||
|
Bluetooth or Zigbee sensors, and all the media plugins will expose the same
|
||||||
|
interface, regardless if they manage Chromecasts, Kodi, Plex, Jellyfin or a
|
||||||
|
local VLC player.
|
||||||
|
|
||||||
|
Once you enable the HTTP backend and a few integrations that export entities
|
||||||
|
and register a user, you can query the detected entities via:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -XPOST -H 'Content-Type: application/json' \
|
||||||
|
-H "Authorization: Bearer $YOUR_TOKEN" \
|
||||||
|
-d '{"type":"request", "action":"entities.get"}' \
|
||||||
|
http://localhost:8008/execute
|
||||||
|
```
|
||||||
|
|
||||||
|
All the entities expose the same interface and can be manipulated through the
|
||||||
|
same API. Also, when an entity is updated it always emits an
|
||||||
|
[`EntityUpdateEvent`](https://docs.platypush.tech/platypush/events/entities.html#platypush.message.event.entities.EntityUpdateEvent),
|
||||||
|
so you can easily create hooks that react to these events and act on multiple
|
||||||
|
types of entities.
|
||||||
|
|
||||||
|
### The web interface
|
||||||
|
|
||||||
|
If
|
||||||
|
[`backend.http`](https://docs.platypush.tech/en/latest/platypush/backend/http.html)
|
||||||
|
is enabled then a web interface will be provided by default on
|
||||||
|
`http://host:8008/`. Besides using the `/execute` endpoint for running
|
||||||
|
requests, the built-in web server also provides a full-featured interface that
|
||||||
|
groups together the controls for most of the plugins - e.g. sensors, switches,
|
||||||
|
music controls and search, media library and torrent management, lights,
|
||||||
|
Zigbee/Z-Wave devices and so on. The UI is responsive and mobile-friendly.
|
||||||
|
|
||||||
|
The web service also provides means for the user to create [custom
|
||||||
|
dashboards](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/conf/dashboard.xml)
|
||||||
|
that can be used to show information from multiple sources on a large screen.
|
||||||
|
|
||||||
## Mobile app
|
## Mobile app
|
||||||
|
|
||||||
An [official Android
|
An [official Android
|
||||||
|
|
Loading…
Reference in a new issue