- More consistent naming for many methods, plus added a more extensive doc. - Refactored the entry points for the daemon and the pusher into two classes, easier to encapsulate and wrap into tests. - Removed the local backend - managing the concurrency of two processes reading and writing on the same socket at the same time was too much, and its utility outside of the tests (which can have mock backends as well) is quite modest. - Managing stop events on the bus. Still some work to do tho. - Fixed several bugs.
5.8 KiB
Platypush
Execute any command or custom complex logic on your devices, wherever they are, using your PushBullet account.
Installation
pip install platypush
Manual Installation
git clone https://github.com/BlackLight/platypush
cd platypush
python setup.py install
Configuration
Copy /etc/platypush/config.example.yaml to /etc/platypush/config.yaml (system-wise settings) or ~/.config/platypush/config.yaml (user-wise settings).
Edit the file to include:
For the PushBullet backend
- Your PushBullet access token (create one here);
- The name of the (virtual) PushBullet device used to listen for events (create one here).
For the Apache Kafka backend
- The host and port of the Kafka installation
- The topic that will be used to deliver and process messages
device_id
Each target device is identified by a unique device_id in the messages sent over your account. The device_id is the hostname by default, unless changed in config.yaml.
Shell interface
platypush
installs pusher
, a command-line tool to send PushBullet messages to the connected devices in the format used by platypush.
Some examples:
pusher --target laptop --action shell.exec --cmd "scp /home/user/photos/*.jpg backup_host:/mnt/hd/photos"
pusher --target raspberrypi --action music.mpd.play
The logic to execute is specified by the --action
option, whose format is package_name.method_name
(with method_name part of the package main class).
Available plugins
platypush.plugins.shell
: The simplest and yet most versatile plugin. Executes a remote command on the host identified by the--target
device_id. Example:
pusher --target laptop --action shell.exec --cmd "scp /home/user/photos/*.jpg backup_host:/mnt/hd/photos"
platypush.plugins.music.mpd
: Controls the playback on a mpd/mopidy music server. Requires the packagempd2
on the target machine. Example:
pusher --target raspberry --action music.mpd.play
Configure the plugin through an entry like this in your config.yaml
:
music.mpd:
host: your_mpd_host
port: 6600
platypush.plugins.switch.wemo
: Controls a WeMo Switch smart switch device. Requires the packageouimeaux
on the target machine. Example:
pusher --target raspberry --action switch.wemo.on
platypush.plugins.light.hue
: Controls a Philips Hue smart lights system. Requires the packagephue
on the target machine. Example:
pusher --target raspberry --action light.hue.scene --name "Sunset" --group "Living Room"
Writing your plugins
Writing your own platypush
plugin, that would execute your own custom logic whenever a bullet with your plugin name is received, is a very simple task.
-
Create your plugin directory under
platypush/plugins
(e.g.light/batsignal
). -
In the case above,
platypush.plugins.light.batsignal
will be your package name. -
Create an
__init__.py
underplatypush/plugins/light/batsignal
. -
If your module is
light/batsignal
, then its main class should be namedLightBatsignalPlugin
. -
The configuration for your module will be read from a section named
light.batsignal
from yourconfig.yaml
. Its values will passed over the plugin constructor arguments.
The __init__.py
will look like this:
import batman
from platypush.message.response import Response
from .. import LightPlugin
class LightBatsignalPlugin(LightPlugin):
def __init__(self, intensity=100):
super().__init__()
self.batsignal = batman.Batsignal(intensity)
def on(self, urgent=False):
if urgent:
self.batsignal.notify_robin()
self.batsignal.on()
return Response(output='ok')
def off(self):
self.batsignal.off()
return Response(output='ok')
def toggle(self):
self.batsignal.toggle()
return Response(output='ok')
-
Rebuild and reinstall
platypush
if required and relaunch it. -
Test your new plugin by sending some bullets to it:
pusher --target your_pc --action light.batsignal.on --urgent 1
Writing your backends
You can also write your own backends, where a backend is nothing but a thread that listens for messages on a certain channel and pokes the main app whenever it receives one.
-
Create your backend directory under
platypush/backend
(e.g.voicemail
) -
In the case above,
platypush.backend.voicemail
will be your package name. -
Create an
__init__.py
underplatypush/backend/voicemail
. -
If your module is
voicemail
, then its main class should be namedVoicemailBackend
. -
The configuration for your module will be read from a section named
backend.voicemail
from yourconfig.yaml
. Its values will be passed over the backend constructor arguments. -
Implement the
run
method. Since a backend is a thread that polls for new messages on a channel, this will be the thread main method.send_message
should callself.on_message
at the end to post a new message to the application. -
Implement the
send_message
method. This method will be called whenever the application needs to send a new message throughsend_request
andsend_response
. You should never callsend_message
directly.
The __init__.py
will look like this:
from .. import Backend
class VoicemailBackend(Backend)
def __init__(self, phone)
super().__init__()
self.phone = phone
self.voicemail = Voicemail(...)
def send_message(self, msg):
self.voicemail.save_msg(msg)
def run(self):
while True:
msg = self.voicemail.poll()
self.on_message(msg)