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

keep-around/2b5698bdfe9765ccc32527b492d73d8d743f27d5^2
Fabio Manganiello 1 year ago
parent ac0dd95bcc
commit 3bfc5b83ef
  1. 1
      MANIFEST.in
  2. 176
      bin/platyvenv
  3. 5
      docs/source/backends.rst
  4. 2
      docs/source/conf.py
  5. 15
      docs/source/plugins.rst
  6. 17
      generate_missing_docs.py
  7. 4
      platypush/backend/__init__.py
  8. 11
      platypush/backend/adafruit/io/__init__.py
  9. 12
      platypush/backend/adafruit/io/manifest.yaml
  10. 0
      platypush/backend/alarm/__init__.py
  11. 10
      platypush/backend/alarm/manifest.yaml
  12. 1
      platypush/backend/assistant/__init__.py
  13. 0
      platypush/backend/assistant/google/__init__.py
  14. 26
      platypush/backend/assistant/google/manifest.yaml
  15. 9
      platypush/backend/assistant/snowboy/manifest.yaml
  16. 2
      platypush/backend/bluetooth/__init__.py
  17. 0
      platypush/backend/bluetooth/fileserver/__init__.py
  18. 8
      platypush/backend/bluetooth/fileserver/manifest.yaml
  19. 0
      platypush/backend/bluetooth/pushserver/__init__.py
  20. 8
      platypush/backend/bluetooth/pushserver/manifest.yaml
  21. 0
      platypush/backend/bluetooth/scanner/ble/__init__.py
  22. 10
      platypush/backend/bluetooth/scanner/ble/manifest.yaml
  23. 10
      platypush/backend/bluetooth/scanner/manifest.yaml
  24. 9
      platypush/backend/button/flic/__init__.py
  25. 1
      platypush/backend/button/flic/fliclib/aioflic.py
  26. 9
      platypush/backend/button/flic/manifest.yaml
  27. 1
      platypush/backend/camera/pi/__init__.py
  28. 7
      platypush/backend/camera/pi/manifest.yaml
  29. 0
      platypush/backend/chat/telegram/__init__.py
  30. 19
      platypush/backend/chat/telegram/manifest.yaml
  31. 0
      platypush/backend/clipboard/__init__.py
  32. 8
      platypush/backend/clipboard/manifest.yaml
  33. 0
      platypush/backend/covid19/__init__.py
  34. 7
      platypush/backend/covid19/manifest.yaml
  35. 0
      platypush/backend/dbus/__init__.py
  36. 7
      platypush/backend/dbus/manifest.yaml
  37. 10
      platypush/backend/file/monitor/manifest.yaml
  38. 0
      platypush/backend/foursquare/__init__.py
  39. 8
      platypush/backend/foursquare/manifest.yaml
  40. 0
      platypush/backend/github/__init__.py
  41. 32
      platypush/backend/github/manifest.yaml
  42. 0
      platypush/backend/google/fit/__init__.py
  43. 8
      platypush/backend/google/fit/manifest.yaml
  44. 0
      platypush/backend/google/pubsub/__init__.py
  45. 9
      platypush/backend/google/pubsub/manifest.yaml
  46. 0
      platypush/backend/gps/__init__.py
  47. 16
      platypush/backend/gps/manifest.yaml
  48. 15
      platypush/backend/http/__init__.py
  49. 2
      platypush/backend/http/app/routes/plugins/camera/ir/mlx90640.py
  50. 2
      platypush/backend/http/app/routes/plugins/camera/pi.py
  51. 2
      platypush/backend/http/app/routes/plugins/media/__init__.py
  52. 9
      platypush/backend/http/manifest.yaml
  53. 3
      platypush/backend/http/media/handlers/__init__.py
  54. 2
      platypush/backend/http/poll/__init__.py
  55. 6
      platypush/backend/http/poll/manifest.yaml
  56. 0
      platypush/backend/http/request/ota/__init__.py
  57. 48
      platypush/backend/http/request/ota/booking/__init__.py
  58. 5
      platypush/backend/http/request/rss/__init__.py
  59. 0
      platypush/backend/inotify/__init__.py
  60. 15
      platypush/backend/inotify/manifest.yaml
  61. 0
      platypush/backend/joystick/jstest/__init__.py
  62. 21
      platypush/backend/joystick/jstest/manifest.yaml
  63. 0
      platypush/backend/joystick/linux/__init__.py
  64. 16
      platypush/backend/joystick/linux/manifest.yaml
  65. 8
      platypush/backend/joystick/manifest.yaml
  66. 1
      platypush/backend/kafka/__init__.py
  67. 7
      platypush/backend/kafka/manifest.yaml
  68. 0
      platypush/backend/light/hue/__init__.py
  69. 8
      platypush/backend/light/hue/manifest.yaml
  70. 0
      platypush/backend/linode/__init__.py
  71. 8
      platypush/backend/linode/manifest.yaml
  72. 0
      platypush/backend/log/http/__init__.py
  73. 8
      platypush/backend/log/http/manifest.yaml
  74. 0
      platypush/backend/mail/__init__.py
  75. 10
      platypush/backend/mail/manifest.yaml
  76. 2
      platypush/backend/midi/__init__.py
  77. 8
      platypush/backend/midi/manifest.yaml
  78. 0
      platypush/backend/mqtt/__init__.py
  79. 9
      platypush/backend/mqtt/manifest.yaml
  80. 7
      platypush/backend/music/mopidy/__init__.py
  81. 17
      platypush/backend/music/mopidy/manifest.yaml
  82. 16
      platypush/backend/music/mpd/manifest.yaml
  83. 0
      platypush/backend/music/snapcast/__init__.py
  84. 15
      platypush/backend/music/snapcast/manifest.yaml
  85. 21
      platypush/backend/music/spotify/manifest.yaml
  86. 0
      platypush/backend/nextcloud/__init__.py
  87. 10
      platypush/backend/nextcloud/manifest.yaml
  88. 0
      platypush/backend/nfc/__init__.py
  89. 13
      platypush/backend/nfc/manifest.yaml
  90. 1
      platypush/backend/nodered/__init__.py
  91. 7
      platypush/backend/nodered/manifest.yaml
  92. 0
      platypush/backend/ping/__init__.py
  93. 8
      platypush/backend/ping/manifest.yaml
  94. 45
      platypush/backend/pushbullet/__init__.py
  95. 8
      platypush/backend/pushbullet/manifest.yaml
  96. 5
      platypush/backend/redis/__init__.py
  97. 6
      platypush/backend/redis/manifest.yaml
  98. 15
      platypush/backend/scard/__init__.py
  99. 9
      platypush/backend/scard/manifest.yaml
  100. 1
      platypush/backend/sensor/__init__.py
  101. Some files were not shown because too many files have changed in this diff Show More

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

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

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

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

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

@ -1,14 +1,27 @@
import os
from platypush.backend import Backend
from platypush.context import get_plugin
from platypush.plugins import Plugin
from platypush.utils.manifest import get_manifests
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():
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():

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

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

@ -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

@ -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

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

@ -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

@ -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

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

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

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

@ -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

@ -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

@ -1,6 +1,3 @@
import importlib
from enum import Enum
from threading import Timer
from time import time
@ -17,11 +14,14 @@ class ButtonFlicBackend(Backend):
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:
* **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
@ -87,6 +87,7 @@ class ButtonFlicBackend(Backend):
return _f
def _on_event(self):
# noinspection PyUnusedLocal
def _f(bd_addr, channel, click_type, was_queued, time_diff):
if was_queued:
return

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

@ -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

@ -18,7 +18,6 @@ class CameraPiBackend(Backend):
Requires:
* **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
Pi camera actions. If you want to start streaming the camera on application start then simply create an event hook

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

@ -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

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

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

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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

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

@ -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.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
__routes__ = [

@ -8,7 +8,7 @@ from platypush.backend.http.app.utils import authenticate, send_request
from platypush.config import Config
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
__routes__ = [

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

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

@ -1,5 +1,6 @@
import logging
class MediaHandler:
"""
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',
'prefix_handlers', 'media_id']:
if hasattr(self, attr):
yield (attr, getattr(self, attr))
yield attr, getattr(self, attr)
from .file import FileHandler

@ -34,7 +34,7 @@ class HttpPollBackend(Backend):
-
# Poll for updates on an RSS feed
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
poll_seconds: 120
max_entries: 10

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

@ -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:

@ -239,7 +239,10 @@ class RssUpdates(HttpRequest):
f.write(content)
elif self.digest_format == 'pdf':
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 + ' }'
font_config = FontConfiguration()

@ -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

@ -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

@ -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

@ -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

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

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

@ -0,0 +1,8 @@
manifest:
events:
platypush.message.event.light.LightStatusChangeEvent: when thestatus of a lightbulb