Files
ha_ecovacs_bumper/sucks.py
T

125 lines
3.6 KiB
Python

import configparser
import itertools
import logging
import os
import time
from threading import Event
import click
from sleekxmpp import ClientXMPP
from sleekxmpp.xmlstream import ET
class VacBot(ClientXMPP):
def __init__(self, user, domain, resource, secret, vacuum):
ClientXMPP.__init__(self, user + '@' + domain, '0/' + resource + '/' + secret)
self.user = user
self.domain = domain
self.resource = resource
self.vacuum = vacuum
self.credentials['authzid'] = user
self.add_event_handler("session_start", self.session_start)
self.ready_flag = Event()
def wait_until_ready(self):
self.ready_flag.wait()
def session_start(self, event):
print("----------------- starting session ----------------")
self.ready_flag.set()
def send_command(self, action):
c = self.wrap_command(action.to_xml())
c.send()
def wrap_command(self, ctl):
q = self.make_iq_query(xmlns=u'com:ctl', ito=self.vacuum + '/atom',
ifrom=self.user + '@' + self.domain + '/' + self.resource)
q['type'] = 'set'
for child in q.xml:
if child.tag.endswith('query'):
child.append(ctl)
return q
def connect_and_wait_until_ready(self):
self.connect(('47.88.66.164', '5223')) # TODO: change to domain name
click.echo("starting")
self.process()
click.echo("done with process")
self.wait_until_ready()
def run(self, action):
click.echo("running " + str(action))
self.send_command(action)
if action.wait:
click.echo("sleeping for " + str(action.wait) + "s")
time.sleep(action.wait)
class VacBotCommand():
def __init__(self, name, args, wait=None, terminal=False):
self.name = name
self.args = args
self.wait = wait
self.terminal = terminal
def to_xml(self):
clean = ET.Element(self.name, self.args)
ctl = ET.Element('ctl', {'td': self.name.capitalize()})
ctl.append(clean)
return ctl
class Clean(VacBotCommand):
def __init__(self, wait):
super().__init__('clean', {'type': 'auto', 'speed': 'standard'}, wait)
class Charge(VacBotCommand):
def __init__(self):
super().__init__('charge', {'type': 'go'}, terminal=True)
def read_config(filename):
parser = configparser.ConfigParser()
with open(filename) as fp:
parser.read_file(itertools.chain(['[global]'], fp), source=filename)
return parser['global']
@click.group(chain=True)
@click.option('--charge/--no-charge', default=True, help='Return to charge after running. Defaults to yes.')
@click.option('--debug/--no-debug', default=False)
def cli(charge, debug):
logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s %(message)s')
@cli.command(help='cleans for the specified number of minutes')
@click.argument('minutes', type=click.FLOAT)
def clean(minutes):
return Clean(minutes * 60)
@cli.command(help='returns to charger')
def charge():
return Charge()
@cli.resultcallback()
def run(actions, charge, debug):
config = read_config(os.path.expanduser('~/.config/sucks.conf'))
vacbot = VacBot(config['user'], config['domain'], config['resource'], config['secret'],
config['vacuum'])
vacbot.connect_and_wait_until_ready()
for action in actions:
vacbot.run(action)
if charge and not actions[-1].terminal:
vacbot.run(Charge())
vacbot.disconnect(wait=True)
if __name__ == '__main__':
cli()