diff --git a/sucks/__init__.py b/sucks/__init__.py
index c009139..938b155 100644
--- a/sucks/__init__.py
+++ b/sucks/__init__.py
@@ -272,7 +272,38 @@ class EcoVacsXMPP(ClientXMPP):
class VacBotCommand:
- def __init__(self, name, args=None, wait=None, terminal=False):
+
+ CLEAN_MODE ={
+ 'auto': 'auto',
+ 'edge': 'border',
+ 'spot': 'spot',
+ 'single_room': 'singleroom',
+ 'stop': 'stop'
+ }
+ FAN_SPEED = {
+ 'normal': 'standard',
+ 'high': 'strong'
+ }
+ CHARGE_MODE = {
+ 'return': 'go',
+ 'returning': 'Going',
+ 'charging': 'SlotCharging',
+ 'idle': 'Idle'
+ }
+ COMPONENT = {
+ 'main_brush': 'Brush',
+ 'side_brush': 'SideBrush',
+ 'filter': 'DustCaseHeap'
+ }
+ ACTION = {
+ 'forward': 'forward',
+ 'left': 'SpinLeft',
+ 'right': 'SpinRight',
+ 'turn_around': 'TurnAround',
+ 'stop': 'stop'
+ }
+
+ def __init__(self, name, args={}, wait=None, terminal=False):
self.name = name
self.args = args
self.wait = wait
@@ -285,9 +316,12 @@ class VacBotCommand:
def to_xml(self):
ctl = ET.Element('ctl', {'td': self.name})
- if self.args:
- inner = ET.Element(self.name.lower(), self.args)
- ctl.append(inner)
+ for key, value in self.args.items():
+ if type(value) is dict:
+ inner = ET.Element(key, value)
+ ctl.append(inner)
+ else:
+ ctl.set(key, value)
return ctl
def __str__(self, *args, **kwargs):
@@ -298,18 +332,44 @@ class VacBotCommand:
class Clean(VacBotCommand):
- def __init__(self, wait):
- super().__init__('Clean', {'type': 'auto', 'speed': 'standard'}, wait)
+ def __init__(self, mode='auto', speed='normal', wait=None, terminal=False):
+ super().__init__('Clean', {'clean': {'type': self.CLEAN_MODE[mode], 'speed': self.FAN_SPEED[speed]}}, wait=wait, terminal=terminal )
-class Edge(VacBotCommand):
- def __init__(self, wait):
- super().__init__('Clean', {'type': 'border', 'speed': 'strong'}, wait)
+class Edge(Clean):
+ def __init__(self, wait=None, terminal=False):
+ super().__init__('edge', 'high', wait=wait, terminal=terminal)
+
+
+class Spot(Clean):
+ def __init__(self, wait=None, terminal=False):
+ super().__init__('spot', 'high', wait=wait, terminal=terminal)
+
+
+class Stop(Clean):
+ def __init__(self, wait=None, terminal=False):
+ super().__init__('stop', 'normal', wait=wait, terminal=terminal)
+
+
+class StopAndWaitForCompletion(Stop):
+ def __init__(self, terminal=False):
+ super().__init__(terminal=False)
+
+ def wait_for_completion(self, bot):
+ logging.debug("waiting in " + self.name)
+ while bot.clean_status not in ['stop']:
+ time.sleep(0.5)
+ logging.debug("done waiting in " + self.name)
class Charge(VacBotCommand):
- def __init__(self):
- super().__init__('Charge', {'type': 'go'}, terminal=True)
+ def __init__(self, terminal=False):
+ super().__init__('Charge', {'charge': {'type': self.CHARGE_MODE['return']}}, terminal=terminal)
+
+
+class ChargeAndWaitForCompletion(Charge):
+ def __init__(self, terminal=False):
+ super().__init__(terminal=terminal)
def wait_for_completion(self, bot):
logging.debug("waiting in " + self.name)
@@ -319,12 +379,31 @@ class Charge(VacBotCommand):
click.echo("docked")
-class Stop(VacBotCommand):
- def __init__(self):
- super().__init__('Clean', {'type': 'stop', 'speed': 'standard'}, terminal=True)
+class Move(VacBotCommand):
+ def __init__(self, action):
+ super().__init__('Move', {'move': {'action': self.ACTION[action]}})
- def wait_for_completion(self, bot):
- logging.debug("waiting in " + self.name)
- while bot.clean_status not in ['stop']:
- time.sleep(0.5)
- logging.debug("done waiting in " + self.name)
+
+class GetCleanState(VacBotCommand):
+ def __init__(self):
+ super().__init__('GetCleanState')
+
+
+class GetChargeState(VacBotCommand):
+ def __init__(self):
+ super().__init__('GetChargeState')
+
+
+class GetBatteryState(VacBotCommand):
+ def __init__(self):
+ super().__init__('GetBatteryInfo')
+
+
+class GetLifeSpan(VacBotCommand):
+ def __init__(self, component):
+ super().__init__('GetLifeSpan', {'type':self.COMPONENT[component]})
+
+
+class SetTime(VacBotCommand):
+ def __init__(self, timestamp, timezone):
+ super().__init__('SetTime', {'time':{'t':timestamp, 'tz':timezone}})
diff --git a/sucks/cli.py b/sucks/cli.py
index a3d6407..c943b7f 100644
--- a/sucks/cli.py
+++ b/sucks/cli.py
@@ -125,7 +125,7 @@ def login(email, password, country_code, continent_code):
@click.argument('minutes', type=click.FLOAT)
def clean(frequency, minutes):
if should_run(frequency):
- return Clean(minutes * 60)
+ return Clean(wait=minutes * 60)
@cli.command(help='cleans room edges for the specified number of minutes')
@@ -133,17 +133,17 @@ def clean(frequency, minutes):
@click.argument('minutes', type=click.FLOAT)
def edge(frequency, minutes):
if should_run(frequency):
- return Edge(minutes * 60)
+ return Edge(wait=minutes * 60)
@cli.command(help='returns to charger')
def charge():
- return Charge()
+ return ChargeAndWaitForCompletion(terminal=True)
@cli.command(help='stops the robot in its current position')
def stop():
- return Stop()
+ return StopAndWaitForCompletion(terminal=True)
@cli.resultcallback()
diff --git a/tests/test_commands.py b/tests/test_commands.py
index e8d9c35..0d21014 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -9,8 +9,14 @@ def test_custom_command():
# Ensure a custom-built command generates the expected XML payload
c = VacBotCommand('CustomCommand', {'type': 'customtype'})
assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
- b'')
+
+def test_custom_command_inner_tag():
+ # Ensure a custom-built command generates the expected XML payload
+ c = VacBotCommand('CustomCommand', {'customtag': {'customvar': 'customvalue'}})
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
def test_custom_command_noargs():
@@ -21,31 +27,96 @@ def test_custom_command_noargs():
def test_clean_command():
- c = Clean(10)
+ c = Clean()
assert_equals(c.terminal, False)
- assert_equals(c.wait, 10)
assert_equals(ElementTree.tostring(c.to_xml()),
b'') # protocol has attribs in other order
+ c = Clean('edge', 'high', 10, terminal=True)
+ assert_equals(c.wait, 10)
+ assert_equals(c.terminal, True)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'') # protocol has attribs in other order
def test_edge_command():
- # called Edge because that's what the UI uses, even though the protocol is different
- c = Edge(10)
+ c = Edge(wait=10)
assert_equals(c.terminal, False)
assert_equals(c.wait, 10)
assert_equals(ElementTree.tostring(c.to_xml()),
b'') # protocol has attribs in other order
+def test_spot_command():
+ c = Spot(wait=5)
+ assert_equals(c.terminal, False)
+ assert_equals(c.wait, 5)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'') # protocol has attribs in other order
+
+
def test_charge_command():
- c = Charge()
+ c = Charge(terminal=True)
assert_equals(c.terminal, True)
assert_equals(ElementTree.tostring(c.to_xml()),
b'')
def test_stop_command():
- c = Stop()
+ c = Stop(terminal=True)
assert_equals(c.terminal, True)
assert_equals(ElementTree.tostring(c.to_xml()),
b'')
+
+
+def test_get_clean_state_command():
+ c = GetCleanState()
+ assert_equals(c.terminal, False)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+
+
+def test_get_charge_state_command():
+ c = GetChargeState()
+ assert_equals(c.terminal, False)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+
+
+def test_get_battery_state_command():
+ c = GetBatteryState()
+ assert_equals(c.terminal, False)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+
+
+
+def test_move_command():
+ c = Move(action='left')
+ assert_equals(c.terminal, False)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = Move(action='right')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = Move(action='turn_around')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = Move(action='forward')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = Move(action='stop')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+
+
+def test_get_lifepsan_command():
+ c = GetLifeSpan('main_brush')
+ assert_equals(c.terminal, False)
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = GetLifeSpan('side_brush')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
+ c = GetLifeSpan('filter')
+ assert_equals(ElementTree.tostring(c.to_xml()),
+ b'')
diff --git a/tests/test_ecovacs_xmpp.py b/tests/test_ecovacs_xmpp.py
index 8bcc0ad..63b2d46 100644
--- a/tests/test_ecovacs_xmpp.py
+++ b/tests/test_ecovacs_xmpp.py
@@ -10,7 +10,7 @@ from sucks import *
def test_wrap_command():
x = make_ecovacs_xmpp()
- c = str(x._wrap_command(Clean(1).to_xml(), 'E0000000001234567890@126.ecorobot.net/atom'))
+ c = str(x._wrap_command(Clean(wait=1).to_xml(), 'E0000000001234567890@126.ecorobot.net/atom'))
assert_true(search(r'from="20170101abcdefabcdefa@ecouser.net/abcdef12"', c))
assert_true(search(r'to="E0000000001234567890@126.ecorobot.net/atom"', c))