Implemented local backend
This commit is contained in:
parent
3b74ed2bb7
commit
e9e0512a52
5 changed files with 91 additions and 6 deletions
17
README.md
17
README.md
|
@ -17,9 +17,22 @@ Copy /etc/runbullet/config.example.yaml to /etc/runbullet/config.yaml (system-wi
|
|||
|
||||
Edit the file to include:
|
||||
|
||||
### For the PushBullet backend
|
||||
|
||||
* Your PushBullet access token (create one [here](https://www.pushbullet.com/#settings/account));
|
||||
* The name of the (virtual) PushBullet device used to listen for events (create one [here](https://www.pushbullet.com/#devices)).
|
||||
|
||||
### For the Apache Kafka backend
|
||||
|
||||
* The host and port of the Kafka installation
|
||||
* The topic that will be used to deliver and process messages
|
||||
|
||||
### For the local socket backend
|
||||
|
||||
* The name of the local FIFO 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
|
||||
|
@ -65,10 +78,10 @@ music.mpd:
|
|||
pusher --target raspberry --action switch.wemo.on
|
||||
```
|
||||
|
||||
* *TODO* `runbullet.plugins.light.hue`: Controls a Philips Hue smart lights system. Requires the package `phue` on the target machine. Example:
|
||||
* `runbullet.plugins.light.hue`: Controls a Philips Hue smart lights system. Requires the package `phue` on the target machine. Example:
|
||||
|
||||
```shell
|
||||
pusher --target raspberry --action light.hue.set_scene --scene "Sunset" --group "Living Room"
|
||||
pusher --target raspberry --action light.hue.scene --name "Sunset" --group "Living Room"
|
||||
```
|
||||
|
||||
Writing your plugins
|
||||
|
|
|
@ -39,12 +39,16 @@ class Backend(Thread):
|
|||
if cls is not object and hasattr(cls, '_init'):
|
||||
cls._init(self, **config)
|
||||
|
||||
def is_local(self):
|
||||
from runbullet.backend.local import LocalBackend
|
||||
return isinstance(self, LocalBackend)
|
||||
|
||||
def on_msg(self, msg):
|
||||
if 'target' not in msg:
|
||||
return # No target
|
||||
|
||||
target = msg.pop('target')
|
||||
if target != runbullet.get_device_id():
|
||||
if target != runbullet.get_device_id() and not self.is_local():
|
||||
return # Not for me
|
||||
|
||||
if 'action' not in msg:
|
||||
|
|
49
runbullet/backend/local/__init__.py
Normal file
49
runbullet/backend/local/__init__.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
import logging
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
from .. import Backend
|
||||
|
||||
class LocalBackend(Backend):
|
||||
def _init(self, fifo):
|
||||
self.fifo = fifo
|
||||
try: os.mkfifo(self.fifo)
|
||||
except FileExistsError as e: pass
|
||||
logging.info('Initialized local backend on fifo {}'.format(self.fifo))
|
||||
|
||||
def send_msg(self, msg):
|
||||
if isinstance(msg, dict):
|
||||
msg = json.dumps(msg)
|
||||
if not isinstance(msg, str):
|
||||
msg = json.dumps(msg)
|
||||
raise RuntimeError('Invalid non-JSON message')
|
||||
|
||||
msglen = len(msg)+1 # Include \n
|
||||
msg = bytearray((str(msglen) + '\n' + msg + '\n').encode('utf-8'))
|
||||
with open(self.fifo, 'wb') as f:
|
||||
f.write(msg)
|
||||
|
||||
def run(self):
|
||||
with open(self.fifo, 'rb', 0) as f:
|
||||
while True:
|
||||
try:
|
||||
msglen = int(f.readline())
|
||||
except ValueError as e:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
|
||||
msg = f.read(msglen-1)
|
||||
if not msg: continue
|
||||
|
||||
try:
|
||||
msg = json.loads(msg.decode('utf-8'))
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
continue
|
||||
|
||||
logging.debug('Received message: {}'.format(msg))
|
||||
self.on_msg(msg)
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
@ -10,6 +10,7 @@ import yaml
|
|||
from pushbullet import Pushbullet
|
||||
from runbullet import parse_config_file
|
||||
from runbullet.backend.kafka import KafkaBackend
|
||||
from runbullet.backend.local import LocalBackend
|
||||
|
||||
|
||||
def print_usage():
|
||||
|
@ -40,10 +41,18 @@ def send_pb_message(pb, device_name, msg):
|
|||
def send_kafka_message(backend, msg):
|
||||
backend.send_msg(msg)
|
||||
|
||||
def send_local_message(backend, msg):
|
||||
backend.send_msg(msg)
|
||||
|
||||
def get_backend(config):
|
||||
# TODO Refactor this as something better and reuse the same
|
||||
# backend classes from the runbullet consumer module
|
||||
if 'backend.pushbullet' in config \
|
||||
if 'backend.local' in config \
|
||||
and 'pusher' in config['backend.local'] \
|
||||
and config['backend.local']['pusher']:
|
||||
c = config['backend.local']
|
||||
return LocalBackend({'fifo': c['fifo']})
|
||||
elif 'backend.pushbullet' in config \
|
||||
and 'pusher' in config['backend.pushbullet'] \
|
||||
and config['backend.pushbullet']['pusher']:
|
||||
API_KEY = config['backend.pushbullet']['token']
|
||||
|
@ -66,8 +75,8 @@ def main():
|
|||
|
||||
parser.add_argument('--backend', '-b', dest='backend', required=False,
|
||||
help="Backend to deliver the message " +
|
||||
"[pushbullet|kafka] (default: whatever specified " +
|
||||
"in your config with pusher=True)")
|
||||
"[pushbullet|kafka|local] (default: whatever " +
|
||||
"specified in your config with pusher=True)")
|
||||
|
||||
opts, args = parser.parse_known_args(sys.argv[1:])
|
||||
payload = {}
|
||||
|
@ -76,6 +85,11 @@ def main():
|
|||
raise RuntimeError('Odd number of key-value options passed: {}'.
|
||||
format(args))
|
||||
|
||||
if opts.target == 'localhost' and 'backend.local' in config:
|
||||
cfg = config['backend.local']
|
||||
cfg['pusher'] = True
|
||||
config = { 'backend.local': cfg }
|
||||
|
||||
if opts.backend:
|
||||
backend_cfg_name = 'backend.' + opts.backend
|
||||
if backend_cfg_name not in config:
|
||||
|
@ -103,6 +117,8 @@ def main():
|
|||
send_pb_message(backend, config['backend.pushbullet']['device'], msg)
|
||||
elif isinstance(backend, KafkaBackend):
|
||||
send_kafka_message(backend, msg)
|
||||
elif isinstance(backend, LocalBackend):
|
||||
send_local_message(backend, msg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -11,6 +11,9 @@ backend.pushbullet:
|
|||
token: your_pushbullet_token_here
|
||||
device: your_pushbullet_virtual_device_name
|
||||
|
||||
backend.local:
|
||||
fifo: /tmp/runbullet.fifo
|
||||
|
||||
# device_id: <your_device_id> (default: current hostname)
|
||||
# debug: True (default: False)
|
||||
|
||||
|
|
Loading…
Reference in a new issue