forked from platypush/platypush
Moved to manifest files for describing plugins and backends and their dependencies
This commit is contained in:
parent
ac0dd95bcc
commit
3bfc5b83ef
437 changed files with 3139 additions and 1121 deletions
|
@ -1,2 +1,3 @@
|
|||
recursive-include platypush/backend/http/webapp/dist *
|
||||
include platypush/plugins/http/webpage/mercury-parser.js
|
||||
global-include manifest.yaml
|
||||
|
|
174
bin/platyvenv
174
bin/platyvenv
|
@ -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
|
||||
from platypush.utils.manifest import get_install_commands_from_conf
|
||||
|
||||
Config.init('`realpath ${cfgfile}`')
|
||||
register_backends()
|
||||
backend_config = Config.get_backends()
|
||||
deps = get_install_commands_from_conf('$(realpath "${cfgfile}")')
|
||||
print(f'device_id: {Config.get("device_id")}')
|
||||
|
||||
for name in Config.get_backends().keys():
|
||||
backend = get_backend(name)
|
||||
print(backend.__doc__)
|
||||
if deps.get('pip'):
|
||||
print(f'pip: {deps["pip"]}')
|
||||
|
||||
for name in Config.get_plugins().keys():
|
||||
try:
|
||||
plugin = get_plugin(name)
|
||||
print(plugin.__doc__)
|
||||
except:
|
||||
pass
|
||||
EOF
|
||||
)
|
||||
if deps.get('packages'):
|
||||
print(f'packages: {deps["packages"]}')
|
||||
|
||||
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
|
||||
|
||||
Config.init('`realpath ${cfgfile}`')
|
||||
for cmd in deps.get('exec', []):
|
||||
print(f'exec: {cmd}')
|
||||
|
||||
for include in Config._included_files:
|
||||
print(include)
|
||||
print(f'include: {include}')
|
||||
EOF
|
||||
)
|
||||
)"
|
||||
|
||||
device_id=$(python <<EOF
|
||||
from platypush.config import Config
|
||||
|
||||
Config.init('`realpath ${cfgfile}`')
|
||||
print(Config.get('device_id'))
|
||||
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)
|
12
platypush/backend/adafruit/io/manifest.yaml
Normal file
12
platypush/backend/adafruit/io/manifest.yaml
Normal 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
|
10
platypush/backend/alarm/manifest.yaml
Normal file
10
platypush/backend/alarm/manifest.yaml
Normal 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
|
|
@ -1,3 +1,4 @@
|
|||
from abc import ABC
|
||||
import threading
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
|
||||
|
|
26
platypush/backend/assistant/google/manifest.yaml
Normal file
26
platypush/backend/assistant/google/manifest.yaml
Normal 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
|
9
platypush/backend/assistant/snowboy/manifest.yaml
Normal file
9
platypush/backend/assistant/snowboy/manifest.yaml
Normal 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
|
|
@ -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]))
|
||||
|
|
8
platypush/backend/bluetooth/fileserver/manifest.yaml
Normal file
8
platypush/backend/bluetooth/fileserver/manifest.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- pybluez
|
||||
- pyobex
|
||||
package: platypush.backend.bluetooth.fileserver
|
||||
type: backend
|
8
platypush/backend/bluetooth/pushserver/manifest.yaml
Normal file
8
platypush/backend/bluetooth/pushserver/manifest.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- pybluez
|
||||
- pyobex
|
||||
package: platypush.backend.bluetooth.pushserver
|
||||
type: backend
|
10
platypush/backend/bluetooth/scanner/ble/manifest.yaml
Normal file
10
platypush/backend/bluetooth/scanner/ble/manifest.yaml
Normal 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
|
10
platypush/backend/bluetooth/scanner/manifest.yaml
Normal file
10
platypush/backend/bluetooth/scanner/manifest.yaml
Normal 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
|
|
@ -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):
|
||||
|
|
9
platypush/backend/button/flic/manifest.yaml
Normal file
9
platypush/backend/button/flic/manifest.yaml
Normal 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
|
|
@ -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
|
7
platypush/backend/camera/pi/manifest.yaml
Normal file
7
platypush/backend/camera/pi/manifest.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- picamera
|
||||
package: platypush.backend.camera.pi
|
||||
type: backend
|
19
platypush/backend/chat/telegram/manifest.yaml
Normal file
19
platypush/backend/chat/telegram/manifest.yaml
Normal 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
|
8
platypush/backend/clipboard/manifest.yaml
Normal file
8
platypush/backend/clipboard/manifest.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
manifest:
|
||||
events:
|
||||
platypush.message.event.clipboard.ClipboardEvent: on clipboard update.
|
||||
install:
|
||||
pip:
|
||||
- pyperclip
|
||||
package: platypush.backend.clipboard
|
||||
type: backend
|
7
platypush/backend/covid19/manifest.yaml
Normal file
7
platypush/backend/covid19/manifest.yaml
Normal 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
|
7
platypush/backend/dbus/manifest.yaml
Normal file
7
platypush/backend/dbus/manifest.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- dbus-python
|
||||
package: platypush.backend.dbus
|
||||
type: backend
|
10
platypush/backend/file/monitor/manifest.yaml
Normal file
10
platypush/backend/file/monitor/manifest.yaml
Normal 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
|
8
platypush/backend/foursquare/manifest.yaml
Normal file
8
platypush/backend/foursquare/manifest.yaml
Normal 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
|
32
platypush/backend/github/manifest.yaml
Normal file
32
platypush/backend/github/manifest.yaml
Normal 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
|
8
platypush/backend/google/fit/manifest.yaml
Normal file
8
platypush/backend/google/fit/manifest.yaml
Normal 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
|
9
platypush/backend/google/pubsub/manifest.yaml
Normal file
9
platypush/backend/google/pubsub/manifest.yaml
Normal 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
|
16
platypush/backend/gps/manifest.yaml
Normal file
16
platypush/backend/gps/manifest.yaml
Normal 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
|
|
@ -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
|
||||
|
|
9
platypush/backend/http/manifest.yaml
Normal file
9
platypush/backend/http/manifest.yaml
Normal file
|
@ -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
|
||||
|
|
6
platypush/backend/http/poll/manifest.yaml
Normal file
6
platypush/backend/http/poll/manifest.yaml
Normal file
|
@ -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()
|
||||
|
|
15
platypush/backend/inotify/manifest.yaml
Normal file
15
platypush/backend/inotify/manifest.yaml
Normal 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
|
21
platypush/backend/joystick/jstest/manifest.yaml
Normal file
21
platypush/backend/joystick/jstest/manifest.yaml
Normal 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
|
16
platypush/backend/joystick/linux/manifest.yaml
Normal file
16
platypush/backend/joystick/linux/manifest.yaml
Normal 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
|
8
platypush/backend/joystick/manifest.yaml
Normal file
8
platypush/backend/joystick/manifest.yaml
Normal 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
|
|
@ -1,4 +1,3 @@
|
|||
import json
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
|
7
platypush/backend/kafka/manifest.yaml
Normal file
7
platypush/backend/kafka/manifest.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- kafka
|
||||
package: platypush.backend.kafka
|
||||
type: backend
|
8
platypush/backend/light/hue/manifest.yaml
Normal file
8
platypush/backend/light/hue/manifest.yaml
Normal 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
|
8
platypush/backend/linode/manifest.yaml
Normal file
8
platypush/backend/linode/manifest.yaml
Normal 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
|
8
platypush/backend/log/http/manifest.yaml
Normal file
8
platypush/backend/log/http/manifest.yaml
Normal 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
|
10
platypush/backend/mail/manifest.yaml
Normal file
10
platypush/backend/mail/manifest.yaml
Normal 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
|
|
@ -120,7 +120,7 @@ class MidiBackend(Backend):
|
|||
self.logger.exception(e)
|
||||
|
||||
if self.midi:
|
||||
self.midi.close_port(self.port_number)
|
||||
self.midi.close_port()
|
||||
self.midi = None
|
||||
|
||||
|
8
platypush/backend/midi/manifest.yaml
Normal file
8
platypush/backend/midi/manifest.yaml
Normal 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
|
9
platypush/backend/mqtt/manifest.yaml
Normal file
9
platypush/backend/mqtt/manifest.yaml
Normal 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
|
|
@ -2,6 +2,8 @@ import json
|
|||
import re
|
||||
import threading
|
||||
|
||||
import websocket
|
||||
|
||||
from platypush.backend import Backend
|
||||
from platypush.message.event.music import MusicPlayEvent, MusicPauseEvent, \
|
||||
MusicStopEvent, NewPlayingTrackEvent, PlaylistChangeEvent, VolumeChangeEvent, \
|
||||
|
@ -32,7 +34,7 @@ class MusicMopidyBackend(Backend):
|
|||
* :class:`platypush.message.event.music.SeekChangeEvent` if a track seek event occurs
|
||||
|
||||
Requires:
|
||||
* **websocket-client** (``pip install websocket-client``)
|
||||
|
||||
* Mopidy installed and the HTTP service enabled
|
||||
"""
|
||||
|
||||
|
@ -88,7 +90,6 @@ class MusicMopidyBackend(Backend):
|
|||
return conv_track
|
||||
|
||||
def _communicate(self, msg):
|
||||
import websocket
|
||||
|
||||
if isinstance(msg, str):
|
||||
msg = json.loads(msg)
|
||||
|
@ -242,8 +243,6 @@ class MusicMopidyBackend(Backend):
|
|||
return hndl
|
||||
|
||||
def _connect(self):
|
||||
import websocket
|
||||
|
||||
if not self._ws:
|
||||
self._ws = websocket.WebSocketApp(self.url,
|
||||
on_open=self._on_open(),
|
17
platypush/backend/music/mopidy/manifest.yaml
Normal file
17
platypush/backend/music/mopidy/manifest.yaml
Normal 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
|
16
platypush/backend/music/mpd/manifest.yaml
Normal file
16
platypush/backend/music/mpd/manifest.yaml
Normal 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
|
15
platypush/backend/music/snapcast/manifest.yaml
Normal file
15
platypush/backend/music/snapcast/manifest.yaml
Normal 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
|
21
platypush/backend/music/spotify/manifest.yaml
Normal file
21
platypush/backend/music/spotify/manifest.yaml
Normal 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
|
10
platypush/backend/nextcloud/manifest.yaml
Normal file
10
platypush/backend/nextcloud/manifest.yaml
Normal 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
|
13
platypush/backend/nfc/manifest.yaml
Normal file
13
platypush/backend/nfc/manifest.yaml
Normal 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
|
|
@ -17,6 +17,7 @@ class NoderedBackend(Backend):
|
|||
Requires:
|
||||
|
||||
* **pynodered** (``pip install pynodered``)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, port: int = 5051, *args, **kwargs):
|
||||
|
|
7
platypush/backend/nodered/manifest.yaml
Normal file
7
platypush/backend/nodered/manifest.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip:
|
||||
- pynodered
|
||||
package: platypush.backend.nodered
|
||||
type: backend
|
8
platypush/backend/ping/manifest.yaml
Normal file
8
platypush/backend/ping/manifest.yaml
Normal 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
|
|
@ -21,8 +21,8 @@ class PushbulletBackend(Backend):
|
|||
|
||||
Requires:
|
||||
|
||||
* **requests** (``pip install requests``)
|
||||
* **pushbullet.py** (``pip install git+https://github.com/rbrcsk/pushbullet.py``)
|
||||
* **pushbullet.py** (``pip install git+https://github.com/pushbullet.py/pushbullet.py``)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, token: str, device: str = 'Platypush', proxy_host: Optional[str] = None,
|
||||
|
@ -52,7 +52,7 @@ class PushbulletBackend(Backend):
|
|||
try:
|
||||
self.device = self.pb.get_device(self.device_name)
|
||||
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.pb_device_id = self.get_device_id()
|
||||
|
@ -91,17 +91,15 @@ class PushbulletBackend(Backend):
|
|||
|
||||
if 'body' not in push:
|
||||
return
|
||||
self.logger.debug('Received push: {}'.format(push))
|
||||
self.logger.debug(f'Received push: {push}')
|
||||
|
||||
body = push['body']
|
||||
try:
|
||||
body = json.loads(body)
|
||||
self.on_message(body)
|
||||
except Exception as e:
|
||||
self.logger.debug(('Unexpected message received on the ' +
|
||||
'Pushbullet backend: {}. Message: {}')
|
||||
.format(str(e), body))
|
||||
|
||||
self.logger.debug('Unexpected message received on the ' +
|
||||
f'Pushbullet backend: {e}. Message: {body}')
|
||||
except Exception as e:
|
||||
self.logger.exception(e)
|
||||
return
|
||||
|
@ -116,9 +114,7 @@ class PushbulletBackend(Backend):
|
|||
device = self.pb.new_device(self.device_name, model='Platypush virtual device',
|
||||
manufacturer='platypush', icon='system')
|
||||
|
||||
self.logger.info('Created Pushbullet device {}'.format(
|
||||
self.device_name))
|
||||
|
||||
self.logger.info(f'Created Pushbullet device {self.device_name}')
|
||||
return device.device_iden
|
||||
|
||||
def close(self):
|
||||
|
@ -133,27 +129,33 @@ class PushbulletBackend(Backend):
|
|||
self.logger.info('Pushbullet backend terminated')
|
||||
|
||||
def on_close(self, err=None):
|
||||
self.listener = None
|
||||
raise RuntimeError(err or 'Connection closed')
|
||||
def callback(*_):
|
||||
self.listener = None
|
||||
raise RuntimeError(err or 'Connection closed')
|
||||
|
||||
return callback
|
||||
|
||||
def on_open(self):
|
||||
self.logger.info('Pushbullet service connected')
|
||||
def callback(*_):
|
||||
self.logger.info('Pushbullet service connected')
|
||||
|
||||
return callback
|
||||
|
||||
def run_listener(self):
|
||||
from .listener import Listener
|
||||
|
||||
self.logger.info('Initializing Pushbullet backend - device_id: {}'.format(self.device_name))
|
||||
self.listener = Listener(account=self.pb, on_push=self.on_push(),
|
||||
on_open=self.on_open,
|
||||
on_close=self.on_close,
|
||||
on_error=self.on_close,
|
||||
self.logger.info(f'Initializing Pushbullet backend - device_id: {self.device_name}')
|
||||
self.listener = Listener(account=self.pb,
|
||||
on_push=self.on_push(),
|
||||
on_open=self.on_open(),
|
||||
on_close=self.on_close(),
|
||||
on_error=self.on_close(),
|
||||
http_proxy_host=self.proxy_host,
|
||||
http_proxy_port=self.proxy_port)
|
||||
|
||||
self.listener.run_forever()
|
||||
|
||||
def run(self):
|
||||
# noinspection PyPackageRequirements
|
||||
super().run()
|
||||
initialized = False
|
||||
|
||||
|
@ -163,7 +165,7 @@ class PushbulletBackend(Backend):
|
|||
initialized = True
|
||||
except Exception as 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)
|
||||
|
||||
while not self.should_stop():
|
||||
|
@ -175,5 +177,4 @@ class PushbulletBackend(Backend):
|
|||
self.logger.info('Retrying connection')
|
||||
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
8
platypush/backend/pushbullet/manifest.yaml
Normal file
8
platypush/backend/pushbullet/manifest.yaml
Normal 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
|
|
@ -14,11 +14,6 @@ class RedisBackend(Backend):
|
|||
``platypush_bus_mq``) and posts them to the application bus. Very
|
||||
useful when you have plugin whose code is executed in another process
|
||||
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):
|
6
platypush/backend/redis/manifest.yaml
Normal file
6
platypush/backend/redis/manifest.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
manifest:
|
||||
events: {}
|
||||
install:
|
||||
pip: []
|
||||
package: platypush.backend.redis
|
||||
type: backend
|
|
@ -1,5 +1,3 @@
|
|||
import json
|
||||
|
||||
from platypush.backend import Backend
|
||||
from platypush.message.event.scard import SmartCardDetectedEvent, SmartCardRemovedEvent
|
||||
|
||||
|
@ -41,10 +39,15 @@ class ScardBackend(Backend):
|
|||
"supported types: string, list".format(
|
||||
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:
|
||||
self.cardtype = AnyCardType()
|
||||
|
||||
@staticmethod
|
||||
def _to_bytes(data) -> bytes:
|
||||
if isinstance(data, str):
|
||||
data = data.encode()
|
||||
return data
|
||||
|
||||
def run(self):
|
||||
from smartcard.CardRequest import CardRequest
|
||||
|
@ -54,7 +57,7 @@ class ScardBackend(Backend):
|
|||
super().run()
|
||||
|
||||
self.logger.info('Initialized smart card reader backend - ATR filter: {}'.
|
||||
format(self.ATRs))
|
||||
format(self.ATRs))
|
||||
|
||||
prev_atr = None
|
||||
reader = None
|
||||
|
@ -70,7 +73,7 @@ class ScardBackend(Backend):
|
|||
|
||||
if atr != prev_atr:
|
||||
self.logger.info('Smart card detected on reader {}, ATR: {}'.
|
||||
format(reader, atr))
|
||||
format(reader, atr))
|
||||
|
||||
self.bus.post(SmartCardDetectedEvent(atr=atr, reader=reader))
|
||||
prev_atr = atr
|
||||
|
@ -82,6 +85,4 @@ class ScardBackend(Backend):
|
|||
|
||||
prev_atr = None
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
||||
|
|
9
platypush/backend/scard/manifest.yaml
Normal file
9
platypush/backend/scard/manifest.yaml
Normal 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
|
|
@ -17,6 +17,7 @@ class SensorBackend(Backend):
|
|||
gone above a configured threshold
|
||||
* :class:`platypush.message.event.sensor.SensorDataBelowThresholdEvent` if the measurements of a sensor have
|
||||
gone below a configured threshold
|
||||
|
||||
"""
|
||||
|
||||
default_tolerance = 1e-7
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue