Moved to manifest files for describing plugins and backends and their dependencies

This commit is contained in:
Fabio Manganiello 2021-09-16 17:53:40 +02:00
parent ac0dd95bcc
commit 3bfc5b83ef
437 changed files with 3139 additions and 1121 deletions

View File

@ -1,2 +1,3 @@
recursive-include platypush/backend/http/webapp/dist * recursive-include platypush/backend/http/webapp/dist *
include platypush/plugins/http/webpage/mercury-parser.js include platypush/plugins/http/webpage/mercury-parser.js
global-include manifest.yaml

View File

@ -6,12 +6,12 @@
# and automatically managed the required dependencies, as well as start, # # and automatically managed the required dependencies, as well as start, #
# stop and remove them # # stop and remove them #
# # # #
# @author: Fabio Manganiello <blacklight86@gmail.com> # # @author: Fabio Manganiello <fabio@platypush.tech> #
# @licence: MIT # # @licence: MIT #
############################################################################## ##############################################################################
workdir=$HOME/.local/share/platypush/venv workdir="$HOME/.local/share/platypush/venv"
function build { function build {
cfgfile= cfgfile=
@ -35,88 +35,74 @@ function build {
fi fi
echo "Parsing configuration file" echo "Parsing configuration file"
deps=() pip_cmd=
pkg_cmd=
includes=() includes=()
cmd_exec=()
while read -r line; do while read -r line; do
echo ${line} | egrep '``pip install .+?``' > /dev/null 2>&1 if echo "$line" | grep -E "^pip:\s*"; then
if (( $? != 0 )); then pip_cmd="$(echo "$line" | sed -r -e 's/^pip:\s*(.*)'/\\1/)"
continue elif echo "$line" | grep -E "^packages:\s*"; then
fi pkg_cmd="$(echo "$line" | sed -r -e 's/^packages:\s*(.*)'/\\1/)"
elif echo "$line" | grep -E "^exec:\s*"; then
dep=$(echo ${line} | sed -r -e 's/.*``pip install (.+?)``.*/\1/') cmd_exec+=("$(echo "$line" | sed -r -e 's/^exec:\s*(.*)'/\\1/)")
deps+=("$dep") elif echo "$line" | grep -E "^include:\s*"; then
done <<< $(python <<EOF includes+=("$(echo "$line" | sed -r -e 's/^include:\s*(.*)'/\\1/)")
elif echo "$line" | grep -E "^device_id:\s*"; then
device_id="$(echo "$line" | sed -r -e 's/^device_id:\s*(.*)'/\\1/)"
fi
done <<< "$(python <<EOF
from platypush.config import Config from platypush.config import Config
from platypush.context import get_plugin, get_backend, register_backends from platypush.utils.manifest import get_install_commands_from_conf
Config.init('`realpath ${cfgfile}`') deps = get_install_commands_from_conf('$(realpath "${cfgfile}")')
register_backends() print(f'device_id: {Config.get("device_id")}')
backend_config = Config.get_backends()
for name in Config.get_backends().keys(): if deps.get('pip'):
backend = get_backend(name) print(f'pip: {deps["pip"]}')
print(backend.__doc__)
for name in Config.get_plugins().keys(): if deps.get('packages'):
try: print(f'packages: {deps["packages"]}')
plugin = get_plugin(name)
print(plugin.__doc__)
except:
pass
EOF
)
while read -r include; do for cmd in deps.get('exec', []):
includes+=(${include}) print(f'exec: {cmd}')
done <<< $(python <<EOF
from platypush.config import Config
from platypush.context import get_plugin, get_backend, register_backends
Config.init('`realpath ${cfgfile}`')
for include in Config._included_files: for include in Config._included_files:
print(include) print(f'include: {include}')
EOF EOF
) )"
device_id=$(python <<EOF envdir="${workdir}/${device_id}"
from platypush.config import Config etcdir="${envdir}/etc/platypush"
Config.init('`realpath ${cfgfile}`')
print(Config.get('device_id'))
EOF
)
envdir=${workdir}/${device_id}
etcdir=${envdir}/etc/platypush
echo "Preparing virtual environment for device $device_id" echo "Preparing virtual environment for device $device_id"
mkdir -p "$envdir" mkdir -p "$envdir"
mkdir -p "$etcdir" mkdir -p "$etcdir"
srcdir=`dirname "$cfgfile"` srcdir=$(dirname "$cfgfile")
for ((i=0; $i < ${#includes[@]}; i++)); do for ((i=0; i < ${#includes[@]}; i++)); do
incdir=`dirname "${includes[$i]}"` incdir=$(dirname "${includes[$i]}")
incdir=`realpath --relative-to="$srcdir" "$incdir"` incdir=$(realpath --relative-to="$srcdir" "$incdir")
destdir="$etcdir/$incdir" destdir="$etcdir/$incdir"
mkdir -p "$destdir" mkdir -p "$destdir"
cp "${includes[$i]}" "$destdir" cp "${includes[$i]}" "$destdir"
done done
cp "$cfgfile" "$etcdir/config.yaml" cp "$cfgfile" "$etcdir/config.yaml"
cfgfile=${etcdir}/config.yaml cfgfile="${etcdir}/config.yaml"
python3 -m venv ${envdir} python3 -m venv "${envdir}"
cd ${envdir} cd "${envdir}" || exit 1
source ${envdir}/bin/activate source "${envdir}/bin/activate"
echo "Installing required dependencies" echo "Installing required dependencies"
# shellcheck disable=SC2086
[ -n "${pkg_cmd}" ] && sudo ${pkg_cmd}
[ -n "${pip_cmd}" ] && ${pip_cmd}
for ((i=0; $i < ${#deps[@]}; i++)); do for ((i=0; i < ${#cmd_exec[@]}; i++)); do
echo ${deps[$i]} ${cmd_exec[$i]}
done | sort -u | while read dep; do
pip install ${dep}
done done
pip install --upgrade git+https://git.platypush.tech/platypush/platypush.git pip install --upgrade git+https://git.platypush.tech/platypush/platypush.git
@ -130,44 +116,43 @@ function start {
fi fi
env=$1 env=$1
envdir=${workdir}/${env} envdir="${workdir}/${env}"
logsdir=${envdir}/var/log/platypush logsdir="${envdir}/var/log/platypush"
rundir=${envdir}/var/run rundir="${envdir}/var/run"
pidfile=${rundir}/platypush.pid pidfile="${rundir}/platypush.pid"
cfgfile=${envdir}/etc/platypush/config.yaml cfgfile="${envdir}/etc/platypush/config.yaml"
if [[ ! -d "$envdir" ]]; then if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2 echo "No such directory: $envdir" >&2
exit 1 exit 1
fi fi
mkdir -p ${logsdir} mkdir -p "${logsdir}"
mkdir -p ${rundir} mkdir -p "${rundir}"
if [[ -f "$pidfile" ]]; then if [[ -f "$pidfile" ]]; then
pid=`cat "$pidfile"` if pgrep -F "${pidfile}"; then
if ps -p ${pid} | grep platypush; then echo "Another instance (PID $(cat "${pidfile}")) is running, please stop that instance first"
echo "Another instance (PID $pid) is running, please stop that instance first"
exit 1 exit 1
fi fi
echo "A PID file was found but the process doesn't seem to be running, starting anyway" echo "A PID file was found but the process does not seem to be running, starting anyway"
rm -f "$pidfile" rm -f "$pidfile"
fi fi
python3 -m venv ${envdir} python3 -m venv "${envdir}"
cd ${envdir} cd "${envdir}" || exit 1
source bin/activate source bin/activate
bin/platypush -c "$cfgfile" -P "$pidfile" > ${logsdir}/stdout.log 2> ${logsdir}/stderr.log & bin/platypush -c "$cfgfile" -P "$pidfile" > "${logsdir}/stdout.log" 2> "${logsdir}/stderr.log" &
start_time=`date +'%s'` start_time=$(date +'%s')
timeout=30 timeout=30
while :; do while :; do
[[ -f "$pidfile" ]] && break [[ -f "$pidfile" ]] && break
now=`date +'%s'` now=$(date +'%s')
let elapsed=$now-$start_time elapsed=$(( now-start_time ))
if (( ${elapsed} >= ${timeout} )); then if (( elapsed >= timeout )); then
echo "Platypush instance '$env' didn't start within $timeout seconds" >&2 echo "Platypush instance '$env' did not start within $timeout seconds" >&2
exit 1 exit 1
fi fi
@ -175,7 +160,7 @@ function start {
sleep 1 sleep 1
done done
pid=`cat "$pidfile"` pid=$(cat "$pidfile")
echo echo
echo "Platypush environment $env started with PID $pid, logs dir: $logsdir" echo "Platypush environment $env started with PID $pid, logs dir: $logsdir"
} }
@ -187,9 +172,9 @@ function stop {
fi fi
env=$1 env=$1
envdir=${workdir}/${env} envdir="${workdir}/${env}"
rundir=${envdir}/var/run rundir="${envdir}/var/run"
pidfile=${rundir}/platypush.pid pidfile="${rundir}/platypush.pid"
if [[ ! -d "$envdir" ]]; then if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2 echo "No such directory: $envdir" >&2
@ -197,12 +182,13 @@ function stop {
fi fi
if [[ ! -f "$pidfile" ]]; then if [[ ! -f "$pidfile" ]]; then
echo "No pidfile found for instance "${env}"" echo "No pidfile found for instance \"${env}\""
exit 1 exit 1
fi fi
pid=`cat "$pidfile"` pid=$(cat "$pidfile")
pids="$pid `ps --no-headers -o pid= --ppid $pid`" pids="$pid $(ps --no-headers -o pid= --ppid "$pid")"
# shellcheck disable=SC2086
kill -9 ${pids} kill -9 ${pids}
rm -f "$pidfile" rm -f "$pidfile"
echo "Instance '$env' with PID $pid stopped" echo "Instance '$env' with PID $pid stopped"
@ -214,9 +200,9 @@ function rme {
exit 1 exit 1
fi fi
envdir=${workdir}/$1 envdir="${workdir}/$1"
rundir=${envdir}/var/run rundir="${envdir}/var/run"
pidfile=${rundir}/platypush.pid pidfile="${rundir}/platypush.pid"
if [[ ! -d "$envdir" ]]; then if [[ ! -d "$envdir" ]]; then
echo "No such directory: $envdir" >&2 echo "No such directory: $envdir" >&2
@ -224,14 +210,18 @@ function rme {
fi fi
if [[ -f "$pidfile" ]]; then if [[ -f "$pidfile" ]]; then
if ps -p `cat "$pidfile"` | grep platypush; then if pgrep -F "${pidfile}"; then
echo "Another instance (PID $pidfile) is running, please stop that instance first" echo "Another instance (PID $(cat "$pidfile")) is running, please stop that instance first"
exit 1 exit 1
fi fi
echo "A PID file was found but the process doesn't seem to be running, removing anyway" echo "A PID file was found but the process does not seem to be running, removing anyway"
fi fi
echo "WARNING: This operation will permanently remove the Platypush environment $1"
echo -n "Are you sure you want to continue? (y/N) "
IFS= read -r answer
echo "$answer" | grep -E '^[yY]' >/dev/null || exit 0
rm -rf "$envdir" rm -rf "$envdir"
echo "$envdir removed" echo "$envdir removed"
} }
@ -247,13 +237,13 @@ fi
action=$1 action=$1
shift shift
mkdir -p ${workdir} mkdir -p "${workdir}"
# shellcheck disable=SC2048,SC2086
case ${action} in case ${action} in
'build') build;; 'build') build $*;;
'start') start $*;; 'start') start $*;;
'stop') stop $*;; 'stop') stop $*;;
'rm') rme $*;; 'rm') rme $*;;
*) usage;; *) usage;;
esac esac

View File

@ -8,10 +8,8 @@ Backends
platypush/backend/adafruit.io.rst platypush/backend/adafruit.io.rst
platypush/backend/alarm.rst platypush/backend/alarm.rst
platypush/backend/assistant.rst
platypush/backend/assistant.google.rst platypush/backend/assistant.google.rst
platypush/backend/assistant.snowboy.rst platypush/backend/assistant.snowboy.rst
platypush/backend/bluetooth.rst
platypush/backend/bluetooth.fileserver.rst platypush/backend/bluetooth.fileserver.rst
platypush/backend/bluetooth.pushserver.rst platypush/backend/bluetooth.pushserver.rst
platypush/backend/bluetooth.scanner.rst platypush/backend/bluetooth.scanner.rst
@ -52,7 +50,6 @@ Backends
platypush/backend/pushbullet.rst platypush/backend/pushbullet.rst
platypush/backend/redis.rst platypush/backend/redis.rst
platypush/backend/scard.rst platypush/backend/scard.rst
platypush/backend/sensor.rst
platypush/backend/sensor.accelerometer.rst platypush/backend/sensor.accelerometer.rst
platypush/backend/sensor.arduino.rst platypush/backend/sensor.arduino.rst
platypush/backend/sensor.battery.rst platypush/backend/sensor.battery.rst
@ -67,7 +64,6 @@ Backends
platypush/backend/sensor.mcp3008.rst platypush/backend/sensor.mcp3008.rst
platypush/backend/sensor.motion.pwm3901.rst platypush/backend/sensor.motion.pwm3901.rst
platypush/backend/sensor.serial.rst platypush/backend/sensor.serial.rst
platypush/backend/stt.rst
platypush/backend/stt.deepspeech.rst platypush/backend/stt.deepspeech.rst
platypush/backend/stt.picovoice.hotword.rst platypush/backend/stt.picovoice.hotword.rst
platypush/backend/stt.picovoice.speech.rst platypush/backend/stt.picovoice.speech.rst
@ -75,7 +71,6 @@ Backends
platypush/backend/todoist.rst platypush/backend/todoist.rst
platypush/backend/travisci.rst platypush/backend/travisci.rst
platypush/backend/trello.rst platypush/backend/trello.rst
platypush/backend/weather.rst
platypush/backend/weather.buienradar.rst platypush/backend/weather.buienradar.rst
platypush/backend/weather.darksky.rst platypush/backend/weather.darksky.rst
platypush/backend/weather.openweathermap.rst platypush/backend/weather.openweathermap.rst

View File

@ -238,7 +238,7 @@ autodoc_mock_imports = ['googlesamples.assistant.grpc.audio_helpers',
'envirophat', 'envirophat',
'gps', 'gps',
'picamera', 'picamera',
'pwm3901', 'pmw3901',
'PIL', 'PIL',
'croniter', 'croniter',
'pyaudio', 'pyaudio',

View File

@ -9,7 +9,6 @@ Plugins
platypush/plugins/adafruit.io.rst platypush/plugins/adafruit.io.rst
platypush/plugins/alarm.rst platypush/plugins/alarm.rst
platypush/plugins/arduino.rst platypush/plugins/arduino.rst
platypush/plugins/assistant.rst
platypush/plugins/assistant.echo.rst platypush/plugins/assistant.echo.rst
platypush/plugins/assistant.google.rst platypush/plugins/assistant.google.rst
platypush/plugins/assistant.google.pushtotalk.rst platypush/plugins/assistant.google.pushtotalk.rst
@ -18,14 +17,12 @@ Plugins
platypush/plugins/bluetooth.ble.rst platypush/plugins/bluetooth.ble.rst
platypush/plugins/calendar.rst platypush/plugins/calendar.rst
platypush/plugins/calendar.ical.rst platypush/plugins/calendar.ical.rst
platypush/plugins/camera.rst
platypush/plugins/camera.android.ipcam.rst platypush/plugins/camera.android.ipcam.rst
platypush/plugins/camera.cv.rst platypush/plugins/camera.cv.rst
platypush/plugins/camera.ffmpeg.rst platypush/plugins/camera.ffmpeg.rst
platypush/plugins/camera.gstreamer.rst platypush/plugins/camera.gstreamer.rst
platypush/plugins/camera.ir.mlx90640.rst platypush/plugins/camera.ir.mlx90640.rst
platypush/plugins/camera.pi.rst platypush/plugins/camera.pi.rst
platypush/plugins/chat.rst
platypush/plugins/chat.telegram.rst platypush/plugins/chat.telegram.rst
platypush/plugins/clipboard.rst platypush/plugins/clipboard.rst
platypush/plugins/config.rst platypush/plugins/config.rst
@ -38,7 +35,6 @@ Plugins
platypush/plugins/ffmpeg.rst platypush/plugins/ffmpeg.rst
platypush/plugins/file.rst platypush/plugins/file.rst
platypush/plugins/foursquare.rst platypush/plugins/foursquare.rst
platypush/plugins/google.rst
platypush/plugins/google.calendar.rst platypush/plugins/google.calendar.rst
platypush/plugins/google.drive.rst platypush/plugins/google.drive.rst
platypush/plugins/google.fit.rst platypush/plugins/google.fit.rst
@ -48,7 +44,6 @@ Plugins
platypush/plugins/google.translate.rst platypush/plugins/google.translate.rst
platypush/plugins/google.youtube.rst platypush/plugins/google.youtube.rst
platypush/plugins/gpio.rst platypush/plugins/gpio.rst
platypush/plugins/gpio.sensor.rst
platypush/plugins/gpio.sensor.accelerometer.rst platypush/plugins/gpio.sensor.accelerometer.rst
platypush/plugins/gpio.sensor.bme280.rst platypush/plugins/gpio.sensor.bme280.rst
platypush/plugins/gpio.sensor.dht.rst platypush/plugins/gpio.sensor.dht.rst
@ -69,18 +64,14 @@ Plugins
platypush/plugins/inspect.rst platypush/plugins/inspect.rst
platypush/plugins/kafka.rst platypush/plugins/kafka.rst
platypush/plugins/lastfm.rst platypush/plugins/lastfm.rst
platypush/plugins/lcd.rst
platypush/plugins/lcd.gpio.rst platypush/plugins/lcd.gpio.rst
platypush/plugins/lcd.i2c.rst platypush/plugins/lcd.i2c.rst
platypush/plugins/light.rst
platypush/plugins/light.hue.rst platypush/plugins/light.hue.rst
platypush/plugins/linode.rst platypush/plugins/linode.rst
platypush/plugins/logger.rst platypush/plugins/logger.rst
platypush/plugins/luma.oled.rst platypush/plugins/luma.oled.rst
platypush/plugins/mail.rst
platypush/plugins/mail.imap.rst platypush/plugins/mail.imap.rst
platypush/plugins/mail.smtp.rst platypush/plugins/mail.smtp.rst
platypush/plugins/media.rst
platypush/plugins/media.chromecast.rst platypush/plugins/media.chromecast.rst
platypush/plugins/media.gstreamer.rst platypush/plugins/media.gstreamer.rst
platypush/plugins/media.kodi.rst platypush/plugins/media.kodi.rst
@ -95,7 +86,6 @@ Plugins
platypush/plugins/ml.cv.rst platypush/plugins/ml.cv.rst
platypush/plugins/mobile.join.rst platypush/plugins/mobile.join.rst
platypush/plugins/mqtt.rst platypush/plugins/mqtt.rst
platypush/plugins/music.rst
platypush/plugins/music.mpd.rst platypush/plugins/music.mpd.rst
platypush/plugins/music.snapcast.rst platypush/plugins/music.snapcast.rst
platypush/plugins/music.spotify.rst platypush/plugins/music.spotify.rst
@ -110,19 +100,16 @@ Plugins
platypush/plugins/qrcode.rst platypush/plugins/qrcode.rst
platypush/plugins/redis.rst platypush/plugins/redis.rst
platypush/plugins/rtorrent.rst platypush/plugins/rtorrent.rst
platypush/plugins/sensor.rst
platypush/plugins/serial.rst platypush/plugins/serial.rst
platypush/plugins/shell.rst platypush/plugins/shell.rst
platypush/plugins/slack.rst platypush/plugins/slack.rst
platypush/plugins/smartthings.rst platypush/plugins/smartthings.rst
platypush/plugins/sound.rst platypush/plugins/sound.rst
platypush/plugins/ssh.rst platypush/plugins/ssh.rst
platypush/plugins/stt.rst
platypush/plugins/stt.deepspeech.rst platypush/plugins/stt.deepspeech.rst
platypush/plugins/stt.picovoice.hotword.rst platypush/plugins/stt.picovoice.hotword.rst
platypush/plugins/stt.picovoice.speech.rst platypush/plugins/stt.picovoice.speech.rst
platypush/plugins/sun.rst platypush/plugins/sun.rst
platypush/plugins/switch.rst
platypush/plugins/switch.tplink.rst platypush/plugins/switch.tplink.rst
platypush/plugins/switch.wemo.rst platypush/plugins/switch.wemo.rst
platypush/plugins/switchbot.rst platypush/plugins/switchbot.rst
@ -142,7 +129,6 @@ Plugins
platypush/plugins/user.rst platypush/plugins/user.rst
platypush/plugins/utils.rst platypush/plugins/utils.rst
platypush/plugins/variable.rst platypush/plugins/variable.rst
platypush/plugins/weather.rst
platypush/plugins/weather.buienradar.rst platypush/plugins/weather.buienradar.rst
platypush/plugins/weather.darksky.rst platypush/plugins/weather.darksky.rst
platypush/plugins/weather.openweathermap.rst platypush/plugins/weather.openweathermap.rst
@ -151,5 +137,4 @@ Plugins
platypush/plugins/zeroconf.rst platypush/plugins/zeroconf.rst
platypush/plugins/zigbee.mqtt.rst platypush/plugins/zigbee.mqtt.rst
platypush/plugins/zwave.rst platypush/plugins/zwave.rst
platypush/plugins/zwave._base.rst
platypush/plugins/zwave.mqtt.rst platypush/plugins/zwave.mqtt.rst

View File

@ -1,14 +1,27 @@
import os import os
from platypush.backend import Backend
from platypush.context import get_plugin from platypush.context import get_plugin
from platypush.plugins import Plugin
from platypush.utils.manifest import get_manifests
def get_all_plugins(): def get_all_plugins():
return get_plugin('inspect').get_all_plugins().output manifests = {mf.component_name for mf in get_manifests(Plugin)}
return {
plugin_name: plugin_info
for plugin_name, plugin_info in get_plugin('inspect').get_all_plugins().output.items()
if plugin_name in manifests
}
def get_all_backends(): def get_all_backends():
return get_plugin('inspect').get_all_backends().output manifests = {mf.component_name for mf in get_manifests(Backend)}
return {
backend_name: backend_info
for backend_name, backend_info in get_plugin('inspect').get_all_backends().output.items()
if backend_name in manifests
}
def get_all_events(): def get_all_events():

View File

@ -12,6 +12,7 @@ from threading import Thread, Event as ThreadEvent, get_ident
from typing import Optional, Dict from typing import Optional, Dict
from platypush.bus import Bus from platypush.bus import Bus
from platypush.common import ExtensionWithManifest
from platypush.config import Config from platypush.config import Config
from platypush.context import get_backend from platypush.context import get_backend
from platypush.message.event.zeroconf import ZeroconfServiceAddedEvent, ZeroconfServiceRemovedEvent from platypush.message.event.zeroconf import ZeroconfServiceAddedEvent, ZeroconfServiceRemovedEvent
@ -26,7 +27,7 @@ from platypush.message.request import Request
from platypush.message.response import Response from platypush.message.response import Response
class Backend(Thread, EventGenerator): class Backend(Thread, EventGenerator, ExtensionWithManifest):
""" """
Parent class for backends. Parent class for backends.
@ -53,6 +54,7 @@ class Backend(Thread, EventGenerator):
self._thread_name = self.__class__.__name__ self._thread_name = self.__class__.__name__
EventGenerator.__init__(self) EventGenerator.__init__(self)
ExtensionWithManifest.__init__(self)
Thread.__init__(self, name=self._thread_name, daemon=True) Thread.__init__(self, name=self._thread_name, daemon=True)
# If no bus is specified, create an internal queue where # If no bus is specified, create an internal queue where

View File

@ -1,3 +1,5 @@
from typing import Optional
from platypush.backend import Backend from platypush.backend import Backend
from platypush.context import get_plugin from platypush.context import get_plugin
from platypush.message.event.adafruit import ConnectedEvent, DisconnectedEvent, \ from platypush.message.event.adafruit import ConnectedEvent, DisconnectedEvent, \
@ -30,8 +32,9 @@ class AdafruitIoBackend(Backend):
""" """
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
from Adafruit_IO import MQTTClient
self.feeds = feeds self.feeds = feeds
self._client = None self._client: Optional[MQTTClient] = None
def _init_client(self): def _init_client(self):
if self._client: if self._client:
@ -57,12 +60,12 @@ class AdafruitIoBackend(Backend):
return _handler return _handler
def on_disconnect(self): def on_disconnect(self):
def _handler(client): def _handler(*_, **__):
self.bus.post(DisconnectedEvent()) self.bus.post(DisconnectedEvent())
return _handler return _handler
def on_message(self, msg): def on_message(self, *_, **__):
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def _handler(client, feed, data): def _handler(client, feed, data):
try: try:
@ -83,7 +86,9 @@ class AdafruitIoBackend(Backend):
while not self.should_stop(): while not self.should_stop():
try: try:
self._init_client() self._init_client()
# noinspection PyUnresolvedReferences
self._client.connect() self._client.connect()
# noinspection PyUnresolvedReferences
self._client.loop_blocking() self._client.loop_blocking()
except Exception as e: except Exception as e:
self.logger.exception(e) self.logger.exception(e)

View File

@ -0,0 +1,12 @@
manifest:
events:
platypush.message.event.adafruit.ConnectedEvent: when thebackend connects to the
Adafruit queue
platypush.message.event.adafruit.DisconnectedEvent: when thebackend disconnects
from the Adafruit queue
platypush.message.event.adafruit.FeedUpdateEvent: when anupdate event is received
on a monitored feed
install:
pip: []
package: platypush.backend.adafruit.io
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.alarm.AlarmDismissedEvent: when an alarm is dismissed.
platypush.message.event.alarm.AlarmSnoozedEvent: when an alarm is snoozed.
platypush.message.event.alarm.AlarmStartedEvent: when an alarm starts.
platypush.message.event.alarm.AlarmTimeoutEvent: when an alarm times out.
install:
pip: []
package: platypush.backend.alarm
type: backend

View File

@ -1,3 +1,4 @@
from abc import ABC
import threading import threading
from typing import Optional, Dict, Any, Tuple from typing import Optional, Dict, Any, Tuple

View File

@ -0,0 +1,26 @@
manifest:
events:
platypush.message.event.assistant.AlarmEndEvent: when an alarm ends
platypush.message.event.assistant.AlarmStartedEvent: when an alarm starts
platypush.message.event.assistant.ConversationEndEvent: when a new conversation
ends
platypush.message.event.assistant.ConversationStartEvent: when a new conversation
starts
platypush.message.event.assistant.ConversationTimeoutEvent: when a conversation
times out
platypush.message.event.assistant.MicMutedEvent: when the microphone is muted.
platypush.message.event.assistant.MicUnmutedEvent: when the microphone is un-muted.
platypush.message.event.assistant.NoResponse: when a conversation returned no
response
platypush.message.event.assistant.ResponseEvent: when the assistant is speaking
a response
platypush.message.event.assistant.SpeechRecognizedEvent: when a new voice command
is recognized
platypush.message.event.assistant.TimerEndEvent: when a timer ends
platypush.message.event.assistant.TimerStartedEvent: when a timer starts
install:
pip:
- google-assistant-library
- google-assistant-sdk[samples]
package: platypush.backend.assistant.google
type: backend

View File

@ -0,0 +1,9 @@
manifest:
events:
platypush.message.event.assistant.HotwordDetectedEvent: whenever the hotword has
been detected
install:
pip:
- snowboy
package: platypush.backend.assistant.snowboy
type: backend

View File

@ -83,7 +83,7 @@ class BluetoothBackend(Backend, Server):
self.connect(connection, request) self.connect(connection, request)
self.bus.post(BluetoothDeviceConnectedEvent(address=address[0], port=address[1])) self.bus.post(BluetoothDeviceConnectedEvent(address=address[0], port=address[1]))
elif isinstance(request, requests.Disconnect): elif isinstance(request, requests.Disconnect):
self.disconnect(connection) self.disconnect(connection, request)
self.bus.post(BluetoothDeviceDisconnectedEvent(address=address[0], port=address[1])) self.bus.post(BluetoothDeviceDisconnectedEvent(address=address[0], port=address[1]))
elif isinstance(request, requests.Put): elif isinstance(request, requests.Put):
self.bus.post(BluetoothFilePutRequestEvent(address=address[0], port=address[1])) self.bus.post(BluetoothFilePutRequestEvent(address=address[0], port=address[1]))

View File

@ -0,0 +1,8 @@
manifest:
events: {}
install:
pip:
- pybluez
- pyobex
package: platypush.backend.bluetooth.fileserver
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events: {}
install:
pip:
- pybluez
- pyobex
package: platypush.backend.bluetooth.pushserver
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.bluetooth.BluetoothDeviceFoundEvent: when a new bluetooth
device is found.
platypush.message.event.bluetooth.BluetoothDeviceLostEvent: when a bluetooth device
is lost.
install:
pip: []
package: platypush.backend.bluetooth.scanner.ble
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.bluetooth.BluetoothDeviceFoundEvent: when a new bluetooth
device is found.
platypush.message.event.bluetooth.BluetoothDeviceLostEvent: when a bluetooth device
is lost.
install:
pip: []
package: platypush.backend.bluetooth.scanner
type: backend

View File

@ -1,6 +1,3 @@
import importlib
from enum import Enum
from threading import Timer from threading import Timer
from time import time from time import time
@ -17,11 +14,14 @@ class ButtonFlicBackend(Backend):
Triggers: Triggers:
* :class:`platypush.message.event.button.flic.FlicButtonEvent` when a button is pressed. The event will also contain the press sequence (e.g. ``["ShortPressEvent", "LongPressEvent", "ShortPressEvent"]``) * :class:`platypush.message.event.button.flic.FlicButtonEvent` when a button is pressed.
The event will also contain the press sequence
(e.g. ``["ShortPressEvent", "LongPressEvent", "ShortPressEvent"]``)
Requires: Requires:
* **fliclib** (https://github.com/50ButtonsEach/fliclib-linux-hci). For the backend to work properly you need to have the ``flicd`` daemon from the fliclib running, and you have to first pair the buttons with your device using any of the scanners provided by the library. * **fliclib** (https://github.com/50ButtonsEach/fliclib-linux-hci). For the backend to work properly you need to have the ``flicd`` daemon from the fliclib running, and you have to first pair the buttons with your device using any of the scanners provided by the library.
""" """
_long_press_timeout = 0.3 _long_press_timeout = 0.3
@ -87,6 +87,7 @@ class ButtonFlicBackend(Backend):
return _f return _f
def _on_event(self): def _on_event(self):
# noinspection PyUnusedLocal
def _f(bd_addr, channel, click_type, was_queued, time_diff): def _f(bd_addr, channel, click_type, was_queued, time_diff):
if was_queued: if was_queued:
return return

View File

@ -15,6 +15,7 @@ from enum import Enum
from collections import namedtuple from collections import namedtuple
import struct import struct
import itertools import itertools
import threading
class CreateConnectionChannelError(Enum): class CreateConnectionChannelError(Enum):

View File

@ -0,0 +1,9 @@
manifest:
events:
platypush.message.event.button.flic.FlicButtonEvent: when a button is pressed.The
event will also contain the press sequence(e.g. ``["ShortPressEvent", "LongPressEvent",
"ShortPressEvent"]``)
install:
pip: []
package: platypush.backend.button.flic
type: backend

View File

@ -18,7 +18,6 @@ class CameraPiBackend(Backend):
Requires: Requires:
* **picamera** (``pip install picamera``) * **picamera** (``pip install picamera``)
* **redis** (``pip install redis``) for inter-process communication with the camera process
This backend is **DEPRECATED**. Use the plugin :class:`platypush.plugins.camera.pi.CameraPiPlugin` instead to run This backend is **DEPRECATED**. Use the plugin :class:`platypush.plugins.camera.pi.CameraPiPlugin` instead to run
Pi camera actions. If you want to start streaming the camera on application start then simply create an event hook Pi camera actions. If you want to start streaming the camera on application start then simply create an event hook

View File

@ -0,0 +1,7 @@
manifest:
events: {}
install:
pip:
- picamera
package: platypush.backend.camera.pi
type: backend

View File

@ -0,0 +1,19 @@
manifest:
events:
platypush.message.event.chat.telegram.CommandMessageEvent: when a command message
is received.
platypush.message.event.chat.telegram.ContactMessageEvent: when a contact is received.
platypush.message.event.chat.telegram.DocumentMessageEvent: when a document is
received.
platypush.message.event.chat.telegram.GroupCreatedEvent: when the bot is invited
to a new group.
platypush.message.event.chat.telegram.LocationMessageEvent: when a location is
received.
platypush.message.event.chat.telegram.PhotoMessageEvent: when a photo is received.
platypush.message.event.chat.telegram.TextMessageEvent: when a text message is
received.
platypush.message.event.chat.telegram.VideoMessageEvent: when a video is received.
install:
pip: []
package: platypush.backend.chat.telegram
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.clipboard.ClipboardEvent: on clipboard update.
install:
pip:
- pyperclip
package: platypush.backend.clipboard
type: backend

View File

@ -0,0 +1,7 @@
manifest:
events:
platypush.message.event.covid19.Covid19UpdateEvent: when new data is available.
install:
pip: []
package: platypush.backend.covid19
type: backend

View File

@ -0,0 +1,7 @@
manifest:
events: {}
install:
pip:
- dbus-python
package: platypush.backend.dbus
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.file.FileSystemCreateEvent: if a resource is created.
platypush.message.event.file.FileSystemDeleteEvent: if a resource is removed.
platypush.message.event.file.FileSystemModifyEvent: if a resource is modified.
install:
pip:
- watchdog
package: platypush.backend.file.monitor
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.foursquare.FoursquareCheckinEvent: when a new check-in
occurs.
install:
pip: []
package: platypush.backend.foursquare
type: backend

View File

@ -0,0 +1,32 @@
manifest:
events:
platypush.message.event.github.GithubCommitCommentEvent: when a new commit comment
is created.
platypush.message.event.github.GithubCreateEvent: when a tag or branch is created.
platypush.message.event.github.GithubDeleteEvent: when a tag or branch is deleted.
platypush.message.event.github.GithubEvent: for any event that doesn't fall in
the above categories(``event_type`` will be set accordingly).
platypush.message.event.github.GithubForkEvent: when a user forks a repository.
platypush.message.event.github.GithubIssueCommentEvent: when new activity happens
on an issue comment.
platypush.message.event.github.GithubIssueEvent: when new repository issue activity
happens.
platypush.message.event.github.GithubMemberEvent: when new repository collaborators
activity happens.
platypush.message.event.github.GithubPublicEvent: when a repository goes public.
platypush.message.event.github.GithubPullRequestEvent: when new pull request related
activity happens.
platypush.message.event.github.GithubPullRequestReviewCommentEvent: when activity
happens on a pullrequest commit.
platypush.message.event.github.GithubPushEvent: when a new push is created.
platypush.message.event.github.GithubReleaseEvent: when a new release happens.
platypush.message.event.github.GithubSponsorshipEvent: when new sponsorship related
activity happens.
platypush.message.event.github.GithubWatchEvent: when someone stars/starts watching
a repository.
platypush.message.event.github.GithubWikiEvent: when new activity happens on a
repository wiki.
install:
pip: []
package: platypush.backend.github
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.google.fit.GoogleFitEvent: when a newdata point is received
on one of the registered streams.
install:
pip: []
package: platypush.backend.google.fit
type: backend

View File

@ -0,0 +1,9 @@
manifest:
events:
platypush.message.event.google.pubsub.GooglePubsubMessageEvent: when a new message
is received ona subscribed topic.
install:
pip:
- google-cloud-pubsub
package: platypush.backend.google.pubsub
type: backend

View File

@ -0,0 +1,16 @@
manifest:
events:
platypush.message.event.gps.GPSDeviceEvent: when a GPS device is connected or
updated
platypush.message.event.gps.GPSUpdateEvent: when a GPS device has new data
platypush.message.event.gps.GPSVersionEvent: when a GPS device advertises its
version data
install:
pip:
- gps
pacman:
- gpsd
apt:
- gpsd
package: platypush.backend.gps
type: backend

View File

@ -4,6 +4,11 @@ import threading
from multiprocessing import Process from multiprocessing import Process
try:
from websockets.exceptions import ConnectionClosed
except ImportError:
from websockets import ConnectionClosed
from platypush.backend import Backend from platypush.backend import Backend
from platypush.backend.http.app import application from platypush.backend.http.app import application
from platypush.context import get_or_create_event_loop from platypush.context import get_or_create_event_loop
@ -146,9 +151,7 @@ class HttpBackend(Backend):
Requires: Requires:
* **flask** (``pip install flask``) * **flask** (``pip install flask``)
* **redis** (``pip install redis``) * **bcrypt** (``pip install bcrypt``)
* **websockets** (``pip install websockets``)
* **python-dateutil** (``pip install python-dateutil``)
* **magic** (``pip install python-magic``), optional, for MIME type * **magic** (``pip install python-magic``), optional, for MIME type
support if you want to enable media streaming support if you want to enable media streaming
* **uwsgi** (``pip install uwsgi`` plus uwsgi server installed on your * **uwsgi** (``pip install uwsgi`` plus uwsgi server installed on your
@ -328,8 +331,6 @@ class HttpBackend(Backend):
def notify_web_clients(self, event): def notify_web_clients(self, event):
""" Notify all the connected web clients (over websocket) of a new event """ """ Notify all the connected web clients (over websocket) of a new event """
import websockets
async def send_event(ws): async def send_event(ws):
try: try:
self._acquire_websocket_lock(ws) self._acquire_websocket_lock(ws)
@ -345,7 +346,7 @@ class HttpBackend(Backend):
for _ws in wss: for _ws in wss:
try: try:
loop.run_until_complete(send_event(_ws)) loop.run_until_complete(send_event(_ws))
except websockets.exceptions.ConnectionClosed: except ConnectionClosed:
self.logger.warning('Websocket client {} connection lost'.format(_ws.remote_address)) self.logger.warning('Websocket client {} connection lost'.format(_ws.remote_address))
self.active_websockets.remove(_ws) self.active_websockets.remove(_ws)
if _ws.remote_address in self._websocket_locks: if _ws.remote_address in self._websocket_locks:
@ -365,7 +366,7 @@ class HttpBackend(Backend):
try: try:
await websocket.recv() await websocket.recv()
except websockets.exceptions.ConnectionClosed: except ConnectionClosed:
self.logger.info('Websocket client {} closed connection'.format(address)) self.logger.info('Websocket client {} closed connection'.format(address))
self.active_websockets.remove(websocket) self.active_websockets.remove(websocket)
if address in self._websocket_locks: if address in self._websocket_locks:

View File

@ -4,7 +4,7 @@ from platypush.backend.http.app import template_folder
from platypush.backend.http.app.routes.plugins.camera import get_photo, get_video from platypush.backend.http.app.routes.plugins.camera import get_photo, get_video
from platypush.backend.http.app.utils import authenticate from platypush.backend.http.app.utils import authenticate
camera_ir_mlx90640 = Blueprint('camera.ir.mlx90640', __name__, template_folder=template_folder) camera_ir_mlx90640 = Blueprint('camera-ir-mlx90640', __name__, template_folder=template_folder)
# Declare routes list # Declare routes list
__routes__ = [ __routes__ = [

View File

@ -8,7 +8,7 @@ from platypush.backend.http.app.utils import authenticate, send_request
from platypush.config import Config from platypush.config import Config
from platypush.plugins.camera.pi import CameraPiPlugin from platypush.plugins.camera.pi import CameraPiPlugin
camera_pi = Blueprint('camera.pi', __name__, template_folder=template_folder) camera_pi = Blueprint('camera-pi', __name__, template_folder=template_folder)
# Declare routes list # Declare routes list
__routes__ = [ __routes__ = [

View File

@ -2,7 +2,7 @@ import hashlib
import json import json
import threading import threading
from flask import Response, render_template from flask import Response
from platypush.backend.http.app.utils import get_remote_base_url, logger, \ from platypush.backend.http.app.utils import get_remote_base_url, logger, \
send_message send_message

View File

@ -0,0 +1,9 @@
manifest:
events: {}
install:
pip:
- flask
- bcrypt
- python-magic
package: platypush.backend.http
type: backend

View File

@ -1,5 +1,6 @@
import logging import logging
class MediaHandler: class MediaHandler:
""" """
Abstract class to manage media handlers that can be streamed over the HTTP Abstract class to manage media handlers that can be streamed over the HTTP
@ -57,7 +58,7 @@ class MediaHandler:
for attr in ['name', 'source', 'mime_type', 'url', 'subtitles', for attr in ['name', 'source', 'mime_type', 'url', 'subtitles',
'prefix_handlers', 'media_id']: 'prefix_handlers', 'media_id']:
if hasattr(self, attr): if hasattr(self, attr):
yield (attr, getattr(self, attr)) yield attr, getattr(self, attr)
from .file import FileHandler from .file import FileHandler

View File

@ -34,7 +34,7 @@ class HttpPollBackend(Backend):
- -
# Poll for updates on an RSS feed # Poll for updates on an RSS feed
type: platypush.backend.http.request.rss.RssUpdates type: platypush.backend.http.request.rss.RssUpdates
url: http://www.theguardian.com/rss/world url: https://www.theguardian.com/rss/world
title: The Guardian - World News title: The Guardian - World News
poll_seconds: 120 poll_seconds: 120
max_entries: 10 max_entries: 10

View File

@ -0,0 +1,6 @@
manifest:
events: {}
install:
pip: []
package: platypush.backend.http.poll
type: backend

View File

@ -1,48 +0,0 @@
import datetime
import dateutil.parser
import json
from platypush.backend.http.request import JsonHttpRequest
from platypush.message.event.http.ota.booking import NewReservationEvent
class GetReservationUpdates(JsonHttpRequest):
""" Gets the reservation updates """
def __init__(self, hotel_id, token, *args, **kwargs):
self.hotel_id = hotel_id
self.token = token
self.seen_entries = set()
self.last_update = None
args = {
'method': 'get',
'url': 'https://hub-api.booking.com/v1/hotels/{}/reservations'.format(self.hotel_id),
'headers': { 'X-Booking-Auth-Token': self.token },
'params': { 'updatedSince': datetime.date.today().isoformat() }
}
super().__init__(args=args, **kwargs)
def get_new_items(self, response):
response = response.json()
entries = []
for entry in response:
update_timestamp = dateutil.parser.parse(entry['updateDate'])
last_update_timestamp = dateutil.parser.parse(self.last_update['updateDate']) \
if self.last_update else None
if self.last_update is None \
or (update_timestamp > last_update_timestamp
and not (
entry['booker']['email'] == self.last_update['booker']['email']
and entry['status'] == self.last_update['status'])):
self.last_update = entry
entries.append(entry)
return NewReservationEvent(dict(self), entries)
# vim:sw=4:ts=4:et:

View File

@ -239,7 +239,10 @@ class RssUpdates(HttpRequest):
f.write(content) f.write(content)
elif self.digest_format == 'pdf': elif self.digest_format == 'pdf':
from weasyprint import HTML, CSS from weasyprint import HTML, CSS
from weasyprint.fonts import FontConfiguration try:
from weasyprint.fonts import FontConfiguration
except ImportError:
from weasyprint.document import FontConfiguration
body_style = 'body { ' + self.body_style + ' }' body_style = 'body { ' + self.body_style + ' }'
font_config = FontConfiguration() font_config = FontConfiguration()

View File

@ -0,0 +1,15 @@
manifest:
events:
platypush.message.event.inotify.InotifyAccessEvent: if a resource is accessed
platypush.message.event.inotify.InotifyCloseEvent: if a resource is closed
platypush.message.event.inotify.InotifyCreateEvent: if a resource is created
platypush.message.event.inotify.InotifyDeleteEvent: if a resource is removed
platypush.message.event.inotify.InotifyModifyEvent: if a resource is modified
platypush.message.event.inotify.InotifyOpenEvent: if a resource is opened
platypush.message.event.inotify.InotifyPermissionsChangeEvent: if the permissions
of a resource are changed
install:
pip:
- inotify
package: platypush.backend.inotify
type: backend

View File

@ -0,0 +1,21 @@
manifest:
events:
platypush.message.event.joystick.JoystickAxisEvent: when an axis value of the
joystick changes.
platypush.message.event.joystick.JoystickButtonPressedEvent: when a joystick button
is pressed.
platypush.message.event.joystick.JoystickButtonReleasedEvent: when a joystick
button is released.
platypush.message.event.joystick.JoystickConnectedEvent: when the joystick is
connected.
platypush.message.event.joystick.JoystickDisconnectedEvent: when the joystick
is disconnected.
platypush.message.event.joystick.JoystickStateEvent: when the state of the joystick
(i.e. some of itsaxes or buttons values) changes.
install:
apt:
- joystick
pacman:
- jsutils
package: platypush.backend.joystick.jstest
type: backend

View File

@ -0,0 +1,16 @@
manifest:
events:
platypush.message.event.joystick.JoystickAxisEvent: when an axis value of the
joystick changes.
platypush.message.event.joystick.JoystickButtonPressedEvent: when a joystick button
is pressed.
platypush.message.event.joystick.JoystickButtonReleasedEvent: when a joystick
button is released.
platypush.message.event.joystick.JoystickConnectedEvent: when the joystick is
connected.
platypush.message.event.joystick.JoystickDisconnectedEvent: when the joystick
is disconnected.
install:
pip: []
package: platypush.backend.joystick.linux
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.joystick.JoystickEvent: when a new joystick event is received
install:
pip:
- inputs
package: platypush.backend.joystick
type: backend

View File

@ -1,4 +1,3 @@
import json
import logging import logging
import time import time

View File

@ -0,0 +1,7 @@
manifest:
events: {}
install:
pip:
- kafka
package: platypush.backend.kafka
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.light.LightStatusChangeEvent: when thestatus of a lightbulb
changes
install:
pip: []
package: platypush.backend.light.hue
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.linode.LinodeInstanceStatusChanged: when the status of
an instance changes.
install:
pip: []
package: platypush.backend.linode
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.log.http.HttpLogEvent: when a new log line is created.
install:
pip:
- watchdog
package: platypush.backend.log.http
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.mail.MailFlaggedEvent: when a message is marked as flagged/starred.
platypush.message.event.mail.MailReceivedEvent: when a new message is received.
platypush.message.event.mail.MailSeenEvent: when a message is marked as seen.
platypush.message.event.mail.MailUnflaggedEvent: when a message is marked as unflagged/unstarred.
install:
pip: []
package: platypush.backend.mail
type: backend

View File

@ -120,7 +120,7 @@ class MidiBackend(Backend):
self.logger.exception(e) self.logger.exception(e)
if self.midi: if self.midi:
self.midi.close_port(self.port_number) self.midi.close_port()
self.midi = None self.midi = None

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.midi.MidiMessageEvent: when a new MIDI event is received
install:
pip:
- rtmidi
package: platypush.backend.midi
type: backend

View File

@ -0,0 +1,9 @@
manifest:
events:
platypush.message.event.mqtt.MQTTMessageEvent: when a newmessage is received on
one of the custom listeners
install:
pip:
- paho-mqtt
package: platypush.backend.mqtt
type: backend

View File

@ -2,6 +2,8 @@ import json
import re import re
import threading import threading
import websocket
from platypush.backend import Backend from platypush.backend import Backend
from platypush.message.event.music import MusicPlayEvent, MusicPauseEvent, \ from platypush.message.event.music import MusicPlayEvent, MusicPauseEvent, \
MusicStopEvent, NewPlayingTrackEvent, PlaylistChangeEvent, VolumeChangeEvent, \ MusicStopEvent, NewPlayingTrackEvent, PlaylistChangeEvent, VolumeChangeEvent, \
@ -32,7 +34,7 @@ class MusicMopidyBackend(Backend):
* :class:`platypush.message.event.music.SeekChangeEvent` if a track seek event occurs * :class:`platypush.message.event.music.SeekChangeEvent` if a track seek event occurs
Requires: Requires:
* **websocket-client** (``pip install websocket-client``)
* Mopidy installed and the HTTP service enabled * Mopidy installed and the HTTP service enabled
""" """
@ -88,7 +90,6 @@ class MusicMopidyBackend(Backend):
return conv_track return conv_track
def _communicate(self, msg): def _communicate(self, msg):
import websocket
if isinstance(msg, str): if isinstance(msg, str):
msg = json.loads(msg) msg = json.loads(msg)
@ -242,8 +243,6 @@ class MusicMopidyBackend(Backend):
return hndl return hndl
def _connect(self): def _connect(self):
import websocket
if not self._ws: if not self._ws:
self._ws = websocket.WebSocketApp(self.url, self._ws = websocket.WebSocketApp(self.url,
on_open=self._on_open(), on_open=self._on_open(),

View File

@ -0,0 +1,17 @@
manifest:
events:
platypush.message.event.music.MusicPauseEvent: if the playback state changed to
pause
platypush.message.event.music.MusicPlayEvent: if the playback state changed to
play
platypush.message.event.music.MusicStopEvent: if the playback state changed to
stop
platypush.message.event.music.MuteChangeEvent: if the mute status has changed
platypush.message.event.music.NewPlayingTrackEvent: if a new track is being played
platypush.message.event.music.PlaylistChangeEvent: if the main playlist has changed
platypush.message.event.music.SeekChangeEvent: if a track seek event occurs
platypush.message.event.music.VolumeChangeEvent: if the main volume has changed
install:
pip: []
package: platypush.backend.music.mopidy
type: backend

View File

@ -0,0 +1,16 @@
manifest:
events:
platypush.message.event.music.MusicPauseEvent: if the playback state changed to
pause
platypush.message.event.music.MusicPlayEvent: if the playback state changed to
play
platypush.message.event.music.MusicStopEvent: if the playback state changed to
stop
platypush.message.event.music.NewPlayingTrackEvent: if a new track is being played
platypush.message.event.music.PlaylistChangeEvent: if the main playlist has changed
platypush.message.event.music.VolumeChangeEvent: if the main volume has changed
install:
pip:
- python-mpd2
package: platypush.backend.music.mpd
type: backend

View File

@ -0,0 +1,15 @@
manifest:
events:
platypush.message.event.music.snapcast.ClientConnectedEvent: ''
platypush.message.event.music.snapcast.ClientDisconnectedEvent: ''
platypush.message.event.music.snapcast.ClientLatencyChangeEvent: ''
platypush.message.event.music.snapcast.ClientNameChangeEvent: ''
platypush.message.event.music.snapcast.ClientVolumeChangeEvent: ''
platypush.message.event.music.snapcast.GroupMuteChangeEvent: ''
platypush.message.event.music.snapcast.GroupStreamChangeEvent: ''
platypush.message.event.music.snapcast.ServerUpdateEvent: ''
platypush.message.event.music.snapcast.StreamUpdateEvent: ''
install:
pip: []
package: platypush.backend.music.snapcast
type: backend

View File

@ -0,0 +1,21 @@
manifest:
events:
platypush.message.event.music.MusicPauseEvent: if the playback state changed to
pause
platypush.message.event.music.MusicPlayEvent: if the playback state changed to
play
platypush.message.event.music.MusicStopEvent: if the playback state changed to
stop
platypush.message.event.music.NewPlayingTrackEvent: if a new track is being played
platypush.message.event.music.VolumeChangeEvent: if the volume changes
install:
apt:
- sudo
- cargo
pacman:
- sudo
- cargo
exec:
- sudo cargo install librespot
package: platypush.backend.music.spotify
type: backend

View File

@ -0,0 +1,10 @@
manifest:
events:
platypush.message.event.nextcloud.NextCloudActivityEvent: 'when new activity occurs
on the instance.The field ``activity_type`` identifies the activity type (e.g.
``file_created``, ``file_deleted``,``file_changed``). Example in the case of
the creation of new files:'
install:
pip: []
package: platypush.backend.nextcloud
type: backend

View File

@ -0,0 +1,13 @@
manifest:
events:
platypush.message.event.nfc.NFCDeviceConnectedEvent: when an NFC reader/writer
is connected
platypush.message.event.nfc.NFCDeviceDisconnectedEvent: when an NFC reader/writer
is disconnected
platypush.message.event.nfc.NFCTagDetectedEvent: when an NFC tag is detected
platypush.message.event.nfc.NFCTagRemovedEvent: when an NFC tag is removed
install:
pip:
- ndef
package: platypush.backend.nfc
type: backend

View File

@ -17,6 +17,7 @@ class NoderedBackend(Backend):
Requires: Requires:
* **pynodered** (``pip install pynodered``) * **pynodered** (``pip install pynodered``)
""" """
def __init__(self, port: int = 5051, *args, **kwargs): def __init__(self, port: int = 5051, *args, **kwargs):

View File

@ -0,0 +1,7 @@
manifest:
events: {}
install:
pip:
- pynodered
package: platypush.backend.nodered
type: backend

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.ping.HostDownEvent: if a host stops responding ping requests
platypush.message.event.ping.HostUpEvent: if a host starts responding ping requests
install:
pip: []
package: platypush.backend.ping
type: backend

View File

@ -21,8 +21,8 @@ class PushbulletBackend(Backend):
Requires: Requires:
* **requests** (``pip install requests``) * **pushbullet.py** (``pip install git+https://github.com/pushbullet.py/pushbullet.py``)
* **pushbullet.py** (``pip install git+https://github.com/rbrcsk/pushbullet.py``)
""" """
def __init__(self, token: str, device: str = 'Platypush', proxy_host: Optional[str] = None, def __init__(self, token: str, device: str = 'Platypush', proxy_host: Optional[str] = None,
@ -52,7 +52,7 @@ class PushbulletBackend(Backend):
try: try:
self.device = self.pb.get_device(self.device_name) self.device = self.pb.get_device(self.device_name)
except Exception as e: except Exception as e:
self.logger.info('Device {} does not exist: {}. Creating it'.format(self.device_name, str(e))) self.logger.info(f'Device {self.device_name} does not exist: {e}. Creating it')
self.device = self.pb.new_device(self.device_name) self.device = self.pb.new_device(self.device_name)
self.pb_device_id = self.get_device_id() self.pb_device_id = self.get_device_id()
@ -91,17 +91,15 @@ class PushbulletBackend(Backend):
if 'body' not in push: if 'body' not in push:
return return
self.logger.debug('Received push: {}'.format(push)) self.logger.debug(f'Received push: {push}')
body = push['body'] body = push['body']
try: try:
body = json.loads(body) body = json.loads(body)
self.on_message(body) self.on_message(body)
except Exception as e: except Exception as e:
self.logger.debug(('Unexpected message received on the ' + self.logger.debug('Unexpected message received on the ' +
'Pushbullet backend: {}. Message: {}') f'Pushbullet backend: {e}. Message: {body}')
.format(str(e), body))
except Exception as e: except Exception as e:
self.logger.exception(e) self.logger.exception(e)
return return
@ -116,9 +114,7 @@ class PushbulletBackend(Backend):
device = self.pb.new_device(self.device_name, model='Platypush virtual device', device = self.pb.new_device(self.device_name, model='Platypush virtual device',
manufacturer='platypush', icon='system') manufacturer='platypush', icon='system')
self.logger.info('Created Pushbullet device {}'.format( self.logger.info(f'Created Pushbullet device {self.device_name}')
self.device_name))
return device.device_iden return device.device_iden
def close(self): def close(self):
@ -133,27 +129,33 @@ class PushbulletBackend(Backend):
self.logger.info('Pushbullet backend terminated') self.logger.info('Pushbullet backend terminated')
def on_close(self, err=None): def on_close(self, err=None):
self.listener = None def callback(*_):
raise RuntimeError(err or 'Connection closed') self.listener = None
raise RuntimeError(err or 'Connection closed')
return callback
def on_open(self): def on_open(self):
self.logger.info('Pushbullet service connected') def callback(*_):
self.logger.info('Pushbullet service connected')
return callback
def run_listener(self): def run_listener(self):
from .listener import Listener from .listener import Listener
self.logger.info('Initializing Pushbullet backend - device_id: {}'.format(self.device_name)) self.logger.info(f'Initializing Pushbullet backend - device_id: {self.device_name}')
self.listener = Listener(account=self.pb, on_push=self.on_push(), self.listener = Listener(account=self.pb,
on_open=self.on_open, on_push=self.on_push(),
on_close=self.on_close, on_open=self.on_open(),
on_error=self.on_close, on_close=self.on_close(),
on_error=self.on_close(),
http_proxy_host=self.proxy_host, http_proxy_host=self.proxy_host,
http_proxy_port=self.proxy_port) http_proxy_port=self.proxy_port)
self.listener.run_forever() self.listener.run_forever()
def run(self): def run(self):
# noinspection PyPackageRequirements
super().run() super().run()
initialized = False initialized = False
@ -163,7 +165,7 @@ class PushbulletBackend(Backend):
initialized = True initialized = True
except Exception as e: except Exception as e:
self.logger.exception(e) self.logger.exception(e)
self.logger.error('Pushbullet initialization error: {}'.format(str(e))) self.logger.error(f'Pushbullet initialization error: {e}')
time.sleep(10) time.sleep(10)
while not self.should_stop(): while not self.should_stop():
@ -175,5 +177,4 @@ class PushbulletBackend(Backend):
self.logger.info('Retrying connection') self.logger.info('Retrying connection')
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et:

View File

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.pushbullet.PushbulletEvent: if a new push is received
install:
pip:
- git+https://github.com/rbrcsk/pushbullet.py
package: platypush.backend.pushbullet
type: backend

View File

@ -14,11 +14,6 @@ class RedisBackend(Backend):
``platypush_bus_mq``) and posts them to the application bus. Very ``platypush_bus_mq``) and posts them to the application bus. Very
useful when you have plugin whose code is executed in another process useful when you have plugin whose code is executed in another process
and can't post events or requests to the application bus. and can't post events or requests to the application bus.
Requires:
* **redis** (``pip install redis``)
""" """
def __init__(self, queue='platypush_bus_mq', redis_args=None, *args, **kwargs): def __init__(self, queue='platypush_bus_mq', redis_args=None, *args, **kwargs):

View File

@ -0,0 +1,6 @@
manifest:
events: {}
install:
pip: []
package: platypush.backend.redis
type: backend

View File

@ -1,5 +1,3 @@
import json
from platypush.backend import Backend from platypush.backend import Backend
from platypush.message.event.scard import SmartCardDetectedEvent, SmartCardRemovedEvent from platypush.message.event.scard import SmartCardDetectedEvent, SmartCardRemovedEvent
@ -41,10 +39,15 @@ class ScardBackend(Backend):
"supported types: string, list".format( "supported types: string, list".format(
atr, type(atr))) atr, type(atr)))
self.cardtype = ATRCardType( *[toBytes(atr) for atr in self.ATRs] ) self.cardtype = ATRCardType(*[self._to_bytes(atr) for atr in self.ATRs])
else: else:
self.cardtype = AnyCardType() self.cardtype = AnyCardType()
@staticmethod
def _to_bytes(data) -> bytes:
if isinstance(data, str):
data = data.encode()
return data
def run(self): def run(self):
from smartcard.CardRequest import CardRequest from smartcard.CardRequest import CardRequest
@ -54,7 +57,7 @@ class ScardBackend(Backend):
super().run() super().run()
self.logger.info('Initialized smart card reader backend - ATR filter: {}'. self.logger.info('Initialized smart card reader backend - ATR filter: {}'.
format(self.ATRs)) format(self.ATRs))
prev_atr = None prev_atr = None
reader = None reader = None
@ -70,7 +73,7 @@ class ScardBackend(Backend):
if atr != prev_atr: if atr != prev_atr:
self.logger.info('Smart card detected on reader {}, ATR: {}'. self.logger.info('Smart card detected on reader {}, ATR: {}'.
format(reader, atr)) format(reader, atr))
self.bus.post(SmartCardDetectedEvent(atr=atr, reader=reader)) self.bus.post(SmartCardDetectedEvent(atr=atr, reader=reader))
prev_atr = atr prev_atr = atr
@ -82,6 +85,4 @@ class ScardBackend(Backend):
prev_atr = None prev_atr = None
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et:

View File

@ -0,0 +1,9 @@
manifest:
events:
platypush.message.event.scard.SmartCardDetectedEvent: when a smart card is detected
platypush.message.event.scard.SmartCardRemovedEvent: when a smart card is removed
install:
pip:
- pyscard
package: platypush.backend.scard
type: backend

View File

@ -17,6 +17,7 @@ class SensorBackend(Backend):
gone above a configured threshold gone above a configured threshold
* :class:`platypush.message.event.sensor.SensorDataBelowThresholdEvent` if the measurements of a sensor have * :class:`platypush.message.event.sensor.SensorDataBelowThresholdEvent` if the measurements of a sensor have
gone below a configured threshold gone below a configured threshold
""" """
default_tolerance = 1e-7 default_tolerance = 1e-7

Some files were not shown because too many files have changed in this diff Show More